Skip to content

Commit 7c5b35f

Browse files
[GeoMechanicsApplication] Tests for Mohr Coulomb (#13302)
* Registered 2D and 3D laws for Mohr-Coulomb * Fixes * Added an extra region * Added unit tests for the new zone * clang format * fixed documentation * Added unit tests * Changes based or review comments * Changes based on review requests * Fixed a bug + changes based on review * fix in tests * fixes based on review * changes based on review * fixes * fixes * fixes in readme * used SetStrainSize/SetSpaceDimension and ransformPrincipalStressesToSigmaAndTau is taked out of three functions * cleaned unit tests * made the tolerance relative * response to the review comments * reverted properties settings * Changes based on review * typos * Cleanup tests * Added unit tests for 3D * Fixes based on review --------- Co-authored-by: markelov <gennady.markelov@deltares.nl>
1 parent 1c07d95 commit 7c5b35f

26 files changed

Lines changed: 2065 additions & 229 deletions

File tree

applications/GeoMechanicsApplication/custom_constitutive/README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,8 @@ To incorporate the Mohr-Coulomb model with tensile cutoff in numerical simulatio
9595

9696
4. Evaluate the condition and mapping
9797
- If the trial stress falls in the elastic zone, it stays unchanged. No mapping is applied.
98-
- If the trial stress falls in the axial zone. The trial stress then needs to be mapped back to the cutoff curve.
98+
- If the trial stress falls in the tensile apex return zone. The trial stress then needs to be mapped back to the apex.
99+
- If the trial stress falls in the tensile cutoff zone. The trial stress then needs to be mapped back to the tension cutoff line.
99100
- If it falls in the tensile corner return zone, then it needs to be mapped to the corner point.
100101
- In the case of regular failure zone, then it is mapped back to the Mohr-Coulomb curve along the normal direction of flow function. The flow function is defined by
101102

applications/GeoMechanicsApplication/custom_constitutive/documentation_data/mohr-coulomb-with-tension-cutoff-zones.svg

Lines changed: 1 addition & 1 deletion
Loading

applications/GeoMechanicsApplication/custom_constitutive/mohr_coulomb_with_tension_cutoff.cpp

Lines changed: 70 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -65,19 +65,27 @@ Vector CalculateCornerPoint(double FrictionAngle, double Cohesion, double Tensil
6565
return result;
6666
}
6767

68-
Vector ReturnStressAtAxialZone(const Vector& rPrincipalTrialStressVector, double TensileStrength)
68+
Vector ReturnStressAtTensionApexReturnZone(const Vector& rPrincipalTrialStressVector, double TensileStrength)
6969
{
7070
auto result = rPrincipalTrialStressVector;
7171
result[0] = TensileStrength;
72-
result[2] = TensileStrength - rPrincipalTrialStressVector[0] + rPrincipalTrialStressVector[2];
72+
result[2] = result[0];
7373
return result;
7474
}
7575

76+
Vector ReturnStressAtTensionCutoffReturnZone(const Vector& rPrincipalTrialStressVector,
77+
const Vector& rDerivativeOfFlowFunction,
78+
double TensileStrength)
79+
{
80+
const auto lambda = (TensileStrength - rPrincipalTrialStressVector[0]) / rDerivativeOfFlowFunction[0];
81+
return rPrincipalTrialStressVector + lambda * rDerivativeOfFlowFunction;
82+
}
83+
7684
Vector ReturnStressAtCornerReturnZone(const Vector& rPrincipalTrialStressVector, const Vector& rCornerPoint)
7785
{
78-
Vector result = rPrincipalTrialStressVector;
79-
result[0] = rCornerPoint[0] + rCornerPoint[1];
80-
result[2] = rCornerPoint[0] - rCornerPoint[1];
86+
auto result = rPrincipalTrialStressVector;
87+
result[0] = rCornerPoint[0] + rCornerPoint[1];
88+
result[2] = rCornerPoint[0] - rCornerPoint[1];
8189
return result;
8290
}
8391

@@ -122,7 +130,7 @@ Vector& MohrCoulombWithTensionCutOff::GetValue(const Variable<Vector>& rThisVari
122130
if (rThisVariable == CAUCHY_STRESS_VECTOR) {
123131
rValue = mStressVector;
124132
} else {
125-
KRATOS_ERROR << "Can't get value of " << rThisVariable.Name() << ": unsupported variable\n";
133+
rValue = ConstitutiveLaw::GetValue(rThisVariable, rValue);
126134
}
127135
return rValue;
128136
}
@@ -190,6 +198,27 @@ void MohrCoulombWithTensionCutOff::InitializeMaterial(const Properties& rMateria
190198
mTensionCutOff = TensionCutoff(rMaterialProperties[GEO_TENSILE_STRENGTH]);
191199
}
192200

201+
void MohrCoulombWithTensionCutOff::InitializeMaterialResponseCauchy(Parameters& rValues)
202+
{
203+
if (!mIsModelInitialized) {
204+
mStressVectorFinalized = rValues.GetStressVector();
205+
mStrainVectorFinalized = rValues.GetStrainVector();
206+
mIsModelInitialized = true;
207+
}
208+
}
209+
210+
void MohrCoulombWithTensionCutOff::GetLawFeatures(Features& rFeatures)
211+
{
212+
rFeatures.SetOptions(mpConstitutiveDimension->GetSpatialType());
213+
rFeatures.SetOptions(INFINITESIMAL_STRAINS);
214+
rFeatures.SetOptions(ISOTROPIC);
215+
216+
rFeatures.SetStrainMeasure(StrainMeasure_Infinitesimal);
217+
218+
rFeatures.SetStrainSize(GetStrainSize());
219+
rFeatures.SetSpaceDimension(WorkingSpaceDimension());
220+
}
221+
193222
void MohrCoulombWithTensionCutOff::CalculateMaterialResponseCauchy(ConstitutiveLaw::Parameters& rParameters)
194223
{
195224
const auto& r_prop = rParameters.GetMaterialProperties();
@@ -209,12 +238,18 @@ void MohrCoulombWithTensionCutOff::CalculateMaterialResponseCauchy(ConstitutiveL
209238
CalculateCornerPoint(MathUtils<>::DegreesToRadians(r_prop[GEO_FRICTION_ANGLE]),
210239
r_prop[GEO_COHESION], r_prop[GEO_TENSILE_STRENGTH]);
211240

212-
if (IsStressAtAxialZone(principal_trial_stress_vector, r_prop[GEO_TENSILE_STRENGTH], apex, corner_point)) {
213-
principal_trial_stress_vector =
214-
ReturnStressAtAxialZone(principal_trial_stress_vector, r_prop[GEO_TENSILE_STRENGTH]);
215-
} else if (IsStressAtCornerReturnZone(principal_trial_stress_vector,
216-
MathUtils<>::DegreesToRadians(r_prop[GEO_DILATANCY_ANGLE]),
217-
corner_point)) {
241+
if (const auto trial_sigma_tau = TransformPrincipalStressesToSigmaAndTau(principal_trial_stress_vector);
242+
IsStressAtTensionApexReturnZone(trial_sigma_tau, r_prop[GEO_TENSILE_STRENGTH], apex)) {
243+
principal_trial_stress_vector = ReturnStressAtTensionApexReturnZone(
244+
principal_trial_stress_vector, r_prop[GEO_TENSILE_STRENGTH]);
245+
} else if (IsStressAtTensionCutoffReturnZone(trial_sigma_tau, r_prop[GEO_TENSILE_STRENGTH],
246+
apex, corner_point)) {
247+
principal_trial_stress_vector = ReturnStressAtTensionCutoffReturnZone(
248+
principal_trial_stress_vector,
249+
mTensionCutOff.DerivativeOfFlowFunction(principal_trial_stress_vector),
250+
r_prop[GEO_TENSILE_STRENGTH]);
251+
} else if (IsStressAtCornerReturnZone(
252+
trial_sigma_tau, MathUtils<>::DegreesToRadians(r_prop[GEO_DILATANCY_ANGLE]), corner_point)) {
218253
principal_trial_stress_vector =
219254
ReturnStressAtCornerReturnZone(principal_trial_stress_vector, corner_point);
220255
} else {
@@ -230,30 +265,41 @@ void MohrCoulombWithTensionCutOff::CalculateMaterialResponseCauchy(ConstitutiveL
230265

231266
mStressVector = StressStrainUtilities::RotatePrincipalStresses(
232267
principal_trial_stress_vector, rotation_matrix, mpConstitutiveDimension->GetStrainSize());
268+
269+
rParameters.GetStressVector() = mStressVector;
233270
}
234271

235272
bool MohrCoulombWithTensionCutOff::IsAdmissiblePrincipalStressState(const Vector& rPrincipalStresses) const
236273
{
237-
return mCoulombYieldSurface.YieldFunctionValue(rPrincipalStresses) <= 0.0 &&
238-
mTensionCutOff.YieldFunctionValue(rPrincipalStresses) <= 0.0;
274+
constexpr auto tolerance = 1.0e-10;
275+
const auto coulomb_yield_function = mCoulombYieldSurface.YieldFunctionValue(rPrincipalStresses);
276+
const auto tension_yield_function = mTensionCutOff.YieldFunctionValue(rPrincipalStresses);
277+
const auto coulomb_tolerance = tolerance * (1.0 + std::abs(coulomb_yield_function));
278+
const auto tension_tolerance = tolerance * (1.0 + std::abs(tension_yield_function));
279+
return coulomb_yield_function < coulomb_tolerance && tension_yield_function < tension_tolerance;
280+
}
281+
282+
bool MohrCoulombWithTensionCutOff::IsStressAtTensionApexReturnZone(const Vector& rTrialSigmaTau,
283+
double TensileStrength,
284+
double Apex) const
285+
{
286+
return TensileStrength < Apex && rTrialSigmaTau[0] - rTrialSigmaTau[1] - TensileStrength > 0.0;
239287
}
240288

241-
bool MohrCoulombWithTensionCutOff::IsStressAtAxialZone(const Vector& rPrincipalTrialStresses,
242-
double TensileStrength,
243-
double Apex,
244-
const Vector& rCornerPoint) const
289+
bool MohrCoulombWithTensionCutOff::IsStressAtTensionCutoffReturnZone(const Vector& rTrialSigmaTau,
290+
double TensileStrength,
291+
double Apex,
292+
const Vector& rCornerPoint) const
245293
{
246-
const auto trial_tau = TransformPrincipalStressesToSigmaAndTau(rPrincipalTrialStresses)[1];
247-
return TensileStrength < Apex && trial_tau <= rCornerPoint[1] &&
248-
mTensionCutOff.YieldFunctionValue(rPrincipalTrialStresses) >= 0.0;
294+
return TensileStrength < Apex &&
295+
rCornerPoint[1] - rTrialSigmaTau[1] - rCornerPoint[0] + rTrialSigmaTau[0] > 0.0;
249296
}
250297

251-
bool MohrCoulombWithTensionCutOff::IsStressAtCornerReturnZone(const Vector& rPrincipalTrialStresses,
298+
bool MohrCoulombWithTensionCutOff::IsStressAtCornerReturnZone(const Vector& rTrialSigmaTau,
252299
double DilatancyAngle,
253300
const Vector& rCornerPoint)
254301
{
255-
const auto trial_sigma_tau = TransformPrincipalStressesToSigmaAndTau(rPrincipalTrialStresses);
256-
return trial_sigma_tau[0] - rCornerPoint[0] - (trial_sigma_tau[1] - rCornerPoint[1]) * std::sin(DilatancyAngle) >= 0.0;
302+
return rTrialSigmaTau[0] - rCornerPoint[0] - (rTrialSigmaTau[1] - rCornerPoint[1]) * std::sin(DilatancyAngle) >= 0.0;
257303
}
258304

259305
Vector MohrCoulombWithTensionCutOff::CalculateTrialStressVector(const Vector& rStrainVector,

applications/GeoMechanicsApplication/custom_constitutive/mohr_coulomb_with_tension_cutoff.h

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ class KRATOS_API(GEO_MECHANICS_APPLICATION) MohrCoulombWithTensionCutOff : publi
3232
public:
3333
KRATOS_CLASS_POINTER_DEFINITION(MohrCoulombWithTensionCutOff);
3434

35+
MohrCoulombWithTensionCutOff() = default;
3536
explicit MohrCoulombWithTensionCutOff(std::unique_ptr<ConstitutiveLawDimension> pConstitutiveDimension);
3637

3738
// Copying is not allowed. Use member `Clone` instead.
@@ -52,6 +53,8 @@ class KRATOS_API(GEO_MECHANICS_APPLICATION) MohrCoulombWithTensionCutOff : publi
5253
void InitializeMaterial(const Properties& rMaterialProperties,
5354
const Geometry<Node>& rElementGeometry,
5455
const Vector& rShapeFunctionsValues) override;
56+
void InitializeMaterialResponseCauchy(Parameters& rValues) override;
57+
void GetLawFeatures(Features& rFeatures) override;
5558
Vector& GetValue(const Variable<Vector>& rThisVariable, Vector& rValue) override;
5659
using ConstitutiveLaw::GetValue;
5760
void SetValue(const Variable<Vector>& rVariable, const Vector& rValue, const ProcessInfo& rCurrentProcessInfo) override;
@@ -69,16 +72,20 @@ class KRATOS_API(GEO_MECHANICS_APPLICATION) MohrCoulombWithTensionCutOff : publi
6972
Vector mStrainVectorFinalized;
7073
CoulombYieldSurface mCoulombYieldSurface;
7174
TensionCutoff mTensionCutOff;
75+
bool mIsModelInitialized = false;
7276

7377
[[nodiscard]] Vector CalculateTrialStressVector(const Vector& rStrainVector,
7478
double YoungsModulus,
7579
double PoissonsRatio) const;
7680
[[nodiscard]] bool IsAdmissiblePrincipalStressState(const Vector& rPrincipalStresses) const;
77-
[[nodiscard]] bool IsStressAtAxialZone(const Vector& rPrincipalTrialStresses,
78-
double TensileStrength,
79-
double Apex,
80-
const Vector& rCornerPoint) const;
81-
[[nodiscard]] static bool IsStressAtCornerReturnZone(const Vector& rPrincipalTrialStresses,
81+
[[nodiscard]] bool IsStressAtTensionApexReturnZone(const Vector& rTrialSigmaTau,
82+
double TensileStrength,
83+
double Apex) const;
84+
[[nodiscard]] bool IsStressAtTensionCutoffReturnZone(const Vector& rTrialSigmaTau,
85+
double TensileStrength,
86+
double Apex,
87+
const Vector& rCornerPoint) const;
88+
[[nodiscard]] static bool IsStressAtCornerReturnZone(const Vector& rTrialSigmaTau,
8289
double DilatancyAngle,
8390
const Vector& rCornerPoint);
8491
}; // Class MohrCoulombWithTensionCutOff

applications/GeoMechanicsApplication/geo_mechanics_application.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,9 @@ void KratosGeoMechanicsApplication::Register()
366366

367367
KRATOS_REGISTER_CONSTITUTIVE_LAW("Geo_IncrementalLinearElasticInterfaceLaw", mIncrementalLinearElasticInterfaceLaw)
368368

369+
KRATOS_REGISTER_CONSTITUTIVE_LAW("GeoMohrCoulombWithTensionCutOff2D", mMohrCoulombWithTensionCutOff2D)
370+
KRATOS_REGISTER_CONSTITUTIVE_LAW("GeoMohrCoulombWithTensionCutOff3D", mMohrCoulombWithTensionCutOff3D)
371+
369372
// Register Variables
370373
KRATOS_REGISTER_VARIABLE(VELOCITY_COEFFICIENT)
371374
KRATOS_REGISTER_VARIABLE(DT_PRESSURE_COEFFICIENT)

applications/GeoMechanicsApplication/geo_mechanics_application.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@
122122
#include "custom_constitutive/linear_elastic_2D_interface_law.h"
123123
#include "custom_constitutive/linear_elastic_3D_interface_law.h"
124124
#include "custom_constitutive/linear_elastic_plane_stress_2D_law.h"
125+
#include "custom_constitutive/mohr_coulomb_with_tension_cutoff.h"
125126
#include "custom_constitutive/plane_strain.h"
126127
#include "custom_constitutive/small_strain_udsm_2D_interface_law.hpp"
127128
#include "custom_constitutive/small_strain_udsm_2D_plane_strain_law.hpp"
@@ -970,6 +971,8 @@ class KRATOS_API(GEO_MECHANICS_APPLICATION) KratosGeoMechanicsApplication : publ
970971

971972
const GeoIncrementalLinearElasticInterfaceLaw mIncrementalLinearElasticInterfaceLaw;
972973

974+
const MohrCoulombWithTensionCutOff mMohrCoulombWithTensionCutOff2D{std::make_unique<PlaneStrain>()};
975+
const MohrCoulombWithTensionCutOff mMohrCoulombWithTensionCutOff3D{std::make_unique<ThreeDimensional>()};
973976
///@}
974977

975978
}; // Class KratosGeoMechanicsApplication

0 commit comments

Comments
 (0)