OGS
Ehlers.cpp
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#include "Ehlers.h"
5
6#include <Eigen/LU>
7#include <boost/math/special_functions/pow.hpp>
8
9#include "BaseLib/cpp23.h"
13
14namespace MPL = MaterialPropertyLib;
15
38
39namespace MaterialLib
40{
41namespace Solids
42{
43namespace Ehlers
44{
45template <int DisplacementDim>
47{
48 return std::sqrt(2.0 / 3.0 * Invariants::FrobeniusNorm(eps_p.D.eval()));
49}
50
57template <int DisplacementDim>
60
61template <int DisplacementDim>
87
90{
91 OnePlusGamma_pTheta(double const gamma_p, double const theta,
92 double const m_p)
93 : value{1 + gamma_p * theta},
94 pow_m_p{std::pow(value, m_p)},
96 {
97 }
98
99 double const value;
100 double const pow_m_p;
101 double const pow_m_p1;
102};
103
104template <int DisplacementDim>
107 double const sqrtPhi, double const alpha_p, double const beta_p,
108 double const delta_p, double const epsilon_p)
109{
110 return 3 *
111 (alpha_p * s.I_1 +
112 4 * boost::math::pow<2>(delta_p) * boost::math::pow<3>(s.I_1)) /
113 (2 * sqrtPhi) +
114 3 * beta_p + 6 * epsilon_p * s.I_1;
115}
116
117template <int DisplacementDim>
120 OnePlusGamma_pTheta const& one_gt, double const sqrtPhi,
121 typename SolidEhlers<DisplacementDim>::KelvinVector const& dtheta_dsigma,
122 double const gamma_p, double const m_p)
123{
124 return (one_gt.pow_m_p *
125 (s.D + s.J_2 * m_p * gamma_p * dtheta_dsigma / one_gt.value)) /
126 (2 * sqrtPhi);
127}
128
129template <int DisplacementDim>
132 double const k)
133{
134 double const I_1_squared = boost::math::pow<2>(s.I_1);
135 assert(s.J_2 != 0);
136
137 return std::sqrt(s.J_2 * std::pow(1 + mp.gamma * s.J_3 /
138 (s.J_2 * std::sqrt(s.J_2)),
139 mp.m) +
140 mp.alpha / 2. * I_1_squared +
141 boost::math::pow<2>(mp.delta) *
142 boost::math::pow<2>(I_1_squared)) +
143 mp.beta * s.I_1 + mp.epsilon * I_1_squared - k;
144}
145
146template <int DisplacementDim>
147std::pair<MathLib::KelvinVector::KelvinVectorType<DisplacementDim>,
151{
152 constexpr int KelvinVectorSize =
155 using KelvinVector =
157 using KelvinMatrix =
159
160 if (theta == 0)
161 {
162 return {KelvinVector::Zero(), KelvinMatrix::Zero()};
163 }
164
165 auto const& P_dev = Invariants::deviatoric_projection;
166
167 // inverse of deviatoric stress tensor
168 if (Invariants::determinant(s.D) == 0)
169 {
170 OGS_FATAL("Determinant is zero. Matrix is non-invertable.");
171 }
172 // inverse of sigma_D
173 KelvinVector const sigma_D_inverse = MathLib::KelvinVector::inverse(s.D);
174 KelvinVector const sigma_D_inverse_D = P_dev * sigma_D_inverse;
175
176 KelvinVector const dtheta_dsigma =
177 theta * sigma_D_inverse_D - 3. / 2. * theta / s.J_2 * s.D;
178 KelvinMatrix const d2theta_dsigma2 =
179 theta * P_dev * sOdotS<DisplacementDim>(sigma_D_inverse) * P_dev +
180 sigma_D_inverse_D * dtheta_dsigma.transpose() -
181 3. / 2. * theta / s.J_2 * P_dev -
182 3. / 2. * dtheta_dsigma / s.J_2 * s.D.transpose() +
183 3. / 2. * theta / boost::math::pow<2>(s.J_2) * s.D * s.D.transpose();
184
185 return {dtheta_dsigma, d2theta_dsigma2};
186}
187
188template <int DisplacementDim>
192 double const eps_V,
196 double const eps_p_V,
197 double const eps_p_V_dot,
198 double const eps_p_eff_dot,
199 double const lambda,
200 double const k,
201 MaterialProperties const& mp)
202{
203 static int const KelvinVectorSize =
206 using KelvinVector =
208
209 auto const& identity2 = Invariants::identity2;
210
211 double const theta = s.J_3 / (s.J_2 * std::sqrt(s.J_2));
212
214 // calculate stress residual
215 residual.template segment<KelvinVectorSize>(0).noalias() =
216 s.value / mp.G - 2 * (eps_D - eps_p_D) -
217 mp.K / mp.G * (eps_V - eps_p_V) * identity2;
218
219 auto const [dtheta_dsigma, d2theta_dsigma2] =
220 thetaSigmaDerivatives(theta, s);
221
222 OnePlusGamma_pTheta const one_gt{mp.gamma_p, theta, mp.m_p};
223 double const sqrtPhi = std::sqrt(
224 s.J_2 * one_gt.pow_m_p + mp.alpha_p / 2. * boost::math::pow<2>(s.I_1) +
225 boost::math::pow<2>(mp.delta_p) * boost::math::pow<4>(s.I_1));
226 KelvinVector const flow_D = plasticFlowDeviatoricPart(
227 s, one_gt, sqrtPhi, dtheta_dsigma, mp.gamma_p, mp.m_p);
228 KelvinVector const lambda_flow_D = lambda * flow_D;
229
230 residual.template segment<KelvinVectorSize>(KelvinVectorSize).noalias() =
231 eps_p_D_dot - lambda_flow_D;
232
233 // plastic volume strain
234 {
235 double const flow_V = plasticFlowVolumetricPart<DisplacementDim>(
236 s, sqrtPhi, mp.alpha_p, mp.beta_p, mp.delta_p, mp.epsilon_p);
237 residual(2 * KelvinVectorSize, 0) = eps_p_V_dot - lambda * flow_V;
238 }
239
240 // evolution of plastic equivalent strain
241 residual(2 * KelvinVectorSize + 1) =
242 eps_p_eff_dot -
243 std::sqrt(2. / 3. * lambda_flow_D.transpose() * lambda_flow_D);
244
245 // yield function (for plastic multiplier)
246 residual(2 * KelvinVectorSize + 2) = yieldFunction(mp, s, k) / mp.G;
247 return residual;
248}
249
250template <int DisplacementDim>
252 double const dt,
254 double const lambda,
255 MaterialProperties const& mp)
256{
257 static int const KelvinVectorSize =
260 using KelvinVector =
262 using KelvinMatrix =
264
265 auto const& P_dev = Invariants::deviatoric_projection;
266 auto const& identity2 = Invariants::identity2;
267
268 double const theta = s.J_3 / (s.J_2 * std::sqrt(s.J_2));
269 OnePlusGamma_pTheta const one_gt{mp.gamma_p, theta, mp.m_p};
270
271 auto const [dtheta_dsigma, d2theta_dsigma2] =
272 thetaSigmaDerivatives(theta, s);
273
274 // deviatoric flow
275 double const sqrtPhi = std::sqrt(
276 s.J_2 * one_gt.pow_m_p + mp.alpha_p / 2. * boost::math::pow<2>(s.I_1) +
277 boost::math::pow<2>(mp.delta_p) * boost::math::pow<4>(s.I_1));
278 KelvinVector const flow_D = plasticFlowDeviatoricPart(
279 s, one_gt, sqrtPhi, dtheta_dsigma, mp.gamma_p, mp.m_p);
280 KelvinVector const lambda_flow_D = lambda * flow_D;
281
284
285 // G_11
286 jacobian.template block<KelvinVectorSize, KelvinVectorSize>(0, 0)
287 .noalias() = KelvinMatrix::Identity();
288
289 // G_12
290 jacobian
291 .template block<KelvinVectorSize, KelvinVectorSize>(0, KelvinVectorSize)
292 .noalias() = 2 * KelvinMatrix::Identity();
293
294 // G_13
295 jacobian.template block<KelvinVectorSize, 1>(0, 2 * KelvinVectorSize)
296 .noalias() = mp.K / mp.G * identity2;
297
298 // G_14 and G_15 are zero
299
300 // G_21 -- derivative of deviatoric flow
301
302 double const gm_p = mp.gamma_p * mp.m_p;
303 // intermediate variable for derivative of deviatoric flow
304 KelvinVector const M0 = s.J_2 / one_gt.value * dtheta_dsigma;
305 // derivative of Phi w.r.t. sigma
306 KelvinVector const dPhi_dsigma =
307 one_gt.pow_m_p * (s.D + gm_p * M0) +
308 (mp.alpha_p * s.I_1 +
309 4 * boost::math::pow<2>(mp.delta_p) * boost::math::pow<3>(s.I_1)) *
310 identity2;
311
312 // intermediate variable for derivative of deviatoric flow
313 KelvinMatrix const M1 =
314 one_gt.pow_m_p *
315 (s.D * dPhi_dsigma.transpose() + gm_p * M0 * dPhi_dsigma.transpose());
316 // intermediate variable for derivative of deviatoric flow
317 KelvinMatrix const M2 =
318 one_gt.pow_m_p * (P_dev + s.D * gm_p * M0.transpose());
319
320 // intermediate variable for derivative of deviatoric flow
321 KelvinMatrix const M3 =
322 gm_p * one_gt.pow_m_p1 *
323 ((s.D + (gm_p - mp.gamma_p) * M0) * dtheta_dsigma.transpose() +
324 s.J_2 * d2theta_dsigma2);
325
326 // derivative of flow_D w.r.t. sigma
327 KelvinMatrix const dflow_D_dsigma =
328 (-M1 / (4 * boost::math::pow<3>(sqrtPhi)) + (M2 + M3) / (2 * sqrtPhi)) *
329 mp.G;
330 jacobian
331 .template block<KelvinVectorSize, KelvinVectorSize>(KelvinVectorSize, 0)
332 .noalias() = -lambda * dflow_D_dsigma;
333
334 // G_22
335 jacobian
336 .template block<KelvinVectorSize, KelvinVectorSize>(KelvinVectorSize,
337 KelvinVectorSize)
338 .noalias() = KelvinMatrix::Identity() / dt;
339
340 // G_23 and G_24 are zero
341
342 // G_25
343 jacobian
344 .template block<KelvinVectorSize, 1>(KelvinVectorSize,
345 2 * KelvinVectorSize + 2)
346 .noalias() = -flow_D;
347
348 // G_31
349 {
350 // derivative of flow_V w.r.t. sigma
351 KelvinVector const dflow_V_dsigma =
352 3 * mp.G *
353 (-(mp.alpha_p * s.I_1 + 4 * boost::math::pow<2>(mp.delta_p) *
354 boost::math::pow<3>(s.I_1)) /
355 (4 * boost::math::pow<3>(sqrtPhi)) * dPhi_dsigma +
356 (mp.alpha_p * identity2 +
357 12 * boost::math::pow<2>(mp.delta_p * s.I_1) * identity2) /
358 (2 * sqrtPhi) +
359 2 * mp.epsilon_p * identity2);
360
361 jacobian.template block<1, KelvinVectorSize>(2 * KelvinVectorSize, 0)
362 .noalias() = -lambda * dflow_V_dsigma.transpose();
363 }
364
365 // G_32 is zero
366
367 // G_33
368 jacobian(2 * KelvinVectorSize, 2 * KelvinVectorSize) = 1. / dt;
369
370 // G_34 is zero
371
372 // G_35
373 {
374 double const flow_V = plasticFlowVolumetricPart<DisplacementDim>(
375 s, sqrtPhi, mp.alpha_p, mp.beta_p, mp.delta_p, mp.epsilon_p);
376 jacobian(2 * KelvinVectorSize, 2 * KelvinVectorSize + 2) = -flow_V;
377 }
378
379 // increment of effectiv plastic strain
380 double const eff_flow =
381 std::sqrt(2. / 3. * lambda_flow_D.transpose() * lambda_flow_D);
382
383 if (eff_flow > 0)
384 {
385 // intermediate variable for derivative of plastic jacobian
386 KelvinVector const eff_flow23_lambda_flow_D =
387 -2 / 3. / eff_flow * lambda_flow_D;
388 // G_41
389 jacobian
390 .template block<1, KelvinVectorSize>(2 * KelvinVectorSize + 1, 0)
391 .noalias() = lambda * dflow_D_dsigma * eff_flow23_lambda_flow_D;
392 // G_45
393 jacobian(2 * KelvinVectorSize + 1, 2 * KelvinVectorSize + 2) =
394 eff_flow23_lambda_flow_D.transpose() * flow_D;
395 }
396
397 // G_42 and G_43 are zero
398
399 // G_44
400 jacobian(2 * KelvinVectorSize + 1, 2 * KelvinVectorSize + 1) = 1. / dt;
401
402 // G_51
403 {
404 double const one_gt_pow_m = std::pow(one_gt.value, mp.m);
405 double const gm = mp.gamma * mp.m;
406 // derivative of yield function w.r.t. sigma
407 KelvinVector const dF_dsigma =
408 mp.G *
409 (one_gt_pow_m * (s.D + gm * M0) +
410 (mp.alpha * s.I_1 + 4 * boost::math::pow<2>(mp.delta) *
411 boost::math::pow<3>(s.I_1)) *
412 identity2) /
413 (2. * sqrtPhi) +
414 mp.G * (mp.beta + 2 * mp.epsilon_p * s.I_1) * identity2;
415
416 jacobian
417 .template block<1, KelvinVectorSize>(2 * KelvinVectorSize + 2, 0)
418 .noalias() = dF_dsigma.transpose() / mp.G;
419 }
420
421 // G_54
422 jacobian(2 * KelvinVectorSize + 2, 2 * KelvinVectorSize + 1) =
423 -mp.kappa * mp.hardening_coefficient / mp.G;
424
425 // G_52, G_53, G_55 are zero
426 return jacobian;
427}
428
431template <int DisplacementDim>
433 double const K, double const G)
434{
435 static int const KelvinVectorSize =
438
439 auto const& P_dev = Invariants::deviatoric_projection;
440 auto const& P_sph = Invariants::spherical_projection;
441 auto const& I =
443
444 return -2. * I * P_dev - 3. * K / G * I * P_sph;
445}
446
447inline double calculateIsotropicHardening(double const kappa,
448 double const hardening_coefficient,
449 double const eps_p_eff)
450{
451 return kappa * (1. + eps_p_eff * hardening_coefficient);
452}
453
454template <int DisplacementDim>
456 double const G, double const K,
457 typename SolidEhlers<DisplacementDim>::KelvinVector const& sigma_prev,
459 typename SolidEhlers<DisplacementDim>::KelvinVector const& eps_prev,
460 double const eps_V)
461{
462 static int const KelvinVectorSize =
465 auto const& P_dev = Invariants::deviatoric_projection;
466
467 // dimensionless initial hydrostatic pressure
468 double const pressure_prev = Invariants::trace(sigma_prev) / (-3. * G);
469 // initial strain invariant
470 double const e_prev = Invariants::trace(eps_prev);
471 // dimensioness hydrostatic stress increment
472 double const pressure = pressure_prev - K / G * (eps_V - e_prev);
473 // dimensionless deviatoric initial stress
474 typename SolidEhlers<DisplacementDim>::KelvinVector const sigma_D_prev =
475 P_dev * sigma_prev / G;
476 // dimensionless deviatoric stress
477 typename SolidEhlers<DisplacementDim>::KelvinVector const sigma_D =
478 sigma_D_prev + 2 * P_dev * (eps - eps_prev);
479 return sigma_D - pressure * Invariants::identity2;
480}
481
484template <typename ResidualVector, typename KelvinVector>
485std::tuple<KelvinVector, PlasticStrain<KelvinVector>, double>
486splitSolutionVector(ResidualVector const& solution)
487{
488 static auto const size = KelvinVector::SizeAtCompileTime;
489 return std::forward_as_tuple(
490 solution.template segment<size>(size * 0),
491 PlasticStrain<KelvinVector>{solution.template segment<size>(size * 1),
492 solution[size * 2], solution[size * 2 + 1]},
493 solution[size * 2 + 2]);
494}
495
496template <int DisplacementDim>
498 NumLib::NewtonRaphsonSolverParameters nonlinear_solver_parameters,
499 MaterialPropertiesParameters material_properties,
500 std::unique_ptr<DamagePropertiesParameters>&& damage_properties,
501 TangentType tangent_type)
502 : _nonlinear_solver_parameters(std::move(nonlinear_solver_parameters)),
503 _mp(std::move(material_properties)),
504 _damage_properties(std::move(damage_properties)),
505 _tangent_type(tangent_type)
506{
507}
508
509template <int DisplacementDim>
511 double const /*t*/,
513 double const /*dt*/,
514 KelvinVector const& eps,
515 KelvinVector const& sigma,
517 material_state_variables) const
518{
519 assert(dynamic_cast<StateVariables<DisplacementDim> const*>(
520 &material_state_variables) != nullptr);
521
522 auto const& eps_p = static_cast<StateVariables<DisplacementDim> const&>(
523 material_state_variables)
524 .eps_p;
526 auto const& identity2 = Invariants::identity2;
527 return (eps - eps_p.D - eps_p.V / 3 * identity2).dot(sigma) / 2;
528}
529
530template <int DisplacementDim>
531std::optional<std::tuple<typename SolidEhlers<DisplacementDim>::KelvinVector,
532 std::unique_ptr<typename MechanicsBase<
533 DisplacementDim>::MaterialStateVariables>,
536 MaterialPropertyLib::VariableArray const& variable_array_prev,
537 MaterialPropertyLib::VariableArray const& variable_array, double const t,
538 ParameterLib::SpatialPosition const& x, double const dt,
540 material_state_variables) const
541{
542 auto const& eps_m = std::get<MPL::SymmetricTensor<DisplacementDim>>(
543 variable_array.mechanical_strain);
544 auto const& eps_m_prev = std::get<MPL::SymmetricTensor<DisplacementDim>>(
545 variable_array_prev.mechanical_strain);
546 auto const& sigma_prev = std::get<MPL::SymmetricTensor<DisplacementDim>>(
547 variable_array_prev.stress);
548
549 assert(dynamic_cast<StateVariables<DisplacementDim> const*>(
550 &material_state_variables) != nullptr);
551
553 static_cast<StateVariables<DisplacementDim> const&>(
554 material_state_variables);
555 state.setInitialConditions();
556
558
559 // volumetric strain
560 double const eps_V = Invariants::trace(eps_m);
561
562 auto const& P_dev = Invariants::deviatoric_projection;
563 // deviatoric strain
564 KelvinVector const eps_D = P_dev * eps_m;
565
566 // do the evaluation once per function call.
567 MaterialProperties const mp(t, x, _mp);
568
570 mp.G, mp.K, sigma_prev, eps_m, eps_m_prev, eps_V);
571
572 KelvinMatrix tangentStiffness;
573
575 // Quit early if sigma is zero (nothing to do), or dt is zero, or if we are
576 // still in elastic zone.
577 // dt can be zero if we are in the initialization phase and the tangent
578 // stiffness will no be necessary. Anyway the newton loop below would not
579 // work because of division by zero.
580 if ((sigma.squaredNorm() == 0. || dt == 0. ||
582 mp, s,
584 state.eps_p.eff)) < 0.))
585 {
587 mp.K - 2. / 3 * mp.G, mp.G);
588 }
589 else
590 {
591 // Linear solver for the newton loop is required after the loop with the
592 // same matrix. This saves one decomposition.
593 Eigen::FullPivLU<Eigen::Matrix<double, JacobianResidualSize,
594 JacobianResidualSize, Eigen::RowMajor>>
595 linear_solver;
596
597 {
598 using KelvinVector =
600 using ResidualVectorType =
601 Eigen::Matrix<double, JacobianResidualSize, 1>;
602 using JacobianMatrix =
603 Eigen::Matrix<double, JacobianResidualSize,
604 JacobianResidualSize, Eigen::RowMajor>;
605
606 JacobianMatrix jacobian;
607
608 // Agglomerated solution vector construction. It is later split
609 // into individual parts by splitSolutionVector().
610 ResidualVectorType solution;
611 solution << sigma, state.eps_p.D, state.eps_p.V, state.eps_p.eff, 0;
612
613 auto const update_residual = [&](ResidualVectorType& residual)
614 {
615 auto const& eps_p_D =
616 solution.template segment<KelvinVectorSize>(
618 KelvinVector const eps_p_D_dot =
619 (eps_p_D - state.eps_p_prev.D) / dt;
620
621 double const& eps_p_V = solution[KelvinVectorSize * 2];
622 double const eps_p_V_dot = (eps_p_V - state.eps_p_prev.V) / dt;
623
624 double const& eps_p_eff = solution[KelvinVectorSize * 2 + 1];
625 double const eps_p_eff_dot =
626 (eps_p_eff - state.eps_p_prev.eff) / dt;
627
628 double const k_hardening = calculateIsotropicHardening(
630 solution[KelvinVectorSize * 2 + 1]);
632 eps_D, eps_V, s,
633 solution.template segment<KelvinVectorSize>(
635 eps_p_D_dot, solution[KelvinVectorSize * 2], eps_p_V_dot,
636 eps_p_eff_dot, solution[KelvinVectorSize * 2 + 2],
637 k_hardening, mp);
638 };
639
640 auto const update_jacobian = [&](JacobianMatrix& jacobian)
641 {
643 dt, s, solution[KelvinVectorSize * 2 + 2], mp);
644 };
645
646 auto const update_solution =
647 [&](ResidualVectorType const& increment)
648 {
649 solution += increment;
651 mp.G * solution.template segment<KelvinVectorSize>(0)};
652 };
653
654 auto newton_solver = NumLib::NewtonRaphson(
655 linear_solver, update_jacobian, update_residual,
656 update_solution, _nonlinear_solver_parameters);
657
658 auto const success_iterations = newton_solver.solve(jacobian);
659
660 if (!success_iterations)
661 {
662 return {};
663 }
664
665 // If the Newton loop didn't run, the linear solver will not be
666 // initialized.
667 // This happens usually for the first iteration of the first
668 // timestep.
669 if (*success_iterations == 0)
670 {
671 linear_solver.compute(jacobian);
672 }
673
674 std::tie(sigma, state.eps_p, std::ignore) =
676 }
677
678 // Calculate residual derivative w.r.t. strain
679 Eigen::Matrix<double, JacobianResidualSize, KelvinVectorSize,
680 Eigen::RowMajor>
681 dresidual_deps =
682 Eigen::Matrix<double, JacobianResidualSize, KelvinVectorSize,
683 Eigen::RowMajor>::Zero();
684 dresidual_deps.template block<KelvinVectorSize, KelvinVectorSize>(0, 0)
685 .noalias() = calculateDResidualDEps<DisplacementDim>(mp.K, mp.G);
686
688 {
689 tangentStiffness =
691 }
694 {
695 tangentStiffness =
696 mp.G *
697 linear_solver.solve(-dresidual_deps)
698 .template block<KelvinVectorSize, KelvinVectorSize>(0, 0);
700 {
701 tangentStiffness *= 1 - state.damage.value();
702 }
703 }
704 else
705 {
706 OGS_FATAL(
707 "Unimplemented tangent type behaviour for the tangent type "
708 "'{}'.",
710 }
711 }
712
713 KelvinVector sigma_final = mp.G * sigma;
714
715 return {std::make_tuple(
716 sigma_final,
717 std::unique_ptr<
720 static_cast<StateVariables<DisplacementDim> const&>(state)}},
721 tangentStiffness)};
722}
723
724template <int DisplacementDim>
725std::vector<typename MechanicsBase<DisplacementDim>::InternalVariable>
727{
728 return {{"damage.kappa_d", 1,
729 [](typename MechanicsBase<
730 DisplacementDim>::MaterialStateVariables const& state,
731 std::vector<double>& cache) -> std::vector<double> const&
732 {
733 assert(dynamic_cast<StateVariables<DisplacementDim> const*>(
734 &state) != nullptr);
735 auto const& ehlers_state =
736 static_cast<StateVariables<DisplacementDim> const&>(state);
737
738 cache.resize(1);
739 cache.front() = ehlers_state.damage.kappa_d();
740 return cache;
741 },
743 state) -> std::span<double>
744 {
745 assert(dynamic_cast<StateVariables<DisplacementDim> const*>(
746 &state) != nullptr);
747 auto& ehlers_state =
748 static_cast<StateVariables<DisplacementDim>&>(state);
749
750 return {&ehlers_state.damage.kappa_d(), 1};
751 }},
752 {"damage.value", 1,
753 [](typename MechanicsBase<
754 DisplacementDim>::MaterialStateVariables const& state,
755 std::vector<double>& cache) -> std::vector<double> const&
756 {
757 assert(dynamic_cast<StateVariables<DisplacementDim> const*>(
758 &state) != nullptr);
759 auto const& ehlers_state =
760 static_cast<StateVariables<DisplacementDim> const&>(state);
761
762 cache.resize(1);
763 cache.front() = ehlers_state.damage.value();
764 return cache;
765 },
767 state) -> std::span<double>
768 {
769 assert(dynamic_cast<StateVariables<DisplacementDim> const*>(
770 &state) != nullptr);
771 auto& ehlers_state =
772 static_cast<StateVariables<DisplacementDim>&>(state);
773
774 return {&ehlers_state.damage.value(), 1};
775 }},
776 {"eps_p.D", KelvinVector::RowsAtCompileTime,
777 [](typename MechanicsBase<
778 DisplacementDim>::MaterialStateVariables const& state,
779 std::vector<double>& cache) -> std::vector<double> const&
780 {
781 assert(dynamic_cast<StateVariables<DisplacementDim> const*>(
782 &state) != nullptr);
783 auto const& ehlers_state =
784 static_cast<StateVariables<DisplacementDim> const&>(state);
785
786 cache.resize(KelvinVector::RowsAtCompileTime);
788 cache, KelvinVector::RowsAtCompileTime) =
790 ehlers_state.eps_p.D);
791
792 return cache;
793 },
795 state) -> std::span<double>
796 {
797 assert(dynamic_cast<StateVariables<DisplacementDim> const*>(
798 &state) != nullptr);
799 auto& ehlers_state =
800 static_cast<StateVariables<DisplacementDim>&>(state);
801
802 return {
803 ehlers_state.eps_p.D.data(),
804 static_cast<std::size_t>(KelvinVector::RowsAtCompileTime)};
805 }},
806 {"eps_p.V", 1,
807 [](typename MechanicsBase<
808 DisplacementDim>::MaterialStateVariables const& state,
809 std::vector<double>& cache) -> std::vector<double> const&
810 {
811 assert(dynamic_cast<StateVariables<DisplacementDim> const*>(
812 &state) != nullptr);
813 auto const& ehlers_state =
814 static_cast<StateVariables<DisplacementDim> const&>(state);
815
816 cache.resize(1);
817 cache.front() = ehlers_state.eps_p.V;
818 return cache;
819 },
821 state) -> std::span<double>
822 {
823 assert(dynamic_cast<StateVariables<DisplacementDim> const*>(
824 &state) != nullptr);
825 auto& ehlers_state =
826 static_cast<StateVariables<DisplacementDim>&>(state);
827
828 return {&ehlers_state.eps_p.V, 1};
829 }},
830 {"eps_p.eff", 1,
831 [](typename MechanicsBase<
832 DisplacementDim>::MaterialStateVariables const& state,
833 std::vector<double>& cache) -> std::vector<double> const&
834 {
835 assert(dynamic_cast<StateVariables<DisplacementDim> const*>(
836 &state) != nullptr);
837 auto const& ehlers_state =
838 static_cast<StateVariables<DisplacementDim> const&>(state);
839
840 cache.resize(1);
841 cache.front() = ehlers_state.eps_p.eff;
842 return cache;
843 },
845 state) -> std::span<double>
846 {
847 assert(dynamic_cast<StateVariables<DisplacementDim> const*>(
848 &state) != nullptr);
849 auto& ehlers_state =
850 static_cast<StateVariables<DisplacementDim>&>(state);
851
852 return {&ehlers_state.eps_p.eff, 1};
853 }}};
854}
855
856template class SolidEhlers<2>;
857template class SolidEhlers<3>;
858
859template struct StateVariables<2>;
860template struct StateVariables<3>;
861
862template <>
865{
867
868 result(0, 0) = v(0) * v(0);
869 result(0, 1) = result(1, 0) = v(3) * v(3) / 2.;
870 result(0, 2) = result(2, 0) = v(5) * v(5) / 2.;
871 result(0, 3) = result(3, 0) = v(0) * v(3);
872 result(0, 4) = result(4, 0) = v(3) * v(5) / std::sqrt(2.);
873 result(0, 5) = result(5, 0) = v(0) * v(5);
874
875 result(1, 1) = v(1) * v(1);
876 result(1, 2) = result(2, 1) = v(4) * v(4) / 2.;
877 result(1, 3) = result(3, 1) = v(3) * v(1);
878 result(1, 4) = result(4, 1) = v(1) * v(4);
879 result(1, 5) = result(5, 1) = v(3) * v(4) / std::sqrt(2.);
880
881 result(2, 2) = v(2) * v(2);
882 result(2, 3) = result(3, 2) = v(5) * v(4) / std::sqrt(2.);
883 result(2, 4) = result(4, 2) = v(4) * v(2);
884 result(2, 5) = result(5, 2) = v(5) * v(2);
885
886 result(3, 3) = v(0) * v(1) + v(3) * v(3) / 2.;
887 result(3, 4) = result(4, 3) =
888 v(3) * v(4) / 2. + v(5) * v(1) / std::sqrt(2.);
889 result(3, 5) = result(5, 3) =
890 v(0) * v(4) / std::sqrt(2.) + v(3) * v(5) / 2.;
891
892 result(4, 4) = v(1) * v(2) + v(4) * v(4) / 2.;
893 result(4, 5) = result(5, 4) =
894 v(3) * v(2) / std::sqrt(2.) + v(5) * v(4) / 2.;
895
896 result(5, 5) = v(0) * v(2) + v(5) * v(5) / 2.;
897 return result;
898}
899
900template <>
903{
905
906 result(0, 0) = v(0) * v(0);
907 result(0, 1) = result(1, 0) = v(3) * v(3) / 2.;
908 result(0, 2) = result(2, 0) = 0;
909 result(0, 3) = result(3, 0) = v(0) * v(3);
910
911 result(1, 1) = v(1) * v(1);
912 result(1, 2) = result(2, 1) = 0;
913 result(1, 3) = result(3, 1) = v(3) * v(1);
914
915 result(2, 2) = v(2) * v(2);
916 result(2, 3) = result(3, 2) = 0;
917
918 result(3, 3) = v(0) * v(1) + v(3) * v(3) / 2.;
919
920 return result;
921}
922
923} // namespace Ehlers
924} // namespace Solids
925} // namespace MaterialLib
#define OGS_FATAL(...)
Definition Error.h:19
std::vector< typename MechanicsBase< DisplacementDim >::InternalVariable > getInternalVariables() const override
Definition Ehlers.cpp:726
MaterialPropertiesParameters _mp
Definition Ehlers.h:348
NumLib::NewtonRaphsonSolverParameters const _nonlinear_solver_parameters
Definition Ehlers.h:346
Eigen::Matrix< double, JacobianResidualSize, JacobianResidualSize, Eigen::RowMajor > JacobianMatrix
Definition Ehlers.h:279
std::optional< std::tuple< KelvinVector, std::unique_ptr< typename MechanicsBase< DisplacementDim >::MaterialStateVariables >, KelvinMatrix > > integrateStress(MaterialPropertyLib::VariableArray const &variable_array_prev, MaterialPropertyLib::VariableArray const &variable_array, double const t, ParameterLib::SpatialPosition const &x, double const dt, typename MechanicsBase< DisplacementDim >::MaterialStateVariables const &material_state_variables) const override
Definition Ehlers.cpp:535
MathLib::KelvinVector::KelvinVectorType< DisplacementDim > KelvinVector
Definition Ehlers.h:291
std::unique_ptr< DamagePropertiesParameters > _damage_properties
Definition Ehlers.h:349
MathLib::KelvinVector::KelvinMatrixType< DisplacementDim > KelvinMatrix
Definition Ehlers.h:293
Eigen::Matrix< double, JacobianResidualSize, 1 > ResidualVectorType
Definition Ehlers.h:278
SolidEhlers(NumLib::NewtonRaphsonSolverParameters nonlinear_solver_parameters, MaterialPropertiesParameters material_properties, std::unique_ptr< DamagePropertiesParameters > &&damage_properties, TangentType tangent_type)
Definition Ehlers.cpp:497
double computeFreeEnergyDensity(double const, ParameterLib::SpatialPosition const &, double const, KelvinVector const &eps, KelvinVector const &sigma, typename MechanicsBase< DisplacementDim >::MaterialStateVariables const &material_state_variables) const override
Definition Ehlers.cpp:510
constexpr auto to_underlying(E e) noexcept
Converts an enumeration to its underlying type.
Definition cpp23.h:22
MathLib::KelvinVector::KelvinMatrixType< 3 > sOdotS< 3 >(MathLib::KelvinVector::KelvinVectorType< 3 > const &v)
Definition Ehlers.cpp:863
MathLib::KelvinVector::KelvinMatrixType< DisplacementDim > calculateDResidualDEps(double const K, double const G)
Definition Ehlers.cpp:432
SolidEhlers< DisplacementDim >::JacobianMatrix calculatePlasticJacobian(double const dt, PhysicalStressWithInvariants< DisplacementDim > const &s, double const lambda, MaterialProperties const &mp)
Definition Ehlers.cpp:251
SolidEhlers< DisplacementDim >::KelvinVector plasticFlowDeviatoricPart(PhysicalStressWithInvariants< DisplacementDim > const &s, OnePlusGamma_pTheta const &one_gt, double const sqrtPhi, typename SolidEhlers< DisplacementDim >::KelvinVector const &dtheta_dsigma, double const gamma_p, double const m_p)
Definition Ehlers.cpp:118
MathLib::KelvinVector::KelvinMatrixType< DisplacementDim > sOdotS(MathLib::KelvinVector::KelvinVectorType< DisplacementDim > const &v)
double plasticFlowVolumetricPart(PhysicalStressWithInvariants< DisplacementDim > const &s, double const sqrtPhi, double const alpha_p, double const beta_p, double const delta_p, double const epsilon_p)
Definition Ehlers.cpp:105
double calculateIsotropicHardening(double const kappa, double const hardening_coefficient, double const eps_p_eff)
Definition Ehlers.cpp:447
MathLib::KelvinVector::KelvinMatrixType< 2 > sOdotS< 2 >(MathLib::KelvinVector::KelvinVectorType< 2 > const &v)
Definition Ehlers.cpp:901
std::tuple< KelvinVector, PlasticStrain< KelvinVector >, double > splitSolutionVector(ResidualVector const &solution)
Definition Ehlers.cpp:486
std::pair< MathLib::KelvinVector::KelvinVectorType< DisplacementDim >, MathLib::KelvinVector::KelvinMatrixType< DisplacementDim > > thetaSigmaDerivatives(double theta, PhysicalStressWithInvariants< DisplacementDim > const &s)
Definition Ehlers.cpp:149
double yieldFunction(MaterialProperties const &mp, PhysicalStressWithInvariants< DisplacementDim > const &s, double const k)
Definition Ehlers.cpp:130
SolidEhlers< DisplacementDim >::KelvinVector predict_sigma(double const G, double const K, typename SolidEhlers< DisplacementDim >::KelvinVector const &sigma_prev, typename SolidEhlers< DisplacementDim >::KelvinVector const &eps, typename SolidEhlers< DisplacementDim >::KelvinVector const &eps_prev, double const eps_V)
Definition Ehlers.cpp:455
SolidEhlers< DisplacementDim >::ResidualVectorType calculatePlasticResidual(MathLib::KelvinVector::KelvinVectorType< DisplacementDim > const &eps_D, double const eps_V, PhysicalStressWithInvariants< DisplacementDim > const &s, MathLib::KelvinVector::KelvinVectorType< DisplacementDim > const &eps_p_D, MathLib::KelvinVector::KelvinVectorType< DisplacementDim > const &eps_p_D_dot, double const eps_p_V, double const eps_p_V_dot, double const eps_p_eff_dot, double const lambda, double const k, MaterialProperties const &mp)
Definition Ehlers.cpp:190
MathLib::KelvinVector::KelvinMatrixType< DisplacementDim > elasticTangentStiffness(double const first_lame_parameter, double const shear_modulus)
Eigen::Matrix< double, 4, 1 > kelvinVectorToSymmetricTensor(Eigen::Matrix< double, 4, 1, Eigen::ColMajor, 4, 1 > const &v)
constexpr int kelvin_vector_dimensions(int const displacement_dim)
Kelvin vector dimensions for given displacement dimension.
Eigen::Matrix< double, kelvin_vector_dimensions(DisplacementDim), 1, Eigen::ColMajor > KelvinVectorType
Eigen::Matrix< double, kelvin_vector_dimensions(DisplacementDim), kelvin_vector_dimensions(DisplacementDim), Eigen::RowMajor > KelvinMatrixType
Eigen::Matrix< double, 4, 1, Eigen::ColMajor, 4, 1 > inverse(Eigen::Matrix< double, 4, 1, Eigen::ColMajor, 4, 1 > const &v)
Eigen::Map< const Vector > toVector(std::vector< double > const &data, Eigen::VectorXd::Index size)
Creates an Eigen mapped vector from the given data vector.
Holds powers of 1 + gamma_p*theta to base 0, m_p, and m_p-1.
Definition Ehlers.cpp:90
OnePlusGamma_pTheta(double const gamma_p, double const theta, double const m_p)
Definition Ehlers.cpp:91
PhysicalStressWithInvariants(KelvinVector const &stress)
Definition Ehlers.cpp:70
MathLib::KelvinVector::Invariants< KelvinVectorSize > Invariants
Definition Ehlers.cpp:66
MathLib::KelvinVector::KelvinVectorType< DisplacementDim > KelvinVector
Definition Ehlers.cpp:67
Damage damage
damage part of the state.
Definition Ehlers.h:241
PlasticStrain< KelvinVector > eps_p
plastic part of the state.
Definition Ehlers.h:240
double getEquivalentPlasticStrain() const override
Definition Ehlers.cpp:46
PlasticStrain< KelvinVector > eps_p_prev
plastic part of the state.
Definition Ehlers.h:244
static double FrobeniusNorm(Eigen::Matrix< double, KelvinVectorSize, 1 > const &deviatoric_v)
Get the norm of the deviatoric stress.