https://mooseframework.inl.gov
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 
150 void
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 
161 void
163 {
165  std::copy(_intnl_old[_qp].begin(), _intnl_old[_qp].end(), _intnl[_qp].begin());
167 }
168 
169 void
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)
248  _del_stress_params[i] = _trial_sp[i] - _ok_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,
326  _current_sp,
327  gaE,
328  _trial_sp,
329  _smoothed_q,
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,
352  _smoothed_q,
353  step_size,
354  compute_full_tangent_operator,
355  _dvar_dtrial);
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,
384  _smoothed_q,
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,
399  _smoothed_q,
401  compute_full_tangent_operator,
402  _dvar_dtrial,
403  tangent_operator);
404 }
405 
407 MultiParameterPlasticityStressUpdate::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  {
444  if (_all_q_scratch[res_f].f >= _all_q_scratch[a].f + _smoothing_tol)
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 
499 Real
501 {
502  if (std::abs(f_diff) >= _smoothing_tol)
503  return 0.0;
504  switch (_smoother_function_type)
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 
525 Real
527 {
528  if (std::abs(f_diff) >= _smoothing_tol)
529  return 0.0;
530  switch (_smoother_function_type)
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 
548 Real
550 {
551  if (std::abs(f_diff) >= _smoothing_tol)
552  return 0.0;
553  switch (_smoother_function_type)
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 
568 int
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 
656 int
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 
687 void
689 {
690  throw MooseException(message);
691 }
692 
693 void
695 {
696 }
697 
698 void
700  const RankTwoTensor & /*rotation_increment*/)
701 {
702 }
703 
704 void
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 
714 Real
715 MultiParameterPlasticityStressUpdate::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 
723 Real
724 MultiParameterPlasticityStressUpdate::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 
739 void
740 MultiParameterPlasticityStressUpdate::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 
751 void
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  {
778  RankTwoTensor s = _Cij[b][a] * _dsp_scratch[b];
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 
812 void
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 
828 Real
829 MultiParameterPlasticityStressUpdate::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 
837 void
838 MultiParameterPlasticityStressUpdate::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 
854 void
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 
899 void
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 " +
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 
1012 bool
1013 MultiParameterPlasticityStressUpdate::precisionLoss(const std::vector<Real> & solution,
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 }
const Real _smoothing_tol2
Square of the smoothing tolerance.
std::vector< yieldAndFlow > _all_q_scratch
all the yield function information, for use in smoothAllQuantities, to avoid repeatedly allocating/de...
yieldAndFlow _smoothed_q
Current values of the yield function, derivatives, etc during updateState.
FEProblemBase & _fe_problem
MaterialProperty< std::vector< Real > > & _yf
yield functions
std::vector< Real > _trial_sp
"Trial" value of stress_params that initializes the return-map process This is derived from stress = ...
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 ...
MultiParameterPlasticityStressUpdate(const InputParameters &parameters, unsigned num_sp, unsigned num_yf, unsigned num_intnl)
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
MPI_Info info
virtual void setEffectiveElasticity(const RankFourTensor &Eijkl)=0
Sets _Eij and _En and _Cij.
const bool _warn_about_precision_loss
Output a warning message if precision loss is encountered during the return-map process.
std::vector< PetscBLASInt > _ipiv_scratch
container to hold LAPACK ipiv integers, to avoid repeatedly allocating/deallocating this vector ...
virtual void errorHandler(const std::string &message) const
Performs any necessary cleaning-up, then throw MooseException(message)
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.
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:
std::vector< Real > _sp_params_old_scratch
container to hold old values of old stress_params in lineSearch to avoid repeatedly allocating/deallo...
const unsigned _num_intnl
Number of internal parameters.
Struct designed to hold info about a single yield function and its derivatives, as well as the flow d...
const double v
std::vector< std::vector< Real > > _Cij
_Cij[i, j] * _Eij[j, k] = 1 iff j == k
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.
static InputParameters validParams()
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...
std::vector< Real > _ok_intnl
The state (ok_sp, ok_intnl) is known to be admissible.
const Real _f_tol2
Square of the yield-function tolerance.
const Real _min_step_size
In order to help the Newton-Raphson procedure, the applied strain increment may be applied in sub-inc...
Real smoother(Real f_diff) const
Derivative of ismoother.
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...
void addRequiredParam(const std::string &name, const std::string &doc_string)
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 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
MaterialProperty< std::vector< Real > > & _intnl
internal parameters
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.
Real elasticity_tensor(unsigned int i, unsigned int j, unsigned int k, unsigned int l)
unsigned int _qp
std::vector< std::vector< Real > > _Eij
E[i, j] in the system of equations to be solved.
const Real _f_tol
The yield-function tolerance.
const unsigned _num_yf
Number of yield functions.
std::vector< Real > _yfs_scratch
values of yield functions in yieldF, to avoid repeatedly allocating/deallocating this vector ...
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.
int & _t_step
const std::vector< Real > _definitely_ok_sp
An admissible value of stress_params at the initial time.
const MaterialProperty< std::vector< Real > > & _intnl_old
old values of internal parameters
RankTwoTensor _stress_trial
"Trial" value of stress that is set at the beginning of the return-map process.
Real deriv(unsigned n, unsigned alpha, unsigned beta, Real x)
virtual void propagateQpStatefulProperties() override
If updateState is not called during a timestep, this will be.
Real f(Real x)
Test function for Brents method.
virtual void computeStressParams(const RankTwoTensor &stress, std::vector< Real > &stress_params) const =0
Computes stress_params, given stress.
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 ...
std::vector< double > _jac_scratch
jacobian in the NR process, 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.
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, their current values, and the current values of the internal parameters.
RankFourTensorTempl< T > transposeMajor() const
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.
StressUpdateBase is a material that is not called by MOOSE because of the compute=false flag set in t...
std::string stringify(const T &t)
Real dsmoother(Real f_diff) const
Derivative of smoother.
enum MultiParameterPlasticityStressUpdate::SmootherFunctionType _smoother_function_type
MaterialProperty< Real > & _iter
Number of Newton-Raphson iterations used in the return-map.
virtual void d2stressparam_dstress(const RankTwoTensor &stress, std::vector< RankFourTensor > &d2sp) const =0
d2(stress_param[i])/d(stress)/d(stress) at given stress.
MaterialProperty< RankTwoTensor > & _plastic_strain
plastic strain
const Real _smoothing_tol
Smoothing tolerance: edges of the yield surface get smoothed by this amount.
std::vector< Real > _current_intnl
The current values of the internal params during the Newton-Raphson.
virtual void finalizeReturnProcess(const RankTwoTensor &rotation_increment)
Derived classes may use this to perform calculations after the return-map process has completed succe...
ExpressionBuilder::EBTerm pow(const ExpressionBuilder::EBTerm &left, T exponent)
virtual void dstressparam_dstress(const RankTwoTensor &stress, std::vector< RankTwoTensor > &dsp) const =0
d(stress_param[i])/d(stress) at given stress.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
static const std::string message
MaterialProperty< Real > & _linesearch_needed
Whether a line-search was needed in the latest Newton-Raphson process (1 if true, 0 otherwise) ...
std::vector< std::vector< Real > > _dvar_dtrial
d({stress_param[i], gaE})/d(trial_stress_param[j])
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...
std::vector< Real > _delta_nr_params_scratch
container to hold initial values of rhs in lineSearch to avoid repeatedly allocating/deallocating thi...
void mooseWarning(Args &&... args) const
std::vector< Real > _current_sp
The current values of the stress params during the Newton-Raphson.
bool _step_one
handles case of initial_stress that is inadmissible being supplied
void mooseError(Args &&... args) const
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 addClassDescription(const std::string &doc_string)
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
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 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...
void addRangeCheckedParam(const std::string &name, const T &value, const std::string &parsed_function, const std::string &doc_string)
MaterialProperty< Real > & _max_iter_used
Maximum number of Newton-Raphson iterations used in the return-map during the course of the entire si...
std::vector< std::vector< Real > > _dintnl_scratch
derivative of internal parameters with respect to stress parameters, to avoid repeatedly allocating/d...
bool precisionLoss(const std::vector< Real > &solution, const std::vector< Real > &stress_params, Real gaE) const
Check whether precision loss has occurred.
std::vector< RankTwoTensor > _dsp_trial_scratch
d(stress_param[:])/d(stress_trial) used in dstressparam_dstress to avoid repeatedly allocating/deallo...
const bool & currentlyComputingJacobian() const
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...
const unsigned _max_nr_its
Maximum number of Newton-Raphson iterations allowed in the return-map process.
virtual void initializeReturnProcess()
Derived classes may use this to perform calculations before any return-map process is performed...
const MaterialProperty< RankTwoTensor > & _plastic_strain_old
Old value of plastic strain.
RankFourTensorTempl< T > invSymm() const
static const std::string k
Definition: NS.h:134
Real yieldF(const std::vector< Real > &stress_params, const std::vector< Real > &intnl) const
Computes the smoothed yield function.
std::vector< RankFourTensor > _d2sp_scratch
d2(stress_param[:])/d(stress)/d(stress) used in d2stressparam_dstress to avoid repeatedly allocating/...
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...
const Elem & get(const ElemType type_in)
const Elem *const & _current_elem
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"...
std::vector< RankTwoTensor > _dsp_scratch
d(stress_param[:])/d(stress) used in dstressparam_dstress to avoid repeatedly allocating/deallocating...
const unsigned _num_sp
Number of stress parameters.
void addParamNamesToGroup(const std::string &space_delim_names, const std::string group_name)
Real ismoother(Real f_diff) const
Smooths yield functions.