Skip to content

Commit

Permalink
Merge pull request #12703 from KratosMultiphysics/core/identical-geom…
Browse files Browse the repository at this point in the history
…etries-in-model-part

[Core] Identical geometries in model part and geometry container
  • Loading branch information
rubenzorrilla authored Oct 1, 2024
2 parents 9e60964 + 37e75f1 commit e5465ba
Show file tree
Hide file tree
Showing 5 changed files with 362 additions and 39 deletions.
13 changes: 11 additions & 2 deletions kratos/containers/geometry_container.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,17 @@ class GeometryContainer
return mGeometries.insert(pNewGeometry);
} else if (&(*i) == pNewGeometry.get()) { // check if the pointee coincides
return i;
} else {
KRATOS_ERROR << "Attempting to add Geometry with Id: " << pNewGeometry->Id() << ", unfortunately a (different) geometry with the same Id already exists!" << std::endl;
} else { // Check if the connectivities coincide
// First check for the geometry type
KRATOS_ERROR_IF_NOT(TGeometryType::HasSameGeometryType(*i, *pNewGeometry)) << "Attempting to add geometry with Id: " << pNewGeometry->Id() << ". A different geometry with the same Id already exists." << std::endl;
// Check that the connectivities are the same
// note that we deliberately check the node ids and not the pointer adresses as there might be very rare situations

// (e.g., creating nodes bypassing the model part interface) with same connectivities but different pointer addresses
for (IndexType i_node = 0; i_node < i->PointsNumber(); ++i_node) {
KRATOS_ERROR_IF((*i)[i_node].Id() != (*pNewGeometry)[i_node].Id()) << "Attempting to add a new geometry with Id: " << pNewGeometry->Id() << ". A same type geometry with same Id but different connectivities already exists." << std::endl;
}
return i;
}
}

