-
Notifications
You must be signed in to change notification settings - Fork 249
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
[GeoMechanicsApplication] Add a minimal 3+3 line interface element #12674
[GeoMechanicsApplication] Add a minimal 3+3 line interface element #12674
Conversation
…ero matrix with the correct size
…geometry is the same as the underlying mid geometry and changed the tests accordingly
… for a line interface element
…x for a line interface element
Moved the application-wide tolerance values for testing to a dedicated namespace.
Don't increment a local variable at function call time. Increment first, then pass the updated value to the function.
To better reflect what the test case actually covers.
…or a line interface element
So far we expect a zero vector (this will soon change). Also renamed a local variable.
…imal-3_3-line-interface-element
So far, the function under test doesn't calculate anything. It simply returns a default-constructed vector.
The calculation follows the formulation found in any textbook about the finite element method
…es counterclockwise
…AIN` and `CAUCHY_STRESS_VECTOR` might be overwritten by the base class
…-interface-element' into geo/12649-add-a-minimal-3_3-line-interface-element
…-interface-element' into geo/12649-add-a-minimal-3_3-line-interface-element
applications/GeoMechanicsApplication/custom_elements/line_interface_element.cpp
Outdated
Show resolved
Hide resolved
applications/GeoMechanicsApplication/custom_elements/line_interface_element.cpp
Outdated
Show resolved
Hide resolved
applications/GeoMechanicsApplication/custom_elements/line_interface_element.cpp
Outdated
Show resolved
Hide resolved
applications/GeoMechanicsApplication/custom_elements/line_interface_element.cpp
Show resolved
Hide resolved
applications/GeoMechanicsApplication/custom_elements/line_interface_element.cpp
Show resolved
Hide resolved
KRATOS_EXPECT_EQ(degrees_of_freedom.size(), 8); | ||
const std::vector<double> expected_dof_values = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0}; | ||
for (std::size_t i = 0; i < degrees_of_freedom.size(); i++) { | ||
KRATOS_EXPECT_DOUBLE_EQ(degrees_of_freedom[i]->GetSolutionStepValue(), expected_dof_values[i]); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As discussed before, perhaps we'd better check the degrees of freedom themselves, rather than their associated values (since that should be covered by the unit tests for the degrees of freedom class itself).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
...ions/GeoMechanicsApplication/tests/cpp_tests/custom_elements/test_line_interface_element.cpp
Outdated
Show resolved
Hide resolved
...ions/GeoMechanicsApplication/tests/cpp_tests/custom_elements/test_line_interface_element.cpp
Outdated
Show resolved
Hide resolved
|
||
// Assert | ||
Vector expected_cauchy_stress{2}; | ||
expected_cauchy_stress <<= 10.0, 2.0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the traction vector using the local axis system. Is that we intend?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is intended, but let's discuss with @WPK4FEM before merging
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For me the tractions ( I also think its clearer to call the thing traction in the test, even if we are forced to use functions for strain and Cauchy stress ) are clearer in the local axes than in a global system.
For our continuum elements the local and the global axes system coincide, for interface elements that would be very uncomfortable. Please keep the interface element integration point results local.
...ions/GeoMechanicsApplication/tests/cpp_tests/custom_elements/test_line_interface_element.cpp
Outdated
Show resolved
Hide resolved
…ts instead of pointers
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
|
||
using Element::GeometryType; | ||
using Element::PropertiesType; | ||
using BaseType = Element; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why to not remove "using BaseType = Element" and use "Element" everywhere in the function, to be more clear.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Initially we did it to be able to insert a class into the hierarchy more easily. In that case some of these Element:: should remain as they are, and some should be changed to a new base class. However, we had some discussion about it before already if we really need it and after your comment decided to indeed remove BaseType, good suggestion!
applications/GeoMechanicsApplication/custom_elements/line_interface_element.cpp
Show resolved
Hide resolved
using Element::PropertiesType; | ||
using BaseType = Element; | ||
|
||
LineInterfaceElement() = default; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As this is a peurly header file, preferly "default" to be in the cpp, to be consistent with the other constructors. Also to be more clear in reading the code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The argument here is that (since it's default only, this doesn't hold when there is a real implementation), in this way we don't have to go to the source file just to see it's a default constructor, but I think it's a matter of preference.
applications/GeoMechanicsApplication/custom_elements/line_interface_element.h
Show resolved
Hide resolved
applications/GeoMechanicsApplication/custom_elements/line_interface_element.h
Show resolved
Hide resolved
const Geometry<GeometricalObject::NodeType>::Pointer& rGeometry, | ||
const Properties::Pointer& rProperties) | ||
: Element(NewId, rGeometry, rProperties), | ||
mIntegrationScheme(std::make_unique<LobattoIntegrationScheme>(GetGeometry().PointsNumber() / 2)), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here, the integration scheme is defined based on the number of the points. For now, it is enough, but for further development, it is not flexible. In other elements, we define "GetIntegrationMethod" to be able define the scheme based on the desired order. For example, consider different order element. However, this further investigation/definition can be in a different PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem with GetIntegrationMethod is that the enum it returns doesn't have entries for Lobatto integration, which is why we cannot directly use it.
void LineInterfaceElement::CalculateLeftHandSide(MatrixType& rLeftHandSideMatrix, const ProcessInfo&) | ||
{ | ||
// Currently, the left-hand side matrix only includes the stiffness matrix. In the future, it | ||
// will also include water pressure contributions and coupling terms. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is for my curiousity. Do you then set the pressure as zero? As far as I know, there is no solver for U available in Geo, and our solvers are Pw and U-Pw (and T)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We'll have to double check if this method works when looking at integration tests (first indication is it does, but we'll have to see if that holds), but we're just not giving Pw as degrees of freedom in these interfaces, meaning the interfaces shouldn't change water pressure at all. It basically works as a 'diff order' element, but the pressure geometry is set to empty.
{ | ||
// Currently, the right-hand side only includes the internal force vector. In the future, it | ||
// will also include water pressure contributions and coupling terms. | ||
const auto local_b_matrices = CalculateLocalBMatricesAtIntegrationPoints(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Calculation of B-Matrix is done twice, once for left hand, then for right hand, by means of "CalculateLocalBMatricesAtIntegrationPoints()". It is more efficient to calculate it once for the left hand side, then use it for the right hand side.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we're using the CalculateRightHandSide function from the Element interface, we cannot change the signature of the function. I agree we do double work now, so we could look into caching certain lists if we see it's a performance bottleneck. For now, I think it would add complexity to the element that might have limited value until we solve more prominent performance problems.
const auto local_b_matrices = CalculateLocalBMatricesAtIntegrationPoints(); | ||
const auto relative_displacements = CalculateRelativeDisplacementsAtIntegrationPoints(local_b_matrices); | ||
const auto tractions = CalculateTractionsAtIntegrationPoints(relative_displacements); | ||
const auto integration_coefficients = CalculateIntegrationCoefficients(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"CalculateIntegrationCoefficients();" is done for left as well as, right hand side. Keep the values in an array reuse them
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Valid point, but as per my previous comment, I'd rather choose readability for now and optimize performance later.
Element::Pointer LineInterfaceElement::Create(IndexType NewId, | ||
const NodesArrayType& rNodes, | ||
PropertiesType::Pointer pProperties) const | ||
{ | ||
return Create(NewId, this->GetGeometry().Create(rNodes), pProperties); | ||
} | ||
|
||
Element::Pointer LineInterfaceElement::Create(IndexType NewId, | ||
GeometryType::Pointer pGeometry, | ||
PropertiesType::Pointer pProperties) const | ||
{ | ||
return make_intrusive<LineInterfaceElement>(NewId, pGeometry, pProperties); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Preferly Creat to be after the constructors to be consistent with the other element classes design
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, moved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dear Anne and Richard,
Thank you for the element setup. Not much to complain about from my side.
Wijtze Pieter
applications/GeoMechanicsApplication/custom_elements/line_interface_element.cpp
Show resolved
Hide resolved
applications/GeoMechanicsApplication/custom_elements/line_interface_element.cpp
Show resolved
Hide resolved
// For interface elements, the shape function gradients are not defined, since these are | ||
// non-continuum elements. Therefore, we pass an empty matrix. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shape function gradients are always defined, they are not used for interface elements.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adjusted the comment, thanks for the clarification!
applications/GeoMechanicsApplication/custom_elements/line_interface_element.cpp
Show resolved
Hide resolved
...ions/GeoMechanicsApplication/tests/cpp_tests/custom_elements/test_line_interface_element.cpp
Show resolved
Hide resolved
...ions/GeoMechanicsApplication/tests/cpp_tests/custom_elements/test_line_interface_element.cpp
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the thorough reviews! I think I processed/answered to all of them, please let me know if you think any other changes are necessary
applications/GeoMechanicsApplication/custom_elements/line_interface_element.h
Show resolved
Hide resolved
...ions/GeoMechanicsApplication/tests/cpp_tests/custom_elements/test_line_interface_element.cpp
Show resolved
Hide resolved
const Geometry<GeometricalObject::NodeType>::Pointer& rGeometry, | ||
const Properties::Pointer& rProperties) | ||
: Element(NewId, rGeometry, rProperties), | ||
mIntegrationScheme(std::make_unique<LobattoIntegrationScheme>(GetGeometry().PointsNumber() / 2)), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem with GetIntegrationMethod is that the enum it returns doesn't have entries for Lobatto integration, which is why we cannot directly use it.
void LineInterfaceElement::CalculateLeftHandSide(MatrixType& rLeftHandSideMatrix, const ProcessInfo&) | ||
{ | ||
// Currently, the left-hand side matrix only includes the stiffness matrix. In the future, it | ||
// will also include water pressure contributions and coupling terms. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We'll have to double check if this method works when looking at integration tests (first indication is it does, but we'll have to see if that holds), but we're just not giving Pw as degrees of freedom in these interfaces, meaning the interfaces shouldn't change water pressure at all. It basically works as a 'diff order' element, but the pressure geometry is set to empty.
{ | ||
// Currently, the right-hand side only includes the internal force vector. In the future, it | ||
// will also include water pressure contributions and coupling terms. | ||
const auto local_b_matrices = CalculateLocalBMatricesAtIntegrationPoints(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we're using the CalculateRightHandSide function from the Element interface, we cannot change the signature of the function. I agree we do double work now, so we could look into caching certain lists if we see it's a performance bottleneck. For now, I think it would add complexity to the element that might have limited value until we solve more prominent performance problems.
|
||
using Element::GeometryType; | ||
using Element::PropertiesType; | ||
using BaseType = Element; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Initially we did it to be able to insert a class into the hierarchy more easily. In that case some of these Element:: should remain as they are, and some should be changed to a new base class. However, we had some discussion about it before already if we really need it and after your comment decided to indeed remove BaseType, good suggestion!
using Element::PropertiesType; | ||
using BaseType = Element; | ||
|
||
LineInterfaceElement() = default; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The argument here is that (since it's default only, this doesn't hold when there is a real implementation), in this way we don't have to go to the source file just to see it's a default constructor, but I think it's a matter of preference.
applications/GeoMechanicsApplication/custom_elements/line_interface_element.h
Show resolved
Hide resolved
void Initialize(const ProcessInfo& rCurrentProcessInfo) override; | ||
|
||
Element::Pointer Create(IndexType NewId, const NodesArrayType& rNodes, PropertiesType::Pointer pProperties) const override; | ||
Element::Pointer Create(IndexType NewId, GeometryType::Pointer pGeom, PropertiesType::Pointer pProperties) const override; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch! Added a check that calls the base class check, verifies that the constitutive laws are there and calls check on them.
...ions/GeoMechanicsApplication/tests/cpp_tests/custom_elements/test_line_interface_element.cpp
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dear Anne and Richard,
To me this looks quite good to go, I don't find things that are really worth putting substantial effort in first anymore.
Thank you, Wijtze Pieter
expected_right_hand_side <<= 0.33333333, 1.66666667, 0.33333333, 1.66666667, 1.33333333, | ||
6.66666667, -0.33333333, -1.66666667, -0.33333333, -1.66666667, -1.33333333, -6.66666667; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we use this or write 1/3, 5/3, 1/3, 5/3, 4/3, 19/3, -1/3 et.c
Similarly maybe at line 429, 463 and the similar things where square roots of 3 are involved
Guess this is a matter of preference.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For this set of 'n/3' I completely agree, if I remember correctly the 429 and 463 examples, the analytical solution was not a lot more clear than just the numbers generated by Annes python 'check' script.
I'll wait for the sonarcloud results here: if I need to make changes because of that, I'll change this line, otherwise I'd propose to merge this and avoid another pipeline wait.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks OK to me.
📝 Description
This PR adds a minimal implementation for a line interface element (which could be 2+2 or 3+3 depending on the geometry passed on during construction). The functionality (e.g. for the LHS/RHS calculations and the other functions) is unit tested.