https://mooseframework.inl.gov
Loading...
Searching...
No Matches
MultiParameterPlasticityStressUpdate.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 "Conversion.h" // for stringify
12#include "MooseEnum.h" // for enum
13
14// libMesh includes
15#include "libmesh/utility.h" // for Utility::pow
16
17// PETSc includes
18#include <petscblaslapack.h> // LAPACKgesv_
19
22{
24 params.addClassDescription("Return-map and Jacobian algorithms for plastic models where the "
25 "yield function and flow directions depend on multiple functions of "
26 "stress");
27 params.addRangeCheckedParam<unsigned int>(
28 "max_NR_iterations",
29 20,
30 "max_NR_iterations>0",
31 "Maximum number of Newton-Raphson iterations allowed during the return-map algorithm");
32 params.addParam<bool>("perform_finite_strain_rotations",
33 false,
34 "Tensors are correctly rotated "
35 "in finite-strain simulations. "
36 "For optimal performance you can "
37 "set this to 'false' if you are "
38 "only ever using small strains");
39 params.addRequiredParam<Real>(
40 "smoothing_tol",
41 "Intersections of the yield surfaces will be smoothed by this amount (this "
42 "is measured in units of stress). Often this is related to other physical "
43 "parameters (eg, 0.1*cohesion) but it is important to set this small enough "
44 "so that the individual yield surfaces do not mix together in the smoothing "
45 "process to produce a result where no stress is admissible (for example, "
46 "mixing together tensile and compressive failure envelopes).");
47 params.addRequiredParam<Real>("yield_function_tol",
48 "The return-map process will be deemed to have converged if all "
49 "yield functions are within yield_function_tol of zero. If this "
50 "is set very low then precision-loss might be encountered: if the "
51 "code detects precision loss then it also deems the return-map "
52 "process has converged.");
53 MooseEnum tangent_operator("elastic nonlinear", "nonlinear");
54 params.addParam<Real>("min_step_size",
55 1.0,
56 "In order to help the Newton-Raphson procedure, the applied strain "
57 "increment may be applied in sub-increments of size greater than this "
58 "value. Usually it is better for Moose's nonlinear convergence to "
59 "increase max_NR_iterations rather than decrease this parameter.");
60 params.addParam<bool>("warn_about_precision_loss",
61 false,
62 "Output a message to the console every "
63 "time precision-loss is encountered "
64 "during the Newton-Raphson process");
65 params.addParam<std::vector<Real>>("admissible_stress",
66 "A single admissible value of the value of the stress "
67 "parameters for internal parameters = 0. This is used "
68 "to initialize the return-mapping algorithm during the first "
69 "nonlinear iteration. If not given then it is assumed that "
70 "stress parameters = 0 is admissible.");
71 MooseEnum smoother_fcn_enum("cos poly1 poly2 poly3", "cos");
72 params.addParam<MooseEnum>("smoother_function_type",
73 smoother_fcn_enum,
74 "Type of smoother function to use. 'cos' means (-a/pi)cos(pi x/2/a), "
75 "'polyN' means a polynomial of degree 2N+2");
76 params.addParamNamesToGroup("smoother_function_type", "Advanced");
77 return params;
78}
79
81 const InputParameters & parameters, unsigned num_sp, unsigned num_yf, unsigned num_intnl)
82 : StressUpdateBase(parameters),
83 _num_sp(num_sp),
84 _definitely_ok_sp(isParamValid("admissible_stress")
85 ? getParam<std::vector<Real>>("admissible_stress")
86 : std::vector<Real>(_num_sp, 0.0)),
87 _Eij(num_sp, std::vector<Real>(num_sp)),
88 _En(1.0),
89 _Cij(num_sp, std::vector<Real>(num_sp)),
90 _num_yf(num_yf),
91 _num_intnl(num_intnl),
92 _max_nr_its(getParam<unsigned>("max_NR_iterations")),
93 _perform_finite_strain_rotations(getParam<bool>("perform_finite_strain_rotations")),
94 _smoothing_tol(getParam<Real>("smoothing_tol")),
95 _smoothing_tol2(Utility::pow<2>(getParam<Real>("smoothing_tol"))),
96 _f_tol(getParam<Real>("yield_function_tol")),
97 _f_tol2(Utility::pow<2>(getParam<Real>("yield_function_tol"))),
98 _min_step_size(getParam<Real>("min_step_size")),
99 _step_one(declareRestartableData<bool>("step_one", true)),
100 _warn_about_precision_loss(getParam<bool>("warn_about_precision_loss")),
101
102 _plastic_strain(declareProperty<RankTwoTensor>(_base_name + "plastic_strain")),
103 _plastic_strain_old(getMaterialPropertyOld<RankTwoTensor>(_base_name + "plastic_strain")),
104 _intnl(declareProperty<std::vector<Real>>(_base_name + "plastic_internal_parameter")),
105 _intnl_old(
106 getMaterialPropertyOld<std::vector<Real>>(_base_name + "plastic_internal_parameter")),
107 _yf(declareProperty<std::vector<Real>>(_base_name + "plastic_yield_function")),
108 _iter(declareProperty<Real>(_base_name +
109 "plastic_NR_iterations")), // this is really an unsigned int, but
110 // for visualisation i convert it to Real
111 _max_iter_used(declareProperty<Real>(
112 _base_name + "max_plastic_NR_iterations")), // this is really an unsigned int, but
113 // for visualisation i convert it to Real
114 _max_iter_used_old(getMaterialPropertyOld<Real>(_base_name + "max_plastic_NR_iterations")),
115 _linesearch_needed(
116 declareProperty<Real>(_base_name + "plastic_linesearch_needed")), // this is really a
117 // boolean, but for
118 // visualisation i
119 // convert it to Real
120 _trial_sp(num_sp),
121 _stress_trial(RankTwoTensor()),
122 _rhs(num_sp + 1),
123 _dvar_dtrial(num_sp + 1, std::vector<Real>(num_sp, 0.0)),
124 _ok_sp(num_sp),
125 _ok_intnl(num_intnl),
126 _del_stress_params(num_sp),
127 _current_sp(num_sp),
128 _current_intnl(num_intnl),
129 _smoothed_q(yieldAndFlow(yieldAndFlow(num_sp, num_intnl))),
130 _dsp_scratch(num_sp),
131 _dsp_trial_scratch(num_sp),
132 _d2sp_scratch(num_sp),
133 _yfs_scratch(num_yf),
134 _sp_params_old_scratch(num_sp),
135 _delta_nr_params_scratch(num_sp + 1),
136 _dintnl_scratch(num_intnl, std::vector<Real>(num_sp)),
137 _jac_scratch((num_sp + 1) * (num_sp + 1)),
138 _ipiv_scratch(num_sp + 1),
139 _all_q_scratch(num_yf, yieldAndFlow(num_sp, num_intnl)),
140
141 _smoother_function_type(
142 parameters.get<MooseEnum>("smoother_function_type").getEnum<SmootherFunctionType>())
143{
144 if (_definitely_ok_sp.size() != _num_sp)
145 mooseError("MultiParameterPlasticityStressUpdate: admissible_stress parameter must consist of ",
146 _num_sp,
147 " numbers");
148}
149
150void
152{
153 _plastic_strain[_qp].zero();
154 _intnl[_qp].assign(_num_intnl, 0);
155 _yf[_qp].assign(_num_yf, 0);
156 _iter[_qp] = 0.0;
157 _max_iter_used[_qp] = 0.0;
158 _linesearch_needed[_qp] = 0.0;
159}
160
161void
168
169void
171 RankTwoTensor & inelastic_strain_increment,
172 const RankTwoTensor & rotation_increment,
173 RankTwoTensor & stress_new,
174 const RankTwoTensor & stress_old,
175 const RankFourTensor & elasticity_tensor,
176 const RankTwoTensor & /*elastic_strain_old*/,
177 bool compute_full_tangent_operator,
178 RankFourTensor & tangent_operator)
179{
180 // Size _yf[_qp] appropriately
181 _yf[_qp].assign(_num_yf, 0);
182 // _plastic_strain and _intnl are usually sized appropriately because they are stateful, but this
183 // Material may be used from a DiracKernel where stateful materials are not allowed. The best we
184 // can do is:
185 if (_intnl[_qp].size() != _num_intnl)
187
189
190 if (_t_step >= 2)
191 _step_one = false;
192
193 // initially assume an elastic deformation
194 std::copy(_intnl_old[_qp].begin(), _intnl_old[_qp].end(), _intnl[_qp].begin());
195
196 _iter[_qp] = 0.0;
198 _linesearch_needed[_qp] = 0.0;
199
200 computeStressParams(stress_new, _trial_sp);
202
203 if (yieldF(_yf[_qp]) <= _f_tol)
204 {
206 inelastic_strain_increment.zero();
208 tangent_operator = elasticity_tensor;
209 return;
210 }
211
212 _stress_trial = stress_new;
213 /* The trial stress must be inadmissible
214 * so we need to return to the yield surface. The following
215 * equations must be satisfied.
216 *
217 * 0 = rhs[0] = S[0] - S[0]^trial + ga * E[0, i] * dg/dS[i]
218 * 0 = rhs[1] = S[1] - S[1]^trial + ga * E[1, i] * dg/dS[i]
219 * ...
220 * 0 = rhs[N-1] = S[N-1] - S[N-1]^trial + ga * E[N-1, i] * dg/dS[i]
221 * 0 = rhs[N] = f(S, intnl)
222 *
223 * as well as equations defining intnl parameters as functions of
224 * stress_params, trial_stress_params and intnl_old
225 *
226 * The unknowns are S[0], ..., S[N-1], gaE, and the intnl parameters.
227 * Here gaE = ga * _En (the _En serves to make gaE similar magnitude to S)
228 * I find it convenient to solve the first N+1 equations for p, q and gaE,
229 * while substituting the "intnl parameters" equations into these during the solve process
230 */
231
232 for (auto & deriv : _dvar_dtrial)
233 deriv.assign(_num_sp, 0.0);
234
236
238
239 if (_step_one)
240 std::copy(_definitely_ok_sp.begin(), _definitely_ok_sp.end(), _ok_sp.begin());
241 else
242 computeStressParams(stress_old, _ok_sp);
243 std::copy(_intnl_old[_qp].begin(), _intnl_old[_qp].end(), _ok_intnl.begin());
244
245 // Return-map problem: must apply the following changes in stress_params,
246 // and find the returned stress_params and gaE
247 for (unsigned i = 0; i < _num_sp; ++i)
249
250 Real step_taken = 0.0; // amount of del_stress_params that we've applied and the return-map
251 // problem has succeeded
252 Real step_size = 1.0; // potentially can apply del_stress_params in substeps
253 Real gaE_total = 0.0;
254
255 // In the following sub-stepping procedure it is possible that
256 // the last step is an elastic step, and therefore _smoothed_q won't
257 // be computed on the last step, so we have to compute it.
258 bool smoothed_q_calculated = false;
259
260 while (step_taken < 1.0 && step_size >= _min_step_size)
261 {
262 if (1.0 - step_taken < step_size)
263 // prevent over-shoots of substepping
264 step_size = 1.0 - step_taken;
265
266 // trial variables in terms of admissible variables
267 for (unsigned i = 0; i < _num_sp; ++i)
268 _trial_sp[i] = _ok_sp[i] + step_size * _del_stress_params[i];
269
270 // initialize variables that are to be found via Newton-Raphson
272 Real gaE = 0.0;
273
274 // flags indicating failure of Newton-Raphson and line-search
275 int nr_failure = 0;
276 int ls_failure = 0;
277
278 // NR iterations taken in this substep
279 unsigned step_iter = 0;
280
281 // The residual-squared for the line-search
282 Real res2 = 0.0;
283
284 if (step_size < 1.0 && yieldF(_trial_sp, _ok_intnl) <= _f_tol)
285 // This is an elastic step
286 // The "step_size < 1.0" in above condition is for efficiency: we definitely
287 // know that this is a plastic step if step_size = 1.0
288 smoothed_q_calculated = false;
289 else
290 {
291 // this is a plastic step
292
293 // initialize current_sp, gaE and current_intnl based on the non-smoothed situation
295 // and find the smoothed yield function, flow potential and derivatives
297 smoothed_q_calculated = true;
299 res2 = calculateRes2(_rhs);
300
301 // Perform a Newton-Raphson with linesearch to get current_sp, gaE, and also _smoothed_q
302 while (res2 > _f_tol2 && step_iter < _max_nr_its && nr_failure == 0 && ls_failure == 0)
303 {
304 // solve the linear system and store the answer (the "updates") in rhs
306 if (nr_failure != 0)
307 break;
308
309 // handle precision loss
310 if (precisionLoss(_rhs, _current_sp, gaE))
311 {
313 {
314 Moose::err << "MultiParameterPlasticityStressUpdate: precision-loss in element "
315 << _current_elem->id() << " quadpoint=" << _qp << ". Stress_params =";
316 for (unsigned i = 0; i < _num_sp; ++i)
317 Moose::err << " " << _current_sp[i];
318 Moose::err << " gaE = " << gaE << "\n";
319 }
320 res2 = 0.0;
321 break;
322 }
323
324 // apply (parts of) the updates, re-calculate _smoothed_q, and res2
325 ls_failure = lineSearch(res2,
327 gaE,
328 _trial_sp,
330 _ok_intnl,
332 _rhs,
334 step_iter++;
335 }
336 }
337 if (res2 <= _f_tol2 && step_iter < _max_nr_its && nr_failure == 0 && ls_failure == 0 &&
338 gaE >= 0.0)
339 {
340 // this Newton-Raphson worked fine, or this was an elastic step
341 std::copy(_current_sp.begin(), _current_sp.end(), _ok_sp.begin());
342 gaE_total += gaE;
343 step_taken += step_size;
345 std::copy(_intnl[_qp].begin(), _intnl[_qp].end(), _ok_intnl.begin());
346 // calculate dp/dp_trial, dp/dq_trial, etc, for Jacobian
347 dVardTrial(!smoothed_q_calculated,
348 _trial_sp,
349 _ok_sp,
350 gaE,
351 _ok_intnl,
353 step_size,
354 compute_full_tangent_operator,
356 if (static_cast<Real>(step_iter) > _iter[_qp])
357 _iter[_qp] = static_cast<Real>(step_iter);
358 if (static_cast<Real>(step_iter) > _max_iter_used[_qp])
359 _max_iter_used[_qp] = static_cast<Real>(step_iter);
360 step_size *= 1.1;
361 }
362 else
363 {
364 // Newton-Raphson + line-search process failed
365 step_size *= 0.5;
366 }
367 }
368
369 if (step_size < _min_step_size)
370 errorHandler("MultiParameterPlasticityStressUpdate: Minimum step-size violated");
371
372 // success!
373 finalizeReturnProcess(rotation_increment);
375
376 if (!smoothed_q_calculated)
378
380 _stress_trial, _ok_sp, gaE_total, _intnl[_qp], _smoothed_q, elasticity_tensor, stress_new);
381
383 gaE_total,
386 stress_new,
387 inelastic_strain_increment);
388
389 strain_increment = strain_increment - inelastic_strain_increment;
390 _plastic_strain[_qp] = _plastic_strain_old[_qp] + inelastic_strain_increment;
391
393 // for efficiency, do not compute the tangent operator if not currently computing Jacobian
395 _trial_sp,
396 stress_new,
397 _ok_sp,
398 gaE_total,
401 compute_full_tangent_operator,
403 tangent_operator);
404}
405
407MultiParameterPlasticityStressUpdate::smoothAllQuantities(const std::vector<Real> & stress_params,
408 const std::vector<Real> & intnl) const
409{
410 mooseAssert(_all_q_scratch.size() == _num_yf,
411 "_all_q_scratch incorrectly sized in smoothAllQuantities");
412 for (auto & q : _all_q_scratch)
413 q.reset();
414 computeAllQV(stress_params, intnl, _all_q_scratch);
415
416 /* This routine holds the key to my smoothing strategy. It
417 * may be proved that this smoothing strategy produces a
418 * yield surface that is both C2 differentiable and convex,
419 * assuming the individual yield functions are C2 and
420 * convex too.
421 * Of course all the derivatives must also be smoothed.
422 * Also, I assume that d(flow potential)/dstress gets smoothed
423 * by the Yield Function (which produces a C2 flow potential).
424 * See the line identified in the loop below.
425 * Only time will tell whether this is a good strategy, but it
426 * works well in all tests so far. Convexity is irrelevant
427 * for the non-associated case, but at least the return-map
428 * problem should always have a unique solution.
429 * For two yield functions+flows, labelled 1 and 2, we
430 * should have
431 * d(g1 - g2) . d(f1 - f2) >= 0
432 * If not then the return-map problem for even the
433 * multi-surface plasticity with no smoothing won't have a
434 * unique solution. If the multi-surface plasticity has
435 * a unique solution then the smoothed version defined
436 * below will too.
437 */
438
439 // res_f is the index that contains the smoothed yieldAndFlow
440 std::size_t res_f = 0;
441
442 for (std::size_t a = 1; a < _all_q_scratch.size(); ++a)
443 {
445 // no smoothing is needed: res_f is already indexes the largest yield function
446 continue;
447 else if (_all_q_scratch[a].f >= _all_q_scratch[res_f].f + _smoothing_tol)
448 {
449 // no smoothing is needed, and res_f needs to index to _all_q_scratch[a]
450 res_f = a;
451 continue;
452 }
453 else
454 {
455 // smoothing is required
456 const Real f_diff = _all_q_scratch[res_f].f - _all_q_scratch[a].f;
457 const Real ism = ismoother(f_diff);
458 const Real sm = smoother(f_diff);
459 const Real dsm = dsmoother(f_diff);
460 // we want: _all_q_scratch[res_f].f = 0.5 * _all_q_scratch[res_f].f + _all_q_scratch[a].f +
461 // _smoothing_tol) + ism, but we have to do the derivatives first
462 for (unsigned i = 0; i < _num_sp; ++i)
463 {
464 for (unsigned j = 0; j < _num_sp; ++j)
465 _all_q_scratch[res_f].d2g[i][j] =
466 0.5 * (_all_q_scratch[res_f].d2g[i][j] + _all_q_scratch[a].d2g[i][j]) +
467 dsm * (_all_q_scratch[res_f].df[j] - _all_q_scratch[a].df[j]) *
468 (_all_q_scratch[res_f].dg[i] - _all_q_scratch[a].dg[i]) +
469 sm * (_all_q_scratch[res_f].d2g[i][j] - _all_q_scratch[a].d2g[i][j]);
470 for (unsigned j = 0; j < _num_intnl; ++j)
471 _all_q_scratch[res_f].d2g_di[i][j] =
472 0.5 * (_all_q_scratch[res_f].d2g_di[i][j] + _all_q_scratch[a].d2g_di[i][j]) +
473 dsm * (_all_q_scratch[res_f].df_di[j] - _all_q_scratch[a].df_di[j]) *
474 (_all_q_scratch[res_f].dg[i] - _all_q_scratch[a].dg[i]) +
475 sm * (_all_q_scratch[res_f].d2g_di[i][j] - _all_q_scratch[a].d2g_di[i][j]);
476 }
477 for (unsigned i = 0; i < _num_sp; ++i)
478 {
479 _all_q_scratch[res_f].df[i] =
480 0.5 * (_all_q_scratch[res_f].df[i] + _all_q_scratch[a].df[i]) +
481 sm * (_all_q_scratch[res_f].df[i] - _all_q_scratch[a].df[i]);
482 // whether the following (smoothing g with f's smoother) is a good strategy remains to be
483 // seen...
484 _all_q_scratch[res_f].dg[i] =
485 0.5 * (_all_q_scratch[res_f].dg[i] + _all_q_scratch[a].dg[i]) +
486 sm * (_all_q_scratch[res_f].dg[i] - _all_q_scratch[a].dg[i]);
487 }
488 for (unsigned i = 0; i < _num_intnl; ++i)
489 _all_q_scratch[res_f].df_di[i] =
490 0.5 * (_all_q_scratch[res_f].df_di[i] + _all_q_scratch[a].df_di[i]) +
491 sm * (_all_q_scratch[res_f].df_di[i] - _all_q_scratch[a].df_di[i]);
492 _all_q_scratch[res_f].f =
493 0.5 * (_all_q_scratch[res_f].f + _all_q_scratch[a].f + _smoothing_tol) + ism;
494 }
495 }
496 return _all_q_scratch[res_f];
497}
498
499Real
501{
502 if (std::abs(f_diff) >= _smoothing_tol)
503 return 0.0;
505 {
507 return -_smoothing_tol / M_PI * std::cos(0.5 * M_PI * f_diff / _smoothing_tol);
509 return 0.75 / _smoothing_tol *
510 (0.5 * (Utility::pow<2>(f_diff) - _smoothing_tol2) -
511 (_smoothing_tol2 / 12.0) * (Utility::pow<4>(f_diff / _smoothing_tol) - 1.0));
513 return 0.625 / _smoothing_tol *
514 (0.5 * (Utility::pow<2>(f_diff) - _smoothing_tol2) -
515 (_smoothing_tol2 / 30.0) * (Utility::pow<6>(f_diff / _smoothing_tol) - 1.0));
517 return (7.0 / 12.0 / _smoothing_tol) *
518 (0.5 * (Utility::pow<2>(f_diff) - _smoothing_tol2) -
519 (_smoothing_tol2 / 56.0) * (Utility::pow<8>(f_diff / _smoothing_tol) - 1.0));
520 default:
521 return 0.0;
522 }
523}
524
525Real
527{
528 if (std::abs(f_diff) >= _smoothing_tol)
529 return 0.0;
531 {
533 return 0.5 * std::sin(f_diff * M_PI * 0.5 / _smoothing_tol);
535 return 0.75 / _smoothing_tol *
536 (f_diff - (_smoothing_tol / 3.0) * Utility::pow<3>(f_diff / _smoothing_tol));
538 return 0.625 / _smoothing_tol *
539 (f_diff - (_smoothing_tol / 5.0) * Utility::pow<5>(f_diff / _smoothing_tol));
541 return (7.0 / 12.0 / _smoothing_tol) *
542 (f_diff - (_smoothing_tol / 7.0) * Utility::pow<7>(f_diff / _smoothing_tol));
543 default:
544 return 0.0;
545 }
546}
547
548Real
550{
551 if (std::abs(f_diff) >= _smoothing_tol)
552 return 0.0;
554 {
556 return 0.25 * M_PI / _smoothing_tol * std::cos(f_diff * M_PI * 0.5 / _smoothing_tol);
558 return 0.75 / _smoothing_tol * (1.0 - Utility::pow<2>(f_diff / _smoothing_tol));
560 return 0.625 / _smoothing_tol * (1.0 - Utility::pow<4>(f_diff / _smoothing_tol));
562 return (7.0 / 12.0 / _smoothing_tol) * (1.0 - Utility::pow<6>(f_diff / _smoothing_tol));
563 default:
564 return 0.0;
565 }
566}
567
568int
570 std::vector<Real> & stress_params,
571 Real & gaE,
572 const std::vector<Real> & trial_stress_params,
573 yieldAndFlow & smoothed_q,
574 const std::vector<Real> & intnl_ok,
575 std::vector<Real> & intnl,
576 std::vector<Real> & rhs,
577 Real & linesearch_needed) const
578{
579 const Real res2_old = res2;
580 mooseAssert(_sp_params_old_scratch.size() == _num_sp,
581 "_sp_params_old_scratch incorrectly sized in lineSearch");
582 _sp_params_old_scratch = stress_params;
583 const Real gaE_old = gaE;
584 mooseAssert(_delta_nr_params_scratch.size() == rhs.size(),
585 "_delta_nr_params_scratch incorrectly sized in lineSearch");
587
588 Real lam = 1.0; // line-search parameter
589 const Real lam_min = 1E-10; // minimum value of lam allowed
590 const Real slope = -2.0 * res2_old; // "Numerical Recipes" uses -b*A*x, in order to check for
591 // roundoff, but i hope the nrStep would warn if there were
592 // problems
593 Real tmp_lam; // cached value of lam used in quadratic & cubic line search
594 Real f2 = res2_old; // cached value of f = residual2 used in the cubic in the line search
595 Real lam2 = lam; // cached value of lam used in the cubic in the line search
596
597 while (true)
598 {
599 // update variables using the current line-search parameter
600 for (unsigned i = 0; i < _num_sp; ++i)
601 stress_params[i] = _sp_params_old_scratch[i] + lam * _delta_nr_params_scratch[i];
602 gaE = gaE_old + lam * _delta_nr_params_scratch[_num_sp];
603
604 // and internal parameters
605 setIntnlValuesV(trial_stress_params, stress_params, intnl_ok, intnl);
606
607 smoothed_q = smoothAllQuantities(stress_params, intnl);
608
609 // update rhs for next-time through
610 calculateRHS(trial_stress_params, stress_params, gaE, smoothed_q, rhs);
611 res2 = calculateRes2(rhs);
612
613 // do the line-search
614 if (res2 < res2_old + 1E-4 * lam * slope)
615 break;
616 else if (lam < lam_min)
617 return 1;
618 else if (lam == 1.0)
619 {
620 // model as a quadratic
621 tmp_lam = -0.5 * slope / (res2 - res2_old - slope);
622 }
623 else
624 {
625 // model as a cubic
626 const Real rhs1 = res2 - res2_old - lam * slope;
627 const Real rhs2 = f2 - res2_old - lam2 * slope;
628 const Real a = (rhs1 / Utility::pow<2>(lam) - rhs2 / Utility::pow<2>(lam2)) / (lam - lam2);
629 const Real b =
630 (-lam2 * rhs1 / Utility::pow<2>(lam) + lam * rhs2 / Utility::pow<2>(lam2)) / (lam - lam2);
631 if (a == 0.0)
632 tmp_lam = -slope / (2.0 * b);
633 else
634 {
635 const Real disc = Utility::pow<2>(b) - 3.0 * a * slope;
636 if (disc < 0)
637 tmp_lam = 0.5 * lam;
638 else if (b <= 0)
639 tmp_lam = (-b + std::sqrt(disc)) / (3.0 * a);
640 else
641 tmp_lam = -slope / (b + std::sqrt(disc));
642 }
643 if (tmp_lam > 0.5 * lam)
644 tmp_lam = 0.5 * lam;
645 }
646 lam2 = lam;
647 f2 = res2;
648 lam = std::max(tmp_lam, 0.1 * lam);
649 }
650
651 if (lam < 1.0)
652 linesearch_needed = 1.0;
653 return 0;
654}
655
656int
658 const std::vector<Real> & trial_stress_params,
659 const std::vector<Real> & stress_params,
660 const std::vector<Real> & intnl,
661 Real gaE,
662 std::vector<Real> & rhs) const
663{
664 mooseAssert(_dintnl_scratch.size() == _num_intnl, "_dintnl_scratch incorrectly sized in nrStep");
665 setIntnlDerivativesV(trial_stress_params, stress_params, intnl, _dintnl_scratch);
666
667 mooseAssert(_jac_scratch.size() == (_num_sp + 1) * (_num_sp + 1),
668 "_jac_scratch incorrectly sized in nrStep");
669 dnRHSdVar(smoothed_q, _dintnl_scratch, stress_params, gaE, _jac_scratch);
670
671 // use LAPACK to solve the linear system
672 const PetscBLASInt nrhs = 1;
673 mooseAssert(_ipiv_scratch.size() == _num_sp + 1, "_ipiv_scratch incorrectly sized in nrStep");
674 PetscBLASInt info;
675 const PetscBLASInt gesv_num_rhs = _num_sp + 1;
676 LAPACKgesv_(&gesv_num_rhs,
677 &nrhs,
678 &_jac_scratch[0],
679 &gesv_num_rhs,
680 &_ipiv_scratch[0],
681 &rhs[0],
682 &gesv_num_rhs,
683 &info);
684 return info;
685}
686
687void
689{
690 throw MooseException(message);
691}
692
693void
697
698void
703
704void
706 const std::vector<Real> & /*trial_stress_params*/,
707 const RankTwoTensor & /*stress_trial*/,
708 const std::vector<Real> & /*intnl_old*/,
709 const std::vector<Real> & /*yf*/,
710 const RankFourTensor & /*Eijkl*/)
711{
712}
713
714Real
715MultiParameterPlasticityStressUpdate::yieldF(const std::vector<Real> & stress_params,
716 const std::vector<Real> & intnl) const
717{
718 mooseAssert(_yfs_scratch.size() == _num_yf, "_yfs_scratch incorrectly sized in yieldF");
719 yieldFunctionValuesV(stress_params, intnl, _yfs_scratch);
720 return yieldF(_yfs_scratch);
721}
722
723Real
724MultiParameterPlasticityStressUpdate::yieldF(const std::vector<Real> & yfs) const
725{
726 Real yf = yfs[0];
727 for (std::size_t i = 1; i < yfs.size(); ++i)
728 if (yf >= yfs[i] + _smoothing_tol)
729 // no smoothing is needed, and yf is the biggest yield function
730 continue;
731 else if (yfs[i] >= yf + _smoothing_tol)
732 // no smoothing is needed, and yfs[i] is the biggest yield function
733 yf = yfs[i];
734 else
735 yf = 0.5 * (yf + yfs[i] + _smoothing_tol) + ismoother(yf - yfs[i]);
736 return yf;
737}
738
739void
740MultiParameterPlasticityStressUpdate::initializeVarsV(const std::vector<Real> & trial_stress_params,
741 const std::vector<Real> & intnl_old,
742 std::vector<Real> & stress_params,
743 Real & gaE,
744 std::vector<Real> & intnl) const
745{
746 gaE = 0.0;
747 std::copy(trial_stress_params.begin(), trial_stress_params.end(), stress_params.begin());
748 std::copy(intnl_old.begin(), intnl_old.end(), intnl.begin());
749}
750
751void
753 const RankTwoTensor & stress_trial,
754 const std::vector<Real> & /*trial_stress_params*/,
755 const RankTwoTensor & stress,
756 const std::vector<Real> & /*stress_params*/,
757 Real gaE,
758 const yieldAndFlow & smoothed_q,
759 const RankFourTensor & elasticity_tensor,
760 bool compute_full_tangent_operator,
761 const std::vector<std::vector<Real>> & dvar_dtrial,
762 RankFourTensor & cto)
763{
764 cto = elasticity_tensor;
765 if (!compute_full_tangent_operator)
766 return;
767
768 const Real ga = gaE / _En;
769
772
773 for (unsigned a = 0; a < _num_sp; ++a)
774 {
775 for (unsigned b = 0; b < _num_sp; ++b)
776 {
779 for (unsigned c = 0; c < _num_sp; ++c)
780 s -= _dsp_scratch[b] * _Cij[b][c] * dvar_dtrial[c][a];
781 s = elasticity_tensor * s;
782 cto -= s.outerProduct(t);
783 }
784 }
785
787 RankFourTensor Tijab;
788 for (unsigned i = 0; i < _num_sp; ++i)
789 Tijab += smoothed_q.dg[i] * _d2sp_scratch[i];
790 Tijab = ga * elasticity_tensor * Tijab;
791
793 try
794 {
795 inv = inv.transposeMajor().invSymm();
796 }
797 catch (const MooseException & e)
798 {
799 // Cannot form the inverse, so probably at some degenerate place in stress space.
800 // Just return with the "best estimate" of the cto.
801 mooseWarning("MultiParameterPlasticityStressUpdate: Cannot invert 1+T in consistent tangent "
802 "operator computation at quadpoint ",
803 _qp,
804 " of element ",
805 _current_elem->id());
806 return;
807 }
808
809 cto = (cto.transposeMajor() * inv).transposeMajor();
810}
811
812void
814 const RankTwoTensor & /*stress_trial*/,
815 Real gaE,
816 const yieldAndFlow & smoothed_q,
817 const RankFourTensor & /*elasticity_tensor*/,
818 const RankTwoTensor & returned_stress,
819 RankTwoTensor & inelastic_strain_increment)
820{
821 dstressparam_dstress(returned_stress, _dsp_scratch);
822 inelastic_strain_increment = RankTwoTensor();
823 for (unsigned i = 0; i < _num_sp; ++i)
824 inelastic_strain_increment += smoothed_q.dg[i] * _dsp_scratch[i];
825 inelastic_strain_increment *= gaE / _En;
826}
827
828Real
829MultiParameterPlasticityStressUpdate::calculateRes2(const std::vector<Real> & rhs) const
830{
831 Real res2 = 0.0;
832 for (const auto & r : rhs)
833 res2 += r * r;
834 return res2;
835}
836
837void
838MultiParameterPlasticityStressUpdate::calculateRHS(const std::vector<Real> & trial_stress_params,
839 const std::vector<Real> & stress_params,
840 Real gaE,
841 const yieldAndFlow & smoothed_q,
842 std::vector<Real> & rhs) const
843{
844 const Real ga = gaE / _En;
845 for (unsigned i = 0; i < _num_sp; ++i)
846 {
847 rhs[i] = stress_params[i] - trial_stress_params[i];
848 for (unsigned j = 0; j < _num_sp; ++j)
849 rhs[i] += ga * _Eij[i][j] * smoothed_q.dg[j];
850 }
851 rhs[_num_sp] = smoothed_q.f;
852}
853
854void
856 const std::vector<std::vector<Real>> & dintnl,
857 const std::vector<Real> & /*stress_params*/,
858 Real gaE,
859 std::vector<double> & jac) const
860{
861 for (auto & jac_entry : jac)
862 jac_entry = 0.0;
863
864 const Real ga = gaE / _En;
865
866 unsigned ind = 0;
867 for (unsigned var = 0; var < _num_sp; ++var)
868 {
869 for (unsigned rhs = 0; rhs < _num_sp; ++rhs)
870 {
871 if (var == rhs)
872 jac[ind] -= 1.0;
873 for (unsigned j = 0; j < _num_sp; ++j)
874 {
875 jac[ind] -= ga * _Eij[rhs][j] * smoothed_q.d2g[j][var];
876 for (unsigned k = 0; k < _num_intnl; ++k)
877 jac[ind] -= ga * _Eij[rhs][j] * smoothed_q.d2g_di[j][k] * dintnl[k][var];
878 }
879 ind++;
880 }
881 // now rhs = _num_sp (that is, the yield function)
882 jac[ind] -= smoothed_q.df[var];
883 for (unsigned k = 0; k < _num_intnl; ++k)
884 jac[ind] -= smoothed_q.df_di[k] * dintnl[k][var];
885 ind++;
886 }
887
888 // now var = _num_sp (that is, gaE)
889 for (unsigned rhs = 0; rhs < _num_sp; ++rhs)
890 {
891 for (unsigned j = 0; j < _num_sp; ++j)
892 jac[ind] -= (1.0 / _En) * _Eij[rhs][j] * smoothed_q.dg[j];
893 ind++;
894 }
895 // now rhs = _num_sp (that is, the yield function)
896 jac[ind] = 0.0;
897}
898
899void
901 const std::vector<Real> & trial_stress_params,
902 const std::vector<Real> & stress_params,
903 Real gaE,
904 const std::vector<Real> & intnl,
905 const yieldAndFlow & smoothed_q,
906 Real step_size,
907 bool compute_full_tangent_operator,
908 std::vector<std::vector<Real>> & dvar_dtrial) const
909{
911 return;
912
913 if (!compute_full_tangent_operator)
914 return;
915
916 if (elastic_only)
917 {
918 // no change to gaE, and all off-diag stuff remains unchanged from previous step
919 for (unsigned v = 0; v < _num_sp; ++v)
920 dvar_dtrial[v][v] += step_size;
921 return;
922 }
923
924 const Real ga = gaE / _En;
925
926 // the following uses heap allocations in the belief that the compute time spent on alloc/dealloc
927 // will be dwarfed by other aspects of implicit time stepping
928
929 std::vector<std::vector<Real>> dintnl(_num_intnl, std::vector<Real>(_num_sp));
930 setIntnlDerivativesV(trial_stress_params, stress_params, intnl, dintnl);
931
932 // rhs is described elsewhere, the following are changes in rhs wrt the trial_stress_param
933 // values
934 // In the following we use d(intnl)/d(trial variable) = - d(intnl)/d(variable)
935 std::vector<Real> rhs_cto((_num_sp + 1) * _num_sp);
936
937 unsigned ind = 0;
938 for (unsigned a = 0; a < _num_sp; ++a)
939 {
940 // change in RHS[b] wrt changes in stress_param_trial[a]
941 for (unsigned b = 0; b < _num_sp; ++b)
942 {
943 if (a == b)
944 rhs_cto[ind] -= 1.0;
945 for (unsigned j = 0; j < _num_sp; ++j)
946 for (unsigned k = 0; k < _num_intnl; ++k)
947 rhs_cto[ind] -= ga * _Eij[b][j] * smoothed_q.d2g_di[j][k] * dintnl[k][a];
948 ind++;
949 }
950 // now b = _num_sp (that is, the yield function)
951 for (unsigned k = 0; k < _num_intnl; ++k)
952 rhs_cto[ind] -= smoothed_q.df_di[k] * dintnl[k][a];
953 ind++;
954 }
955
956 // jac = d(-rhs)/d(var)
957 std::vector<double> jac((_num_sp + 1) * (_num_sp + 1));
958 dnRHSdVar(smoothed_q, dintnl, stress_params, gaE, jac);
959
960 std::vector<PetscBLASInt> ipiv(_num_sp + 1);
961 PetscBLASInt info;
962 const PetscBLASInt gesv_num_rhs = _num_sp + 1;
963 const PetscBLASInt gesv_num_pq = _num_sp;
964 LAPACKgesv_(&gesv_num_rhs,
965 &gesv_num_pq,
966 &jac[0],
967 &gesv_num_rhs,
968 &ipiv[0],
969 &rhs_cto[0],
970 &gesv_num_rhs,
971 &info);
972 if (info != 0)
973 errorHandler("MultiParameterPlasticityStressUpdate: PETSC LAPACK gsev routine returned with "
974 "error code " +
975 Moose::stringify(info));
976
977 ind = 0;
978 std::vector<std::vector<Real>> dvarn_dtrialn(_num_sp + 1, std::vector<Real>(_num_sp, 0.0));
979 for (unsigned spt = 0; spt < _num_sp; ++spt) // loop over trial stress-param variables
980 {
981 for (unsigned v = 0; v < _num_sp; ++v) // loop over variables in NR procedure
982 {
983 dvarn_dtrialn[v][spt] = rhs_cto[ind];
984 ind++;
985 }
986 // the final NR variable is gaE
987 dvarn_dtrialn[_num_sp][spt] = rhs_cto[ind];
988 ind++;
989 }
990
991 const std::vector<std::vector<Real>> dvar_dtrial_old = dvar_dtrial;
992
993 for (unsigned v = 0; v < _num_sp; ++v) // loop over variables in NR procedure
994 {
995 for (unsigned spt = 0; spt < _num_sp; ++spt) // loop over trial stress-param variables
996 {
997 dvar_dtrial[v][spt] = step_size * dvarn_dtrialn[v][spt];
998 for (unsigned a = 0; a < _num_sp; ++a)
999 dvar_dtrial[v][spt] += dvarn_dtrialn[v][a] * dvar_dtrial_old[a][spt];
1000 }
1001 }
1002 // for gaE the formulae are a little different
1003 const unsigned v = _num_sp;
1004 for (unsigned spt = 0; spt < _num_sp; ++spt)
1005 {
1006 dvar_dtrial[v][spt] += step_size * dvarn_dtrialn[v][spt]; // note +=
1007 for (unsigned a = 0; a < _num_sp; ++a)
1008 dvar_dtrial[v][spt] += dvarn_dtrialn[v][a] * dvar_dtrial_old[a][spt];
1009 }
1010}
1011
1012bool
1014 const std::vector<Real> & stress_params,
1015 Real gaE) const
1016{
1017 if (std::abs(solution[_num_sp]) > 1E-13 * std::abs(gaE))
1018 return false;
1019 for (unsigned i = 0; i < _num_sp; ++i)
1020 if (std::abs(solution[i]) > 1E-13 * std::abs(stress_params[i]))
1021 return false;
1022 return true;
1023}
Real f(Real x)
Test function for Brents method.
ExpressionBuilder::EBTerm pow(const ExpressionBuilder::EBTerm &left, T exponent)
const double v
void addParamNamesToGroup(const std::string &space_delim_names, const std::string group_name)
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 addRangeCheckedParam(const std::string &name, const T &value, const std::string &parsed_function, const std::string &doc_string)
FEProblemBase & _fe_problem
void mooseError(Args &&... args) const
void mooseWarning(Args &&... args) const
const std::vector< Real > _definitely_ok_sp
An admissible value of stress_params at the initial time.
const Real _min_step_size
In order to help the Newton-Raphson procedure, the applied strain increment may be applied in sub-inc...
std::vector< yieldAndFlow > _all_q_scratch
all the yield function information, for use in smoothAllQuantities, to avoid repeatedly allocating/de...
RankTwoTensor _stress_trial
"Trial" value of stress that is set at the beginning of the return-map process.
yieldAndFlow _smoothed_q
Current values of the yield function, derivatives, etc during updateState.
virtual void yieldFunctionValuesV(const std::vector< Real > &stress_params, const std::vector< Real > &intnl, std::vector< Real > &yf) const =0
Computes the values of the yield functions, given stress_params and intnl parameters.
std::vector< RankFourTensor > _d2sp_scratch
d2(stress_param[:])/d(stress)/d(stress) used in d2stressparam_dstress to avoid repeatedly allocating/...
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
MaterialProperty< Real > & _iter
Number of Newton-Raphson iterations used in the return-map.
virtual void errorHandler(const std::string &message) const
Performs any necessary cleaning-up, then throw MooseException(message)
bool _step_one
handles case of initial_stress that is inadmissible being supplied
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)
Calculates the consistent tangent operator.
std::vector< std::vector< Real > > _dvar_dtrial
d({stress_param[i], gaE})/d(trial_stress_param[j])
MaterialProperty< std::vector< Real > > & _yf
yield functions
virtual void updateState(RankTwoTensor &strain_increment, RankTwoTensor &inelastic_strain_increment, const RankTwoTensor &rotation_increment, RankTwoTensor &stress_new, const RankTwoTensor &stress_old, const RankFourTensor &elasticity_tensor, const RankTwoTensor &elastic_strain_old, bool compute_full_tangent_operator, RankFourTensor &tangent_operator) override
const unsigned _num_sp
Number of stress parameters.
const Real _smoothing_tol2
Square of the smoothing tolerance.
const MaterialProperty< std::vector< Real > > & _intnl_old
old values of internal parameters
virtual void setInelasticStrainIncrementAfterReturn(const RankTwoTensor &stress_trial, Real gaE, const yieldAndFlow &smoothed_q, const RankFourTensor &elasticity_tensor, const RankTwoTensor &returned_stress, RankTwoTensor &inelastic_strain_increment)
Sets inelastic strain increment from the returned configuration This is called after the return-map p...
MultiParameterPlasticityStressUpdate(const InputParameters &parameters, unsigned num_sp, unsigned num_yf, unsigned num_intnl)
std::vector< Real > _current_intnl
The current values of the internal params during the Newton-Raphson.
const unsigned _max_nr_its
Maximum number of Newton-Raphson iterations allowed in the return-map process.
MaterialProperty< Real > & _linesearch_needed
Whether a line-search was needed in the latest Newton-Raphson process (1 if true, 0 otherwise)
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 =0
Sets stress from the admissible parameters.
virtual void d2stressparam_dstress(const RankTwoTensor &stress, std::vector< RankFourTensor > &d2sp) const =0
d2(stress_param[i])/d(stress)/d(stress) at given stress.
Real smoother(Real f_diff) const
Derivative of ismoother.
std::vector< RankTwoTensor > _dsp_scratch
d(stress_param[:])/d(stress) used in dstressparam_dstress to avoid repeatedly allocating/deallocating...
std::vector< Real > _trial_sp
"Trial" value of stress_params that initializes the return-map process This is derived from stress = ...
Real ismoother(Real f_diff) const
Smooths yield functions.
virtual void computeStressParams(const RankTwoTensor &stress, std::vector< Real > &stress_params) const =0
Computes stress_params, given stress.
MaterialProperty< RankTwoTensor > & _plastic_strain
plastic strain
const MaterialProperty< RankTwoTensor > & _plastic_strain_old
Old value of plastic strain.
const unsigned _num_yf
Number of yield functions.
std::vector< Real > _sp_params_old_scratch
container to hold old values of old stress_params in lineSearch to avoid repeatedly allocating/deallo...
MaterialProperty< Real > & _max_iter_used
Maximum number of Newton-Raphson iterations used in the return-map during the course of the entire si...
const MaterialProperty< Real > & _max_iter_used_old
Old value of maximum number of Newton-Raphson iterations used in the return-map during the course of ...
virtual void initializeReturnProcess()
Derived classes may use this to perform calculations before any return-map process is performed,...
std::vector< RankTwoTensor > _dsp_trial_scratch
d(stress_param[:])/d(stress_trial) used in dstressparam_dstress to avoid repeatedly allocating/deallo...
std::vector< Real > _del_stress_params
_del_stress_params = trial_stress_params - ok_sp This is fixed at the beginning of the return-map pro...
std::vector< Real > _current_sp
The current values of the stress params during the Newton-Raphson.
std::vector< Real > _yfs_scratch
values of yield functions in yieldF, to avoid repeatedly allocating/deallocating this vector
Real calculateRes2(const std::vector< Real > &rhs) const
Calculates the residual-squared for the Newton-Raphson + line-search.
std::vector< double > _jac_scratch
jacobian in the NR process, to avoid repeatedly allocating/deallocating this vector
virtual void dstressparam_dstress(const RankTwoTensor &stress, std::vector< RankTwoTensor > &dsp) const =0
d(stress_param[i])/d(stress) at given stress.
virtual void setEffectiveElasticity(const RankFourTensor &Eijkl)=0
Sets _Eij and _En and _Cij.
std::vector< Real > _delta_nr_params_scratch
container to hold initial values of rhs in lineSearch to avoid repeatedly allocating/deallocating thi...
virtual void computeAllQV(const std::vector< Real > &stress_params, const std::vector< Real > &intnl, std::vector< yieldAndFlow > &all_q) const =0
Completely fills all_q with correct values.
void calculateRHS(const std::vector< Real > &trial_stress_params, const std::vector< Real > &stress_params, Real gaE, const yieldAndFlow &smoothed_q, std::vector< Real > &rhs) const
Calculates the RHS in the following 0 = rhs[0] = S[0] - S[0]^trial + ga * E[0, j] * dg/dS[j] 0 = rhs[...
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)
Derived classes may employ this function to record stuff or do other computations prior to the return...
Real dsmoother(Real f_diff) const
Derivative of smoother.
void dVardTrial(bool elastic_only, const std::vector< Real > &trial_stress_params, const std::vector< Real > &stress_params, Real gaE, const std::vector< Real > &intnl, const yieldAndFlow &smoothed_q, Real step_size, bool compute_full_tangent_operator, std::vector< std::vector< Real > > &dvar_dtrial) const
Calculates derivatives of the stress_params and gaE with repect to the trial values of the stress_par...
void dnRHSdVar(const yieldAndFlow &smoothed_q, const std::vector< std::vector< Real > > &dintnl, const std::vector< Real > &stress_params, Real gaE, std::vector< double > &jac) const
Derivative of -RHS with respect to the stress_params and gaE, placed into an array ready for solving ...
std::vector< PetscBLASInt > _ipiv_scratch
container to hold LAPACK ipiv integers, to avoid repeatedly allocating/deallocating this vector
const bool _warn_about_precision_loss
Output a warning message if precision loss is encountered during the return-map process.
Real yieldF(const std::vector< Real > &stress_params, const std::vector< Real > &intnl) const
Computes the smoothed yield function.
yieldAndFlow smoothAllQuantities(const std::vector< Real > &stress_params, const std::vector< Real > &intnl) const
Calculates all yield functions and derivatives, and then performs the smoothing scheme.
virtual 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 =0
Sets the derivatives of internal parameters, based on the trial values of stress_params,...
const Real _smoothing_tol
Smoothing tolerance: edges of the yield surface get smoothed by this amount.
bool precisionLoss(const std::vector< Real > &solution, const std::vector< Real > &stress_params, Real gaE) const
Check whether precision loss has occurred.
std::vector< Real > _rhs
0 = rhs[0] = S[0] - S[0]^trial + ga * E[0, i] * dg/dS[i] 0 = rhs[1] = S[1] - S[1]^trial + ga * E[1,...
virtual 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 =0
Sets the internal parameters based on the trial values of stress_params, their current values,...
const unsigned _num_intnl
Number of internal parameters.
std::vector< Real > _ok_intnl
The state (ok_sp, ok_intnl) is known to be admissible.
int lineSearch(Real &res2, std::vector< Real > &stress_params, Real &gaE, const std::vector< Real > &trial_stress_params, yieldAndFlow &smoothed_q, const std::vector< Real > &intnl_ok, std::vector< Real > &intnl, std::vector< Real > &rhs, Real &linesearch_needed) const
Performs a line-search to find stress_params and gaE Upon entry:
int nrStep(const yieldAndFlow &smoothed_q, const std::vector< Real > &trial_stress_params, const std::vector< Real > &stress_params, const std::vector< Real > &intnl, Real gaE, std::vector< Real > &rhs) const
Performs a Newton-Raphson step to attempt to zero rhs Upon return, rhs will contain the solution.
virtual void finalizeReturnProcess(const RankTwoTensor &rotation_increment)
Derived classes may use this to perform calculations after the return-map process has completed succe...
MaterialProperty< std::vector< Real > > & _intnl
internal parameters
std::vector< Real > _ok_sp
The state (ok_sp, ok_intnl) is known to be admissible, so ok_sp are stress_params that are "OK".
virtual 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
Sets (stress_params, intnl) at "good guesses" of the solution to the Return-Map algorithm.
virtual void propagateQpStatefulProperties() override
If updateState is not called during a timestep, this will be.
const Real _f_tol2
Square of the yield-function tolerance.
enum MultiParameterPlasticityStressUpdate::SmootherFunctionType _smoother_function_type
std::vector< std::vector< Real > > _dintnl_scratch
derivative of internal parameters with respect to stress parameters, to avoid repeatedly allocating/d...
RankFourTensorTempl< T > transposeMajor() const
RankFourTensorTempl< T > outerProduct(const RankTwoTensorTempl< T > &b) const
StressUpdateBase is a material that is not called by MOOSE because of the compute=false flag set in t...
static InputParameters validParams()
const Elem *const & _current_elem
const bool & currentlyComputingJacobian() const
int & _t_step
std::string stringify(const T &t)
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...