OGS
PhaseFieldBase.h
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Copyright (c) OpenGeoSys Community (opengeosys.org)
2// SPDX-License-Identifier: BSD-3-Clause
3
4#pragma once
5
6#include <Eigen/Core>
7#include <numbers>
8#include <optional>
9
10#include "BaseLib/Logging.h"
15
16namespace MaterialLib
17{
18namespace Solids
19{
20namespace Phasefield
21{
28
29template <int DisplacementDim>
31 std::string const& phasefield_model)
32{
33 if (phasefield_model == "AT1")
34 {
36 }
37 if (phasefield_model == "AT2")
38 {
40 }
41 if (phasefield_model == "COHESIVE")
42 {
44 }
46 "phasefield_model must be 'AT1', 'AT2' or 'COHESIVE' but '{}' "
47 "was given",
48 phasefield_model.c_str());
49};
50
56
57template <int DisplacementDim>
59 std::optional<std::string> const& softening_curve)
60{
61 if (softening_curve)
62 {
63 if (*softening_curve == "Linear")
64 {
66 }
67 if (*softening_curve == "Exponential")
68 {
70 }
72 "softening_curve must be 'Linear' or 'Exponential' but '{}' "
73 "was given",
74 softening_curve->c_str());
75 }
76 return SofteningCurve::Linear; // default
77};
78
88
89template <int DisplacementDim>
91 std::string const& energy_split_model)
92{
93 if (energy_split_model == "Isotropic")
94 {
96 }
97 if (energy_split_model == "VolumetricDeviatoric")
98 {
100 }
101 if (energy_split_model == "Spectral")
102 {
104 }
105 if (energy_split_model == "EffectiveStress")
106 {
108 }
109 if (energy_split_model == "OrthoVolDev")
110 {
112 }
113 if (energy_split_model == "OrthoMasonry")
114 {
116 }
117 OGS_FATAL(
118 "energy_split_model must be 'Isotropic', 'VolumetricDeviatoric', "
119 "'EffectiveStress', 'OrthoVolDev' or 'OrthoMasonry' but '{}' was given",
120 energy_split_model.c_str());
121};
122
124{
125public:
126 virtual ~DegradationDerivative() = default;
127 virtual double degradation(double const d_ip,
128 double const k,
129 double const ls) = 0; /* degradation_df0 */
130 virtual double degradationDf1(double const d_ip, double const k,
131 double const ls) = 0;
132 virtual double degradationDf2(double const d_ip, double const k,
133 double const ls) = 0;
134};
135
137{
138public:
139 double degradation(double const d_ip,
140 double const k,
141 double const /* ls */) override
142 {
143 return d_ip * d_ip * (1. - k) + k;
144 };
145 double degradationDf1(double const d_ip, double const k,
146 double const /* ls */) override
147 {
148 return 2. * (1. - k) * d_ip;
149 };
150 double degradationDf2(double const /* d_ip */, double const k,
151 double const /* ls */) override
152 {
153 return 2. * (1. - k);
154 };
155};
156
158{
159private:
160 double const lch;
162
163public:
164 COHESIVE_DegradationDerivative(double const Parameter_lch,
165 SofteningCurve Parameter_softening_curve)
166 : lch(Parameter_lch), softening_curve(Parameter_softening_curve){};
167 double degradation(double const d_ip,
168 double const k,
169 double const ls) override
170 {
171 double const m1 = 4.0 * lch / acos(-1.) / ls;
172 switch (softening_curve)
173 {
175 {
176 double const m2 = std::pow(2., 5. / 3.) - 3.;
177 double const n = 2.5;
178 return std::pow(d_ip, n) /
179 (std::pow(d_ip, n) +
180 m1 * (1. - d_ip) * (1. + m2 * (1. - d_ip))) *
181 (1.0 - k) +
182 k;
183 }
184 default:
185 {
186 double const m2 = -0.5;
187 double const n = 2.;
188 return std::pow(d_ip, n) /
189 (std::pow(d_ip, n) +
190 m1 * (1. - d_ip) * (1. + m2 * (1. - d_ip))) *
191 (1. - k) +
192 k;
193 }
194 }
195 };
196 double degradationDf1(double const d_ip, double const k,
197 double const ls) override
198 {
199 double const m1 = 4.0 * lch / acos(-1.) / ls;
200 switch (softening_curve)
201 {
203 {
204 double const m2 = std::pow(2., 5. / 3.) - 3.;
205 double const n = 2.5;
206 double const a1 = std::pow(d_ip, n) +
207 m1 * (1. - d_ip) * (1. + m2 * (1. - d_ip));
208 double const a2 = n * std::pow(d_ip, n - 1.) -
209 2. * m1 * m2 * (1. - d_ip) - m1;
210 return (1. - k) *
211 (n * std::pow(d_ip, n - 1.) * a1 -
212 std::pow(d_ip, n) * a2) /
213 (a1 * a1);
214 }
215 default:
216 {
217 double const m2 = -0.5;
218 double const n = 2.;
219 double const a1 = std::pow(d_ip, n) +
220 m1 * (1. - d_ip) * (1. + m2 * (1. - d_ip));
221 double const a2 = n * std::pow(d_ip, n - 1.) -
222 2. * m1 * m2 * (1. - d_ip) - m1;
223 return (1. - k) *
224 (n * std::pow(d_ip, n - 1.) * a1 -
225 std::pow(d_ip, n) * a2) /
226 (a1 * a1);
227 }
228 }
229 };
230 double degradationDf2(double const d_ip, double const k,
231 double const ls) override
232 {
233 double const m1 = 4.0 * lch / acos(-1.) / ls;
234 switch (softening_curve)
235 {
237 {
238 double const m2 = std::pow(2., 5. / 3.) - 3.;
239 double const n = 2.5;
240 double a1 = std::pow(d_ip, n) +
241 m1 * (1. - d_ip) * (1. + m2 * (1. - d_ip));
242 double a2 = n * std::pow(d_ip, n - 1.) -
243 2. * m1 * m2 * (1. - d_ip) - m1;
244 return (1. - k) *
245 (2. * a2 * a2 * std::pow(d_ip, n) -
246 a1 * std::pow(d_ip, n) *
247 (2. * m1 * m2 +
248 n * std::pow(d_ip, n - 2.) * (n - 1.)) -
249 2. * a1 * a2 * n * std::pow(d_ip, n - 1.) +
250 a1 * a1 * n * std::pow(d_ip, n - 2.) * (n - 1.)) /
251 (std::pow(a1, 3));
252 }
253 default:
254 {
255 double const m2 = -0.5;
256 double const n = 2.;
257 double const a1 = std::pow(d_ip, n) +
258 m1 * (1. - d_ip) * (1. + m2 * (1. - d_ip));
259 double const a2 = n * std::pow(d_ip, n - 1.) -
260 2. * m1 * m2 * (1. - d_ip) - m1;
261 return (1. - k) *
262 (2. * a2 * a2 * std::pow(d_ip, n) -
263 a1 * std::pow(d_ip, n) *
264 (2. * m1 * m2 +
265 n * std::pow(d_ip, n - 2.) * (n - 1.)) -
266 2. * a1 * a2 * n * std::pow(d_ip, n - 1.) +
267 a1 * a1 * n * std::pow(d_ip, n - 2.) * (n - 1.)) /
268 (std::pow(a1, 3));
269 }
270 }
271 };
272};
273
274template <int DisplacementDim>
275std::unique_ptr<DegradationDerivative> creatDegradationDerivative(
276 PhaseFieldModel const& phasefield_model, double const lch,
277 SofteningCurve const& softening_curve)
278{
279 switch (phasefield_model)
280 {
282 return std::make_unique<COHESIVE_DegradationDerivative>(
283 lch, softening_curve);
284 default:
285 return std::make_unique<AT_DegradationDerivative>();
286 }
287};
288
289template <typename T_DNDX, typename T_N, typename T_W, typename T_D,
290 typename T_LOCAL_JAC, typename T_LOCAL_RHS>
291void calculateCrackLocalJacobianAndResidual(T_DNDX& dNdx, T_N& N, T_W& w,
292 T_D& d, T_LOCAL_JAC& local_Jac,
293 T_LOCAL_RHS local_rhs,
294 double const gc, double const ls,
295 PhaseFieldModel& phasefield_model)
296{
297 switch (phasefield_model)
298 {
300 {
301 auto const local_Jac_AT1 =
302 (gc * 0.75 * dNdx.transpose() * dNdx * ls * w).eval();
303 local_Jac.noalias() += local_Jac_AT1;
304
305 local_rhs.noalias() -=
306 gc * (-0.375 * N.transpose() / ls) * w + local_Jac_AT1 * d;
307 break;
308 }
310 {
311 auto const local_Jac_AT2 =
312 (gc * (N.transpose() * N / ls + dNdx.transpose() * dNdx * ls) *
313 w)
314 .eval();
315 local_Jac.noalias() += local_Jac_AT2;
316
317 local_rhs.noalias() -=
318 local_Jac_AT2 * d - gc * (N.transpose() / ls) * w;
319 break;
320 }
322 {
323 auto const local_Jac_COHESIVE =
324 (2.0 / std::numbers::pi * gc *
325 (-N.transpose() * N / ls + dNdx.transpose() * dNdx * ls) * w)
326 .eval();
327
328 local_Jac.noalias() += local_Jac_COHESIVE;
329
330 local_rhs.noalias() -= local_Jac_COHESIVE * d;
331 break;
332 }
333 default:
334 {
335 OGS_FATAL("Invalid phase field model specified.");
336 }
337 }
338};
339
340template <typename T_VECTOR, typename T_MATRIX, int DisplacementDim>
342 T_VECTOR& sigma, T_VECTOR& sigma_tensile, T_VECTOR& sigma_compressive,
343 T_VECTOR& eps_tensile, T_MATRIX& D, T_MATRIX& C_tensile,
344 T_MATRIX& C_compressive, double& strain_energy_tensile,
345 double& elastic_energy, double const degradation, T_VECTOR const& eps,
346 EnergySplitModel const& energy_split_model, double const t,
349{
350 auto linear_elastic_mp =
352 DisplacementDim> const&>(solid_material)
353 .getMaterialProperties();
354
355 auto const lambda = linear_elastic_mp.lambda(t, x);
356 auto const bulk_modulus = linear_elastic_mp.bulk_modulus(t, x);
357 auto const mu = linear_elastic_mp.mu(t, x);
358 switch (energy_split_model)
359 {
361 {
362 std::tie(sigma, sigma_tensile, D, strain_energy_tensile,
363 elastic_energy, C_tensile, C_compressive) =
366 degradation, bulk_modulus, mu, eps);
367 break;
368 }
370 {
371 std::tie(sigma, sigma_tensile, D, strain_energy_tensile,
372 elastic_energy, C_tensile, C_compressive) =
374 DisplacementDim>(degradation, bulk_modulus, mu, eps);
375 break;
376 }
378 {
379 std::tie(sigma, sigma_tensile, D, strain_energy_tensile,
380 elastic_energy, C_tensile, C_compressive) =
383 degradation, lambda, mu, eps);
384 break;
385 }
387 {
388 std::tie(sigma, sigma_tensile, D, strain_energy_tensile,
389 elastic_energy, C_tensile, C_compressive) =
390 MaterialLib::Solids::Phasefield::
391 calculateIsotropicDegradedStressWithRankineEnergy<
392 DisplacementDim>(degradation, bulk_modulus, mu, eps);
393 break;
394 }
396 {
397 double temperature = 0.;
400 DisplacementDim> const&>(solid_material)
401 .getElasticTensor(t, x, temperature);
402
403 std::tie(eps_tensile, sigma, sigma_tensile, sigma_compressive, D,
404 strain_energy_tensile, elastic_energy, C_tensile,
405 C_compressive) = MaterialLib::Solids::Phasefield::
407 degradation, eps, C_ortho);
408 break;
409 }
411 {
412 double temperature = 0.;
415 DisplacementDim> const&>(solid_material)
416 .getElasticTensor(t, x, temperature);
417
418 std::tie(eps_tensile, sigma, sigma_tensile, D,
419 strain_energy_tensile, elastic_energy, C_tensile,
420 C_compressive) = MaterialLib::Solids::Phasefield::
422 degradation, eps, C_ortho);
423 break;
424 }
425 default:
426 OGS_FATAL("Invalid energy split model specified.");
427 }
428};
429} // namespace Phasefield
430} // namespace Solids
431} // namespace MaterialLib
#define OGS_FATAL(...)
Definition Error.h:19
double degradation(double const d_ip, double const k, double const) override
double degradationDf1(double const d_ip, double const k, double const) override
double degradationDf2(double const, double const k, double const) override
double degradationDf1(double const d_ip, double const k, double const ls) override
double degradationDf2(double const d_ip, double const k, double const ls) override
double degradation(double const d_ip, double const k, double const ls) override
COHESIVE_DegradationDerivative(double const Parameter_lch, SofteningCurve Parameter_softening_curve)
virtual double degradationDf2(double const d_ip, double const k, double const ls)=0
virtual double degradation(double const d_ip, double const k, double const ls)=0
virtual double degradationDf1(double const d_ip, double const k, double const ls)=0
std::tuple< MathLib::KelvinVector::KelvinVectorType< DisplacementDim >, MathLib::KelvinVector::KelvinVectorType< DisplacementDim >, MathLib::KelvinVector::KelvinVectorType< DisplacementDim >, MathLib::KelvinVector::KelvinVectorType< DisplacementDim >, MathLib::KelvinVector::KelvinMatrixType< DisplacementDim >, double, double, MathLib::KelvinVector::KelvinMatrixType< DisplacementDim >, MathLib::KelvinVector::KelvinMatrixType< DisplacementDim > > calculateOrthoVolDevDegradedStress(double const degradation, MathLib::KelvinVector::KelvinVectorType< DisplacementDim > const &eps, MathLib::KelvinVector::KelvinMatrixType< DisplacementDim > const &C_ortho)
void calculateStress(T_VECTOR &sigma, T_VECTOR &sigma_tensile, T_VECTOR &sigma_compressive, T_VECTOR &eps_tensile, T_MATRIX &D, T_MATRIX &C_tensile, T_MATRIX &C_compressive, double &strain_energy_tensile, double &elastic_energy, double const degradation, T_VECTOR const &eps, EnergySplitModel const &energy_split_model, double const t, ParameterLib::SpatialPosition const &x, MaterialLib::Solids::MechanicsBase< DisplacementDim > const &solid_material)
std::tuple< MathLib::KelvinVector::KelvinVectorType< DisplacementDim >, MathLib::KelvinVector::KelvinVectorType< DisplacementDim >, MathLib::KelvinVector::KelvinMatrixType< DisplacementDim >, double, double, MathLib::KelvinVector::KelvinMatrixType< DisplacementDim >, MathLib::KelvinVector::KelvinMatrixType< DisplacementDim > > calculateIsotropicDegradedStress(double const degradation, double const bulk_modulus, double const mu, MathLib::KelvinVector::KelvinVectorType< DisplacementDim > const &eps)
std::tuple< MathLib::KelvinVector::KelvinVectorType< DisplacementDim >, MathLib::KelvinVector::KelvinVectorType< DisplacementDim >, MathLib::KelvinVector::KelvinMatrixType< DisplacementDim >, double, double, MathLib::KelvinVector::KelvinMatrixType< DisplacementDim >, MathLib::KelvinVector::KelvinMatrixType< DisplacementDim > > calculateSpectralDegradedStress(double const degradation, double const lambda, double const mu, MathLib::KelvinVector::KelvinVectorType< DisplacementDim > const &eps)
void calculateCrackLocalJacobianAndResidual(T_DNDX &dNdx, T_N &N, T_W &w, T_D &d, T_LOCAL_JAC &local_Jac, T_LOCAL_RHS local_rhs, double const gc, double const ls, PhaseFieldModel &phasefield_model)
std::unique_ptr< DegradationDerivative > creatDegradationDerivative(PhaseFieldModel const &phasefield_model, double const lch, SofteningCurve const &softening_curve)
std::tuple< MathLib::KelvinVector::KelvinVectorType< DisplacementDim >, MathLib::KelvinVector::KelvinVectorType< DisplacementDim >, MathLib::KelvinVector::KelvinMatrixType< DisplacementDim >, double, double, MathLib::KelvinVector::KelvinMatrixType< DisplacementDim >, MathLib::KelvinVector::KelvinMatrixType< DisplacementDim > > calculateVolDevDegradedStress(double const degradation, double const bulk_modulus, double const mu, MathLib::KelvinVector::KelvinVectorType< DisplacementDim > const &eps)
PhaseFieldModel convertStringToPhaseFieldModel(std::string const &phasefield_model)
SofteningCurve convertStringToSofteningCurve(std::optional< std::string > const &softening_curve)
EnergySplitModel convertStringToEnergySplitModel(std::string const &energy_split_model)
std::tuple< MathLib::KelvinVector::KelvinVectorType< DisplacementDim >, MathLib::KelvinVector::KelvinVectorType< DisplacementDim >, MathLib::KelvinVector::KelvinVectorType< DisplacementDim >, MathLib::KelvinVector::KelvinMatrixType< DisplacementDim >, double, double, MathLib::KelvinVector::KelvinMatrixType< DisplacementDim >, MathLib::KelvinVector::KelvinMatrixType< DisplacementDim > > calculateOrthoMasonryDegradedStress(double const degradation, MathLib::KelvinVector::KelvinVectorType< DisplacementDim > const &eps, MathLib::KelvinVector::KelvinMatrixType< DisplacementDim > const &C_ortho)
Eigen::Matrix< double, kelvin_vector_dimensions(DisplacementDim), kelvin_vector_dimensions(DisplacementDim), Eigen::RowMajor > KelvinMatrixType