Skip to content

Commit

Permalink
Merge pull request #12616 from KratosMultiphysics/Core/adding-new-tes…
Browse files Browse the repository at this point in the history
…t-parallelfillcommunicator

[Core] Adding new test for `ParallelFillCommunicator`
  • Loading branch information
loumalouomega authored Oct 9, 2024
2 parents b316375 + a3cad88 commit 23c3728
Show file tree
Hide file tree
Showing 3 changed files with 210 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -131,4 +131,100 @@ KRATOS_TEST_CASE_IN_SUITE(ParallelFillCommunicatorExecuteTriangleMesh, KratosMPI
}
}

KRATOS_TEST_CASE_IN_SUITE(ParallelFillCommunicatorExecuteTriforceMesh, KratosMPICoreFastSuite)
{
// The model part
Model current_model;
ModelPart& r_model_part = current_model.CreateModelPart("Main");

// The data communicator
const DataCommunicator& r_data_communicator = Testing::GetDefaultDataCommunicator();

// MPI data
const int rank = r_data_communicator.Rank();
const int world_size = r_data_communicator.Size();

// Fill the model part
MPICppTestUtilities::GenerateDistributedTriforceMesh(r_model_part, r_data_communicator);

// Check that the communicator is correctly filled
const auto& r_neighbours_indices = r_model_part.GetCommunicator().NeighbourIndices();
if (world_size == 1) {
KRATOS_EXPECT_EQ(r_neighbours_indices.size(), 0);
KRATOS_EXPECT_EQ(r_model_part.GetCommunicator().LocalMesh().NumberOfNodes(), 6);
KRATOS_EXPECT_EQ(r_model_part.GetCommunicator().GhostMesh().NumberOfNodes(), 0);
KRATOS_EXPECT_EQ(r_model_part.GetCommunicator().InterfaceMesh().NumberOfNodes(), 0);
} else if (world_size == 2) {
KRATOS_EXPECT_EQ(r_neighbours_indices.size(), 1);
if (rank == 0) {
KRATOS_EXPECT_EQ(r_neighbours_indices[0], 1);
KRATOS_EXPECT_EQ(r_model_part.GetCommunicator().LocalMesh().NumberOfNodes(), 5);
KRATOS_EXPECT_EQ(r_model_part.GetCommunicator().GhostMesh().NumberOfNodes(), 1);
KRATOS_EXPECT_EQ(r_model_part.GetCommunicator().InterfaceMesh().NumberOfNodes(), 3);
} else if (rank == 1) {
KRATOS_EXPECT_EQ(r_neighbours_indices[0], 0);
KRATOS_EXPECT_EQ(r_model_part.GetCommunicator().LocalMesh().NumberOfNodes(), 1);
KRATOS_EXPECT_EQ(r_model_part.GetCommunicator().GhostMesh().NumberOfNodes(), 2);
KRATOS_EXPECT_EQ(r_model_part.GetCommunicator().InterfaceMesh().NumberOfNodes(), 3);
}
} else {
if (rank == 0) {
KRATOS_EXPECT_EQ(r_neighbours_indices[0], 1);
KRATOS_EXPECT_EQ(r_model_part.GetCommunicator().LocalMesh().NumberOfNodes(), 5);
KRATOS_EXPECT_EQ(r_model_part.GetCommunicator().GhostMesh().NumberOfNodes(), 1);
KRATOS_EXPECT_EQ(r_model_part.GetCommunicator().InterfaceMesh().NumberOfNodes(), 3);
} else if (rank == 1) {
KRATOS_EXPECT_EQ(r_neighbours_indices[0], 0);
KRATOS_EXPECT_EQ(r_model_part.GetCommunicator().LocalMesh().NumberOfNodes(), 1);
KRATOS_EXPECT_EQ(r_model_part.GetCommunicator().GhostMesh().NumberOfNodes(), 2);
KRATOS_EXPECT_EQ(r_model_part.GetCommunicator().InterfaceMesh().NumberOfNodes(), 3);
} else { // The rest of the ranks
KRATOS_EXPECT_EQ(r_model_part.GetCommunicator().LocalMesh().NumberOfNodes(), 0);
KRATOS_EXPECT_EQ(r_model_part.GetCommunicator().GhostMesh().NumberOfNodes(), 0);
KRATOS_EXPECT_EQ(r_model_part.GetCommunicator().InterfaceMesh().NumberOfNodes(), 0);
}
}

// Check the submodelpart
ModelPart& r_sub_model_part = r_model_part.GetSubModelPart("SkinModelPart");

// Check that the communicator is correctly filled
const auto& r_sub_neighbours_indices = r_sub_model_part.GetCommunicator().NeighbourIndices();
if (world_size == 1) {
KRATOS_EXPECT_EQ(r_sub_neighbours_indices.size(), 0);
KRATOS_EXPECT_EQ(r_sub_model_part.GetCommunicator().LocalMesh().NumberOfNodes(), 6);
KRATOS_EXPECT_EQ(r_sub_model_part.GetCommunicator().GhostMesh().NumberOfNodes(), 0);
KRATOS_EXPECT_EQ(r_sub_model_part.GetCommunicator().InterfaceMesh().NumberOfNodes(), 0);
} else if (world_size == 2) {
KRATOS_EXPECT_EQ(r_sub_neighbours_indices.size(), 1);
if (rank == 0) {
KRATOS_EXPECT_EQ(r_sub_neighbours_indices[0], 1);
KRATOS_EXPECT_EQ(r_sub_model_part.GetCommunicator().LocalMesh().NumberOfNodes(), 5);
KRATOS_EXPECT_EQ(r_sub_model_part.GetCommunicator().GhostMesh().NumberOfNodes(), 1);
KRATOS_EXPECT_EQ(r_sub_model_part.GetCommunicator().InterfaceMesh().NumberOfNodes(), 3);
} else if (rank == 1) {
KRATOS_EXPECT_EQ(r_sub_neighbours_indices[0], 0);
KRATOS_EXPECT_EQ(r_sub_model_part.GetCommunicator().LocalMesh().NumberOfNodes(), 1);
KRATOS_EXPECT_EQ(r_sub_model_part.GetCommunicator().GhostMesh().NumberOfNodes(), 2);
KRATOS_EXPECT_EQ(r_sub_model_part.GetCommunicator().InterfaceMesh().NumberOfNodes(), 3);
}
} else {
if (rank == 0) {
KRATOS_EXPECT_EQ(r_sub_neighbours_indices[0], 1);
KRATOS_EXPECT_EQ(r_sub_model_part.GetCommunicator().LocalMesh().NumberOfNodes(), 5);
KRATOS_EXPECT_EQ(r_sub_model_part.GetCommunicator().GhostMesh().NumberOfNodes(), 1);
KRATOS_EXPECT_EQ(r_sub_model_part.GetCommunicator().InterfaceMesh().NumberOfNodes(), 3);
} else if (rank == 1) {
KRATOS_EXPECT_EQ(r_sub_neighbours_indices[0], 0);
KRATOS_EXPECT_EQ(r_sub_model_part.GetCommunicator().LocalMesh().NumberOfNodes(), 1);
KRATOS_EXPECT_EQ(r_sub_model_part.GetCommunicator().GhostMesh().NumberOfNodes(), 2);
KRATOS_EXPECT_EQ(r_sub_model_part.GetCommunicator().InterfaceMesh().NumberOfNodes(), 3);
} else { // The rest of the ranks
KRATOS_EXPECT_EQ(r_sub_model_part.GetCommunicator().LocalMesh().NumberOfNodes(), 0);
KRATOS_EXPECT_EQ(r_sub_model_part.GetCommunicator().GhostMesh().NumberOfNodes(), 0);
KRATOS_EXPECT_EQ(r_sub_model_part.GetCommunicator().InterfaceMesh().NumberOfNodes(), 0);
}
}
}

} // namespace Kratos::Testing
111 changes: 102 additions & 9 deletions kratos/mpi/tests/test_utilities/mpi_cpp_test_utilities.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -211,13 +211,13 @@ void MPICppTestUtilities::GenerateDistributedTriangleMesh(
}

