Skip to content

Commit 72cf280

Browse files
authored
[GeoMechanicsApplication] Let the K0 procedure process also accept GEO_FRICTION_ANGLE as optional input (#14352)
* added HasFrictionAngle and ValidateFrictionAngle * added unit tests for HasFrictionAngle and ValidateFrictionAngle * changed order of getting friction angle * updated README.md * excluded check of friction angle when k0 values are available * removed {} in unit tests * used Kratos style for local variables * added unit test K0ProcedureIsAppliedCorrectlyWithK0_Values_3D * minor changes * fixed typo * response to the review * response to the review comment * fixed a type mismatch * fixed check * added property Id in output * added more prints of property Id * added even more prints of property Id * fixed a type mismatch
1 parent fd5125e commit 72cf280

7 files changed

Lines changed: 215 additions & 89 deletions

File tree

applications/GeoMechanicsApplication/custom_processes/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ When set to true, the material used for the modelpart used for the $K_0$ procedu
8585
When the stress computation is completed, the original constitutive law is restored.
8686

8787
Depending on the given input parameters, the following scheme is adapted for computation of the $K_0$ value.
88-
$K_0^{nc}$ is gotten from either "K0_NC" the material input file or by computation from input of "INDEX_OF_UMAT_PHI_PARAMETER" and "UMAT_PARAMETERS":
88+
$K_0^{nc}$ is gotten from either "K0_NC" the material input file or by computation from input of "GEO_FRICTION_ANGLE" or "INDEX_OF_UMAT_PHI_PARAMETER" and "UMAT_PARAMETERS":
8989

9090
$$K_0^{nc} = 1.0 - \sin \phi$$
9191

applications/GeoMechanicsApplication/custom_processes/apply_k0_procedure_process.cpp

Lines changed: 60 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
#include "apply_k0_procedure_process.h"
1414

1515
#include <algorithm>
16-
#include <ostream>
1716

1817
#include "containers/model.h"
1918
#include "custom_constitutive/linear_elastic_law.h"
@@ -32,9 +31,10 @@ using namespace std::string_literals;
3231
void SetConsiderDiagonalEntriesOnlyAndNoShear(ModelPart::ElementsContainerType& rElements, bool Whether)
3332
{
3433
block_for_each(rElements, [Whether](Element& rElement) {
35-
auto pLinearElasticLaw =
34+
const auto p_linear_elastic_law =
3635
dynamic_cast<GeoLinearElasticLaw*>(rElement.GetProperties().GetValue(CONSTITUTIVE_LAW).get());
37-
if (pLinearElasticLaw) pLinearElasticLaw->SetConsiderDiagonalEntriesOnlyAndNoShear(Whether);
36+
if (p_linear_elastic_law)
37+
p_linear_elastic_law->SetConsiderDiagonalEntriesOnlyAndNoShear(Whether);
3838
});
3939
}
4040

@@ -72,7 +72,7 @@ int ApplyK0ProcedureProcess::Check()
7272
{
7373
for (const auto& r_model_part : mrModelParts) {
7474
KRATOS_ERROR_IF(r_model_part.get().Elements().empty())
75-
<< "ApplyK0ProcedureProces has no elements in modelpart " << r_model_part.get().Name()
75+
<< "ApplyK0ProcedureProcess has no elements in modelpart " << r_model_part.get().Name()
7676
<< std::endl;
7777
}
7878

@@ -83,8 +83,10 @@ int ApplyK0ProcedureProcess::Check()
8383
CheckSufficientMaterialParameters(r_properties, rElement.Id());
8484
CheckOCRorPOP(r_properties, rElement.Id());
8585
CheckPoissonUnloadingReloading(r_properties, rElement.Id());
86-
CheckPhi(r_properties, rElement.Id());
8786
CheckK0(r_properties, rElement.Id());
87+
if (!(r_properties.Has(K0_NC) || (r_properties.Has(K0_VALUE_XX) && r_properties.Has(K0_VALUE_YY) &&
88+
r_properties.Has(K0_VALUE_ZZ))))
89+
ConstitutiveLawUtilities::ValidateFrictionAngle(r_properties, rElement.Id());
8890
});
8991
}
9092

