https://mooseframework.inl.gov
Loading...
Searching...
No Matches
CappedMohrCoulombStressUpdate.C
Go to the documentation of this file.
1//* This file is part of the MOOSE framework
2//* https://mooseframework.inl.gov
3//*
4//* All rights reserved, see COPYRIGHT for full restrictions
5//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6//*
7//* Licensed under LGPL 2.1, please see LICENSE for details
8//* https://www.gnu.org/licenses/lgpl-2.1.html
9
11#include "libmesh/utility.h"
13
15
18{
20 params.addRequiredParam<UserObjectName>(
21 "tensile_strength",
22 "A SolidMechanicsHardening UserObject that defines hardening of the "
23 "tensile strength. In physical situations this is positive (and always "
24 "must be greater than negative compressive-strength.");
25 params.addRequiredParam<UserObjectName>(
26 "compressive_strength",
27 "A SolidMechanicsHardening UserObject that defines hardening of the "
28 "compressive strength. In physical situations this is positive.");
29 params.addRequiredParam<UserObjectName>(
30 "cohesion", "A SolidMechanicsHardening UserObject that defines hardening of the cohesion");
31 params.addRequiredParam<UserObjectName>("friction_angle",
32 "A SolidMechanicsHardening UserObject "
33 "that defines hardening of the "
34 "friction angle (in radians)");
35 params.addRequiredParam<UserObjectName>(
36 "dilation_angle",
37 "A SolidMechanicsHardening UserObject that defines hardening of the "
38 "dilation angle (in radians). Unless you are quite confident, this should "
39 "be set positive and not greater than the friction angle.");
40 params.addParam<bool>("perfect_guess",
41 true,
42 "Provide a guess to the Newton-Raphson procedure "
43 "that is the result from perfect plasticity. With "
44 "severe hardening/softening this may be "
45 "suboptimal.");
46 params.addClassDescription("Nonassociative, smoothed, Mohr-Coulomb plasticity capped with "
47 "tensile (Rankine) and compressive caps, with hardening/softening");
48 return params;
49}
50
52 : MultiParameterPlasticityStressUpdate(parameters, 3, 12, 2),
53 _tensile_strength(getUserObject<SolidMechanicsHardeningModel>("tensile_strength")),
54 _compressive_strength(getUserObject<SolidMechanicsHardeningModel>("compressive_strength")),
55 _cohesion(getUserObject<SolidMechanicsHardeningModel>("cohesion")),
56 _phi(getUserObject<SolidMechanicsHardeningModel>("friction_angle")),
57 _psi(getUserObject<SolidMechanicsHardeningModel>("dilation_angle")),
58 _perfect_guess(getParam<bool>("perfect_guess")),
59 _poissons_ratio(0.0),
60 _shifter(_f_tol),
61 _eigvecs(RankTwoTensor()),
62 _dsp_trial_scratch(3),
63 _eigvals_scratch(_tensor_dimensionality),
64 _dga_shear_scratch(3),
65 _dshear_correction_scratch(3)
66{
67 if (_psi.value(0.0) <= 0.0 || _psi.value(0.0) > _phi.value(0.0))
68 mooseWarning("Usually the Mohr-Coulomb dilation angle is positive and not greater than the "
69 "friction angle");
70}
71
72void
74 std::vector<Real> & stress_params) const
75{
76 // stress_params[0] = smallest eigenvalue, stress_params[2] = largest eigenvalue
77 stress.symmetricEigenvalues(stress_params);
78}
79
80void
82 std::vector<RankTwoTensor> & dsp) const
83{
84 mooseAssert(dsp.size() == 3,
85 "CappedMohrCoulombStressUpdate: dsp incorrectly sized in dstressparam_dstress");
86 mooseAssert(
88 "_eigvals_scratch incorrectly sized in CappedMohrCoulombStressUpdate:dstressparam_dstress");
90}
91
92void
94 std::vector<RankFourTensor> & d2sp) const
95{
96 /*
97 * This function is not used but is included here in case a derived class needs it.
98 * The reason it is unused is because consistentTangentOperatorV is optimised
99 */
100 mooseAssert(d2sp.size() == 3,
101 "CappedMohrCoulombStressUpdate: d2sp incorrectly sized in d2stressparam_dstress");
102 stress.d2symmetricEigenvalues(d2sp);
103}
104
105void
106CappedMohrCoulombStressUpdate::preReturnMapV(const std::vector<Real> & /*trial_stress_params*/,
107 const RankTwoTensor & stress_trial,
108 const std::vector<Real> & /*intnl_old*/,
109 const std::vector<Real> & /*yf*/,
110 const RankFourTensor & Eijkl)
111{
112 mooseAssert(_eigvals_scratch.size() == _tensor_dimensionality,
113 "_eigvals_scratch incorrectly sized in CappedMohrCoulombStressUpdate:preReturnMapV");
116}
117
118void
120 const std::vector<Real> & stress_params,
121 Real /*gaE*/,
122 const std::vector<Real> & /*intnl*/,
123 const yieldAndFlow & /*smoothed_q*/,
124 const RankFourTensor & /*Eijkl*/,
125 RankTwoTensor & stress) const
126{
127 // form the diagonal stress
128 stress = RankTwoTensor(stress_params[0], stress_params[1], stress_params[2], 0.0, 0.0, 0.0);
129 // rotate to the original frame
130 stress = _eigvecs * stress * (_eigvecs.transpose());
131}
132
133void
134CappedMohrCoulombStressUpdate::yieldFunctionValuesV(const std::vector<Real> & stress_params,
135 const std::vector<Real> & intnl,
136 std::vector<Real> & yf) const
137{
138 // intnl[0] = shear, intnl[1] = tensile
139 const Real ts = _tensile_strength.value(intnl[1]);
140 const Real cs = _compressive_strength.value(intnl[1]);
141 const Real sinphi = std::sin(_phi.value(intnl[0]));
142 const Real cohcos = _cohesion.value(intnl[0]) * std::cos(_phi.value(intnl[0]));
143 const Real smax = stress_params[2]; // largest eigenvalue
144 const Real smid = stress_params[1];
145 const Real smin = stress_params[0]; // smallest eigenvalue
146 yf[0] = smax - ts;
147 yf[1] = smid - ts;
148 yf[2] = smin - ts;
149 yf[3] = -smin - cs;
150 yf[4] = -smid - cs;
151 yf[5] = -smax - cs;
152 yf[6] = 0.5 * (smax - smin) + 0.5 * (smax + smin) * sinphi - cohcos;
153 yf[7] = 0.5 * (smid - smin) + 0.5 * (smid + smin) * sinphi - cohcos;
154 yf[8] = 0.5 * (smax - smid) + 0.5 * (smax + smid) * sinphi - cohcos;
155 yf[9] = 0.5 * (smid - smax) + 0.5 * (smid + smax) * sinphi - cohcos;
156 yf[10] = 0.5 * (smin - smid) + 0.5 * (smin + smid) * sinphi - cohcos;
157 yf[11] = 0.5 * (smin - smax) + 0.5 * (smin + smax) * sinphi - cohcos;
158}
159
160void
161CappedMohrCoulombStressUpdate::computeAllQV(const std::vector<Real> & stress_params,
162 const std::vector<Real> & intnl,
163 std::vector<yieldAndFlow> & all_q) const
164{
165 const Real ts = _tensile_strength.value(intnl[1]);
166 const Real dts = _tensile_strength.derivative(intnl[1]);
167 const Real cs = _compressive_strength.value(intnl[1]);
168 const Real dcs = _compressive_strength.derivative(intnl[1]);
169 const Real sinphi = std::sin(_phi.value(intnl[0]));
170 const Real dsinphi = std::cos(_phi.value(intnl[0])) * _phi.derivative(intnl[0]);
171 const Real sinpsi = std::sin(_psi.value(intnl[0]));
172 const Real dsinpsi = std::cos(_psi.value(intnl[0])) * _psi.derivative(intnl[0]);
173 const Real cohcos = _cohesion.value(intnl[0]) * std::cos(_phi.value(intnl[0]));
174 const Real dcohcos =
175 _cohesion.derivative(intnl[0]) * std::cos(_phi.value(intnl[0])) -
176 _cohesion.value(intnl[0]) * std::sin(_phi.value(intnl[0])) * _phi.derivative(intnl[0]);
177 const Real smax = stress_params[2]; // largest eigenvalue
178 const Real smid = stress_params[1];
179 const Real smin = stress_params[0]; // smallest eigenvalue
180
181 // yield functions. See comment in yieldFunctionValuesV
182 all_q[0].f = smax - ts;
183 all_q[1].f = smid - ts;
184 all_q[2].f = smin - ts;
185 all_q[3].f = -smin - cs;
186 all_q[4].f = -smid - cs;
187 all_q[5].f = -smax - cs;
188 all_q[6].f = 0.5 * (smax - smin) + 0.5 * (smax + smin) * sinphi - cohcos;
189 all_q[7].f = 0.5 * (smid - smin) + 0.5 * (smid + smin) * sinphi - cohcos;
190 all_q[8].f = 0.5 * (smax - smid) + 0.5 * (smax + smid) * sinphi - cohcos;
191 all_q[9].f = 0.5 * (smid - smax) + 0.5 * (smid + smax) * sinphi - cohcos;
192 all_q[10].f = 0.5 * (smin - smid) + 0.5 * (smin + smid) * sinphi - cohcos;
193 all_q[11].f = 0.5 * (smin - smax) + 0.5 * (smin + smax) * sinphi - cohcos;
194
195 // d(yield function)/d(stress_params)
196 for (unsigned yf = 0; yf < _num_yf; ++yf)
197 for (unsigned a = 0; a < _num_sp; ++a)
198 all_q[yf].df[a] = 0.0;
199 all_q[0].df[2] = 1.0;
200 all_q[1].df[1] = 1.0;
201 all_q[2].df[0] = 1.0;
202 all_q[3].df[0] = -1.0;
203 all_q[4].df[1] = -1.0;
204 all_q[5].df[2] = -1.0;
205 all_q[6].df[2] = 0.5 * (1.0 + sinphi);
206 all_q[6].df[0] = 0.5 * (-1.0 + sinphi);
207 all_q[7].df[1] = 0.5 * (1.0 + sinphi);
208 all_q[7].df[0] = 0.5 * (-1.0 + sinphi);
209 all_q[8].df[2] = 0.5 * (1.0 + sinphi);
210 all_q[8].df[1] = 0.5 * (-1.0 + sinphi);
211 all_q[9].df[1] = 0.5 * (1.0 + sinphi);
212 all_q[9].df[2] = 0.5 * (-1.0 + sinphi);
213 all_q[10].df[0] = 0.5 * (1.0 + sinphi);
214 all_q[10].df[1] = 0.5 * (-1.0 + sinphi);
215 all_q[11].df[0] = 0.5 * (1.0 + sinphi);
216 all_q[11].df[2] = 0.5 * (-1.0 + sinphi);
217
218 // d(yield function)/d(intnl)
219 for (unsigned i = 0; i < 6; ++i)
220 all_q[i].df_di[0] = 0.0;
221 all_q[0].df_di[1] = all_q[1].df_di[1] = all_q[2].df_di[1] = -dts;
222 all_q[3].df_di[1] = all_q[4].df_di[1] = all_q[5].df_di[1] = -dcs;
223 for (unsigned i = 6; i < 12; ++i)
224 all_q[i].df_di[1] = 0.0;
225 all_q[6].df_di[0] = 0.5 * (smax + smin) * dsinphi - dcohcos;
226 all_q[7].df_di[0] = 0.5 * (smid + smin) * dsinphi - dcohcos;
227 all_q[8].df_di[0] = 0.5 * (smax + smid) * dsinphi - dcohcos;
228 all_q[9].df_di[0] = 0.5 * (smid + smax) * dsinphi - dcohcos;
229 all_q[10].df_di[0] = 0.5 * (smin + smid) * dsinphi - dcohcos;
230 all_q[11].df_di[0] = 0.5 * (smin + smax) * dsinphi - dcohcos;
231
232 // the flow potential is just the yield function with phi->psi
233 // d(flow potential)/d(stress_params)
234 for (unsigned yf = 0; yf < 6; ++yf)
235 for (unsigned a = 0; a < _num_sp; ++a)
236 all_q[yf].dg[a] = all_q[yf].df[a];
237 all_q[6].dg[2] = all_q[7].dg[1] = all_q[8].dg[2] = all_q[9].dg[1] = all_q[10].dg[0] =
238 all_q[11].dg[0] = 0.5 * (1.0 + sinpsi);
239 all_q[6].dg[0] = all_q[7].dg[0] = all_q[8].dg[1] = all_q[9].dg[2] = all_q[10].dg[1] =
240 all_q[11].dg[2] = 0.5 * (-1.0 + sinpsi);
241
242 // d(flow potential)/d(stress_params)/d(intnl)
243 for (unsigned yf = 0; yf < _num_yf; ++yf)
244 for (unsigned a = 0; a < _num_sp; ++a)
245 for (unsigned i = 0; i < _num_intnl; ++i)
246 all_q[yf].d2g_di[a][i] = 0.0;
247 all_q[6].d2g_di[2][0] = all_q[7].d2g_di[1][0] = all_q[8].d2g_di[2][0] = all_q[9].d2g_di[1][0] =
248 all_q[10].d2g_di[0][0] = all_q[11].d2g_di[0][0] = 0.5 * dsinpsi;
249 all_q[6].d2g_di[0][0] = all_q[7].d2g_di[0][0] = all_q[8].d2g_di[1][0] = all_q[9].d2g_di[2][0] =
250 all_q[10].d2g_di[1][0] = all_q[11].d2g_di[2][0] = 0.5 * dsinpsi;
251
252 // d(flow potential)/d(stress_params)/d(stress_params)
253 for (unsigned yf = 0; yf < _num_yf; ++yf)
254 for (unsigned a = 0; a < _num_sp; ++a)
255 for (unsigned b = 0; b < _num_sp; ++b)
256 all_q[yf].d2g[a][b] = 0.0;
257}
258
259void
261{
262 // Eijkl is required to be isotropic, so we can use the
263 // frame where stress is diagonal
264 for (unsigned a = 0; a < _num_sp; ++a)
265 for (unsigned b = 0; b < _num_sp; ++b)
266 _Eij[a][b] = Eijkl(a, a, b, b);
267 _En = _Eij[2][2];
268 const Real denom = _Eij[0][0] * (_Eij[0][0] + _Eij[0][1]) - 2 * Utility::pow<2>(_Eij[0][1]);
269 for (unsigned a = 0; a < _num_sp; ++a)
270 {
271 _Cij[a][a] = (_Eij[0][0] + _Eij[0][1]) / denom;
272 for (unsigned b = 0; b < a; ++b)
273 _Cij[a][b] = _Cij[b][a] = -_Eij[0][1] / denom;
274 }
275}
276
277void
278CappedMohrCoulombStressUpdate::initializeVarsV(const std::vector<Real> & trial_stress_params,
279 const std::vector<Real> & intnl_old,
280 std::vector<Real> & stress_params,
281 Real & gaE,
282 std::vector<Real> & intnl) const
283{
284 if (!_perfect_guess)
285 {
286 for (unsigned i = 0; i < _num_sp; ++i)
287 stress_params[i] = trial_stress_params[i];
288 gaE = 0.0;
289 }
290 else
291 {
292 const Real ts = _tensile_strength.value(intnl_old[1]);
293 const Real cs = _compressive_strength.value(intnl_old[1]);
294 const Real sinphi = std::sin(_phi.value(intnl_old[0]));
295 const Real cohcos = _cohesion.value(intnl_old[0]) * std::cos(_phi.value(intnl_old[0]));
296
297 const Real trial_tensile_yf = trial_stress_params[2] - ts;
298 const Real trial_compressive_yf = -trial_stress_params[0] - cs;
299 const Real trial_mc_yf = 0.5 * (trial_stress_params[2] - trial_stress_params[0]) +
300 0.5 * (trial_stress_params[2] + trial_stress_params[0]) * sinphi -
301 cohcos;
302
328 bool found_solution = false;
329
330 if (trial_tensile_yf <= _f_tol && trial_compressive_yf <= _f_tol && trial_mc_yf <= _f_tol)
331 {
332 // this is needed because although we know the smoothed yield function is
333 // positive, the individual yield functions may not be
334 for (unsigned i = 0; i < _num_sp; ++i)
335 stress_params[i] = trial_stress_params[i];
336 gaE = 0.0;
337 found_solution = true;
338 }
339
340 const bool tensile_possible = (ts < cohcos / sinphi); // tensile chops MC tip
341 const bool mc_tip_possible = (cohcos / sinphi < ts); // MC tip pokes through tensile
342 const bool mc_impossible = (0.5 * (ts + cs) + 0.5 * (ts - cs) * sinphi - cohcos <
343 _f_tol); // MC outside tensile and compressive
344
345 const Real sinpsi = std::sin(_psi.value(intnl_old[0]));
346 const Real halfplus = 0.5 + 0.5 * sinpsi;
347 const Real neghalfplus = -0.5 + 0.5 * sinpsi;
348
349 if (!found_solution && tensile_possible && trial_tensile_yf > _f_tol &&
350 (trial_compressive_yf <= _f_tol || (trial_compressive_yf > _f_tol && mc_impossible)))
351 {
352 // try pure tensile failure, return to the plane
353 // This involves solving yf[0] = 0 and the three flow-direction equations
354 // Don't try this if there is compressive failure, since returning to
355 // the tensile yield surface will only make compressive failure worse
356 const Real ga = (trial_stress_params[2] - ts) / _Eij[2][2];
357 stress_params[2] = ts; // largest eigenvalue
358 stress_params[1] = trial_stress_params[1] - ga * _Eij[1][2];
359 stress_params[0] = trial_stress_params[0] - ga * _Eij[0][2];
360
361 // if we have to return to the edge, or tip, do that
362 Real dist_mod = 1.0;
363 const Real to_subtract1 = stress_params[1] - (ts - 0.5 * _shifter);
364 if (to_subtract1 > 0.0)
365 {
366 dist_mod += Utility::pow<2>(to_subtract1 / (trial_stress_params[2] - ts));
367 stress_params[1] -= to_subtract1;
368 }
369 const Real to_subtract0 = stress_params[0] - (ts - _shifter);
370 if (to_subtract0 > 0.0)
371 {
372 dist_mod += Utility::pow<2>(to_subtract0 / (trial_stress_params[2] - ts));
373 stress_params[0] -= to_subtract0;
374 }
375 if (mc_impossible) // might have to shift up to the compressive yield surface
376 {
377 const Real to_add0 = -stress_params[0] - cs;
378 if (to_add0 > 0.0)
379 {
380 dist_mod += Utility::pow<2>(to_add0 / (trial_stress_params[2] - ts));
381 stress_params[0] += to_add0;
382 }
383 const Real to_add1 = -cs + 0.5 * _shifter - stress_params[1];
384 if (to_add1 > 0.0)
385 {
386 dist_mod += Utility::pow<2>(to_add1 / (trial_stress_params[2] - ts));
387 stress_params[1] += to_add1;
388 }
389 }
390
391 const Real new_compressive_yf = -stress_params[0] - cs;
392 const Real new_mc_yf = 0.5 * (stress_params[2] - stress_params[0]) +
393 0.5 * (stress_params[2] + stress_params[0]) * sinphi - cohcos;
394 if (new_mc_yf <= _f_tol && new_compressive_yf <= _f_tol)
395 {
396 gaE = std::sqrt(dist_mod) * (trial_stress_params[2] - stress_params[2]);
397 found_solution = true;
398 }
399 }
400 if (!found_solution && trial_compressive_yf > _f_tol &&
401 (trial_tensile_yf <= _f_tol || (trial_tensile_yf > _f_tol && mc_impossible)))
402 {
403 // try pure compressive failure
404 // Don't try this if there is tensile failure, since returning to
405 // the compressive yield surface will only make tensile failure worse
406 const Real ga = (trial_stress_params[0] + cs) / _Eij[0][0]; // this is negative
407 stress_params[0] = -cs;
408 stress_params[1] = trial_stress_params[1] - ga * _Eij[1][0];
409 stress_params[2] = trial_stress_params[2] - ga * _Eij[2][0];
410
411 // if we have to return to the edge, or tip, do that
412 Real dist_mod = 1.0;
413 const Real to_add1 = -cs + 0.5 * _shifter - stress_params[1];
414 if (to_add1 > 0.0)
415 {
416 dist_mod += Utility::pow<2>(to_add1 / (trial_stress_params[0] + cs));
417 stress_params[1] += to_add1;
418 }
419 const Real to_add2 = -cs + _shifter - stress_params[2];
420 if (to_add2 > 0.0)
421 {
422 dist_mod += Utility::pow<2>(to_add2 / (trial_stress_params[0] + cs));
423 stress_params[2] += to_add2;
424 }
425 if (mc_impossible) // might have to shift down to the tensile yield surface
426 {
427 const Real to_subtract2 = stress_params[2] - ts;
428 if (to_subtract2 > 0.0)
429 {
430 dist_mod += Utility::pow<2>(to_subtract2 / (trial_stress_params[0] + cs));
431 stress_params[2] -= to_subtract2;
432 }
433 const Real to_subtract1 = stress_params[1] - (ts - 0.5 * _shifter);
434 if (to_subtract1 > 0.0)
435 {
436 dist_mod += Utility::pow<2>(to_subtract1 / (trial_stress_params[0] + cs));
437 stress_params[1] -= to_subtract1;
438 }
439 }
440
441 const Real new_tensile_yf = stress_params[2] - ts;
442 const Real new_mc_yf = 0.5 * (stress_params[2] - stress_params[0]) +
443 0.5 * (stress_params[2] + stress_params[0]) * sinphi - cohcos;
444 if (new_mc_yf <= _f_tol && new_tensile_yf <= _f_tol)
445 {
446 gaE = std::sqrt(dist_mod) * (-trial_stress_params[0] + stress_params[0]);
447 found_solution = true;
448 }
449 }
450 if (!found_solution && !mc_impossible && trial_mc_yf > _f_tol)
451 {
452 // try pure shear failure, return to the plane
453 // This involves solving yf[6]=0 and the three flow-direction equations
454 const Real ga = ((trial_stress_params[2] - trial_stress_params[0]) +
455 (trial_stress_params[2] + trial_stress_params[0]) * sinphi - 2.0 * cohcos) /
456 (_Eij[2][2] - _Eij[0][2] + (_Eij[2][2] + _Eij[0][2]) * sinpsi * sinphi);
457 stress_params[2] =
458 trial_stress_params[2] - ga * (_Eij[2][2] * halfplus + _Eij[2][0] * neghalfplus);
459 stress_params[1] = trial_stress_params[1] - ga * _Eij[1][0] * sinpsi;
460 stress_params[0] =
461 trial_stress_params[0] - ga * (_Eij[0][0] * neghalfplus + _Eij[0][2] * halfplus);
462 const Real f7 = 0.5 * (stress_params[1] - stress_params[0]) +
463 0.5 * (stress_params[1] + stress_params[0]) * sinphi - cohcos;
464 const Real f8 = 0.5 * (stress_params[2] - stress_params[1]) +
465 0.5 * (stress_params[2] + stress_params[1]) * sinphi - cohcos;
466 const Real new_tensile_yf = stress_params[2] - ts;
467 const Real new_compressive_yf = -stress_params[0] - cs;
468
469 if (f7 <= _f_tol && f8 <= _f_tol && new_tensile_yf <= _f_tol && new_compressive_yf <= _f_tol)
470 {
471 gaE = ((trial_stress_params[2] - trial_stress_params[0]) -
472 (stress_params[2] - stress_params[0])) /
473 (_Eij[2][2] - _Eij[0][2]) * _Eij[2][2];
474 found_solution = true;
475 }
476 }
477 if (!found_solution && !mc_impossible && trial_mc_yf > _f_tol)
478 {
479 // Try return to the max=mid MC line.
480 // To return to the max=mid line, we need to solve f6 = 0 = f7 and
481 // the three flow-direction equations. In the flow-direction equations
482 // there are two plasticity multipliers, which i call ga6 and ga7,
483 // corresponding to the amounts of strain normal to the f6 and f7
484 // directions, respectively.
485 // So:
486 // Smax = Smax^trial - ga6 Emax,a dg6/dSa - ga7 Emax,a dg7/dSa
487 // = Smax^trial - ga6 cmax6 - ga7 cmax7 (with cmax6 and cmax7 evaluated below)
488 // Smid = Smid^trial - ga6 Emid,a dg6/dSa - ga7 Emid,a dg7/dSa
489 // = Smid^trial - ga6 cmid6 - ga7 cmid7
490 // Smin = Smin^trial - ga6 Emin,a dg6/dSa - ga7 Emin,a dg7/dSa
491 // = Smin^trial - ga6 cmin6 - ga7 cmin7
492 const Real cmax6 = _Eij[2][2] * halfplus + _Eij[2][0] * neghalfplus;
493 const Real cmax7 = _Eij[2][1] * halfplus + _Eij[2][0] * neghalfplus;
494 // const Real cmid6 = _Eij[1][2] * halfplus + _Eij[1][0] * neghalfplus;
495 // const Real cmid7 = _Eij[1][1] * halfplus + _Eij[1][0] * neghalfplus;
496 const Real cmin6 = _Eij[0][2] * halfplus + _Eij[0][0] * neghalfplus;
497 const Real cmin7 = _Eij[0][1] * halfplus + _Eij[0][0] * neghalfplus;
498 // Substituting these into f6 = 0 yields
499 // 0 = f6_trial - ga6 (0.5(cmax6 - cmin6) + 0.5(cmax6 + cmin6)sinphi) - ga7 (0.5(cmax6 -
500 // cmin6) + 0.5(cmax6 + cmin6)sinphi) = f6_trial - ga6 c6 - ga7 c7, where
501 const Real c6 = 0.5 * (cmax6 - cmin6) + 0.5 * (cmax6 + cmin6) * sinphi;
502 const Real c7 = 0.5 * (cmax7 - cmin7) + 0.5 * (cmax7 + cmin7) * sinphi;
503 // It isn't too hard to check that the other equation is
504 // 0 = f7_trial - ga6 c7 - ga7 c6
505 // These equations may be inverted to yield
506 if (c6 != c7)
507 {
508 const Real f6_trial = trial_mc_yf;
509 const Real f7_trial = 0.5 * (trial_stress_params[1] - trial_stress_params[0]) +
510 0.5 * (trial_stress_params[1] + trial_stress_params[0]) * sinphi -
511 cohcos;
512 const Real descr = Utility::pow<2>(c6) - Utility::pow<2>(c7);
513 Real ga6 = (c6 * f6_trial - c7 * f7_trial) / descr;
514 Real ga7 = (-c7 * f6_trial + c6 * f7_trial) / descr;
515 // and finally
516 stress_params[2] = trial_stress_params[2] - ga6 * cmax6 - ga7 * cmax7;
517 stress_params[0] = trial_stress_params[0] - ga6 * cmin6 - ga7 * cmin7;
518 stress_params[1] = stress_params[2] - 0.5 * _shifter;
519
520 Real f8 = 0.5 * (stress_params[2] - stress_params[1]) +
521 0.5 * (stress_params[2] + stress_params[1]) * sinphi - cohcos;
522
523 if (mc_tip_possible && f8 > _f_tol)
524 {
525 stress_params[2] = cohcos / sinphi;
526 stress_params[1] = stress_params[2] - 0.5 * _shifter;
527 stress_params[0] = stress_params[2] - _shifter;
528 f8 = 0.0;
529 ga6 = 1.0;
530 ga7 = 1.0;
531 }
532
533 const Real new_tensile_yf = stress_params[2] - ts;
534 const Real new_compressive_yf = -stress_params[0] - cs;
535
536 if (f8 <= _f_tol && new_tensile_yf <= _f_tol && new_compressive_yf <= _f_tol &&
537 ga6 >= 0.0 && ga7 >= 0.0)
538 {
539 gaE = ((trial_stress_params[2] - trial_stress_params[0]) -
540 (stress_params[2] - stress_params[0])) /
541 (_Eij[2][2] - _Eij[0][2]) * _Eij[2][2];
542 found_solution = true;
543 }
544 }
545 }
546 if (!found_solution && !mc_impossible && trial_mc_yf > _f_tol)
547 {
548 // Try return to the mid=min line.
549 // To return to the mid=min line, we need to solve f6 = 0 = f8 and
550 // the three flow-direction equations. In the flow-direction equations
551 // there are two plasticity multipliers, which i call ga6 and ga8,
552 // corresponding to the amounts of strain normal to the f6 and f8
553 // directions, respectively.
554 // So:
555 // Smax = Smax^trial - ga6 Emax,a dg6/dSa - ga8 Emax,a dg8/dSa
556 // = Smax^trial - ga6 cmax6 - ga8 cmax8 (with cmax6 and cmax8 evaluated below)
557 // Smid = Smid^trial - ga6 Emid,a dg6/dSa - ga8 Emid,a dg8/dSa
558 // = Smid^trial - ga6 cmid6 - ga8 cmid8
559 // Smin = Smin^trial - ga6 Emin,a dg6/dSa - ga8 Emin,a dg8/dSa
560 // = Smin^trial - ga6 cmin6 - ga8 cmin8
561 const Real cmax6 = _Eij[2][2] * halfplus + _Eij[2][0] * neghalfplus;
562 const Real cmax8 = _Eij[2][2] * halfplus + _Eij[2][1] * neghalfplus;
563 // const Real cmid6 = _Eij[1][2] * halfplus + _Eij[1][0] * neghalfplus;
564 // const Real cmid8 = _Eij[1][2] * halfplus + _Eij[1][1] * neghalfplus;
565 const Real cmin6 = _Eij[0][2] * halfplus + _Eij[0][0] * neghalfplus;
566 const Real cmin8 = _Eij[0][2] * halfplus + _Eij[0][1] * neghalfplus;
567 // Substituting these into f6 = 0 yields
568 // 0 = f6_trial - ga6 (0.5(cmax6 - cmin6) + 0.5(cmax6 + cmin6)sinphi) - ga8 (0.5(cmax6 -
569 // cmin6) + 0.5(cmax6 + cmin6)sinphi) = f6_trial - ga6 c6 - ga8 c8, where
570 const Real c6 = 0.5 * (cmax6 - cmin6) + 0.5 * (cmax6 + cmin6) * sinphi;
571 const Real c8 = 0.5 * (cmax8 - cmin8) + 0.5 * (cmax8 + cmin8) * sinphi;
572 // It isn't too hard to check that the other equation is
573 // 0 = f8_trial - ga6 c8 - ga8 c6
574 // These equations may be inverted to yield
575 if (c6 != c8)
576 {
577 const Real f6_trial = trial_mc_yf;
578 const Real f8_trial = 0.5 * (trial_stress_params[2] - trial_stress_params[1]) +
579 0.5 * (trial_stress_params[2] + trial_stress_params[1]) * sinphi -
580 cohcos;
581 const Real descr = Utility::pow<2>(c6) - Utility::pow<2>(c8);
582 Real ga6 = (c6 * f6_trial - c8 * f8_trial) / descr;
583 Real ga8 = (-c8 * f6_trial + c6 * f8_trial) / descr;
584 // and finally
585 stress_params[2] = trial_stress_params[2] - ga6 * cmax6 - ga8 * cmax8;
586 stress_params[0] = trial_stress_params[0] - ga6 * cmin6 - ga8 * cmin8;
587 stress_params[1] = stress_params[0] + 0.5 * _shifter;
588
589 Real f7 = 0.5 * (stress_params[1] - stress_params[0]) +
590 0.5 * (stress_params[1] + stress_params[0]) * sinphi - cohcos;
591
592 if (mc_tip_possible && f7 > _f_tol)
593 {
594 stress_params[2] = cohcos / sinphi;
595 stress_params[1] = stress_params[2] - 0.5 * _shifter;
596 stress_params[0] = stress_params[2] - _shifter;
597 f7 = 0.0;
598 ga6 = 1.0;
599 ga8 = 1.0;
600 }
601
602 const Real new_tensile_yf = stress_params[2] - ts;
603 const Real new_compressive_yf = -stress_params[0] - cs;
604
605 if (f7 <= _f_tol && new_tensile_yf <= _f_tol && new_compressive_yf <= _f_tol &&
606 ga6 >= 0.0 && ga8 >= 0.0)
607 {
608 gaE = ((trial_stress_params[2] - trial_stress_params[0]) -
609 (stress_params[2] - stress_params[0])) /
610 (_Eij[2][2] - _Eij[0][2]) * _Eij[2][2];
611 found_solution = true;
612 }
613 }
614 }
615 if (!found_solution && !mc_impossible && tensile_possible && trial_tensile_yf > _f_tol)
616 {
617 // Return to the line where yf[0] = 0 = yf[6].
618 // To return to this line, we need to solve f0 = 0 = f6 and
619 // the three flow-direction equations. In the flow-direction equations
620 // there are two plasticity multipliers, which i call ga0 and ga6
621 // corresponding to the amounts of strain normal to the f0 and f6
622 // directions, respectively.
623 // So:
624 // Smax = Smax^trial - ga6 Emax,a dg6/dSa - ga0 Emax,a dg0/dSa
625 // = Smax^trial - ga6 cmax6 - ga0 cmax0 (with cmax6 and cmax0 evaluated below)
626 // Smid = Smid^trial - ga6 Emid,a dg6/dSa - ga0 Emid,a dg0/dSa
627 // = Smid^trial - ga6 cmid6 - ga0 cmid0
628 // Smin = Smin^trial - ga6 Emin,a dg6/dSa - ga0 Emin,a dg0/dSa
629 // = Smin^trial - ga6 cmin6 - ga0 cmin0
630 const Real cmax6 = _Eij[2][2] * halfplus + _Eij[2][0] * neghalfplus;
631 const Real cmax0 = _Eij[2][2];
632 const Real cmid6 = _Eij[1][2] * halfplus + _Eij[1][0] * neghalfplus;
633 const Real cmid0 = _Eij[1][2];
634 const Real cmin6 = _Eij[0][2] * halfplus + _Eij[0][0] * neghalfplus;
635 const Real cmin0 = _Eij[0][2];
636 // Substituting these into f6 = 0 yields
637 // 0 = f6_trial - ga6 (0.5(cmax6 - cmin6) + 0.5(cmax6 + cmin6)sinphi) - ga0 (0.5(cmax0 -
638 // cmin0) + 0.5(cmax0 + cmin0)sinphi) = f6_trial - ga6 c6 - ga0 c0, where
639 const Real c6 = 0.5 * (cmax6 - cmin6) + 0.5 * (cmax6 + cmin6) * sinphi;
640 const Real c0 = 0.5 * (cmax0 - cmin0) + 0.5 * (cmax0 + cmin0) * sinphi;
641 // Substituting these into f0 = 0 yields
642 // 0 = f0_trial - ga6 cmax6 - ga0 cmax0
643 // These equations may be inverted to yield the following
644 const Real descr = c0 * cmax6 - c6 * cmax0;
645 if (descr != 0.0)
646 {
647 const Real ga0 = (-c6 * trial_tensile_yf + cmax6 * trial_mc_yf) / descr;
648 const Real ga6 = (c0 * trial_tensile_yf - cmax0 * trial_mc_yf) / descr;
649 stress_params[2] = trial_stress_params[2] - ga6 * cmax6 - ga0 * cmax0;
650 stress_params[1] = trial_stress_params[1] - ga6 * cmid6 - ga0 * cmid0;
651 stress_params[0] = trial_stress_params[0] - ga6 * cmin6 - ga0 * cmin0;
652
653 // enforce physicality (go to corners if necessary)
654 stress_params[0] =
655 std::min(stress_params[0],
656 stress_params[2] - _shifter); // account for poor choice from user
657 // if goto_corner then the max(min()) in the subsequent line will force the solution to lie
658 // at the corner where max = mid = tensile. This means the signs of ga0 and ga6 become
659 // irrelevant in the check below
660 const bool goto_corner = (stress_params[1] >= stress_params[2] - 0.5 * _shifter);
661 stress_params[1] = std::max(std::min(stress_params[1], stress_params[2] - 0.5 * _shifter),
662 stress_params[0] + 0.5 * _shifter);
663
664 const Real new_compressive_yf = -stress_params[0] - cs;
665 if (new_compressive_yf <= _f_tol &&
666 (goto_corner || (ga0 >= 0.0 && ga6 >= 0.0))) // enforce ga>=0 unless going to a corner
667 {
668 gaE = ((trial_stress_params[2] - trial_stress_params[0]) -
669 (stress_params[2] - stress_params[0])) /
670 (_Eij[2][2] - _Eij[0][2]) * _Eij[2][2] +
671 (trial_stress_params[2] - stress_params[2]);
672 found_solution = true;
673 }
674 }
675 }
676 if (!found_solution && !mc_impossible)
677 {
678 // Return to the line where yf[3] = 0 = yf[6].
679 // To return to this line, we need to solve f3 = 0 = f6 and
680 // the three flow-direction equations. In the flow-direction equations
681 // there are two plasticity multipliers, which i call ga3 and ga6
682 // corresponding to the amounts of strain normal to the f3 and f6
683 // directions, respectively.
684 // So:
685 // Smax = Smax^trial - ga6 Emax,a dg6/dSa - ga3 Emax,a dg3/dSa
686 // = Smax^trial - ga6 cmax6 - ga3 cmax3 (with cmax6 and cmax3 evaluated below)
687 // Smid = Smid^trial - ga6 Emid,a dg6/dSa - ga3 Emid,a dg3/dSa
688 // = Smid^trial - ga6 cmid6 - ga3 cmid3
689 // Smin = Smin^trial - ga6 Emin,a dg6/dSa - ga3 Emin,a dg3/dSa
690 // = Smin^trial - ga6 cmin6 - ga3 cmin3
691 const Real cmax6 = _Eij[2][2] * halfplus + _Eij[2][0] * neghalfplus;
692 const Real cmax3 = -_Eij[2][0];
693 const Real cmid6 = _Eij[1][2] * halfplus + _Eij[1][0] * neghalfplus;
694 const Real cmid3 = -_Eij[1][0];
695 const Real cmin6 = _Eij[0][2] * halfplus + _Eij[0][0] * neghalfplus;
696 const Real cmin3 = -_Eij[0][0];
697 // Substituting these into f6 = 0 yields
698 // 0 = f6_trial - ga6 (0.5(cmax6 - cmin6) + 0.5(cmax6 + cmin6)sinphi) - ga3 (0.5(cmax3 -
699 // cmin3) + 0.5(cmax3 + cmin3)sinphi) = f6_trial - ga6 c6 - ga3 c3, where
700 const Real c6 = 0.5 * (cmax6 - cmin6) + 0.5 * (cmax6 + cmin6) * sinphi;
701 const Real c3 = 0.5 * (cmax3 - cmin3) + 0.5 * (cmax3 + cmin3) * sinphi;
702 // Substituting these into f3 = 0 yields
703 // 0 = - f3_trial - ga6 cmin6 - ga3 cmin3
704 // These equations may be inverted to yield the following
705 const Real descr = c3 * cmin6 - c6 * cmin3;
706 if (descr != 0.0)
707 {
708 const Real ga3 = (c6 * trial_compressive_yf + cmin6 * trial_mc_yf) / descr;
709 const Real ga6 = (-c3 * trial_compressive_yf - cmin3 * trial_mc_yf) / descr;
710 stress_params[2] = trial_stress_params[2] - ga6 * cmax6 - ga3 * cmax3;
711 stress_params[1] = trial_stress_params[1] - ga6 * cmid6 - ga3 * cmid3;
712 stress_params[0] = trial_stress_params[0] - ga6 * cmin6 - ga3 * cmin3;
713
714 const Real new_tensile_yf = stress_params[2] - ts;
715 stress_params[2] =
716 std::max(stress_params[2],
717 stress_params[0] + _shifter); // account for poor choice from user
718 stress_params[1] = std::max(std::min(stress_params[1], stress_params[2] - 0.5 * _shifter),
719 stress_params[0] + 0.5 * _shifter);
720
721 if (new_tensile_yf <= _f_tol && ga6 >= 0.0)
722 {
723 gaE = ((trial_stress_params[2] - trial_stress_params[0]) -
724 (stress_params[2] - stress_params[0])) /
725 (_Eij[2][2] - _Eij[0][2]) * _Eij[2][2] +
726 (-trial_stress_params[0] - stress_params[0]);
727
728 found_solution = true;
729 }
730 }
731 }
732 if (!found_solution)
733 {
734 // Cannot find an acceptable initialisation
735 for (unsigned i = 0; i < _num_sp; ++i)
736 stress_params[i] = trial_stress_params[i];
737 gaE = 0.0;
738 mooseWarning("CappedMohrCoulombStressUpdate cannot initialize from max = ",
739 stress_params[2],
740 " mid = ",
741 stress_params[1],
742 " min = ",
743 stress_params[0]);
744 }
745 }
746 setIntnlValuesV(trial_stress_params, stress_params, intnl_old, intnl);
747}
748
749void
750CappedMohrCoulombStressUpdate::setIntnlValuesV(const std::vector<Real> & trial_stress_params,
751 const std::vector<Real> & current_stress_params,
752 const std::vector<Real> & intnl_old,
753 std::vector<Real> & intnl) const
754{
755 // intnl[0] = shear, intnl[1] = tensile
756 const Real smax = current_stress_params[2]; // largest eigenvalue
757 const Real smin = current_stress_params[0]; // smallest eigenvalue
758 const Real trial_smax = trial_stress_params[2]; // largest eigenvalue
759 const Real trial_smin = trial_stress_params[0]; // smallest eigenvalue
760 const Real ga_shear = ((trial_smax - trial_smin) - (smax - smin)) / (_Eij[2][2] - _Eij[0][2]);
761 intnl[0] = intnl_old[0] + ga_shear;
762 const Real sinpsi = std::sin(_psi.value(intnl[0]));
763 const Real prefactor = (_Eij[2][2] + _Eij[0][2]) * sinpsi;
764 const Real shear_correction = prefactor * ga_shear;
765 const Real ga_tensile = (1.0 - _poissons_ratio) *
766 ((trial_smax + trial_smin) - (smax + smin) - shear_correction) /
767 _Eij[2][2];
768 intnl[1] = intnl_old[1] + ga_tensile;
769}
770
771void
772CappedMohrCoulombStressUpdate::setIntnlDerivativesV(const std::vector<Real> & trial_stress_params,
773 const std::vector<Real> & current_stress_params,
774 const std::vector<Real> & intnl,
775 std::vector<std::vector<Real>> & dintnl) const
776{
777 // intnl[0] = shear, intnl[1] = tensile
778 const Real smax = current_stress_params[2]; // largest eigenvalue
779 const Real smin = current_stress_params[0]; // smallest eigenvalue
780 const Real trial_smax = trial_stress_params[2]; // largest eigenvalue
781 const Real trial_smin = trial_stress_params[0]; // smallest eigenvalue
782 const Real ga_shear = ((trial_smax - trial_smin) - (smax - smin)) / (_Eij[2][2] - _Eij[0][2]);
783 mooseAssert(
784 _dga_shear_scratch.size() == 3,
785 "_dga_shear_scratch incorrectly sized in CappedMohrCoulombStressUpdate:setIntnlDerivativesV");
786 _dga_shear_scratch[0] = 1.0 / (_Eij[2][2] - _Eij[0][2]);
787 _dga_shear_scratch[1] = 0.0;
788 _dga_shear_scratch[2] = -1.0 / (_Eij[2][2] - _Eij[0][2]);
789 // intnl[0] = intnl_old[0] + ga_shear;
790 for (std::size_t i = 0; i < _num_sp; ++i)
791 dintnl[0][i] = _dga_shear_scratch[i];
792
793 const Real sinpsi = std::sin(_psi.value(intnl[0]));
794 const Real dsinpsi_di0 = _psi.derivative(intnl[0]) * std::cos(_psi.value(intnl[0]));
795
796 const Real prefactor = (_Eij[2][2] + _Eij[0][2]) * sinpsi;
797 const Real dprefactor_di0 = (_Eij[2][2] + _Eij[0][2]) * dsinpsi_di0;
798 // const Real shear_correction = prefactor * ga_shear;
799 mooseAssert(_dshear_correction_scratch.size() == 3,
800 "_dshear_correction_scratch incorrectly sized in "
801 "CappedMohrCoulombStressUpdate:setIntnlDerivativesV");
802 for (std::size_t i = 0; i < _num_sp; ++i)
804 prefactor * _dga_shear_scratch[i] + dprefactor_di0 * dintnl[0][i] * ga_shear;
805 // const Real ga_tensile = (1 - _poissons_ratio) * ((trial_smax + trial_smin) - (smax + smin) -
806 // shear_correction) /
807 // _Eij[2][2];
808 // intnl[1] = intnl_old[1] + ga_tensile;
809 for (std::size_t i = 0; i < _num_sp; ++i)
810 dintnl[1][i] = -(1.0 - _poissons_ratio) * _dshear_correction_scratch[i] / _Eij[2][2];
811 dintnl[1][2] += -(1.0 - _poissons_ratio) / _Eij[2][2];
812 dintnl[1][0] += -(1.0 - _poissons_ratio) / _Eij[2][2];
813}
814
815void
817 const RankTwoTensor & stress_trial,
818 const std::vector<Real> & trial_stress_params,
819 const RankTwoTensor & /*stress*/,
820 const std::vector<Real> & stress_params,
821 Real /*gaE*/,
822 const yieldAndFlow & /*smoothed_q*/,
823 const RankFourTensor & elasticity_tensor,
824 bool compute_full_tangent_operator,
825 const std::vector<std::vector<Real>> & dvar_dtrial,
826 RankFourTensor & cto)
827{
828 cto = elasticity_tensor;
829 if (!compute_full_tangent_operator)
830 return;
831
832 // dvar_dtrial has been computed already, so
833 // d(stress)/d(trial_stress) = d(eigvecs * stress_params * eigvecs.transpose())/d(trial_stress)
834 // eigvecs is a rotation matrix, rot(i, j) = e_j(i) = i^th component of j^th eigenvector
835 // d(rot_ij)/d(stress_kl) = d(e_j(i))/d(stress_kl)
836 // = sum_a 0.5 * e_a(i) * (e_a(k)e_j(l) + e_a(l)e_j(k)) / (la_j - la_a)
837 // = sum_a 0.5 * rot(i,a) * (rot(k,a)rot(l,j) + rot(l,a)*rot(k,j)) / (la_j - la_a)
838 RankFourTensor drot_dstress;
839 for (unsigned i = 0; i < _tensor_dimensionality; ++i)
840 for (unsigned j = 0; j < _tensor_dimensionality; ++j)
841 for (unsigned k = 0; k < _tensor_dimensionality; ++k)
842 for (unsigned l = 0; l < _tensor_dimensionality; ++l)
843 for (unsigned a = 0; a < _num_sp; ++a)
844 {
845 if (trial_stress_params[a] == trial_stress_params[j])
846 continue;
847 drot_dstress(i, j, k, l) +=
848 0.5 * _eigvecs(i, a) *
849 (_eigvecs(k, a) * _eigvecs(l, j) + _eigvecs(l, a) * _eigvecs(k, j)) /
850 (trial_stress_params[j] - trial_stress_params[a]);
851 }
852
853 const RankTwoTensor eT = _eigvecs.transpose();
854
855 RankFourTensor dstress_dtrial;
856 for (unsigned i = 0; i < _tensor_dimensionality; ++i)
857 for (unsigned j = 0; j < _tensor_dimensionality; ++j)
858 for (unsigned k = 0; k < _tensor_dimensionality; ++k)
859 for (unsigned l = 0; l < _tensor_dimensionality; ++l)
860 for (unsigned a = 0; a < _num_sp; ++a)
861 dstress_dtrial(i, j, k, l) +=
862 drot_dstress(i, a, k, l) * stress_params[a] * eT(a, j) +
863 _eigvecs(i, a) * stress_params[a] * drot_dstress(j, a, k, l);
864
866 for (unsigned i = 0; i < _tensor_dimensionality; ++i)
867 for (unsigned j = 0; j < _tensor_dimensionality; ++j)
868 for (unsigned k = 0; k < _tensor_dimensionality; ++k)
869 for (unsigned l = 0; l < _tensor_dimensionality; ++l)
870 for (unsigned a = 0; a < _num_sp; ++a)
871 for (unsigned b = 0; b < _num_sp; ++b)
872 dstress_dtrial(i, j, k, l) +=
873 _eigvecs(i, a) * dvar_dtrial[a][b] * _dsp_trial_scratch[b](k, l) * eT(a, j);
874
875 cto = dstress_dtrial * elasticity_tensor;
876}
registerMooseObject("SolidMechanicsApp", CappedMohrCoulombStressUpdate)
CappedMohrCoulombStressUpdate implements rate-independent nonassociative Mohr-Coulomb plus tensile pl...
const SolidMechanicsHardeningModel & _compressive_strength
Hardening model for compressive strength.
void setIntnlDerivativesV(const std::vector< Real > &trial_stress_params, const std::vector< Real > &current_stress_params, const std::vector< Real > &intnl, std::vector< std::vector< Real > > &dintnl) const override
Sets the derivatives of internal parameters, based on the trial values of stress_params,...
std::vector< Real > _dga_shear_scratch
derivative of ga_shear w.r.t.
virtual void preReturnMapV(const std::vector< Real > &trial_stress_params, const RankTwoTensor &stress_trial, const std::vector< Real > &intnl_old, const std::vector< Real > &yf, const RankFourTensor &Eijkl) override
Derived classes may employ this function to record stuff or do other computations prior to the return...
const SolidMechanicsHardeningModel & _psi
Hardening model for dilation angle.
void setEffectiveElasticity(const RankFourTensor &Eijkl) override
Sets _Eij and _En and _Cij.
std::vector< Real > _dshear_correction_scratch
scratch vector used in setIntnlDerivativesV.
std::vector< RankTwoTensor > _dsp_trial_scratch
this is d(stress_param[:])/d(stress) which is calculated by dstressparam_dstress.
void setIntnlValuesV(const std::vector< Real > &trial_stress_params, const std::vector< Real > &current_stress_params, const std::vector< Real > &intnl_old, std::vector< Real > &intnl) const override
Sets the internal parameters based on the trial values of stress_params, their current values,...
RankTwoTensor _eigvecs
Eigenvectors of the trial stress as a RankTwoTensor, in order to rotate the returned stress back to s...
void computeAllQV(const std::vector< Real > &stress_params, const std::vector< Real > &intnl, std::vector< yieldAndFlow > &all_q) const override
Completely fills all_q with correct values.
void dstressparam_dstress(const RankTwoTensor &stress, std::vector< RankTwoTensor > &dsp) const override
d(stress_param[i])/d(stress) at given stress.
const bool _perfect_guess
Whether to provide an estimate of the returned stress, based on perfect plasticity.
std::vector< Real > _eigvals_scratch
eigenvalues of the stress, used in dstressparam_dstress and preReturnMapV.
const SolidMechanicsHardeningModel & _tensile_strength
Hardening model for tensile strength.
virtual void setStressAfterReturnV(const RankTwoTensor &stress_trial, const std::vector< Real > &stress_params, Real gaE, const std::vector< Real > &intnl, const yieldAndFlow &smoothed_q, const RankFourTensor &Eijkl, RankTwoTensor &stress) const override
Sets stress from the admissible parameters.
void yieldFunctionValuesV(const std::vector< Real > &stress_params, const std::vector< Real > &intnl, std::vector< Real > &yf) const override
Computes the values of the yield functions, given stress_params and intnl parameters.
const Real _shifter
When equal-eigenvalues are predicted from the stress initialization routine, shift them by this amoun...
CappedMohrCoulombStressUpdate(const InputParameters &parameters)
void d2stressparam_dstress(const RankTwoTensor &stress, std::vector< RankFourTensor > &d2sp) const override
d2(stress_param[i])/d(stress)/d(stress) at given stress.
void initializeVarsV(const std::vector< Real > &trial_stress_params, const std::vector< Real > &intnl_old, std::vector< Real > &stress_params, Real &gaE, std::vector< Real > &intnl) const override
Sets (stress_params, intnl) at "good guesses" of the solution to the Return-Map algorithm.
virtual void consistentTangentOperatorV(const RankTwoTensor &stress_trial, const std::vector< Real > &trial_stress_params, const RankTwoTensor &stress, const std::vector< Real > &stress_params, Real gaE, const yieldAndFlow &smoothed_q, const RankFourTensor &Eijkl, bool compute_full_tangent_operator, const std::vector< std::vector< Real > > &dvar_dtrial, RankFourTensor &cto) override
Calculates the consistent tangent operator.
const SolidMechanicsHardeningModel & _cohesion
Hardening model for cohesion.
const SolidMechanicsHardeningModel & _phi
Hardening model for friction angle.
void computeStressParams(const RankTwoTensor &stress, std::vector< Real > &stress_params) const override
Computes stress_params, given stress.
void addRequiredParam(const std::string &name, const std::string &doc_string)
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
void addClassDescription(const std::string &doc_string)
void mooseWarning(Args &&... args) const
MultiParameterPlasticityStressUpdate performs the return-map algorithm and associated stress updates ...
std::vector< std::vector< Real > > _Eij
E[i, j] in the system of equations to be solved.
std::vector< std::vector< Real > > _Cij
_Cij[i, j] * _Eij[j, k] = 1 iff j == k
const unsigned _num_sp
Number of stress parameters.
const unsigned _num_yf
Number of yield functions.
static constexpr unsigned _tensor_dimensionality
Internal dimensionality of tensors (currently this is 3 throughout solid mechanics)
const unsigned _num_intnl
Number of internal parameters.
void dsymmetricEigenvalues(std::vector< T > &eigvals, std::vector< RankTwoTensorTempl< T > > &deigvals) const
RankTwoTensorTempl< T > transpose() const
void d2symmetricEigenvalues(std::vector< RankFourTensorTempl< T > > &deriv) const
void symmetricEigenvalues(std::vector< T > &eigvals) const
void symmetricEigenvaluesEigenvectors(std::vector< T > &eigvals, RankTwoTensorTempl< T > &eigvecs) const
virtual Real derivative(Real intnl) const
virtual Real value(Real intnl) const
T getIsotropicPoissonsRatio(const RankFourTensorTempl< T > &elasticity_tensor)
Get the Poisson's modulus for an isotropic elasticity tensor param elasticity_tensor the tensor (must...
Real elasticity_tensor(unsigned int i, unsigned int j, unsigned int k, unsigned int l)
Struct designed to hold info about a single yield function and its derivatives, as well as the flow d...