Skip to content

Commit ec79f44

Browse files
authored
[GeoMechanicsApplication] Extend class LineInterfaceElement such that it also includes planar interface elements (#13634)
* renamed LineInterfaceElement as InterfaceElement * added LocalSpaceDimension check and Calculate2DRotationMatrixForPlaneGeometry * updated element_hierarchy.svg * added unit tests and 8 still red * added LumpedIntegrationScheme * changed 2D triangle into 3D triangle * column based rotation matrix * added pStressStatePolicy in constructors * fixed unit tests * extracted MakeIntegrationSheme * removed code smells * joint CreateLinearElasticMaterialProperties and CreatePlanarElasticMaterialProperties * joint Create2DInterfaceElementWithUDofs and Create3DInterfaceElementWithUDofs * introduced serializer * extracted CreateAndInitializeElement * used emplace_back * added static_assert * added function pointer mfpCalculateRotationMatrix * response to the review 1 * response to review 2 * created CreateExpectedLeftHandSideForTriangleElement * a bit nicer * one more use of CreateExpectedLeftHandSideForTriangleElement * reverted expected_left_hand_side vlaues * renamed as ExpectedLeftHandSideForTriangleElement
1 parent dfc94a7 commit ec79f44

9 files changed

Lines changed: 1254 additions & 674 deletions

File tree

applications/GeoMechanicsApplication/custom_elements/element_hierarchy.puml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ TransientPwInterfaceElement <|-- SteadyStatePwInterfaceElement
4747
SteadyStatePwInterfaceElement <|-- SteadyStatePwPipingElement
4848
UPwSmallStrainInterfaceElement <|-- UPwSmallStrainLinkInterfaceElement
4949

50-
class LineInterfaceElement
51-
Element <|-- LineInterfaceElement
50+
class InterfaceElement
51+
Element <|-- InterfaceElement
5252

5353
'Pw Elements
5454
class TransientPwLineElement

applications/GeoMechanicsApplication/custom_elements/element_hierarchy.svg

Lines changed: 1 addition & 1 deletion
Loading

applications/GeoMechanicsApplication/custom_elements/line_interface_element.cpp renamed to applications/GeoMechanicsApplication/custom_elements/interface_element.cpp

Lines changed: 63 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,17 @@
88
// License: geo_mechanics_application/license.txt
99
//
1010
// Main authors: Richard Faasse
11+
// Gennady Markelov
1112
//
12-
#include "line_interface_element.h"
13+
#include "interface_element.h"
1314

1415
#include "custom_utilities/dof_utilities.h"
1516
#include "custom_utilities/element_utilities.hpp"
1617
#include "custom_utilities/equation_of_motion_utilities.h"
1718
#include "custom_utilities/geometry_utilities.h"
1819
#include "interface_stress_state.h"
1920
#include "lobatto_integration_scheme.h"
21+
#include "lumped_integration_scheme.h"
2022

2123
namespace
2224
{
@@ -60,42 +62,54 @@ std::vector<Matrix> CalculateConstitutiveMatricesAtIntegrationPoints(
6062
namespace Kratos
6163
{
6264

63-
LineInterfaceElement::LineInterfaceElement(IndexType NewId,
64-
const Geometry<GeometricalObject::NodeType>::Pointer& rGeometry,
65-
const Properties::Pointer& rProperties)
66-
: Element(NewId, rGeometry, rProperties),
67-
mIntegrationScheme(std::make_unique<LobattoIntegrationScheme>(GetGeometry().PointsNumber() / 2)),
68-
mStressStatePolicy(std::make_unique<Line2DInterfaceStressState>())
65+
InterfaceElement::InterfaceElement(IndexType NewId,
66+
const Geometry<GeometricalObject::NodeType>::Pointer& rGeometry,
67+
const Properties::Pointer& rProperties,
68+
std::unique_ptr<StressStatePolicy> pStressStatePolicy)
69+
: Element(NewId, rGeometry, rProperties), mpStressStatePolicy(std::move(pStressStatePolicy))
6970
{
71+
MakeIntegrationSchemeAndAssignFunction();
7072
}
7173

72-
LineInterfaceElement::LineInterfaceElement(IndexType NewId, const GeometryType::Pointer& rGeometry)
73-
: Element(NewId, rGeometry),
74-
mIntegrationScheme(std::make_unique<LobattoIntegrationScheme>(GetGeometry().PointsNumber() / 2)),
75-
mStressStatePolicy(std::make_unique<Line2DInterfaceStressState>())
74+
InterfaceElement::InterfaceElement(IndexType NewId,
75+
const GeometryType::Pointer& rGeometry,
76+
std::unique_ptr<StressStatePolicy> pStressStatePolicy)
77+
: Element(NewId, rGeometry), mpStressStatePolicy(std::move(pStressStatePolicy))
7678
{
79+
MakeIntegrationSchemeAndAssignFunction();
7780
}
7881

79-
Element::Pointer LineInterfaceElement::Create(IndexType NewId,
80-
const NodesArrayType& rNodes,
81-
PropertiesType::Pointer pProperties) const
82+
void InterfaceElement::MakeIntegrationSchemeAndAssignFunction()
83+
{
84+
if (GetGeometry().LocalSpaceDimension() == 1) {
85+
mIntegrationScheme = std::make_unique<LobattoIntegrationScheme>(GetGeometry().PointsNumber() / 2);
86+
mfpCalculateRotationMatrix = GeometryUtilities::Calculate2DRotationMatrixForLineGeometry;
87+
} else {
88+
mIntegrationScheme = std::make_unique<LumpedIntegrationScheme>(GetGeometry().PointsNumber() / 2);
89+
mfpCalculateRotationMatrix = GeometryUtilities::Calculate3DRotationMatrixForPlaneGeometry;
90+
}
91+
}
92+
93+
Element::Pointer InterfaceElement::Create(IndexType NewId,
94+
const NodesArrayType& rNodes,
95+
PropertiesType::Pointer pProperties) const
8296
{
8397
return Create(NewId, this->GetGeometry().Create(rNodes), pProperties);
8498
}
8599

86-
Element::Pointer LineInterfaceElement::Create(IndexType NewId,
87-
GeometryType::Pointer pGeometry,
88-
PropertiesType::Pointer pProperties) const
100+
Element::Pointer InterfaceElement::Create(IndexType NewId,
101+
GeometryType::Pointer pGeometry,
102+
PropertiesType::Pointer pProperties) const
89103
{
90-
return make_intrusive<LineInterfaceElement>(NewId, pGeometry, pProperties);
104+
return make_intrusive<InterfaceElement>(NewId, pGeometry, pProperties, mpStressStatePolicy->Clone());
91105
}
92106

93-
void LineInterfaceElement::EquationIdVector(EquationIdVectorType& rResult, const ProcessInfo&) const
107+
void InterfaceElement::EquationIdVector(EquationIdVectorType& rResult, const ProcessInfo&) const
94108
{
95109
rResult = Geo::DofUtilities::ExtractEquationIdsFrom(GetDofs());
96110
}
97111

98-
void LineInterfaceElement::CalculateLeftHandSide(MatrixType& rLeftHandSideMatrix, const ProcessInfo&)
112+
void InterfaceElement::CalculateLeftHandSide(MatrixType& rLeftHandSideMatrix, const ProcessInfo&)
99113
{
100114
// Currently, the left-hand side matrix only includes the stiffness matrix. In the future, it
101115
// will also include water pressure contributions and coupling terms.
@@ -104,7 +118,7 @@ void LineInterfaceElement::CalculateLeftHandSide(MatrixType& rLeftHandSideMatrix
104118
CalculateConstitutiveMatricesAtIntegrationPoints(), CalculateIntegrationCoefficients());
105119
}
106120

107-
void LineInterfaceElement::CalculateRightHandSide(Element::VectorType& rRightHandSideVector, const ProcessInfo&)
121+
void InterfaceElement::CalculateRightHandSide(Element::VectorType& rRightHandSideVector, const ProcessInfo&)
108122
{
109123
// Currently, the right-hand side only includes the internal force vector. In the future, it
110124
// will also include water pressure contributions and coupling terms.
@@ -116,17 +130,17 @@ void LineInterfaceElement::CalculateRightHandSide(Element::VectorType& rRightHan
116130
local_b_matrices, tractions, integration_coefficients);
117131
}
118132

119-
void LineInterfaceElement::CalculateLocalSystem(MatrixType& rLeftHandSideMatrix,
120-
VectorType& rRightHandSideVector,
121-
const ProcessInfo& rCurrentProcessInfo)
133+
void InterfaceElement::CalculateLocalSystem(MatrixType& rLeftHandSideMatrix,
134+
VectorType& rRightHandSideVector,
135+
const ProcessInfo& rCurrentProcessInfo)
122136
{
123137
CalculateLeftHandSide(rLeftHandSideMatrix, rCurrentProcessInfo);
124138
CalculateRightHandSide(rRightHandSideVector, rCurrentProcessInfo);
125139
}
126140

127-
void LineInterfaceElement::CalculateOnIntegrationPoints(const Variable<Vector>& rVariable,
128-
std::vector<Vector>& rOutput,
129-
const ProcessInfo& rCurrentProcessInfo)
141+
void InterfaceElement::CalculateOnIntegrationPoints(const Variable<Vector>& rVariable,
142+
std::vector<Vector>& rOutput,
143+
const ProcessInfo& rCurrentProcessInfo)
130144
{
131145
if (rVariable == STRAIN) {
132146
const auto local_b_matrices = CalculateLocalBMatricesAtIntegrationPoints();
@@ -140,22 +154,22 @@ void LineInterfaceElement::CalculateOnIntegrationPoints(const Variable<Vector>&
140154
}
141155
}
142156

143-
void LineInterfaceElement::CalculateOnIntegrationPoints(const Variable<ConstitutiveLaw::Pointer>& rVariable,
144-
std::vector<ConstitutiveLaw::Pointer>& rOutput,
145-
const ProcessInfo&)
157+
void InterfaceElement::CalculateOnIntegrationPoints(const Variable<ConstitutiveLaw::Pointer>& rVariable,
158+
std::vector<ConstitutiveLaw::Pointer>& rOutput,
159+
const ProcessInfo&)
146160
{
147161
KRATOS_ERROR_IF_NOT(rVariable == CONSTITUTIVE_LAW)
148162
<< "Cannot calculate on integration points: got unexpected variable " << rVariable.Name() << "\n";
149163

150164
rOutput = mConstitutiveLaws;
151165
}
152166

153-
void LineInterfaceElement::GetDofList(DofsVectorType& rElementalDofList, const ProcessInfo&) const
167+
void InterfaceElement::GetDofList(DofsVectorType& rElementalDofList, const ProcessInfo&) const
154168
{
155169
rElementalDofList = GetDofs();
156170
}
157171

158-
void LineInterfaceElement::Initialize(const ProcessInfo& rCurrentProcessInfo)
172+
void InterfaceElement::Initialize(const ProcessInfo& rCurrentProcessInfo)
159173
{
160174
Element::Initialize(rCurrentProcessInfo);
161175

@@ -170,7 +184,7 @@ void LineInterfaceElement::Initialize(const ProcessInfo& rCurrentProcessInfo)
170184
}
171185
}
172186

173-
int LineInterfaceElement::Check(const ProcessInfo& rCurrentProcessInfo) const
187+
int InterfaceElement::Check(const ProcessInfo& rCurrentProcessInfo) const
174188
{
175189
int error = Element::Check(rCurrentProcessInfo);
176190
if (error != 0) return error;
@@ -189,30 +203,29 @@ int LineInterfaceElement::Check(const ProcessInfo& rCurrentProcessInfo) const
189203
return 0;
190204
}
191205

192-
Element::DofsVectorType LineInterfaceElement::GetDofs() const
206+
Element::DofsVectorType InterfaceElement::GetDofs() const
193207
{
194208
const auto no_Pw_geometry_yet = Geometry<Node>{};
195209
return Geo::DofUtilities::ExtractUPwDofsFromNodes(GetGeometry(), no_Pw_geometry_yet,
196210
GetGeometry().WorkingSpaceDimension());
197211
}
198212

199-
std::vector<Matrix> LineInterfaceElement::CalculateLocalBMatricesAtIntegrationPoints() const
213+
std::vector<Matrix> InterfaceElement::CalculateLocalBMatricesAtIntegrationPoints() const
200214
{
201215
const auto& r_integration_points = mIntegrationScheme->GetIntegrationPoints();
202216
const auto shape_function_values_at_integration_points =
203217
GeoElementUtilities::EvaluateShapeFunctionsAtIntegrationPoints(r_integration_points, GetGeometry());
204218

205219
auto result = std::vector<Matrix>{};
206220
result.reserve(shape_function_values_at_integration_points.size());
207-
auto calculate_local_b_matrix = [&r_geometry = GetGeometry(), p_policy = mStressStatePolicy.get()](
208-
const auto& rShapeFunctionValuesAtIntegrationPoint,
209-
const auto& rIntegrationPoint) {
221+
auto calculate_local_b_matrix = [&r_geometry = GetGeometry(), this](const auto& rShapeFunctionValuesAtIntegrationPoint,
222+
const auto& rIntegrationPoint) {
210223
// For interface elements, the shape function gradients are not used, since these are
211224
// non-continuum elements. Therefore, we pass an empty matrix.
225+
const auto rotation_matrix = mfpCalculateRotationMatrix(r_geometry, rIntegrationPoint);
212226
const auto dummy_gradients = Matrix{};
213-
return Matrix{prod(
214-
GeometryUtilities::Calculate2DRotationMatrixForLineGeometry(r_geometry, rIntegrationPoint),
215-
p_policy->CalculateBMatrix(dummy_gradients, rShapeFunctionValuesAtIntegrationPoint, r_geometry))};
227+
return Matrix{prod(rotation_matrix, mpStressStatePolicy->CalculateBMatrix(dummy_gradients, rShapeFunctionValuesAtIntegrationPoint,
228+
r_geometry))};
216229
};
217230
std::transform(shape_function_values_at_integration_points.begin(),
218231
shape_function_values_at_integration_points.end(), r_integration_points.begin(),
@@ -221,21 +234,20 @@ std::vector<Matrix> LineInterfaceElement::CalculateLocalBMatricesAtIntegrationPo
221234
return result;
222235
}
223236

224-
std::vector<double> LineInterfaceElement::CalculateIntegrationCoefficients() const
237+
std::vector<double> InterfaceElement::CalculateIntegrationCoefficients() const
225238
{
226239
const auto determinants_of_jacobian = CalculateDeterminantsOfJacobiansAtIntegrationPoints(
227240
mIntegrationScheme->GetIntegrationPoints(), GetGeometry());
228241
return mIntegrationCoefficientsCalculator.Run<>(mIntegrationScheme->GetIntegrationPoints(),
229242
determinants_of_jacobian, this);
230243
}
231244

232-
std::vector<Matrix> LineInterfaceElement::CalculateConstitutiveMatricesAtIntegrationPoints()
245+
std::vector<Matrix> InterfaceElement::CalculateConstitutiveMatricesAtIntegrationPoints()
233246
{
234247
return ::CalculateConstitutiveMatricesAtIntegrationPoints(mConstitutiveLaws, GetProperties());
235248
}
236249

237-
std::vector<Vector> LineInterfaceElement::CalculateRelativeDisplacementsAtIntegrationPoints(
238-
const std::vector<Matrix>& rLocalBMatrices) const
250+
std::vector<Vector> InterfaceElement::CalculateRelativeDisplacementsAtIntegrationPoints(const std::vector<Matrix>& rLocalBMatrices) const
239251
{
240252
const Geometry<Node> no_Pw_geometry;
241253
const auto dofs = Geo::DofUtilities::ExtractUPwDofsFromNodes(
@@ -255,7 +267,7 @@ std::vector<Vector> LineInterfaceElement::CalculateRelativeDisplacementsAtIntegr
255267
return result;
256268
}
257269

258-
std::vector<Vector> LineInterfaceElement::CalculateTractionsAtIntegrationPoints(const std::vector<Vector>& rRelativeDisplacements)
270+
std::vector<Vector> InterfaceElement::CalculateTractionsAtIntegrationPoints(const std::vector<Vector>& rRelativeDisplacements)
259271
{
260272
// We have to make a copy of each relative displacement vector, since setting it at the
261273
// constitutive law parameters requires a reference to a _mutable_ object!
@@ -276,4 +288,9 @@ std::vector<Vector> LineInterfaceElement::CalculateTractionsAtIntegrationPoints(
276288
return result;
277289
}
278290

291+
// Instances of this class can not be copied but can be moved. Check that at compile time.
292+
static_assert(!std::is_copy_constructible_v<InterfaceElement>);
293+
static_assert(!std::is_copy_assignable_v<InterfaceElement>);
294+
static_assert(std::is_move_constructible_v<InterfaceElement>);
295+
static_assert(std::is_move_assignable_v<InterfaceElement>);
279296
} // namespace Kratos

applications/GeoMechanicsApplication/custom_elements/line_interface_element.h renamed to applications/GeoMechanicsApplication/custom_elements/interface_element.h

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
// License: geo_mechanics_application/license.txt
99
//
1010
// Main authors: Richard Faasse
11+
// Gennady Markelov
1112
//
1213

1314
#pragma once
@@ -21,28 +22,30 @@
2122
namespace Kratos
2223
{
2324

24-
class KRATOS_API(GEO_MECHANICS_APPLICATION) LineInterfaceElement : public Element
25+
class KRATOS_API(GEO_MECHANICS_APPLICATION) InterfaceElement : public Element
2526
{
2627
public:
27-
KRATOS_CLASS_INTRUSIVE_POINTER_DEFINITION(LineInterfaceElement);
28+
KRATOS_CLASS_INTRUSIVE_POINTER_DEFINITION(InterfaceElement);
2829

2930
using Element::GeometryType;
3031
using Element::PropertiesType;
3132

3233
// Following the UPwBaseElement example, we will follow the rule of 5
3334
// to avoid the noexcept code smell.
34-
LineInterfaceElement() = default;
35-
~LineInterfaceElement() override = default;
36-
LineInterfaceElement(const LineInterfaceElement&) = delete;
37-
LineInterfaceElement& operator=(const LineInterfaceElement&) = delete;
38-
LineInterfaceElement(LineInterfaceElement&&) noexcept = default;
39-
LineInterfaceElement& operator=(LineInterfaceElement&&) noexcept = default;
40-
41-
LineInterfaceElement(IndexType NewId,
42-
const GeometryType::Pointer& rGeometry,
43-
const PropertiesType::Pointer& rProperties);
44-
45-
LineInterfaceElement(IndexType NewId, const GeometryType::Pointer& rGeometry);
35+
~InterfaceElement() override = default;
36+
InterfaceElement(const InterfaceElement&) = delete;
37+
InterfaceElement& operator=(const InterfaceElement&) = delete;
38+
InterfaceElement(InterfaceElement&&) noexcept = default;
39+
InterfaceElement& operator=(InterfaceElement&&) noexcept = default;
40+
41+
InterfaceElement(IndexType NewId,
42+
const GeometryType::Pointer& rGeometry,
43+
const PropertiesType::Pointer& rProperties,
44+
std::unique_ptr<StressStatePolicy> pStressStatePolicy);
45+
46+
InterfaceElement(IndexType NewId,
47+
const GeometryType::Pointer& rGeometry,
48+
std::unique_ptr<StressStatePolicy> pStressStatePolicy);
4649
Element::Pointer Create(IndexType NewId, const NodesArrayType& rNodes, PropertiesType::Pointer pProperties) const override;
4750
Element::Pointer Create(IndexType NewId, GeometryType::Pointer pGeom, PropertiesType::Pointer pProperties) const override;
4851

@@ -65,18 +68,24 @@ class KRATOS_API(GEO_MECHANICS_APPLICATION) LineInterfaceElement : public Elemen
6568
int Check(const ProcessInfo& rCurrentProcessInfo) const override;
6669

6770
private:
71+
InterfaceElement() = default;
72+
6873
Element::DofsVectorType GetDofs() const;
6974

7075
std::vector<Matrix> CalculateLocalBMatricesAtIntegrationPoints() const;
7176
std::vector<double> CalculateIntegrationCoefficients() const;
7277
std::vector<Matrix> CalculateConstitutiveMatricesAtIntegrationPoints();
7378
std::vector<Vector> CalculateRelativeDisplacementsAtIntegrationPoints(const std::vector<Matrix>& rLocalBMatrices) const;
7479
std::vector<Vector> CalculateTractionsAtIntegrationPoints(const std::vector<Vector>& rRelativeDisplacements);
80+
void MakeIntegrationSchemeAndAssignFunction();
81+
std::function<Matrix(const Geometry<Node>&, const array_1d<double, 3>&)> mfpCalculateRotationMatrix;
7582

7683
std::unique_ptr<IntegrationScheme> mIntegrationScheme;
77-
std::unique_ptr<StressStatePolicy> mStressStatePolicy;
84+
std::unique_ptr<StressStatePolicy> mpStressStatePolicy;
7885
std::vector<ConstitutiveLaw::Pointer> mConstitutiveLaws;
7986
IntegrationCoefficientsCalculator mIntegrationCoefficientsCalculator;
87+
88+
friend class Serializer;
8089
};
8190

8291
} // namespace Kratos

applications/GeoMechanicsApplication/custom_utilities/geometry_utilities.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,27 @@ Matrix GeometryUtilities::Calculate2DRotationMatrixForLineGeometry(const Geometr
3535
return result;
3636
}
3737

38+
Matrix GeometryUtilities::Calculate3DRotationMatrixForPlaneGeometry(const Geometry<Node>& rGeometry,
39+
const array_1d<double, 3>& rLocalCoordinate)
40+
{
41+
Matrix jacobian;
42+
rGeometry.Jacobian(jacobian, rLocalCoordinate);
43+
const auto tangential_vector_1 = GeoMechanicsMathUtilities::Normalized(Vector{column(jacobian, 0)});
44+
const auto tangential_vector_2 = GeoMechanicsMathUtilities::Normalized(
45+
Vector{Vector{column(jacobian, 1)} -
46+
inner_prod(Vector{column(jacobian, 1)}, tangential_vector_1) * tangential_vector_1});
47+
Vector normal_vector(3);
48+
MathUtils<>::CrossProduct(normal_vector, tangential_vector_1, tangential_vector_2);
49+
normal_vector = GeoMechanicsMathUtilities::Normalized(normal_vector);
50+
51+
// clang-format off
52+
Matrix result(3, 3);
53+
result <<= tangential_vector_1[0], tangential_vector_2[0], normal_vector[0],
54+
tangential_vector_1[1], tangential_vector_2[1], normal_vector[1],
55+
tangential_vector_1[2], tangential_vector_2[2], normal_vector[2];
56+
// clang-format on
57+
58+
return result;
59+
}
60+
3861
} // namespace Kratos

applications/GeoMechanicsApplication/custom_utilities/geometry_utilities.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ class KRATOS_API(GEO_MECHANICS_APPLICATION) GeometryUtilities
2626
public:
2727
static Matrix Calculate2DRotationMatrixForLineGeometry(const Geometry<Node>& rGeometry,
2828
const array_1d<double, 3>& rLocalCoordinate);
29+
static Matrix Calculate3DRotationMatrixForPlaneGeometry(const Geometry<Node>& rGeometry,
30+
const array_1d<double, 3>& rLocalCoordinate);
2931
};
3032

3133
} // namespace Kratos

0 commit comments

Comments
 (0)