Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
aea9c5a
First draft of the RBF Mapper
juancamarotti May 13, 2025
07ce71d
Creating a matrix of destination coordinates
juancamarotti May 13, 2025
5be0815
Adding the functionality to tranform the mapping from integration poi…
juancamarotti May 27, 2025
f687181
Changes for the VLM solver
juancamarotti Sep 18, 2025
b270b2e
changing the definition odf the TPS
juancamarotti Oct 17, 2025
e344117
Adding new parameters to the mapper
juancamarotti Oct 17, 2025
d7b201b
changing some types
juancamarotti Oct 17, 2025
22377f1
error correction
juancamarotti Oct 17, 2025
9b848b3
adding some new functions in the rbf mapper
juancamarotti Oct 17, 2025
da7cc7a
minor changes and creation of some new functions
juancamarotti Oct 17, 2025
ea6aec0
changing typedef to using and adding some new function
juancamarotti Oct 17, 2025
a01d093
Reimplementing some methods in the RBF mapper
juancamarotti Oct 20, 2025
994dfac
Change comparison for the thin_plate_spline rbf
juancamarotti Oct 24, 2025
c7098fa
Refactoring of the RBF Mapper
juancamarotti Oct 24, 2025
61e7fc5
Merge branch 'master' into mapping/rbf_based_mapper
juancamarotti Oct 24, 2025
3e45bc0
Short explanation for a function
juancamarotti Oct 24, 2025
2fad679
Test for the RBF Mapper
juancamarotti Oct 24, 2025
62ab6c4
small changes and adding error messages
juancamarotti Oct 24, 2025
f7a2a4d
correcting the test
juancamarotti Oct 24, 2025
b10cb87
Changint the rbf type to an enum class and also some minor changes re…
juancamarotti Oct 28, 2025
8d36f20
Merge remote-tracking branch 'origin' into mapping/rbf_based_mapper
juancamarotti Nov 6, 2025
a250955
first commit
juancamarotti Nov 6, 2025
340b316
adding rbf utilities (other PR)
juancamarotti Nov 7, 2025
bfe526a
Initial creation of the new rbf mapper
juancamarotti Nov 7, 2025
3a10cb1
Merge branch 'master' of https://github.com/KratosMultiphysics/Kratos…
juancamarotti Nov 10, 2025
0d075ff
Fixing some old tests
juancamarotti Nov 18, 2025
53233bb
Changing the RBF Test
juancamarotti Nov 19, 2025
113865f
solving a bug in the RBF utilities
juancamarotti Nov 19, 2025
ffb4ad4
solving bug
juancamarotti Nov 19, 2025
ef2b099
adding BuildMappingMatrixRBFMapper to the mapping matrix utilities
juancamarotti Nov 19, 2025
841b5ad
adding AssignInterfaceEquationIdsOnConditions to the MapperUtilities
juancamarotti Nov 19, 2025
42fe081
new parameters for the search
juancamarotti Nov 19, 2025
8b12985
making AddInterfaceInfo virtual so that it can be overriden is derive…
juancamarotti Nov 19, 2025
db5ef77
creating a method called GetRBFSupportAccumulator() inside mapper int…
juancamarotti Nov 19, 2025
9f4327a
creation of the rbf mapper for FEM-FEM and IGA-FEM scenarios
juancamarotti Nov 19, 2025
a9828e2
Merge branch 'master' into mapping/rbf_mapper_proper_implementation
juancamarotti Nov 19, 2025
426df72
reverting the changes in the rbf utilities in the core
juancamarotti Nov 19, 2025
c149291
making CalculateInverseMultiquadricShapeParameter() public so that it…
juancamarotti Nov 19, 2025
89db329
reverting the changes in the interpolative mapper
juancamarotti Nov 19, 2025
5fec50f
reverting changes in interpoaltive base mapper
juancamarotti Nov 19, 2025
1af1275
solving small bug
juancamarotti Nov 19, 2025
f4d1771
correction in the mapper tests
juancamarotti Nov 19, 2025
b0eeb1d
small bug
juancamarotti Nov 19, 2025
1290106
erasing a non-used member function
juancamarotti Nov 19, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,9 @@ InterfaceCommunicator::InterfaceCommunicator(
"max_num_search_iterations" : 0,
"print_bounding_boxes_to_file" : false,
"bounding_boxes_file_path" : "",
"echo_level" : 0
"echo_level" : 0,
"required_rbf_support_points" : 0,
"use_all_rbf_support_points": true
})");
// deliberately only validating defaults, but not assigning, since computing the defaults is expensive
// see "ExchangeInterfaceData"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@