Expand Down
9 changes: 7 additions & 2 deletions kratos/includes/model_part.h
Original file line number Diff line number Diff line change
Expand Up @@ -1534,8 +1534,13 @@ class KRATOS_API(KRATOS_CORE) ModelPart final
aux_root.push_back( it.operator->() );
aux.push_back( it.operator->() );
} else { // If it does exist verify it is the same geometry
if(&(*it_found) != &(*it)) { // Check if the pointee coincides
KRATOS_ERROR << "Attempting to add a new geometry with Id :" << it_found->Id() << ", unfortunately a (different) element with the same Id already exists" << std::endl;
if (GeometryType::HasSameGeometryType(*it, *it_found)) { // Check the geometry type and connectivities
for (IndexType i_pt = 0; i_pt < it->PointsNumber(); ++i_pt) {
KRATOS_ERROR_IF((*it)[i_pt].Id() != (*it_found)[i_pt].Id()) << "Attempting to add a new geometry with Id: " << it->Id() << ". A same type geometry with same Id but different connectivities already exists." << std::endl;
}
aux.push_back( it_found.operator->() ); // If the Id, type and connectivities are the same add the existing geometry
} else if(&(*it_found) != &(*it)) { // Check if the pointee coincides
KRATOS_ERROR << "Attempting to add a new geometry with Id: " << it_found->Id() << ". A different geometry with the same Id already exists." << std::endl;
} else {
aux.push_back( it.operator->() );
}
Expand Down
100 changes: 85 additions & 15 deletions kratos/sources/model_part.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1514,7 +1514,7 @@ ModelPart::ConditionType::Pointer ModelPart::CreateNewCondition(std::string Cond
ModelPart::PropertiesType::Pointer pProperties, ModelPart::IndexType ThisIndex)
{
KRATOS_TRY

if (IsSubModelPart()) {
ConditionType::Pointer p_new_condition = mpParentModelPart->CreateNewCondition(ConditionName, Id, ConditionNodeIds, pProperties, ThisIndex);
GetMesh(ThisIndex).AddCondition(p_new_condition);
Expand Down Expand Up @@ -1808,15 +1808,33 @@ ModelPart::GeometryType::Pointer ModelPart::CreateNewGeometry(
return p_new_geometry;
}

KRATOS_ERROR_IF(this->HasGeometry(GeometryId)) << "Trying to construct an geometry with ID: " << GeometryId << ". A geometry with the same Id exists already." << std::endl;
// Check if the geometry already exists
if (this->HasGeometry(GeometryId)) {
// Get the existing geometry with the same Id
const auto p_existing_geom = this->pGetGeometry(GeometryId);

// Check if the existing geometry has the same type
KRATOS_ERROR_IF_NOT(GeometryType::HasSameGeometryType(*p_existing_geom, KratosComponents<GeometryType>::Get(rGeometryTypeName)))
<< "Attempting to add geometry with Id: " << GeometryId << ". A different geometry with the same Id already exists." << std::endl;

// Check if the connectivities (nodes) of the existing geometry match that of the new
for (IndexType i = 0; i < p_existing_geom->PointsNumber(); ++i) {
KRATOS_ERROR_IF_NOT((p_existing_geom->operator()(i)).get() == &(pGeometryNodes[i]))
<< "Attempting to add a new geometry with Id: " << GeometryId << ". A same type geometry with same Id but different connectivities already exists." << std::endl;
}

// Return the existing geometry
return p_existing_geom;
}

// Create the new geometry
GeometryType const& r_clone_geometry = KratosComponents<GeometryType>::Get(rGeometryTypeName);
GeometryType::Pointer p_geometry = r_clone_geometry.Create(GeometryId, pGeometryNodes);

//add the new geometry
// Add the new geometry
this->AddGeometry(p_geometry);

// Return the new geometry
return p_geometry;

KRATOS_CATCH("")
Expand All @@ -1836,15 +1854,33 @@ ModelPart::GeometryType::Pointer ModelPart::CreateNewGeometry(
return p_new_geometry;
}

KRATOS_ERROR_IF(this->HasGeometry(GeometryId)) << "Trying to construct an geometry with ID: " << GeometryId << ". A geometry with the same Id exists already." << std::endl;
// Check if the geometry already exists
if (this->HasGeometry(GeometryId)) {
// Get the existing geometry with the same Id
const auto p_existing_geom = this->pGetGeometry(GeometryId);

// Check if the existing geometry has the same type
KRATOS_ERROR_IF_NOT(GeometryType::HasSameGeometryType(*p_existing_geom, KratosComponents<GeometryType>::Get(rGeometryTypeName)))
<< "Attempting to add geometry with Id: " << GeometryId << ". A different geometry with the same Id already exists." << std::endl;

// Check if the connectivities (nodes) of the existing geometry match that of the new
for (IndexType i = 0; i < p_existing_geom->PointsNumber(); ++i) {
KRATOS_ERROR_IF_NOT((p_existing_geom->operator()(i)).get() == ((*pGeometry)(i)).get())
<< "Attempting to add a new geometry with Id: " << GeometryId << ". A same type geometry with same Id but different connectivities already exists." << std::endl;
}

// Return the existing geometry
return p_existing_geom;
}

// Create the new geometry
GeometryType const& r_clone_geometry = KratosComponents<GeometryType>::Get(rGeometryTypeName);
GeometryType::Pointer p_geometry = r_clone_geometry.Create(GeometryId, *pGeometry);

//add the new geometry
// Add the new geometry
this->AddGeometry(p_geometry);

// Return the new geometry
return p_geometry;

KRATOS_CATCH("")
Expand Down Expand Up @@ -1878,13 +1914,30 @@ ModelPart::GeometryType::Pointer ModelPart::CreateNewGeometry(
{
KRATOS_TRY

if (IsSubModelPart()) {
GeometryType::Pointer p_new_geometry = mpParentModelPart->CreateNewGeometry(rGeometryTypeName, rGeometryIdentifierName, pGeometryNodes);
this->AddGeometry(p_new_geometry);
return p_new_geometry;
if (IsSubModelPart()) {
GeometryType::Pointer p_new_geometry = mpParentModelPart->CreateNewGeometry(rGeometryTypeName, rGeometryIdentifierName, pGeometryNodes);
this->AddGeometry(p_new_geometry);
return p_new_geometry;
}

// Check if the geometry already exists
if (this->HasGeometry(rGeometryIdentifierName)) {
// Get the existing geometry with the same Id
const auto p_existing_geom = this->pGetGeometry(rGeometryIdentifierName);

// Check if the existing geometry has the same type
KRATOS_ERROR_IF_NOT(GeometryType::HasSameGeometryType(*p_existing_geom, KratosComponents<GeometryType>::Get(rGeometryTypeName)))
<< "Attempting to add geometry with Id: " << rGeometryIdentifierName << ". A different geometry with the same Id already exists." << std::endl;

// Check if the connectivities (nodes) of the existing geometry match that of the new
for (IndexType i = 0; i < p_existing_geom->PointsNumber(); ++i) {
KRATOS_ERROR_IF_NOT((p_existing_geom->operator()(i)).get() == &(pGeometryNodes[i]))
<< "Attempting to add a new geometry with Id: " << rGeometryIdentifierName << ". A same type geometry with same Id but different connectivities already exists." << std::endl;
}

KRATOS_ERROR_IF(this->HasGeometry(rGeometryIdentifierName)) << "Trying to construct an geometry with name: " << rGeometryIdentifierName << ". A geometry with the same name exists already." << std::endl;
// Return the existing geometry
return p_existing_geom;
}

// Create the new geometry
GeometryType const& r_clone_geometry = KratosComponents<GeometryType>::Get(rGeometryTypeName);
Expand All @@ -1906,13 +1959,30 @@ ModelPart::GeometryType::Pointer ModelPart::CreateNewGeometry(
{
KRATOS_TRY

if (IsSubModelPart()) {
GeometryType::Pointer p_new_geometry = mpParentModelPart->CreateNewGeometry(rGeometryTypeName, rGeometryIdentifierName, pGeometry);
this->AddGeometry(p_new_geometry);
return p_new_geometry;
if (IsSubModelPart()) {
GeometryType::Pointer p_new_geometry = mpParentModelPart->CreateNewGeometry(rGeometryTypeName, rGeometryIdentifierName, pGeometry);
this->AddGeometry(p_new_geometry);
return p_new_geometry;
}

// Check if the geometry already exists
if (this->HasGeometry(rGeometryIdentifierName)) {
// Get the existing geometry with the same Id
const auto p_existing_geom = this->pGetGeometry(rGeometryIdentifierName);

// Check if the existing geometry has the same type
KRATOS_ERROR_IF_NOT(GeometryType::HasSameGeometryType(*p_existing_geom, KratosComponents<GeometryType>::Get(rGeometryTypeName)))
<< "Attempting to add geometry with Id: " << rGeometryIdentifierName << ". A different geometry with the same Id already exists." << std::endl;

// Check if the connectivities (nodes) of the existing geometry match that of the new
for (IndexType i = 0; i < p_existing_geom->PointsNumber(); ++i) {
KRATOS_ERROR_IF_NOT((p_existing_geom->operator()(i)).get() == ((*pGeometry)(i)).get())
<< "Attempting to add a new geometry with Id: " << rGeometryIdentifierName << ". A same type geometry with same Id but different connectivities already exists." << std::endl;
}

KRATOS_ERROR_IF(this->HasGeometry(rGeometryIdentifierName)) << "Trying to construct an geometry with name: " << rGeometryIdentifierName << ". A geometry with the same name exists already." << std::endl;
// Return the existing geometry
return p_existing_geom;
}

// Create the new geometry
GeometryType const& r_clone_geometry = KratosComponents<GeometryType>::Get(rGeometryTypeName);
Expand Down
124 changes: 112 additions & 12 deletions kratos/tests/cpp_tests/containers/test_geometry_container.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,46 @@

namespace Kratos::Testing {

Line3D2<Point>::Pointer GenerateLineGeometry() {
return Kratos::make_shared<Line3D2<Point>>(
Kratos::make_shared<Point>(0.0, 0.0, 0.0),
Kratos::make_shared<Point>(1.0, 1.0, 1.0)
);
}
namespace
{

Line3D2<Node>::Pointer GenerateLineGeometry() {
Geometry<Node>::PointsArrayType nodes_vector;
nodes_vector.push_back(Kratos::make_intrusive<Node>(1, 0.0, 0.0, 0.0));
nodes_vector.push_back(Kratos::make_intrusive<Node>(2, 1.0, 1.0, 1.0));
return Kratos::make_shared<Line3D2<Node>>(nodes_vector);
}

void FillGeometryContainer(
Geometry<Node>::PointsArrayType& rAuxNodeList,
GeometryContainer<Geometry<Node>>& rGeometryContainer)
{
rAuxNodeList.push_back(Kratos::make_intrusive<Node>(1, 0.0, 0.0, 0.0));
rAuxNodeList.push_back(Kratos::make_intrusive<Node>(2, 1.0, 0.0, 0.0));
rAuxNodeList.push_back(Kratos::make_intrusive<Node>(3, 0.0, 1.0, 0.0));
rAuxNodeList.push_back(Kratos::make_intrusive<Node>(4, 1.0, 1.0, 0.0));

Geometry<Node>::PointsArrayType nodes_vector_1;
nodes_vector_1.push_back(rAuxNodeList(0));
nodes_vector_1.push_back(rAuxNodeList(1));
nodes_vector_1.push_back(rAuxNodeList(3));
auto p_geom_1 = Kratos::make_shared<Triangle2D3<Node>>(1, nodes_vector_1);

Geometry<Node>::PointsArrayType nodes_vector_2;
nodes_vector_2.push_back(rAuxNodeList(0));
nodes_vector_2.push_back(rAuxNodeList(3));
nodes_vector_2.push_back(rAuxNodeList(2));
auto p_geom_2 = Kratos::make_shared<Triangle2D3<Node>>(2, nodes_vector_2);

rGeometryContainer.AddGeometry(p_geom_1);
rGeometryContainer.AddGeometry(p_geom_2);
}

}

///// Test Geometry Container
KRATOS_TEST_CASE_IN_SUITE(TestgeometryContainer, KratosCoreGeometryContainerFastSuite) {
auto geometry_container = GeometryContainer<Geometry<Point>>();
KRATOS_TEST_CASE_IN_SUITE(TestGeometryContainer, KratosCoreGeometryContainerFastSuite) {
auto geometry_container = GeometryContainer<Geometry<Node>>();

auto p_line_1 = GenerateLineGeometry();
p_line_1->SetId(1);
Expand All @@ -46,10 +76,8 @@ namespace Kratos::Testing {
auto p_line_2 = GenerateLineGeometry();
p_line_2->SetId(1);

// check correct error if multiple geometries with sam id are added
KRATOS_EXPECT_EXCEPTION_IS_THROWN(
geometry_container.AddGeometry(p_line_2),
"Error: Attempting to add Geometry with Id: 1, unfortunately a (different) geometry with the same Id already exists!");
// check that we do nothing if the same geometry (same id and connectivities) is to be added multiple times
KRATOS_EXPECT_EQ(geometry_container.NumberOfGeometries(), 1);

p_line_2->SetId(2);
geometry_container.AddGeometry(p_line_2);
Expand All @@ -74,4 +102,76 @@ namespace Kratos::Testing {
KRATOS_EXPECT_EQ(geometry_container.NumberOfGeometries(), 1);
KRATOS_EXPECT_FALSE(geometry_container.HasGeometry("GeometryLine1"));
}

KRATOS_TEST_CASE_IN_SUITE(TestGeometryContainerWithRepeatedGeometries1, KratosCoreGeometryContainerFastSuite)
{
// Prepare geometry container
Geometry<Node>::PointsArrayType aux_node_pt_list;
GeometryContainer<Geometry<Node>> geometry_container;
FillGeometryContainer(aux_node_pt_list, geometry_container);

// Create and add a geometry with the same connectivities but different Id (valid)
Geometry<Node>::PointsArrayType nodes_vector_3;
nodes_vector_3.push_back(aux_node_pt_list(0));
nodes_vector_3.push_back(aux_node_pt_list(1));
nodes_vector_3.push_back(aux_node_pt_list(3));
auto p_geom_3 = Kratos::make_shared<Triangle2D3<Node>>(3, nodes_vector_3);
geometry_container.AddGeometry(p_geom_3);

// Check results
KRATOS_EXPECT_EQ(geometry_container.NumberOfGeometries(), 3);
}

KRATOS_TEST_CASE_IN_SUITE(TestGeometryContainerWithRepeatedGeometries2, KratosCoreGeometryContainerFastSuite)
{
// Prepare geometry container
Geometry<Node>::PointsArrayType aux_node_pt_list;
GeometryContainer<Geometry<Node>> geometry_container;
FillGeometryContainer(aux_node_pt_list, geometry_container);

// Keep the existing when trying to add an already existing geometry (same Id and same connectivities) (valid)
Geometry<Node>::PointsArrayType nodes_vector_2;
nodes_vector_2.push_back(aux_node_pt_list(0));
nodes_vector_2.push_back(aux_node_pt_list(3));
nodes_vector_2.push_back(aux_node_pt_list(2));
auto p_geom_2 = Kratos::make_shared<Triangle2D3<Node>>(2, nodes_vector_2);
geometry_container.AddGeometry(p_geom_2);

// Check results
KRATOS_EXPECT_EQ(geometry_container.NumberOfGeometries(), 2);
}

KRATOS_TEST_CASE_IN_SUITE(TestGeometryContainerWithRepeatedGeometries3, KratosCoreGeometryContainerFastSuite)
{
// Prepare geometry container
Geometry<Node>::PointsArrayType aux_node_pt_list;
GeometryContainer<Geometry<Node>> geometry_container;
FillGeometryContainer(aux_node_pt_list, geometry_container);

// Throw an error when trying to add a different geometry with an existing Id (not defined)
Geometry<Node>::PointsArrayType nodes_vector_2;
nodes_vector_2.push_back(aux_node_pt_list(0));
nodes_vector_2.push_back(aux_node_pt_list(1));
nodes_vector_2.push_back(aux_node_pt_list(3));
nodes_vector_2.push_back(aux_node_pt_list(2));
auto p_geom_2 = Kratos::make_shared<Quadrilateral2D4<Node>>(2, nodes_vector_2);
KRATOS_EXPECT_EXCEPTION_IS_THROWN(geometry_container.AddGeometry(p_geom_2), "Attempting to add geometry with Id: 2. A different geometry with the same Id already exists.")
}

KRATOS_TEST_CASE_IN_SUITE(TestGeometryContainerWithRepeatedGeometries4, KratosCoreGeometryContainerFastSuite)
{
// Prepare geometry container
Geometry<Node>::PointsArrayType aux_node_pt_list;
GeometryContainer<Geometry<Node>> geometry_container;
FillGeometryContainer(aux_node_pt_list, geometry_container);

// Throw an error when trying to add a same type geometry but with different connectivities and existing Id (not defined)
Geometry<Node>::PointsArrayType nodes_vector_2;
nodes_vector_2.push_back(aux_node_pt_list(2));
nodes_vector_2.push_back(aux_node_pt_list(3));
nodes_vector_2.push_back(aux_node_pt_list(0));
auto p_geom_2 = Kratos::make_shared<Triangle2D3<Node>>(2, nodes_vector_2);
KRATOS_EXPECT_EXCEPTION_IS_THROWN(geometry_container.AddGeometry(p_geom_2), "Attempting to add a new geometry with Id: 2. A same type geometry with same Id but different connectivities already exists.")
}

} // namespace Kratos::Testing.
Loading

0 comments on commit e5465ba

Please sign in to comment.