auto pgeom1 = Kratos::make_shared<Triangle2D3<Node>>(PointerVector<Node>{std::vector<Node::Pointer>({pnode1, pnode2, pnode5})});
rModelPart.AddElement(Kratos::make_intrusive<Testing::TestBarElement>( 1, pgeom1, p_prop));
rModelPart.AddElement(Kratos::make_intrusive<Element>( 1, pgeom1, p_prop));
auto pgeom2 = Kratos::make_shared<Triangle2D3<Node>>(PointerVector<Node>{std::vector<Node::Pointer>({pnode2, pnode3, pnode5})});
rModelPart.AddElement(Kratos::make_intrusive<Testing::TestBarElement>( 2, pgeom2, p_prop));
rModelPart.AddElement(Kratos::make_intrusive<Element>( 2, pgeom2, p_prop));
auto pgeom3 = Kratos::make_shared<Triangle2D3<Node>>(PointerVector<Node>{std::vector<Node::Pointer>({pnode3, pnode4, pnode5})});
rModelPart.AddElement(Kratos::make_intrusive<Testing::TestBarElement>( 3, pgeom3, p_prop));
rModelPart.AddElement(Kratos::make_intrusive<Element>( 3, pgeom3, p_prop));
auto pgeom4 = Kratos::make_shared<Triangle2D3<Node>>(PointerVector<Node>{std::vector<Node::Pointer>({pnode4, pnode1, pnode5})});
rModelPart.AddElement(Kratos::make_intrusive<Testing::TestBarElement>( 4, pgeom4, p_prop));
rModelPart.AddElement(Kratos::make_intrusive<Element>( 4, pgeom4, p_prop));
} else { // if (world_size == 1) { // TODO: Do more than one partition
if (rank == 0) {
auto pnode1 = rModelPart.CreateNewNode(1, 0.0, 0.0, 0.0);
Expand All @@ -233,11 +233,11 @@ void MPICppTestUtilities::GenerateDistributedTriangleMesh(
pnode5->FastGetSolutionStepValue(PARTITION_INDEX) = 1;

auto pgeom1 = Kratos::make_shared<Triangle2D3<Node>>(PointerVector<Node>{std::vector<Node::Pointer>({pnode1, pnode2, pnode5})});
rModelPart.AddElement(Kratos::make_intrusive<Testing::TestBarElement>( 1, pgeom1, p_prop));
rModelPart.AddElement(Kratos::make_intrusive<Element>( 1, pgeom1, p_prop));
auto pgeom2 = Kratos::make_shared<Triangle2D3<Node>>(PointerVector<Node>{std::vector<Node::Pointer>({pnode2, pnode3, pnode5})});
rModelPart.AddElement(Kratos::make_intrusive<Testing::TestBarElement>( 2, pgeom2, p_prop));
auto pgeom4 = Kratos::make_shared<Triangle2D3<Node>>(PointerVector<Node>{std::vector<Node::Pointer>({pnode4, pnode1, pnode5})});
rModelPart.AddElement(Kratos::make_intrusive<Testing::TestBarElement>( 4, pgeom4, p_prop));
rModelPart.AddElement(Kratos::make_intrusive<Element>( 2, pgeom2, p_prop));
auto pgeom4 = Kratos::make_shared<Triangle2D3<Node>>(PointerVector<Node>{std::vector<Node::Pointer>({pnode4, pnode1, pnode5})});
rModelPart.AddElement(Kratos::make_intrusive<Element>( 4, pgeom4, p_prop));
} else if (rank == 1) {
auto pnode3 = rModelPart.CreateNewNode(3, 1.0, 1.0, 0.0);
auto pnode4 = rModelPart.CreateNewNode(4, 0.0, 1.0, 0.0);
Expand All @@ -250,7 +250,100 @@ void MPICppTestUtilities::GenerateDistributedTriangleMesh(
pnode5->FastGetSolutionStepValue(PARTITION_INDEX) = 1;

auto pgeom3 = Kratos::make_shared<Triangle2D3<Node>>(PointerVector<Node>{std::vector<Node::Pointer>({pnode3, pnode4, pnode5})});
rModelPart.AddElement(Kratos::make_intrusive<Testing::TestBarElement>( 3, pgeom3, p_prop));
rModelPart.AddElement(Kratos::make_intrusive<Element>( 3, pgeom3, p_prop));
}
}

// Detect skin
Parameters skin_process_parameters = Parameters(R"(
{
"name_auxiliar_model_part" : "SkinModelPart",
"name_auxiliar_condition" : "Condition",
"list_model_parts_to_assign_conditions" : [],
"echo_level" : 0
})");
auto skin_process = SkinDetectionProcess<2>(rModelPart, skin_process_parameters);
skin_process.Execute();

// Compute communication plan and fill communicator meshes correctly
auto filler = ParallelFillCommunicator(rModelPart, rDataCommunicator);
filler.Execute();
}

/***********************************************************************************/
/***********************************************************************************/

void MPICppTestUtilities::GenerateDistributedTriforceMesh(
ModelPart& rModelPart,
const DataCommunicator& rDataCommunicator
)
{
// Add variables
rModelPart.AddNodalSolutionStepVariable(PARTITION_INDEX);

// Create properties
auto p_prop = rModelPart.CreateNewProperties(1, 0);

// MPI data
const int rank = rDataCommunicator.Rank();
const int world_size = rDataCommunicator.Size();

// Initially everything in one partition
if (world_size == 1) {
auto pnode1 = rModelPart.CreateNewNode(1, 0.0, 0.0, 0.0);
auto pnode2 = rModelPart.CreateNewNode(2, 0.5, 0.0, 0.0);
auto pnode3 = rModelPart.CreateNewNode(3, 1.0, 0.0, 0.0);
auto pnode4 = rModelPart.CreateNewNode(4, 0.25, 0.43301270189221932338, 0.0);
auto pnode5 = rModelPart.CreateNewNode(5, 0.75, 0.43301270189221932338, 0.0);
auto pnode6 = rModelPart.CreateNewNode(6, 0.50, 0.86602540378443864676, 0.0);

/// Add PARTITION_INDEX
for (auto& r_node : rModelPart.Nodes()) {
r_node.FastGetSolutionStepValue(PARTITION_INDEX) = rank;
}

auto pgeom1 = Kratos::make_shared<Triangle2D3<Node>>(PointerVector<Node>{std::vector<Node::Pointer>({pnode1, pnode2, pnode4})});
rModelPart.AddElement(Kratos::make_intrusive<Element>( 1, pgeom1, p_prop));
auto pgeom2 = Kratos::make_shared<Triangle2D3<Node>>(PointerVector<Node>{std::vector<Node::Pointer>({pnode2, pnode3, pnode5})});
rModelPart.AddElement(Kratos::make_intrusive<Element>( 2, pgeom2, p_prop));
auto pgeom3 = Kratos::make_shared<Triangle2D3<Node>>(PointerVector<Node>{std::vector<Node::Pointer>({pnode2, pnode5, pnode4})});
rModelPart.AddElement(Kratos::make_intrusive<Element>( 3, pgeom3, p_prop));
auto pgeom4 = Kratos::make_shared<Triangle2D3<Node>>(PointerVector<Node>{std::vector<Node::Pointer>({pnode4, pnode5, pnode6})});
rModelPart.AddElement(Kratos::make_intrusive<Element>( 4, pgeom4, p_prop));
} else { // if (world_size == 1) { // TODO: Do more than one partition
if (rank == 0) {
auto pnode1 = rModelPart.CreateNewNode(1, 0.0, 0.0, 0.0);
auto pnode2 = rModelPart.CreateNewNode(2, 0.5, 0.0, 0.0);
auto pnode3 = rModelPart.CreateNewNode(3, 1.0, 0.0, 0.0);
auto pnode4 = rModelPart.CreateNewNode(4, 0.25, 0.43301270189221932338, 0.0);
auto pnode5 = rModelPart.CreateNewNode(5, 0.75, 0.43301270189221932338, 0.0);
auto pnode6 = rModelPart.CreateNewNode(6, 0.50, 0.86602540378443864676, 0.0);

/// Add PARTITION_INDEX
for (auto& r_node : rModelPart.Nodes()) {
r_node.FastGetSolutionStepValue(PARTITION_INDEX) = 0;
}
pnode2->FastGetSolutionStepValue(PARTITION_INDEX) = 1;

auto pgeom1 = Kratos::make_shared<Triangle2D3<Node>>(PointerVector<Node>{std::vector<Node::Pointer>({pnode1, pnode2, pnode4})});
rModelPart.AddElement(Kratos::make_intrusive<Element>( 1, pgeom1, p_prop));
auto pgeom2 = Kratos::make_shared<Triangle2D3<Node>>(PointerVector<Node>{std::vector<Node::Pointer>({pnode2, pnode3, pnode5})});
rModelPart.AddElement(Kratos::make_intrusive<Element>( 2, pgeom2, p_prop));
auto pgeom4 = Kratos::make_shared<Triangle2D3<Node>>(PointerVector<Node>{std::vector<Node::Pointer>({pnode4, pnode5, pnode6})});
rModelPart.AddElement(Kratos::make_intrusive<Element>( 4, pgeom4, p_prop));
} else if (rank == 1) {
auto pnode2 = rModelPart.CreateNewNode(2, 0.5, 0.0, 0.0);
auto pnode4 = rModelPart.CreateNewNode(4, 0.25, 0.43301270189221932338, 0.0);
auto pnode5 = rModelPart.CreateNewNode(5, 0.75, 0.43301270189221932338, 0.0);

/// Add PARTITION_INDEX
for (auto& r_node : rModelPart.Nodes()) {
r_node.FastGetSolutionStepValue(PARTITION_INDEX) = 0;
}
pnode2->FastGetSolutionStepValue(PARTITION_INDEX) = 1;

auto pgeom3 = Kratos::make_shared<Triangle2D3<Node>>(PointerVector<Node>{std::vector<Node::Pointer>({pnode2, pnode5, pnode4})});
rModelPart.AddElement(Kratos::make_intrusive<Element>( 3, pgeom3, p_prop));
}
}

Expand Down
12 changes: 12 additions & 0 deletions kratos/mpi/tests/test_utilities/mpi_cpp_test_utilities.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,18 @@ static void GenerateDistributedTriangleMesh(
const DataCommunicator& rDataCommunicator
);

/**
* @brief It generates a Triforce mesh
* @details ▲
* ▲ ▲
* @param rModelPart The model part to be filled
* @param rDataCommunicator The data communicator
*/
static void GenerateDistributedTriforceMesh(
ModelPart& rModelPart,
const DataCommunicator& rDataCommunicator
);

/**
* @brief Synchronizes local pointers to global pointers of the given ModelPart using the provided
* @details DataCommunicator and returns a shared pointer to a GlobalPointerCommunicator<Node>.
Expand Down

0 comments on commit 23c3728

Please sign in to comment.