namespace Kratos
{
class RBFSupportAccumulator;

///@addtogroup MappingApplication
///@{

Expand Down Expand Up @@ -118,6 +120,15 @@ class MapperInterfaceInfo
virtual MapperInterfaceInfo::Pointer Create(const CoordinatesArrayType& rCoordinates,
const IndexType SourceLocalSystemIndex,
const IndexType SourceRank) const = 0;

/**
* @brief Returning the results of the neighbour search for the RBF mapper
* @author Juan I. Camarotti
*/
virtual const RBFSupportAccumulator& GetRBFSupportAccumulator() const
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please dont add a special interface

I solved basically the same issue with static_cast, see here:

const BarycentricInterfaceInfo& r_info = static_cast<const BarycentricInterfaceInfo&>(*mInterfaceInfos[i]);

Its not the greatest solution either, but I think in this case its cleaner

{
KRATOS_ERROR << "Base class function called!" << std::endl;
}

// needed for serialization
virtual MapperInterfaceInfo::Pointer Create() const = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ class MapperLocalSystem
virtual CoordinatesArrayType& Coordinates() const = 0;


void AddInterfaceInfo(MapperInterfaceInfoPointerType pInterfaceInfo) // TODO pass by const ref?
virtual void AddInterfaceInfo(MapperInterfaceInfoPointerType pInterfaceInfo) // TODO pass by const ref?
{
mInterfaceInfos.push_back(pInterfaceInfo);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,26 @@ void AssignInterfaceEquationIds(Communicator& rModelPartCommunicator)
rModelPartCommunicator.SynchronizeNonHistoricalVariable(INTERFACE_EQUATION_ID);
}

void AssignInterfaceEquationIdsOnConditions(Communicator& rModelPartCommunicator)
{
if (rModelPartCommunicator.GetDataCommunicator().IsNullOnThisRank()) {
return;
}

const int num_conditions_local = rModelPartCommunicator.LocalMesh().NumberOfConditions();
int num_conditions_accumulated = rModelPartCommunicator.GetDataCommunicator().ScanSum(num_conditions_local);
const int start_equation_id = num_conditions_accumulated - num_conditions_local;
const auto conditions_begin = rModelPartCommunicator.LocalMesh().ConditionsBegin();

IndexPartition<unsigned int>(num_conditions_local).for_each(
[conditions_begin, start_equation_id](unsigned int i){
(conditions_begin + i)->SetValue(INTERFACE_EQUATION_ID, start_equation_id + i);
}
);

rModelPartCommunicator.SynchronizeNonHistoricalVariable(INTERFACE_EQUATION_ID);
}

template <typename TContainer>
double ComputeMaxEdgeLengthLocal(const TContainer& rEntityContainer)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,16 @@ void UpdateModelPartFromSystemVector(
*/
void KRATOS_API(MAPPING_APPLICATION) AssignInterfaceEquationIds(Communicator& rModelPartCommunicator);

/**
* @brief Assigning INTERFACE_EQUATION_IDs to the conditions, with and without MPI
* This function assigns the INTERFACE_EQUATION_IDs to the conditions, which
* act as EquationIds for the MappingMatrix in the case of IGA. This work with and without MPI,
* in MPI a ScanSum is performed with the local number of nodes
* @param rModelPartCommunicator The Modelpart-Communicator to be used
* @author Juan I. Camarotti
*/
void KRATOS_API(MAPPING_APPLICATION) AssignInterfaceEquationIdsOnConditions(Communicator& rModelPartCommunicator);

void KRATOS_API(MAPPING_APPLICATION) CreateMapperLocalSystemsFromNodes(const MapperLocalSystem& rMapperLocalSystemPrototype,
const Communicator& rModelPartCommunicator,
std::vector<Kratos::unique_ptr<MapperLocalSystem>>& rLocalSystems);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,12 +206,59 @@ void MappingMatrixUtilitiesType::BuildMappingMatrix(

BuildMatrix(rpMappingMatrix, rMapperLocalSystems);

// refactor to be used from the mapper directly
// if (EchoLevel > 2) {
// const std::string base_file_name = "O_" + rModelPartOrigin.Name() + "__D_" + rModelPartDestination.Name() +".mm";
// MappingSparseSpaceType::WriteMatrixMarketMatrix(("MappingMatrix_"+base_file_name).c_str(), *rpMappingMatrix, false);
// CheckRowSum<MappingSparseSpaceType, DenseSpaceType>(*rpMappingMatrix, base_file_name);
// }
MappingMatrixUtilitiesType::InitializeSystemVector(rpInterfaceVectorOrigin, num_nodes_origin);
MappingMatrixUtilitiesType::InitializeSystemVector(rpInterfaceVectorDestination, num_nodes_destination);

KRATOS_CATCH("")
}

template<>
void MappingMatrixUtilitiesType::BuildMappingMatrixRBFMapper(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if its RBF-specific, then please move it to the rbf-mapper

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’d prefer to keep this implementation here. Moving it elsewhere would force MappingMatrixUtilities::ConstructMatrixStructure and MappingMatrixUtilities::BuildMatrix to be static, which is not ideal.

Kratos::unique_ptr<typename MappingSparseSpaceType::MatrixType>& rpMappingMatrix,
Kratos::unique_ptr<typename MappingSparseSpaceType::VectorType>& rpInterfaceVectorOrigin,
Kratos::unique_ptr<typename MappingSparseSpaceType::VectorType>& rpInterfaceVectorDestination,
const ModelPart& rModelPartOrigin,
const ModelPart& rModelPartDestination,
std::vector<Kratos::unique_ptr<MapperLocalSystem>>& rMapperLocalSystems,
const IndexType NumberOfPolynomialTerms,
const bool BuildOriginInterpolationMatrix,
const bool OriginIsIga,
const int EchoLevel)
{
KRATOS_TRY

static_assert(!MappingSparseSpaceType::IsDistributed(), "Using a distributed Space!");

const SizeType num_nodes_origin = rModelPartOrigin.NumberOfNodes();
const SizeType num_conditions_origin = rModelPartOrigin.NumberOfConditions();
const SizeType num_nodes_destination = rModelPartDestination.NumberOfNodes();
const SizeType num_conditions_destination = rModelPartDestination.NumberOfConditions();

IndexType origin_size;
IndexType destination_size;

if (!OriginIsIga){
origin_size = num_nodes_origin;
destination_size = num_nodes_destination;
} else if (OriginIsIga && BuildOriginInterpolationMatrix) {
origin_size = num_conditions_origin;
destination_size = num_conditions_destination;
} else if (OriginIsIga && !BuildOriginInterpolationMatrix) {
origin_size = num_conditions_origin;
destination_size = num_nodes_destination;
}

// Initialize the Matrix
// This has to be done always since the Graph has changed if the Interface is updated!
if (BuildOriginInterpolationMatrix){
ConstructMatrixStructure(rpMappingMatrix, rMapperLocalSystems,
origin_size + NumberOfPolynomialTerms, destination_size + NumberOfPolynomialTerms);
} else {
ConstructMatrixStructure(rpMappingMatrix, rMapperLocalSystems,
origin_size + NumberOfPolynomialTerms, destination_size);
}

BuildMatrix(rpMappingMatrix, rMapperLocalSystems);

MappingMatrixUtilitiesType::InitializeSystemVector(rpInterfaceVectorOrigin, num_nodes_origin);
MappingMatrixUtilitiesType::InitializeSystemVector(rpInterfaceVectorDestination, num_nodes_destination);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,18 @@ static void BuildMappingMatrix(
std::vector<Kratos::unique_ptr<MapperLocalSystem>>& rMapperLocalSystems,
const int EchoLevel);

static void BuildMappingMatrixRBFMapper(
Kratos::unique_ptr<typename TSparseSpace::MatrixType>& rpMappingMatrix,
Kratos::unique_ptr<typename TSparseSpace::VectorType>& rpInterfaceVectorOrigin,
Kratos::unique_ptr<typename TSparseSpace::VectorType>& rpInterfaceVectorDestination,
const ModelPart& rModelPartOrigin,
const ModelPart& rModelPartDestination,
std::vector<Kratos::unique_ptr<MapperLocalSystem>>& rMapperLocalSystems,
const IndexType NumberOfPolynomialTerms,
const bool BuildOriginInterpolationMatrix,
const bool OriginIsIga,
const int EchoLevel);

static void CheckRowSum(
const typename TSparseSpace::MatrixType& rM,
const std::string& rBaseFileName,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ namespace Kratos
namespace RadialBasisFunctionsUtilities
{
// Extracted from: Review of coupling methods for non-matching meshes (https://doi.org/10.1016/j.cma.2006.03.017)
double CalculateWendlandC2SupportRadius(const Matrix& rPoints, const double k = 2.5)
double CalculateWendlandC2SupportRadius(const Matrix& rPoints, const double k)
{
const SizeType n_points = rPoints.size1();
KRATOS_ERROR_IF(n_points < 2) << "At least two points are required to estimate spacing." << std::endl;
Expand All @@ -42,4 +42,4 @@ namespace RadialBasisFunctionsUtilities
}

} // namespace RadialBasisFunctionsUtilities
} // namespace Kratos.
} // namespace Kratos.
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ struct WendlandC2 {
}
};

double KRATOS_API(MAPPING_APPLICATION) CalculateWendlandC2SupportRadius(const Matrix& rPoints, const double k);
double KRATOS_API(MAPPING_APPLICATION) CalculateWendlandC2SupportRadius(const Matrix& rPoints, const double k = 2.5);

} // namespace RadialBasisFunctionsUtilities.

} // namespace Kratos.
} // namespace Kratos.
2 changes: 2 additions & 0 deletions applications/MappingApplication/mapping_application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include "custom_mappers/projection_3D_2D_mapper.h"
#include "custom_mappers/beam_mapper.h"
#include "custom_mappers/coupling_geometry_mapper.h"
#include "custom_mappers/radial_basis_function_mapper.h"
#include "custom_mappers/nearest_neighbor_mapper_iga.h"