@@ -97,15 +99,19 @@ void ApplyK0ProcedureProcess::CheckK0MainDirection(const Properties& rProperties
9799
<< "K0_MAIN_DIRECTION is not defined for element " << ElementId << "." << std::endl;
98100

99101
const auto dimension = rProperties.GetValue(CONSTITUTIVE_LAW).get()->WorkingSpaceDimension();
100-
if (dimension == 2) {
101-
KRATOS_ERROR_IF(rProperties[K0_MAIN_DIRECTION] < 0 || rProperties[K0_MAIN_DIRECTION] > 1)
102-
<< "K0_MAIN_DIRECTION should be 0 or 1 for element " << ElementId << "." << std::endl;
103-
} else if (dimension == 3) {
104-
KRATOS_ERROR_IF(rProperties[K0_MAIN_DIRECTION] < 0 || rProperties[K0_MAIN_DIRECTION] > 2)
105-
<< "K0_MAIN_DIRECTION should be 0, 1 or 2 for element " << ElementId << "." << std::endl;
106-
} else {
107-
KRATOS_ERROR << "dimension should be 2 or 3 for element " << ElementId << "." << std::endl;
102+
KRATOS_ERROR_IF(dimension != 2 && dimension != 3)
103+
<< "dimension should be 2 or 3 for element " << ElementId << "." << std::endl;
104+
std::ostringstream valid_values;
105+
for (std::size_t i = 0; i < dimension; ++i) {
106+
if (i > 0) {
107+
if (i == dimension - 1) valid_values << " or ";
108+
else valid_values << ", ";
109+
}
110+
valid_values << i;
108111
}
112+
KRATOS_ERROR_IF(rProperties[K0_MAIN_DIRECTION] < 0 || rProperties[K0_MAIN_DIRECTION] > static_cast<int>(dimension))
113+
<< "K0_MAIN_DIRECTION should be " << valid_values.str() << " for element " << ElementId
114+
<< "." << std::endl;
109115
}
110116

111117
void ApplyK0ProcedureProcess::CheckK0(const Properties& rProperties, IndexType ElementId)
@@ -122,37 +128,21 @@ void ApplyK0ProcedureProcess::CheckK0(const Properties& rProperties, IndexType E
122128
}
123129
}
124130

