https://mooseframework.inl.gov
Loading...
Searching...
No Matches
CappedDruckerPragerStressUpdate.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
12#include "libmesh/utility.h"
13
15
18{
20 params.addClassDescription("Capped Drucker-Prager plasticity stress calculator");
21 params.addRequiredParam<UserObjectName>(
22 "DP_model",
23 "A SolidMechanicsPlasticDruckerPrager UserObject that defines the "
24 "Drucker-Prager parameters (cohesion, friction angle and dilation angle)");
25 params.addRequiredParam<UserObjectName>(
26 "tensile_strength",
27 "A SolidMechanicsHardening UserObject that defines hardening of the "
28 "tensile strength. In physical situations this is positive (and always "
29 "must be greater than negative compressive-strength.");
30 params.addRequiredParam<UserObjectName>(
31 "compressive_strength",
32 "A SolidMechanicsHardening UserObject that defines hardening of the "
33 "compressive strength. In physical situations this is positive.");
35 "tip_smoother",
36 "tip_smoother>=0",
37 "The cone vertex at J2 = 0 will be smoothed by the given "
38 "amount. Typical value is 0.1*cohesion");
39 params.addParam<bool>("perfect_guess",
40 true,
41 "Provide a guess to the Newton-Raphson procedure "
42 "that is the result from perfect plasticity. With "
43 "severe hardening/softening this may be "
44 "suboptimal.");
45 params.addParam<bool>("small_dilation",
46 true,
47 "If true, and if the trial stress exceeds the "
48 "tensile strength, then the user guarantees that "
49 "the returned stress will be independent of the "
50 "compressive strength.");
51 return params;
52}
53
55 : TwoParameterPlasticityStressUpdate(parameters, 3, 2),
56 _dp(getUserObject<SolidMechanicsPlasticDruckerPrager>("DP_model")),
57 _tstrength(getUserObject<SolidMechanicsHardeningModel>("tensile_strength")),
58 _cstrength(getUserObject<SolidMechanicsHardeningModel>("compressive_strength")),
59 _small_smoother2(Utility::pow<2>(getParam<Real>("tip_smoother"))),
60 _perfect_guess(getParam<bool>("perfect_guess")),
61 _stress_return_type(StressReturnType::nothing_special),
62 _small_dilation(getParam<bool>("small_dilation")),
63 _in_q_trial(0.0)
64{
65 // With arbitary UserObjects, it is impossible to check everything,
66 // but this will catch the common errors
68 mooseError("CappedDruckerPragerStressUpdate: Tensile strength plus compressive strength must "
69 "be greater than smoothing_tol");
70}
71
72void
77
78void
83
84void
86 Real q_trial,
87 const RankTwoTensor & /*stress_trial*/,
88 const std::vector<Real> & /*intnl_old*/,
89 const std::vector<Real> & yf,
90 const RankFourTensor & /*Eijkl*/)
91{
92 // If it's obvious, then simplify the return-type
93 if (yf[2] >= 0)
95 else if (_small_dilation && yf[1] >= 0)
97
98 _in_q_trial = q_trial;
99}
100
101void
102CappedDruckerPragerStressUpdate::computePQ(const RankTwoTensor & stress, Real & p, Real & q) const
103{
104 p = stress.trace();
105 q = std::sqrt(stress.secondInvariant());
106}
107
108void
110 Real & Epp,
111 Real & Eqq) const
112{
113 Epp = Eijkl.sum3x3();
114 Eqq = Eijkl(0, 1, 0, 1);
115}
116
117void
119 Real q_trial,
120 Real /*p*/,
121 Real q,
122 const std::vector<Real> & intnl,
123 std::vector<std::vector<Real>> & dintnl) const
124{
125 Real tanpsi;
126 _dp.onlyB(intnl[0], _dp.dilation, tanpsi);
127 Real dtanpsi;
128 _dp.donlyB(intnl[0], _dp.dilation, dtanpsi);
129 dintnl[0][0] = 0.0;
130 dintnl[0][1] = -1.0 / _Eqq;
131 dintnl[1][0] = -1.0 / _Epp;
132 dintnl[1][1] = tanpsi / _Eqq - (q_trial - q) * dtanpsi * dintnl[0][1] / _Eqq;
133}
134
135void
137 Real q,
138 const std::vector<Real> & intnl,
139 std::vector<Real> & yf) const
140{
141 Real aaa;
142 Real bbb;
143 _dp.bothAB(intnl[0], aaa, bbb);
144 yf[0] = std::sqrt(Utility::pow<2>(q) + _small_smoother2) + p * bbb - aaa;
145
147 yf[1] = std::numeric_limits<Real>::lowest();
148 else
149 yf[1] = p - _tstrength.value(intnl[1]);
150
152 yf[2] = std::numeric_limits<Real>::lowest();
153 else
154 yf[2] = -p - _cstrength.value(intnl[1]);
155}
156
157void
159 Real q,
160 const std::vector<Real> & intnl,
161 std::vector<yieldAndFlow> & all_q) const
162{
163 Real aaa;
164 Real bbb;
165 _dp.bothAB(intnl[0], aaa, bbb);
166 Real daaa;
167 Real dbbb;
168 _dp.dbothAB(intnl[0], daaa, dbbb);
169 Real tanpsi;
170 _dp.onlyB(intnl[0], _dp.dilation, tanpsi);
171 Real dtanpsi;
172 _dp.donlyB(intnl[0], _dp.dilation, dtanpsi);
173
174 // yield function values
175 all_q[0].f = std::sqrt(Utility::pow<2>(q) + _small_smoother2) + p * bbb - aaa;
177 all_q[1].f = std::numeric_limits<Real>::lowest();
178 else
179 all_q[1].f = p - _tstrength.value(intnl[1]);
181 all_q[2].f = std::numeric_limits<Real>::lowest();
182 else
183 all_q[2].f = -p - _cstrength.value(intnl[1]);
184
185 // d(yield Function)/d(p, q)
186 // derivatives wrt p
187 all_q[0].df[0] = bbb;
188 all_q[1].df[0] = 1.0;
189 all_q[2].df[0] = -1.0;
190
191 // derivatives wrt q
192 if (_small_smoother2 == 0.0)
193 all_q[0].df[1] = 1.0;
194 else
195 all_q[0].df[1] = q / std::sqrt(Utility::pow<2>(q) + _small_smoother2);
196 all_q[1].df[1] = 0.0;
197 all_q[2].df[1] = 0.0;
198
199 // d(yield Function)/d(intnl)
200 // derivatives wrt intnl[0] (shear plastic strain)
201 all_q[0].df_di[0] = p * dbbb - daaa;
202 all_q[1].df_di[0] = 0.0;
203 all_q[2].df_di[0] = 0.0;
204 // derivatives wrt intnl[q] (tensile plastic strain)
205 all_q[0].df_di[1] = 0.0;
206 all_q[1].df_di[1] = -_tstrength.derivative(intnl[1]);
207 all_q[2].df_di[1] = -_cstrength.derivative(intnl[1]);
208
209 // d(flowPotential)/d(p, q)
210 // derivatives wrt p
211 all_q[0].dg[0] = tanpsi;
212 all_q[1].dg[0] = 1.0;
213 all_q[2].dg[0] = -1.0;
214 // derivatives wrt q
215 if (_small_smoother2 == 0.0)
216 all_q[0].dg[1] = 1.0;
217 else
218 all_q[0].dg[1] = q / std::sqrt(Utility::pow<2>(q) + _small_smoother2);
219 all_q[1].dg[1] = 0.0;
220 all_q[2].dg[1] = 0.0;
221
222 // d2(flowPotential)/d(p, q)/d(intnl)
223 // d(dg/dp)/dintnl[0]
224 all_q[0].d2g_di[0][0] = dtanpsi;
225 all_q[1].d2g_di[0][0] = 0.0;
226 all_q[2].d2g_di[0][0] = 0.0;
227 // d(dg/dp)/dintnl[1]
228 all_q[0].d2g_di[0][1] = 0.0;
229 all_q[1].d2g_di[0][1] = 0.0;
230 all_q[2].d2g_di[0][1] = 0.0;
231 // d(dg/dq)/dintnl[0]
232 all_q[0].d2g_di[1][0] = 0.0;
233 all_q[1].d2g_di[1][0] = 0.0;
234 all_q[2].d2g_di[1][0] = 0.0;
235 // d(dg/dq)/dintnl[1]
236 all_q[0].d2g_di[1][1] = 0.0;
237 all_q[1].d2g_di[1][1] = 0.0;
238 all_q[2].d2g_di[1][1] = 0.0;
239
240 // d2(flowPotential)/d(p, q)/d(p, q)
241 // d(dg/dp)/dp
242 all_q[0].d2g[0][0] = 0.0;
243 all_q[1].d2g[0][0] = 0.0;
244 all_q[2].d2g[0][0] = 0.0;
245 // d(dg/dp)/dq
246 all_q[0].d2g[0][1] = 0.0;
247 all_q[1].d2g[0][1] = 0.0;
248 all_q[2].d2g[0][1] = 0.0;
249 // d(dg/dq)/dp
250 all_q[0].d2g[1][0] = 0.0;
251 all_q[1].d2g[1][0] = 0.0;
252 all_q[2].d2g[1][0] = 0.0;
253 // d(dg/dq)/dq
254 if (_small_smoother2 == 0.0)
255 all_q[0].d2g[1][1] = 0.0;
256 else
257 all_q[0].d2g[1][1] = _small_smoother2 / std::pow(Utility::pow<2>(q) + _small_smoother2, 1.5);
258 all_q[1].d2g[1][1] = 0.0;
259 all_q[2].d2g[1][1] = 0.0;
260}
261
262void
264 Real q_trial,
265 const std::vector<Real> & intnl_old,
266 Real & p,
267 Real & q,
268 Real & gaE,
269 std::vector<Real> & intnl) const
270{
271 if (!_perfect_guess)
272 {
273 p = p_trial;
274 q = q_trial;
275 gaE = 0.0;
276 }
277 else
278 {
279 Real coh;
280 Real tanphi;
281 _dp.bothAB(intnl[0], coh, tanphi);
282 Real tanpsi;
283 _dp.onlyB(intnl_old[0], _dp.dilation, tanpsi);
284 const Real tens = _tstrength.value(intnl_old[1]);
285 const Real comp = _cstrength.value(intnl_old[1]);
286 const Real q_at_T = coh - tens * tanphi;
287 const Real q_at_C = coh + comp * tanphi;
288
289 if ((p_trial >= tens) && (q_trial <= q_at_T))
290 {
291 // pure tensile failure
292 p = tens;
293 q = q_trial;
294 gaE = p_trial - p;
295 }
296 else if ((p_trial <= -comp) && (q_trial <= q_at_C))
297 {
298 // pure compressive failure
299 p = -comp;
300 q = q_trial;
301 gaE = p - p_trial;
302 }
303 else
304 {
305 // shear failure or a mixture
306 // Calculate ga assuming a pure shear failure
307 const Real ga = (q_trial + p_trial * tanphi - coh) / (_Eqq + _Epp * tanphi * tanpsi);
308 if (ga <= 0 && p_trial <= tens && p_trial >= -comp)
309 {
310 // very close to one of the rounded corners: there is no advantage to guessing the
311 // solution, so:
312 p = p_trial;
313 q = q_trial;
314 gaE = 0.0;
315 }
316 else
317 {
318 q = q_trial - _Eqq * ga;
319 if (q <= 0.0 && q_at_T <= 0.0)
320 {
321 // user has set tensile strength so large that it is irrelevant: return to the tip of the
322 // shear cone
323 q = 0.0;
324 p = coh / tanphi;
325 gaE = (p_trial - p) / tanpsi; // just a guess, based on the angle to the corner
326 }
327 else if (q <= q_at_T)
328 {
329 // pure shear is incorrect: mixture of tension and shear is correct
330 q = q_at_T;
331 p = tens;
332 gaE = (p_trial - p) / tanpsi; // just a guess, based on the angle to the corner
333 }
334 else if (q >= q_at_C)
335 {
336 // pure shear is incorrect: mixture of compression and shear is correct
337 q = q_at_C;
338 p = -comp;
339 if (p - p_trial < _Epp * tanpsi * (q_trial - q) / _Eqq)
340 // trial point is sitting almost directly above corner
341 gaE = (q_trial - q) * _Epp / _Eqq;
342 else
343 // trial point is sitting to the left of the corner
344 gaE = (p - p_trial) / tanpsi;
345 }
346 else
347 {
348 // pure shear was correct
349 p = p_trial - _Epp * ga * tanpsi;
350 gaE = ga * _Epp;
351 }
352 }
353 }
354 }
355 setIntnlValues(p_trial, q_trial, p, q, intnl_old, intnl);
356}
357
358void
360 Real q_trial,
361 Real p,
362 Real q,
363 const std::vector<Real> & intnl_old,
364 std::vector<Real> & intnl) const
365{
366 intnl[0] = intnl_old[0] + (q_trial - q) / _Eqq;
367 Real tanpsi;
368 _dp.onlyB(intnl[0], _dp.dilation, tanpsi);
369 intnl[1] = intnl_old[1] + (p_trial - p) / _Epp - (q_trial - q) * tanpsi / _Eqq;
370}
371
372void
374 Real p_ok,
375 Real q_ok,
376 Real /*gaE*/,
377 const std::vector<Real> & /*intnl*/,
378 const yieldAndFlow & /*smoothed_q*/,
379 const RankFourTensor & /*Eijkl*/,
380 RankTwoTensor & stress) const
381{
382 // stress = s_ij + de_ij tr(stress) / 3 = q / q_trial * s_ij^trial + de_ij p / 3 = q / q_trial *
383 // (stress_ij^trial - de_ij tr(stress^trial) / 3) + de_ij p / 3
384 const Real p_trial = stress_trial.trace();
386 (p_ok - (_in_q_trial == 0.0 ? 0.0 : p_trial * q_ok / _in_q_trial));
387 if (_in_q_trial > 0)
388 stress += q_ok / _in_q_trial * stress_trial;
389}
390
393{
394 return stress.dtrace();
395}
396
399{
400 return RankFourTensor();
401}
402
405{
406 const Real j2 = stress.secondInvariant();
407 if (j2 == 0.0)
408 return RankTwoTensor();
409 return 0.5 * stress.dsecondInvariant() / std::sqrt(j2);
410}
411
414{
415 const Real j2 = stress.secondInvariant();
416 if (j2 == 0.0)
417 return RankFourTensor();
418
419 const RankTwoTensor dj2 = stress.dsecondInvariant();
420 return -0.25 * dj2.outerProduct(dj2) / std::pow(j2, 1.5) +
421 0.5 * stress.d2secondInvariant() / std::sqrt(j2);
422}
423
424void
426 Real /*p_trial*/,
427 Real /*q_trial*/,
428 const RankTwoTensor & stress,
429 Real /*p*/,
430 Real q,
431 Real gaE,
432 const yieldAndFlow & smoothed_q,
433 const RankFourTensor & Eijkl,
434 bool compute_full_tangent_operator,
435 RankFourTensor & cto) const
436{
437 cto = Eijkl;
438 if (!compute_full_tangent_operator)
439 return;
440
441 const RankTwoTensor s_over_q =
442 (q == 0.0 ? RankTwoTensor()
443 : (stress - stress.trace() * RankTwoTensor(RankTwoTensor::initIdentity) / 3.0) / q);
444
445 for (unsigned i = 0; i < _tensor_dimensionality; ++i)
446 for (unsigned j = 0; j < _tensor_dimensionality; ++j)
447 for (unsigned k = 0; k < _tensor_dimensionality; ++k)
448 for (unsigned l = 0; l < _tensor_dimensionality; ++l)
449 {
450 cto(i, j, k, l) -=
451 (i == j) * (1.0 / 3.0) *
452 (_Epp * (1.0 - _dp_dpt) / 3.0 * (k == l) + s_over_q(k, l) * _Eqq * (-_dp_dqt));
453 cto(i, j, k, l) -= s_over_q(i, j) * (_Epp * (-_dq_dpt) / 3.0 * (k == l) +
454 s_over_q(k, l) * _Eqq * (1.0 - _dq_dqt));
455 }
456
457 if (smoothed_q.dg[1] != 0.0)
458 {
459 const RankFourTensor Tijab = Eijkl * (gaE / _Epp) * smoothed_q.dg[1] * d2qdstress2(stress);
461 try
462 {
463 inv = inv.transposeMajor().invSymm();
464 }
465 catch (const MooseException & e)
466 {
467 // Cannot form the inverse, so probably at some degenerate place in stress space.
468 // Just return with the "best estimate" of the cto.
469 mooseWarning("CappedDruckerPragerStressUpdate: Cannot invert 1+T in consistent tangent "
470 "operator computation at quadpoint ",
471 _qp,
472 " of element ",
473 _current_elem->id());
474 return;
475 }
476 cto = (cto.transposeMajor() * inv).transposeMajor();
477 }
478}
registerMooseObject("SolidMechanicsApp", CappedDruckerPragerStressUpdate)
ExpressionBuilder::EBTerm pow(const ExpressionBuilder::EBTerm &left, T exponent)
const Real p
CappedDruckerPragerStressUpdate performs the return-map algorithm and associated stress updates for p...
virtual void setStressAfterReturn(const RankTwoTensor &stress_trial, Real p_ok, Real q_ok, Real gaE, const std::vector< Real > &intnl, const yieldAndFlow &smoothed_q, const RankFourTensor &Eijkl, RankTwoTensor &stress) const override
Sets stress from the admissible parameters.
CappedDruckerPragerStressUpdate(const InputParameters &parameters)
virtual void setIntnlValues(Real p_trial, Real q_trial, Real p, Real q, const std::vector< Real > &intnl_old, std::vector< Real > &intnl) const override
Sets the internal parameters based on the trial values of p and q, their current values,...
virtual void computePQ(const RankTwoTensor &stress, Real &p, Real &q) const override
Computes p and q, given stress.
virtual RankFourTensor d2pdstress2(const RankTwoTensor &stress) const override
d2(p)/d(stress)/d(stress) Derived classes must override this
virtual void consistentTangentOperator(const RankTwoTensor &stress_trial, Real p_trial, Real q_trial, const RankTwoTensor &stress, Real p, Real q, Real gaE, const yieldAndFlow &smoothed_q, const RankFourTensor &Eijkl, bool compute_full_tangent_operator, RankFourTensor &cto) const override
Calculates the consistent tangent operator.
virtual RankTwoTensor dqdstress(const RankTwoTensor &stress) const override
d(q)/d(stress) Derived classes must override this
virtual void initializeVars(Real p_trial, Real q_trial, const std::vector< Real > &intnl_old, Real &p, Real &q, Real &gaE, std::vector< Real > &intnl) const override
Sets (p, q, gaE, intnl) at "good guesses" of the solution to the Return-Map algorithm.
virtual RankFourTensor d2qdstress2(const RankTwoTensor &stress) const override
d2(q)/d(stress)/d(stress) Derived classes must override this
virtual void finalizeReturnProcess(const RankTwoTensor &rotation_increment) override
Derived classes may use this to perform calculations after the return-map process has completed succe...
const SolidMechanicsHardeningModel & _cstrength
Hardening model for compressive strength.
virtual void computeAllQ(Real p, Real q, const std::vector< Real > &intnl, std::vector< yieldAndFlow > &all_q) const override
Completely fills all_q with correct values.
const Real _small_smoother2
The cone vertex is smoothed by this amount.
virtual void preReturnMap(Real p_trial, Real q_trial, 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 bool _small_dilation
If true, and if the trial stress exceeds the tensile strength, then the user gaurantees that the retu...
const SolidMechanicsHardeningModel & _tstrength
Hardening model for tensile strength.
const bool _perfect_guess
Initialize the NR proceedure from a guess coming from perfect plasticity.
virtual void yieldFunctionValues(Real p, Real q, const std::vector< Real > &intnl, std::vector< Real > &yf) const override
Computes the values of the yield functions, given p, q and intnl parameters.
virtual void setIntnlDerivatives(Real p_trial, Real q_trial, Real p, Real q, 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 p and q,...
virtual void setEppEqq(const RankFourTensor &Eijkl, Real &Epp, Real &Eqq) const override
Set Epp and Eqq based on the elasticity tensor Derived classes must override this.
virtual void initializeReturnProcess() override
Derived classes may use this to perform calculations before any return-map process is performed,...
virtual RankTwoTensor dpdstress(const RankTwoTensor &stress) const override
d(p)/d(stress) Derived classes must override this
const SolidMechanicsPlasticDruckerPrager & _dp
Hardening model for cohesion, friction and dilation angles.
StressReturnType
This allows some simplification in the return-map process.
enum CappedDruckerPragerStressUpdate::StressReturnType _stress_return_type
void addRequiredRangeCheckedParam(const std::string &name, const std::string &parsed_function, const std::string &doc_string)
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 mooseError(Args &&... args) const
void mooseWarning(Args &&... args) const
const Real _smoothing_tol
Smoothing tolerance: edges of the yield surface get smoothed by this amount.
static constexpr unsigned _tensor_dimensionality
Internal dimensionality of tensors (currently this is 3 throughout solid mechanics)
RankFourTensorTempl< T > transposeMajor() const
RankFourTensorTempl< T > outerProduct(const RankTwoTensorTempl< T > &b) const
T secondInvariant() const
RankTwoTensorTempl< T > dsecondInvariant() const
RankTwoTensorTempl< T > dtrace() const
RankFourTensorTempl< T > d2secondInvariant() const
virtual Real derivative(Real intnl) const
virtual Real value(Real intnl) const
Rate-independent non-associative Drucker Prager with hardening/softening.
void onlyB(Real intnl, int fd, Real &bbb) const
Calculate bbb or bbb_flow.
void dbothAB(Real intnl, Real &daaa, Real &dbbb) const
Calculates d(aaa)/d(intnl) and d(bbb)/d(intnl) as a function of the internal parameter intnl.
void bothAB(Real intnl, Real &aaa, Real &bbb) const
Calculates aaa and bbb as a function of the internal parameter intnl.
void donlyB(Real intnl, int fd, Real &dbbb) const
Calculate d(bbb)/d(intnl) or d(bbb_flow)/d(intnl)
const Elem *const & _current_elem
TwoParameterPlasticityStressUpdate performs the return-map algorithm and associated stress updates fo...
Real _dq_dpt
derivative of Variable with respect to trial variable (used in consistent-tangent-operator calculatio...
Real _dp_dqt
derivative of Variable with respect to trial variable (used in consistent-tangent-operator calculatio...
Real _dq_dqt
derivative of Variable with respect to trial variable (used in consistent-tangent-operator calculatio...
Real _dp_dpt
derivative of Variable with respect to trial variable (used in consistent-tangent-operator calculatio...
Struct designed to hold info about a single yield function and its derivatives, as well as the flow d...