// Macros for registering mappers
Expand Down Expand Up @@ -95,6 +96,7 @@ void KratosMappingApplication::Register()

KRATOS_REGISTER_MAPPER_WITH_BACKEND(NearestNeighborMapperIGA, "nearest_neighbor_iga");

KRATOS_REGISTER_MAPPER(RadialBasisFunctionMapper, "radial_basis_function");
KRATOS_REGISTER_MAPPER(CouplingGeometryMapper, "coupling_geometry");
KRATOS_REGISTER_MAPPER(BeamMapper, "beam_mapper");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,4 +121,4 @@ KRATOS_TEST_CASE_IN_SUITE(RadialBasisFunctionsUtilities_WendlandC2SupportRadius,
KRATOS_EXPECT_NEAR(support_radius, expected_radius, 1e-12);
}

} // namespace Kratos::Testing
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from KratosMultiphysics import KratosUnittest
from KratosMultiphysics.testing.utilities import ReadModelPart
import os
from KratosMultiphysics.kratos_utilities import CheckIfApplicationsAvailable

def GetFilePath(file_name):
return os.path.join(os.path.dirname(os.path.realpath(__file__)), "mdpa_files", file_name)
Expand Down Expand Up @@ -30,10 +31,11 @@ def test_inverse_map_forces(self):
reference_result = [0.2380991480071958, 0.2380991480071958, 0.2380991480071958, 1.3120351229689677, 1.3120351229689677, 1.3120351229689677, 0.6908309106360845, 0.6908309106360845, 0.6908309106360845, 0.9063686826513201, 0.9063686826513201, 0.9063686826513201, 0.9261336708771284, 0.9261336708771284, 0.9261336708771284, 0.9265324648593039, 0.9265324648593039, 0.9265324648593039]
self.assertVectorAlmostEqual(mapped_results,reference_result)