125-
void ApplyK0ProcedureProcess::CheckPhi(const Properties& rProperties, IndexType ElementId)
126-
{
127-
if (rProperties.Has(INDEX_OF_UMAT_PHI_PARAMETER) && rProperties.Has(UMAT_PARAMETERS)) {
128-
const auto phi_index = rProperties[INDEX_OF_UMAT_PHI_PARAMETER];
129-
const auto number_of_umat_parameters = static_cast<int>(rProperties[UMAT_PARAMETERS].size());
130-
131-
KRATOS_ERROR_IF(phi_index < 1 || phi_index > number_of_umat_parameters)
132-
<< "INDEX_OF_UMAT_PHI_PARAMETER (" << phi_index
133-
<< ") is not in range 1, size of UMAT_PARAMETERS for element " << ElementId << "." << std::endl;
134-
135-
const double phi = rProperties[UMAT_PARAMETERS][phi_index - 1];
136-
KRATOS_ERROR_IF(phi < 0.0 || phi > 90.0)
137-
<< "Phi (" << phi << ") should be between 0 and 90 degrees for element " << ElementId
138-
<< "." << std::endl;
139-
}
140-
}
141-
142131
void ApplyK0ProcedureProcess::CheckOCRorPOP(const Properties& rProperties, IndexType ElementId)
143132
{
144-
if (rProperties.Has(K0_NC) ||
145-
(rProperties.Has(INDEX_OF_UMAT_PHI_PARAMETER) && rProperties.Has(UMAT_PARAMETERS))) {
133+
if (rProperties.Has(K0_NC) || ConstitutiveLawUtilities::HasFrictionAngle(rProperties)) {
146134
if (rProperties.Has(OCR)) {
147135
const auto ocr = rProperties[OCR];
148-
KRATOS_ERROR_IF(ocr < 1.0) << "OCR (" << ocr << ") should be in the range [1.0,-> for element "
149-
<< ElementId << "." << std::endl;
136+
KRATOS_ERROR_IF(ocr < 1.0)
137+
<< "OCR (" << ocr << ") should be in the range [1.0,-> for property Id of "
138+
<< rProperties.Id() << " for element " << ElementId << "." << std::endl;
150139
}
151140

152141
if (rProperties.Has(POP)) {
153142
const auto pop = rProperties[POP];
154-
KRATOS_ERROR_IF(pop < 0.0) << "POP (" << pop << ") should be in the range [0.0,-> for element "
155-
<< ElementId << "." << std::endl;
143+
KRATOS_ERROR_IF(pop < 0.0)
144+
<< "POP (" << pop << ") should be in the range [0.0,-> for property Id of "
145+
<< rProperties.Id() << " element " << ElementId << "." << std::endl;
156146
}
157147
}
158148
}
@@ -163,12 +153,14 @@ void ApplyK0ProcedureProcess::CheckPoissonUnloadingReloading(const Properties& r
163153
(rProperties[POISSON_UNLOADING_RELOADING] < -1.0 ||
164154
rProperties[POISSON_UNLOADING_RELOADING] >= 0.5))
165155
<< "POISSON_UNLOADING_RELOADING (" << rProperties[POISSON_UNLOADING_RELOADING]
166-
<< ") is not in range [-1.0, 0.5> for element " << ElementId << "." << std::endl;
156+
<< ") is not in range [-1.0, 0.5> for property Id of " << rProperties.Id()
157+
<< " for element " << ElementId << "." << std::endl;
167158

168159
if (rProperties.Has(K0_VALUE_XX)) {
169160
KRATOS_ERROR_IF(rProperties.Has(POISSON_UNLOADING_RELOADING) || rProperties.Has(OCR) ||
170161
rProperties.Has(POP))
171-
<< "Insufficient material data for K0 procedure process for element "
162+
<< "Insufficient material data for K0 procedure process for property Id of "
163+
<< rProperties.Id() << " for element "
172164
<< ElementId << ". Poisson unloading-reloading, OCR and POP functionality cannot be combined with K0_VALUE_XX, _YY and _ZZ."
173165
<< std::endl;
174166
}
@@ -177,10 +169,10 @@ void ApplyK0ProcedureProcess::CheckPoissonUnloadingReloading(const Properties& r
177169
void ApplyK0ProcedureProcess::CheckSufficientMaterialParameters(const Properties& rProperties, IndexType ElementId)
178170
{
179171
KRATOS_ERROR_IF_NOT(
180-
rProperties.Has(K0_NC) ||
181-
(rProperties.Has(INDEX_OF_UMAT_PHI_PARAMETER) && rProperties.Has(UMAT_PARAMETERS)) ||
172+
rProperties.Has(K0_NC) || ConstitutiveLawUtilities::HasFrictionAngle(rProperties) ||
182173
(rProperties.Has(K0_VALUE_XX) && rProperties.Has(K0_VALUE_YY) && rProperties.Has(K0_VALUE_ZZ)))
183-
<< "Insufficient material data for K0 procedure process for element " << ElementId << ". No K0_NC, "
174+
<< "Insufficient material data for K0 procedure process for property Id of "
175+
<< rProperties.Id() << " for element " << ElementId << ". No K0_NC, "
184176
<< "(INDEX_OF_UMAT_PHI_PARAMETER and UMAT_PARAMETERS) or (K0_VALUE_XX, _YY and _ZZ found)."
185177
<< std::endl;
186178
}
@@ -206,19 +198,19 @@ bool ApplyK0ProcedureProcess::UseStandardProcedure() const
206198
return !mSettings.Has(setting_name) || mSettings[setting_name].GetBool();
207199
}
208200

209-
array_1d<double, 3> ApplyK0ProcedureProcess::CreateK0Vector(const Element::PropertiesType& rProp)
201+
array_1d<double, 3> ApplyK0ProcedureProcess::CreateK0Vector(const Element::PropertiesType& rProperties)
210202
{
211203
// Check for alternative K0 specifications
212204
array_1d<double, 3> k0_vector;
213-
if (rProp.Has(K0_NC)) {
214-
std::fill(k0_vector.begin(), k0_vector.end(), rProp[K0_NC]);
215-
} else if (rProp.Has(INDEX_OF_UMAT_PHI_PARAMETER) && rProp.Has(UMAT_PARAMETERS)) {
205+
if (rProperties.Has(K0_NC)) {
206+
std::ranges::fill(k0_vector, rProperties[K0_NC]);
207+
} else if (ConstitutiveLawUtilities::HasFrictionAngle(rProperties)) {
216208
std::ranges::fill(k0_vector, ConstitutiveLawUtilities::CalculateK0NCFromFrictionAngleInRadians(
217-
ConstitutiveLawUtilities::GetFrictionAngleInRadians(rProp)));
209+
ConstitutiveLawUtilities::GetFrictionAngleInRadians(rProperties)));
218210
} else {
219-
k0_vector[0] = rProp[K0_VALUE_XX];
220-
k0_vector[1] = rProp[K0_VALUE_YY];
221-
k0_vector[2] = rProp[K0_VALUE_ZZ];
211+
k0_vector[0] = rProperties[K0_VALUE_XX];
212+
k0_vector[1] = rProperties[K0_VALUE_YY];
213+
k0_vector[2] = rProperties[K0_VALUE_ZZ];
222214
}
223215

224216
return k0_vector;
@@ -227,45 +219,46 @@ array_1d<double, 3> ApplyK0ProcedureProcess::CreateK0Vector(const Element::Prope
227219
void ApplyK0ProcedureProcess::CalculateK0Stresses(Element& rElement, const ProcessInfo& rProcessInfo)
228220
{
229221
// Get K0 material parameters of this element ( probably there is something more efficient )
230-
const Element::PropertiesType& rProp = rElement.GetProperties();
231-
const auto k0_main_direction = rProp[K0_MAIN_DIRECTION];
222+
const Element::PropertiesType& r_properties = rElement.GetProperties();
223+
const auto k0_main_direction = r_properties[K0_MAIN_DIRECTION];
232224

233-
auto k0_vector = CreateK0Vector(rProp);
225+
auto k0_vector = CreateK0Vector(r_properties);
234226

235227
// Corrections on k0_vector by OCR or POP
236-
const auto PoissonUR = rProp.Has(POISSON_UNLOADING_RELOADING) ? rProp[POISSON_UNLOADING_RELOADING] : 0.;
237-
const auto PoissonURfactor = PoissonUR / (1. - PoissonUR);
228+
const auto poisson_u_r =
229+
r_properties.Has(POISSON_UNLOADING_RELOADING) ? r_properties[POISSON_UNLOADING_RELOADING] : 0.;
230+
const auto poisson_u_r_factor = poisson_u_r / (1. - poisson_u_r);
238231

239232
double POP_value = 0.0;
240-
if (rProp.Has(K0_NC) || rProp.Has(INDEX_OF_UMAT_PHI_PARAMETER)) {
241-
if (rProp.Has(OCR)) {
233+
if (r_properties.Has(K0_NC) || ConstitutiveLawUtilities::HasFrictionAngle(r_properties)) {
234+
if (r_properties.Has(OCR)) {
242235
// Determine OCR dependent K0 values ( constant per element! )
243-
k0_vector *= rProp[OCR];
244-
const array_1d<double, 3> correction(3, PoissonURfactor * (rProp[OCR] - 1.0));
236+
k0_vector *= r_properties[OCR];
237+
const array_1d<double, 3> correction(3, poisson_u_r_factor * (r_properties[OCR] - 1.0));
245238
k0_vector -= correction;
246-
} else if (rProp.Has(POP)) {
239+
} else if (r_properties.Has(POP)) {
247240
// POP is entered as positive value, convention here is compression negative.
248-
POP_value = -rProp[POP];
241+
POP_value = -r_properties[POP];
249242
}
250243
}
251244
// Get element stress vectors
252-
std::vector<ConstitutiveLaw::StressVectorType> rStressVectors;
253-
rElement.CalculateOnIntegrationPoints(CAUCHY_STRESS_VECTOR, rStressVectors, rProcessInfo);
245+
std::vector<ConstitutiveLaw::StressVectorType> stress_vectors;
246+
rElement.CalculateOnIntegrationPoints(CAUCHY_STRESS_VECTOR, stress_vectors, rProcessInfo);
254247

255248
// Loop over integration point stress vectors
256-
for (auto& rStressVector : rStressVectors) {
249+
for (auto& r_stress_vector : stress_vectors) {
257250
// Apply K0 procedure
258251
for (int i_dir = 0; i_dir <= 2; ++i_dir) {
259252
if (i_dir != k0_main_direction) {
260-
rStressVector[i_dir] = k0_vector[i_dir] * (rStressVector[k0_main_direction] + POP_value) -
261-
PoissonURfactor * POP_value;
253+
r_stress_vector[i_dir] = k0_vector[i_dir] * (r_stress_vector[k0_main_direction] + POP_value) -
254+
poisson_u_r_factor * POP_value;
262255
}
263256
}
264257
// Erase shear stresses
265-
std::fill(rStressVector.begin() + 3, rStressVector.end(), 0.0);
258+
std::fill(r_stress_vector.begin() + 3, r_stress_vector.end(), 0.0);
266259
}
267260
// Set element integration point stress tensors
268-
rElement.SetValuesOnIntegrationPoints(CAUCHY_STRESS_VECTOR, rStressVectors, rProcessInfo);
261+
rElement.SetValuesOnIntegrationPoints(CAUCHY_STRESS_VECTOR, stress_vectors, rProcessInfo);
269262
}
270263

271264
} // namespace Kratos

applications/GeoMechanicsApplication/custom_processes/apply_k0_procedure_process.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,12 @@ class KRATOS_API(GEO_MECHANICS_APPLICATION) ApplyK0ProcedureProcess : public Pro
4040
[[nodiscard]] std::string Info() const override;
4141

4242
private:
43-
[[nodiscard]] bool UseStandardProcedure() const;
44-
[[nodiscard]] static array_1d<double, 3> CreateK0Vector(const Element::PropertiesType& rProp);
43+
[[nodiscard]] bool UseStandardProcedure() const;
44+
[[nodiscard]] static array_1d<double, 3> CreateK0Vector(const Element::PropertiesType& rProperties);
4545
static void CalculateK0Stresses(Element& rElement, const ProcessInfo& rProcessInfo);
4646
static void CheckK0(const Properties& rProperties, IndexType ElementId);
4747
static void CheckK0MainDirection(const Properties& rProperties, IndexType ElementId);
4848
static void CheckOCRorPOP(const Properties& rProperties, IndexType ElementId);
49-
static void CheckPhi(const Properties& rProperties, IndexType ElementId);
5049
static void CheckPoissonUnloadingReloading(const Properties& rProperties, IndexType ElementId);
5150
static void CheckSufficientMaterialParameters(const Properties& rProperties, IndexType ElementId);
5251

applications/GeoMechanicsApplication/custom_utilities/constitutive_law_utilities.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,45 @@ double ConstitutiveLawUtilities::GetCohesion(const Properties& rProperties)
8383
}
8484
}
8585

86+
bool ConstitutiveLawUtilities::HasFrictionAngle(const Properties& rProperties)
87+
{
88+
// Friction angle can be supplied either directly via GEO_FRICTION_ANGLE
89+
// or via UMAT parameters + INDEX_OF_UMAT_PHI_PARAMETER.
90+
return rProperties.Has(GEO_FRICTION_ANGLE) ||
91+
(rProperties.Has(INDEX_OF_UMAT_PHI_PARAMETER) && rProperties.Has(UMAT_PARAMETERS));
92+
}
93+
94+
void ConstitutiveLawUtilities::ValidateFrictionAngle(const Properties& rProperties, IndexType ElementId)
95+
{
96+
double phi = 0.0;
97+
std::string phi_name;
98+
99+
if (rProperties.Has(GEO_FRICTION_ANGLE)) {
100+
phi = rProperties[GEO_FRICTION_ANGLE];
101+
phi_name = "GEO_FRICTION_ANGLE";
102+
} else if (rProperties.Has(INDEX_OF_UMAT_PHI_PARAMETER) && rProperties.Has(UMAT_PARAMETERS)) {
103+
const auto phi_index = rProperties[INDEX_OF_UMAT_PHI_PARAMETER];
104+
const auto number_of_umat_parameters = static_cast<int>(rProperties[UMAT_PARAMETERS].size());
105+
106+
KRATOS_ERROR_IF(phi_index < 1 || phi_index > number_of_umat_parameters)
107+
<< "Properties ( " << rProperties.Id() << ") of element ( " << ElementId
108+
<< "): INDEX_OF_UMAT_PHI_PARAMETER (" << phi_index
109+
<< ") is not in range [1, size of UMAT_PARAMETERS]." << std::endl;
110+
111+
phi = rProperties[UMAT_PARAMETERS][phi_index - 1];
112+
phi_name = "Phi";
113+
}
114+
115+
if (phi_name == "") {
116+
KRATOS_ERROR << "Properties ( " << rProperties.Id() << ") of element ( " << ElementId
117+
<< ") does not have GEO_FRICTION_ANGLE nor INDEX_OF_UMAT_PHI_PARAMETER." << std::endl;
118+
}
119+
120+
KRATOS_ERROR_IF(phi < 0.0 || phi > 90.0)
121+
<< "Properties ( " << rProperties.Id() << ") of element ( " << ElementId << "): " << phi_name
122+
<< " (" << phi << " degrees) should be between 0 and 90 degrees." << std::endl;
123+
}
124+
86125
double ConstitutiveLawUtilities::GetFrictionAngleInDegrees(const Properties& rProperties)
87126
{
88127
if (rProperties.Has(GEO_FRICTION_ANGLE)) {

applications/GeoMechanicsApplication/custom_utilities/constitutive_law_utilities.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ class KRATOS_API(GEO_MECHANICS_APPLICATION) ConstitutiveLawUtilities
3535
double detF);
3636

3737
static double GetCohesion(const Properties& rProperties);
38+
static bool HasFrictionAngle(const Properties& rProperties);
39+
static void ValidateFrictionAngle(const Properties& rProperties, IndexType ElementId);
3840
static double GetFrictionAngleInDegrees(const Properties& rProperties);
3941
static double GetFrictionAngleInRadians(const Properties& rProperties);
4042

0 commit comments

Comments
 (0)