Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Core] Identical geometries in model part and geometry container #12703

Merged
merged 4 commits into from
Oct 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
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
Loading