@KratosUnittest.skipIfApplicationsNotAvailable("IgaApplication")
class TestIgaFEMCouplingGeometryMapper(KratosUnittest.TestCase):
@classmethod
def setUpClass(self):
if not CheckIfApplicationsAvailable("IgaApplication"):
raise KratosUnittest.SkipTest("The IgaApplication is not available!")
import KratosMultiphysics.IgaApplication as Iga
self.mapper_parameters = KM.Parameters("""{
"mapper_type": "coupling_geometry",
Expand Down Expand Up @@ -63,10 +65,11 @@ def test_map_displacements(self):
reference_result = [1.0, 1.0, 1.0, 0.9999999999999998, 0.9999999999999998, 0.9999999999999998]
self.assertVectorAlmostEqual(mapped_results,reference_result)

@KratosUnittest.skipIfApplicationsNotAvailable("IgaApplication")
class TestDualMortarIgaFEMCouplingGeometryMapper(KratosUnittest.TestCase):
@classmethod
def setUpClass(self):
if not CheckIfApplicationsAvailable("IgaApplication"):
raise KratosUnittest.SkipTest("The IgaApplication is not available!")
import KratosMultiphysics.IgaApplication as Iga
self.mapper_parameters = KM.Parameters("""{
"mapper_type": "coupling_geometry",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import blade_mapping_test
import quadratic_mapper_tests
from pathlib import Path
from KratosMultiphysics.kratos_utilities import CheckIfApplicationsAvailable

def GetFilePath(file_name):
return Path(__file__).resolve().parent / "mdpa_files" / file_name
Expand Down Expand Up @@ -163,10 +164,11 @@ def setUpClass(cls):
}""")
super().setUpMapper(mapper_params, switch_sides=True)

@KratosUnittest.skipIfApplicationsNotAvailable("IgaApplication")
class BasicTestsLineMappingIGAFEM(basic_mapper_tests.BasicMapperTests):
@classmethod
def setUpClass(cls):
if not CheckIfApplicationsAvailable("IgaApplication"):
raise KratosUnittest.SkipTest("The IgaApplication is not available!")
import KratosMultiphysics.IgaApplication as Iga
mapper_params = KM.Parameters("""{
"mapper_type": "nearest_element",
Expand Down Expand Up @@ -310,6 +312,8 @@ def test_Map_USE_TRANSPOSE_constant_scalar_both_non_historical(self):
class BasicTestsSurfaceMappingIGAFEM(basic_mapper_tests.BasicMapperTests):
@classmethod
def setUpClass(cls):
if not CheckIfApplicationsAvailable("IgaApplication"):
raise KratosUnittest.SkipTest("The IgaApplication is not available!")
import KratosMultiphysics.IgaApplication as Iga
mapper_params = KM.Parameters("""{
"mapper_type": "nearest_element",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
data_comm = KM.Testing.GetDefaultDataCommunicator()
if data_comm.IsDistributed():
from KratosMultiphysics.MappingApplication import MPIExtension as MappingMPIExtension
from KratosMultiphysics.kratos_utilities import CheckIfApplicationsAvailable

# Additional imports
import mapper_test_case
Expand All @@ -16,10 +17,11 @@
def GetFilePath(file_name):
return Path(__file__).resolve().parent / "mdpa_files" / file_name

@KratosUnittest.skipIfApplicationsNotAvailable("IgaApplication")
class BasicTestsLineMappingIGAFEM(basic_mapper_tests.BasicMapperTests):
@classmethod
def setUpClass(cls):
if not CheckIfApplicationsAvailable("IgaApplication"):
raise KratosUnittest.SkipTest("The IgaApplication is not available!")
import KratosMultiphysics.IgaApplication as Iga
mapper_params = KM.Parameters("""{
"mapper_type": "nearest_neighbor_iga",
Expand Down Expand Up @@ -161,10 +163,11 @@ def test_Map_USE_TRANSPOSE_constant_scalar_FROM_NON_HISTORICAL(self):
def test_Map_USE_TRANSPOSE_constant_scalar_both_non_historical(self):
self.skipTest("Not implemented for this mapper")

@KratosUnittest.skipIfApplicationsNotAvailable("IgaApplication")
class BasicTestsSurfaceMappingIGAFEM(basic_mapper_tests.BasicMapperTests):
@classmethod
def setUpClass(cls):
if not CheckIfApplicationsAvailable("IgaApplication"):
raise KratosUnittest.SkipTest("The IgaApplication is not available!")
import KratosMultiphysics.IgaApplication as Iga
mapper_params = KM.Parameters("""{
"mapper_type": "nearest_neighbor_iga",
Expand Down
Loading
Loading