www.mooseframework.org
MultiParameterPlasticityStressUpdate.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://www.mooseframework.org
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  _smoother_function_type(
130  parameters.get<MooseEnum>("smoother_function_type").getEnum<SmootherFunctionType>())
131 {
132  if (_definitely_ok_sp.size() != _num_sp)
133  mooseError("MultiParameterPlasticityStressUpdate: admissible_stress parameter must consist of ",
134  _num_sp,
135  " numbers");
136 }
137 
138 void
140 {
141  _plastic_strain[_qp].zero();
142  _intnl[_qp].assign(_num_intnl, 0);
143  _yf[_qp].assign(_num_yf, 0);
144  _iter[_qp] = 0.0;
145  _max_iter_used[_qp] = 0.0;
146  _linesearch_needed[_qp] = 0.0;
147 }
148 
149 void
151 {
153  std::copy(_intnl_old[_qp].begin(), _intnl_old[_qp].end(), _intnl[_qp].begin());
155 }
156 
157 void
159  RankTwoTensor & inelastic_strain_increment,
160  const RankTwoTensor & rotation_increment,
161  RankTwoTensor & stress_new,
162  const RankTwoTensor & stress_old,
163  const RankFourTensor & elasticity_tensor,
164  const RankTwoTensor & /*elastic_strain_old*/,
165  bool compute_full_tangent_operator,
166  RankFourTensor & tangent_operator)
167 {
168  // Size _yf[_qp] appropriately
169  _yf[_qp].assign(_num_yf, 0);
170  // _plastic_strain and _intnl are usually sized appropriately because they are stateful, but this
171  // Material may be used from a DiracKernel where stateful materials are not allowed. The best we
172  // can do is:
173  if (_intnl[_qp].size() != _num_intnl)
175 
177 
178  if (_t_step >= 2)
179  _step_one = false;
180 
181  // initially assume an elastic deformation
182  std::copy(_intnl_old[_qp].begin(), _intnl_old[_qp].end(), _intnl[_qp].begin());
183 
184  _iter[_qp] = 0.0;
186  _linesearch_needed[_qp] = 0.0;
187 
188  computeStressParams(stress_new, _trial_sp);
190 
191  if (yieldF(_yf[_qp]) <= _f_tol)
192  {
194  inelastic_strain_increment.zero();
196  tangent_operator = elasticity_tensor;
197  return;
198  }
199 
200  _stress_trial = stress_new;
201  /* The trial stress must be inadmissible
202  * so we need to return to the yield surface. The following
203  * equations must be satisfied.
204  *
205  * 0 = rhs[0] = S[0] - S[0]^trial + ga * E[0, i] * dg/dS[i]
206  * 0 = rhs[1] = S[1] - S[1]^trial + ga * E[1, i] * dg/dS[i]
207  * ...
208  * 0 = rhs[N-1] = S[N-1] - S[N-1]^trial + ga * E[N-1, i] * dg/dS[i]
209  * 0 = rhs[N] = f(S, intnl)
210  *
211  * as well as equations defining intnl parameters as functions of
212  * stress_params, trial_stress_params and intnl_old
213  *
214  * The unknowns are S[0], ..., S[N-1], gaE, and the intnl parameters.
215  * Here gaE = ga * _En (the _En serves to make gaE similar magnitude to S)
216  * I find it convenient to solve the first N+1 equations for p, q and gaE,
217  * while substituting the "intnl parameters" equations into these during the solve process
218  */
219 
220  for (auto & deriv : _dvar_dtrial)
221  deriv.assign(_num_sp, 0.0);
222 
224 
226 
227  if (_step_one)
228  std::copy(_definitely_ok_sp.begin(), _definitely_ok_sp.end(), _ok_sp.begin());
229  else
230  computeStressParams(stress_old, _ok_sp);
231  std::copy(_intnl_old[_qp].begin(), _intnl_old[_qp].end(), _ok_intnl.begin());
232 
233  // Return-map problem: must apply the following changes in stress_params,
234  // and find the returned stress_params and gaE
235  for (unsigned i = 0; i < _num_sp; ++i)
236  _del_stress_params[i] = _trial_sp[i] - _ok_sp[i];
237 
238  Real step_taken = 0.0; // amount of del_stress_params that we've applied and the return-map
239  // problem has succeeded
240  Real step_size = 1.0; // potentially can apply del_stress_params in substeps
241  Real gaE_total = 0.0;
242 
243  // current values of the yield function, derivatives, etc
244  yieldAndFlow smoothed_q;
245 
246  // In the following sub-stepping procedure it is possible that
247  // the last step is an elastic step, and therefore smoothed_q won't
248  // be computed on the last step, so we have to compute it.
249  bool smoothed_q_calculated = false;
250 
251  while (step_taken < 1.0 && step_size >= _min_step_size)
252  {
253  if (1.0 - step_taken < step_size)
254  // prevent over-shoots of substepping
255  step_size = 1.0 - step_taken;
256 
257  // trial variables in terms of admissible variables
258  for (unsigned i = 0; i < _num_sp; ++i)
259  _trial_sp[i] = _ok_sp[i] + step_size * _del_stress_params[i];
260 
261  // initialize variables that are to be found via Newton-Raphson
263  Real gaE = 0.0;
264 
265  // flags indicating failure of Newton-Raphson and line-search
266  int nr_failure = 0;
267  int ls_failure = 0;
268 
269  // NR iterations taken in this substep
270  unsigned step_iter = 0;
271 
272  // The residual-squared for the line-search
273  Real res2 = 0.0;
274 
275  if (step_size < 1.0 && yieldF(_trial_sp, _ok_intnl) <= _f_tol)
276  // This is an elastic step
277  // The "step_size < 1.0" in above condition is for efficiency: we definitely
278  // know that this is a plastic step if step_size = 1.0
279  smoothed_q_calculated = false;
280  else
281  {
282  // this is a plastic step
283 
284  // initialize current_sp, gaE and current_intnl based on the non-smoothed situation
286  // and find the smoothed yield function, flow potential and derivatives
288  smoothed_q_calculated = true;
289  calculateRHS(_trial_sp, _current_sp, gaE, smoothed_q, _rhs);
290  res2 = calculateRes2(_rhs);
291 
292  // Perform a Newton-Raphson with linesearch to get current_sp, gaE, and also smoothed_q
293  while (res2 > _f_tol2 && step_iter < _max_nr_its && nr_failure == 0 && ls_failure == 0)
294  {
295  // solve the linear system and store the answer (the "updates") in rhs
296  nr_failure = nrStep(smoothed_q, _trial_sp, _current_sp, _current_intnl, gaE, _rhs);
297  if (nr_failure != 0)
298  break;
299 
300  // handle precision loss
301  if (precisionLoss(_rhs, _current_sp, gaE))
302  {
304  {
305  Moose::err << "MultiParameterPlasticityStressUpdate: precision-loss in element "
306  << _current_elem->id() << " quadpoint=" << _qp << ". Stress_params =";
307  for (unsigned i = 0; i < _num_sp; ++i)
308  Moose::err << " " << _current_sp[i];
309  Moose::err << " gaE = " << gaE << "\n";
310  }
311  res2 = 0.0;
312  break;
313  }
314 
315  // apply (parts of) the updates, re-calculate smoothed_q, and res2
316  ls_failure = lineSearch(res2,
317  _current_sp,
318  gaE,
319  _trial_sp,
320  smoothed_q,
321  _ok_intnl,
323  _rhs,
325  step_iter++;
326  }
327  }
328  if (res2 <= _f_tol2 && step_iter < _max_nr_its && nr_failure == 0 && ls_failure == 0 &&
329  gaE >= 0.0)
330  {
331  // this Newton-Raphson worked fine, or this was an elastic step
332  std::copy(_current_sp.begin(), _current_sp.end(), _ok_sp.begin());
333  gaE_total += gaE;
334  step_taken += step_size;
336  std::copy(_intnl[_qp].begin(), _intnl[_qp].end(), _ok_intnl.begin());
337  // calculate dp/dp_trial, dp/dq_trial, etc, for Jacobian
338  dVardTrial(!smoothed_q_calculated,
339  _trial_sp,
340  _ok_sp,
341  gaE,
342  _ok_intnl,
343  smoothed_q,
344  step_size,
345  compute_full_tangent_operator,
346  _dvar_dtrial);
347  if (static_cast<Real>(step_iter) > _iter[_qp])
348  _iter[_qp] = static_cast<Real>(step_iter);
349  if (static_cast<Real>(step_iter) > _max_iter_used[_qp])
350  _max_iter_used[_qp] = static_cast<Real>(step_iter);
351  step_size *= 1.1;
352  }
353  else
354  {
355  // Newton-Raphson + line-search process failed
356  step_size *= 0.5;
357  }
358  }
359 
360  if (step_size < _min_step_size)
361  errorHandler("MultiParameterPlasticityStressUpdate: Minimum step-size violated");
362 
363  // success!
364  finalizeReturnProcess(rotation_increment);
366 
367  if (!smoothed_q_calculated)
368  smoothed_q = smoothAllQuantities(_ok_sp, _intnl[_qp]);
369 
371  _stress_trial, _ok_sp, gaE_total, _intnl[_qp], smoothed_q, elasticity_tensor, stress_new);
372 
374  gaE_total,
375  smoothed_q,
377  stress_new,
378  inelastic_strain_increment);
379 
380  strain_increment = strain_increment - inelastic_strain_increment;
381  _plastic_strain[_qp] = _plastic_strain_old[_qp] + inelastic_strain_increment;
382 
384  // for efficiency, do not compute the tangent operator if not currently computing Jacobian
386  _trial_sp,
387  stress_new,
388  _ok_sp,
389  gaE_total,
390  smoothed_q,
392  compute_full_tangent_operator,
393  _dvar_dtrial,
394  tangent_operator);
395 }
396 
398 MultiParameterPlasticityStressUpdate::smoothAllQuantities(const std::vector<Real> & stress_params,
399  const std::vector<Real> & intnl) const
400 {
401  std::vector<yieldAndFlow> all_q(_num_yf, yieldAndFlow(_num_sp, _num_intnl));
402  computeAllQV(stress_params, intnl, all_q);
403 
404  /* This routine holds the key to my smoothing strategy. It
405  * may be proved that this smoothing strategy produces a
406  * yield surface that is both C2 differentiable and convex,
407  * assuming the individual yield functions are C2 and
408  * convex too.
409  * Of course all the derivatives must also be smoothed.
410  * Also, I assume that d(flow potential)/dstress gets smoothed
411  * by the Yield Function (which produces a C2 flow potential).
412  * See the line identified in the loop below.
413  * Only time will tell whether this is a good strategy, but it
414  * works well in all tests so far. Convexity is irrelevant
415  * for the non-associated case, but at least the return-map
416  * problem should always have a unique solution.
417  * For two yield functions+flows, labelled 1 and 2, we
418  * should have
419  * d(g1 - g2) . d(f1 - f2) >= 0
420  * If not then the return-map problem for even the
421  * multi-surface plasticity with no smoothing won't have a
422  * unique solution. If the multi-surface plasticity has
423  * a unique solution then the smoothed version defined
424  * below will too.
425  */
426 
427  // res_f is the index that contains the smoothed yieldAndFlow
428  std::size_t res_f = 0;
429 
430  for (std::size_t a = 1; a < all_q.size(); ++a)
431  {
432  if (all_q[res_f].f >= all_q[a].f + _smoothing_tol)
433  // no smoothing is needed: res_f is already indexes the largest yield function
434  continue;
435  else if (all_q[a].f >= all_q[res_f].f + _smoothing_tol)
436  {
437  // no smoothing is needed, and res_f needs to index to all_q[a]
438  res_f = a;
439  continue;
440  }
441  else
442  {
443  // smoothing is required
444  const Real f_diff = all_q[res_f].f - all_q[a].f;
445  const Real ism = ismoother(f_diff);
446  const Real sm = smoother(f_diff);
447  const Real dsm = dsmoother(f_diff);
448  // we want: all_q[res_f].f = 0.5 * all_q[res_f].f + all_q[a].f + _smoothing_tol) + ism,
449  // but we have to do the derivatives first
450  for (unsigned i = 0; i < _num_sp; ++i)
451  {
452  for (unsigned j = 0; j < _num_sp; ++j)
453  all_q[res_f].d2g[i][j] =
454  0.5 * (all_q[res_f].d2g[i][j] + all_q[a].d2g[i][j]) +
455  dsm * (all_q[res_f].df[j] - all_q[a].df[j]) * (all_q[res_f].dg[i] - all_q[a].dg[i]) +
456  sm * (all_q[res_f].d2g[i][j] - all_q[a].d2g[i][j]);
457  for (unsigned j = 0; j < _num_intnl; ++j)
458  all_q[res_f].d2g_di[i][j] = 0.5 * (all_q[res_f].d2g_di[i][j] + all_q[a].d2g_di[i][j]) +
459  dsm * (all_q[res_f].df_di[j] - all_q[a].df_di[j]) *
460  (all_q[res_f].dg[i] - all_q[a].dg[i]) +
461  sm * (all_q[res_f].d2g_di[i][j] - all_q[a].d2g_di[i][j]);
462  }
463  for (unsigned i = 0; i < _num_sp; ++i)
464  {
465  all_q[res_f].df[i] = 0.5 * (all_q[res_f].df[i] + all_q[a].df[i]) +
466  sm * (all_q[res_f].df[i] - all_q[a].df[i]);
467  // whether the following (smoothing g with f's smoother) is a good strategy remains to be
468  // seen...
469  all_q[res_f].dg[i] = 0.5 * (all_q[res_f].dg[i] + all_q[a].dg[i]) +
470  sm * (all_q[res_f].dg[i] - all_q[a].dg[i]);
471  }
472  for (unsigned i = 0; i < _num_intnl; ++i)
473  all_q[res_f].df_di[i] = 0.5 * (all_q[res_f].df_di[i] + all_q[a].df_di[i]) +
474  sm * (all_q[res_f].df_di[i] - all_q[a].df_di[i]);
475  all_q[res_f].f = 0.5 * (all_q[res_f].f + all_q[a].f + _smoothing_tol) + ism;
476  }
477  }
478  return all_q[res_f];
479 }
480 
481 Real
483 {
484  if (std::abs(f_diff) >= _smoothing_tol)
485  return 0.0;
486  switch (_smoother_function_type)
487  {
489  return -_smoothing_tol / M_PI * std::cos(0.5 * M_PI * f_diff / _smoothing_tol);
491  return 0.75 / _smoothing_tol *
492  (0.5 * (Utility::pow<2>(f_diff) - _smoothing_tol2) -
493  (_smoothing_tol2 / 12.0) * (Utility::pow<4>(f_diff / _smoothing_tol) - 1.0));
495  return 0.625 / _smoothing_tol *
496  (0.5 * (Utility::pow<2>(f_diff) - _smoothing_tol2) -
497  (_smoothing_tol2 / 30.0) * (Utility::pow<6>(f_diff / _smoothing_tol) - 1.0));
499  return (7.0 / 12.0 / _smoothing_tol) *
500  (0.5 * (Utility::pow<2>(f_diff) - _smoothing_tol2) -
501  (_smoothing_tol2 / 56.0) * (Utility::pow<8>(f_diff / _smoothing_tol) - 1.0));
502  default:
503  return 0.0;
504  }
505 }
506 
507 Real
509 {
510  if (std::abs(f_diff) >= _smoothing_tol)
511  return 0.0;
512  switch (_smoother_function_type)
513  {
515  return 0.5 * std::sin(f_diff * M_PI * 0.5 / _smoothing_tol);
517  return 0.75 / _smoothing_tol *
518  (f_diff - (_smoothing_tol / 3.0) * Utility::pow<3>(f_diff / _smoothing_tol));
520  return 0.625 / _smoothing_tol *
521  (f_diff - (_smoothing_tol / 5.0) * Utility::pow<5>(f_diff / _smoothing_tol));
523  return (7.0 / 12.0 / _smoothing_tol) *
524  (f_diff - (_smoothing_tol / 7.0) * Utility::pow<7>(f_diff / _smoothing_tol));
525  default:
526  return 0.0;
527  }
528 }
529 
530 Real
532 {
533  if (std::abs(f_diff) >= _smoothing_tol)
534  return 0.0;
535  switch (_smoother_function_type)
536  {
538  return 0.25 * M_PI / _smoothing_tol * std::cos(f_diff * M_PI * 0.5 / _smoothing_tol);
540  return 0.75 / _smoothing_tol * (1.0 - Utility::pow<2>(f_diff / _smoothing_tol));
542  return 0.625 / _smoothing_tol * (1.0 - Utility::pow<4>(f_diff / _smoothing_tol));
544  return (7.0 / 12.0 / _smoothing_tol) * (1.0 - Utility::pow<6>(f_diff / _smoothing_tol));
545  default:
546  return 0.0;
547  }
548 }
549 
550 int
552  std::vector<Real> & stress_params,
553  Real & gaE,
554  const std::vector<Real> & trial_stress_params,
555  yieldAndFlow & smoothed_q,
556  const std::vector<Real> & intnl_ok,
557  std::vector<Real> & intnl,
558  std::vector<Real> & rhs,
559  Real & linesearch_needed) const
560 {
561  const Real res2_old = res2;
562  const std::vector<Real> sp_params_old = stress_params;
563  const Real gaE_old = gaE;
564  const std::vector<Real> delta_nr_params = rhs;
565 
566  Real lam = 1.0; // line-search parameter
567  const Real lam_min = 1E-10; // minimum value of lam allowed
568  const Real slope = -2.0 * res2_old; // "Numerical Recipes" uses -b*A*x, in order to check for
569  // roundoff, but i hope the nrStep would warn if there were
570  // problems
571  Real tmp_lam; // cached value of lam used in quadratic & cubic line search
572  Real f2 = res2_old; // cached value of f = residual2 used in the cubic in the line search
573  Real lam2 = lam; // cached value of lam used in the cubic in the line search
574 
575  while (true)
576  {
577  // update variables using the current line-search parameter
578  for (unsigned i = 0; i < _num_sp; ++i)
579  stress_params[i] = sp_params_old[i] + lam * delta_nr_params[i];
580  gaE = gaE_old + lam * delta_nr_params[_num_sp];
581 
582  // and internal parameters
583  setIntnlValuesV(trial_stress_params, stress_params, intnl_ok, intnl);
584 
585  smoothed_q = smoothAllQuantities(stress_params, intnl);
586 
587  // update rhs for next-time through
588  calculateRHS(trial_stress_params, stress_params, gaE, smoothed_q, rhs);
589  res2 = calculateRes2(rhs);
590 
591  // do the line-search
592  if (res2 < res2_old + 1E-4 * lam * slope)
593  break;
594  else if (lam < lam_min)
595  return 1;
596  else if (lam == 1.0)
597  {
598  // model as a quadratic
599  tmp_lam = -0.5 * slope / (res2 - res2_old - slope);
600  }
601  else
602  {
603  // model as a cubic
604  const Real rhs1 = res2 - res2_old - lam * slope;
605  const Real rhs2 = f2 - res2_old - lam2 * slope;
606  const Real a = (rhs1 / Utility::pow<2>(lam) - rhs2 / Utility::pow<2>(lam2)) / (lam - lam2);
607  const Real b =
608  (-lam2 * rhs1 / Utility::pow<2>(lam) + lam * rhs2 / Utility::pow<2>(lam2)) / (lam - lam2);
609  if (a == 0.0)
610  tmp_lam = -slope / (2.0 * b);
611  else
612  {
613  const Real disc = Utility::pow<2>(b) - 3.0 * a * slope;
614  if (disc < 0)
615  tmp_lam = 0.5 * lam;
616  else if (b <= 0)
617  tmp_lam = (-b + std::sqrt(disc)) / (3.0 * a);
618  else
619  tmp_lam = -slope / (b + std::sqrt(disc));
620  }
621  if (tmp_lam > 0.5 * lam)
622  tmp_lam = 0.5 * lam;
623  }
624  lam2 = lam;
625  f2 = res2;
626  lam = std::max(tmp_lam, 0.1 * lam);
627  }
628 
629  if (lam < 1.0)
630  linesearch_needed = 1.0;
631  return 0;
632 }
633 
634 int
636  const std::vector<Real> & trial_stress_params,
637  const std::vector<Real> & stress_params,
638  const std::vector<Real> & intnl,
639  Real gaE,
640  std::vector<Real> & rhs) const
641 {
642  std::vector<std::vector<Real>> dintnl(_num_intnl, std::vector<Real>(_num_sp));
643  setIntnlDerivativesV(trial_stress_params, stress_params, intnl, dintnl);
644 
645  std::vector<double> jac((_num_sp + 1) * (_num_sp + 1));
646  dnRHSdVar(smoothed_q, dintnl, stress_params, gaE, jac);
647 
648  // use LAPACK to solve the linear system
649  const PetscBLASInt nrhs = 1;
650  std::vector<PetscBLASInt> ipiv(_num_sp + 1);
651  PetscBLASInt info;
652  const PetscBLASInt gesv_num_rhs = _num_sp + 1;
653  LAPACKgesv_(
654  &gesv_num_rhs, &nrhs, &jac[0], &gesv_num_rhs, &ipiv[0], &rhs[0], &gesv_num_rhs, &info);
655  return info;
656 }
657 
658 void
660 {
661  throw MooseException(message);
662 }
663 
664 void
666 {
667 }
668 
669 void
671  const RankTwoTensor & /*rotation_increment*/)
672 {
673 }
674 
675 void
677  const std::vector<Real> & /*trial_stress_params*/,
678  const RankTwoTensor & /*stress_trial*/,
679  const std::vector<Real> & /*intnl_old*/,
680  const std::vector<Real> & /*yf*/,
681  const RankFourTensor & /*Eijkl*/)
682 {
683 }
684 
685 Real
686 MultiParameterPlasticityStressUpdate::yieldF(const std::vector<Real> & stress_params,
687  const std::vector<Real> & intnl) const
688 {
689  std::vector<Real> yfs(_num_yf);
690  yieldFunctionValuesV(stress_params, intnl, yfs);
691  return yieldF(yfs);
692 }
693 
694 Real
695 MultiParameterPlasticityStressUpdate::yieldF(const std::vector<Real> & yfs) const
696 {
697  Real yf = yfs[0];
698  for (std::size_t i = 1; i < yfs.size(); ++i)
699  if (yf >= yfs[i] + _smoothing_tol)
700  // no smoothing is needed, and yf is the biggest yield function
701  continue;
702  else if (yfs[i] >= yf + _smoothing_tol)
703  // no smoothing is needed, and yfs[i] is the biggest yield function
704  yf = yfs[i];
705  else
706  yf = 0.5 * (yf + yfs[i] + _smoothing_tol) + ismoother(yf - yfs[i]);
707  return yf;
708 }
709 
710 void
711 MultiParameterPlasticityStressUpdate::initializeVarsV(const std::vector<Real> & trial_stress_params,
712  const std::vector<Real> & intnl_old,
713  std::vector<Real> & stress_params,
714  Real & gaE,
715  std::vector<Real> & intnl) const
716 {
717  gaE = 0.0;
718  std::copy(trial_stress_params.begin(), trial_stress_params.end(), stress_params.begin());
719  std::copy(intnl_old.begin(), intnl_old.end(), intnl.begin());
720 }
721 
722 void
724  const RankTwoTensor & stress_trial,
725  const std::vector<Real> & /*trial_stress_params*/,
726  const RankTwoTensor & stress,
727  const std::vector<Real> & /*stress_params*/,
728  Real gaE,
729  const yieldAndFlow & smoothed_q,
730  const RankFourTensor & elasticity_tensor,
731  bool compute_full_tangent_operator,
732  const std::vector<std::vector<Real>> & dvar_dtrial,
733  RankFourTensor & cto)
734 {
735  cto = elasticity_tensor;
736  if (!compute_full_tangent_operator)
737  return;
738 
739  const Real ga = gaE / _En;
740 
741  const std::vector<RankTwoTensor> dsp = dstress_param_dstress(stress);
742  const std::vector<RankTwoTensor> dsp_trial = dstress_param_dstress(stress_trial);
743 
744  for (unsigned a = 0; a < _num_sp; ++a)
745  {
746  for (unsigned b = 0; b < _num_sp; ++b)
747  {
748  const RankTwoTensor t = elasticity_tensor * dsp_trial[a];
749  RankTwoTensor s = _Cij[b][a] * dsp[b];
750  for (unsigned c = 0; c < _num_sp; ++c)
751  s -= dsp[b] * _Cij[b][c] * dvar_dtrial[c][a];
752  s = elasticity_tensor * s;
753  cto -= s.outerProduct(t);
754  }
755  }
756 
757  const std::vector<RankFourTensor> d2sp = d2stress_param_dstress(stress);
758  RankFourTensor Tijab;
759  for (unsigned i = 0; i < _num_sp; ++i)
760  Tijab += smoothed_q.dg[i] * d2sp[i];
761  Tijab = ga * elasticity_tensor * Tijab;
762 
764  try
765  {
766  inv = inv.transposeMajor().invSymm();
767  }
768  catch (const MooseException & e)
769  {
770  // Cannot form the inverse, so probably at some degenerate place in stress space.
771  // Just return with the "best estimate" of the cto.
772  mooseWarning("MultiParameterPlasticityStressUpdate: Cannot invert 1+T in consistent tangent "
773  "operator computation at quadpoint ",
774  _qp,
775  " of element ",
776  _current_elem->id());
777  return;
778  }
779 
780  cto = (cto.transposeMajor() * inv).transposeMajor();
781 }
782 
783 void
785  const RankTwoTensor & /*stress_trial*/,
786  Real gaE,
787  const yieldAndFlow & smoothed_q,
788  const RankFourTensor & /*elasticity_tensor*/,
789  const RankTwoTensor & returned_stress,
790  RankTwoTensor & inelastic_strain_increment) const
791 {
792  const std::vector<RankTwoTensor> dsp_dstress = dstress_param_dstress(returned_stress);
793  inelastic_strain_increment = RankTwoTensor();
794  for (unsigned i = 0; i < _num_sp; ++i)
795  inelastic_strain_increment += smoothed_q.dg[i] * dsp_dstress[i];
796  inelastic_strain_increment *= gaE / _En;
797 }
798 
799 Real
800 MultiParameterPlasticityStressUpdate::calculateRes2(const std::vector<Real> & rhs) const
801 {
802  Real res2 = 0.0;
803  for (const auto & r : rhs)
804  res2 += r * r;
805  return res2;
806 }
807 
808 void
809 MultiParameterPlasticityStressUpdate::calculateRHS(const std::vector<Real> & trial_stress_params,
810  const std::vector<Real> & stress_params,
811  Real gaE,
812  const yieldAndFlow & smoothed_q,
813  std::vector<Real> & rhs) const
814 {
815  const Real ga = gaE / _En;
816  for (unsigned i = 0; i < _num_sp; ++i)
817  {
818  rhs[i] = stress_params[i] - trial_stress_params[i];
819  for (unsigned j = 0; j < _num_sp; ++j)
820  rhs[i] += ga * _Eij[i][j] * smoothed_q.dg[j];
821  }
822  rhs[_num_sp] = smoothed_q.f;
823 }
824 
825 void
827  const std::vector<std::vector<Real>> & dintnl,
828  const std::vector<Real> & /*stress_params*/,
829  Real gaE,
830  std::vector<double> & jac) const
831 {
832  for (auto & jac_entry : jac)
833  jac_entry = 0.0;
834 
835  const Real ga = gaE / _En;
836 
837  unsigned ind = 0;
838  for (unsigned var = 0; var < _num_sp; ++var)
839  {
840  for (unsigned rhs = 0; rhs < _num_sp; ++rhs)
841  {
842  if (var == rhs)
843  jac[ind] -= 1.0;
844  for (unsigned j = 0; j < _num_sp; ++j)
845  {
846  jac[ind] -= ga * _Eij[rhs][j] * smoothed_q.d2g[j][var];
847  for (unsigned k = 0; k < _num_intnl; ++k)
848  jac[ind] -= ga * _Eij[rhs][j] * smoothed_q.d2g_di[j][k] * dintnl[k][var];
849  }
850  ind++;
851  }
852  // now rhs = _num_sp (that is, the yield function)
853  jac[ind] -= smoothed_q.df[var];
854  for (unsigned k = 0; k < _num_intnl; ++k)
855  jac[ind] -= smoothed_q.df_di[k] * dintnl[k][var];
856  ind++;
857  }
858 
859  // now var = _num_sp (that is, gaE)
860  for (unsigned rhs = 0; rhs < _num_sp; ++rhs)
861  {
862  for (unsigned j = 0; j < _num_sp; ++j)
863  jac[ind] -= (1.0 / _En) * _Eij[rhs][j] * smoothed_q.dg[j];
864  ind++;
865  }
866  // now rhs = _num_sp (that is, the yield function)
867  jac[ind] = 0.0;
868 }
869 
870 void
872  const std::vector<Real> & trial_stress_params,
873  const std::vector<Real> & stress_params,
874  Real gaE,
875  const std::vector<Real> & intnl,
876  const yieldAndFlow & smoothed_q,
877  Real step_size,
878  bool compute_full_tangent_operator,
879  std::vector<std::vector<Real>> & dvar_dtrial) const
880 {
882  return;
883 
884  if (!compute_full_tangent_operator)
885  return;
886 
887  if (elastic_only)
888  {
889  // no change to gaE, and all off-diag stuff remains unchanged from previous step
890  for (unsigned v = 0; v < _num_sp; ++v)
891  dvar_dtrial[v][v] += step_size;
892  return;
893  }
894 
895  const Real ga = gaE / _En;
896 
897  std::vector<std::vector<Real>> dintnl(_num_intnl, std::vector<Real>(_num_sp));
898  setIntnlDerivativesV(trial_stress_params, stress_params, intnl, dintnl);
899 
900  // rhs is described elsewhere, the following are changes in rhs wrt the trial_stress_param
901  // values
902  // In the following we use d(intnl)/d(trial variable) = - d(intnl)/d(variable)
903  std::vector<Real> rhs_cto((_num_sp + 1) * _num_sp);
904 
905  unsigned ind = 0;
906  for (unsigned a = 0; a < _num_sp; ++a)
907  {
908  // change in RHS[b] wrt changes in stress_param_trial[a]
909  for (unsigned b = 0; b < _num_sp; ++b)
910  {
911  if (a == b)
912  rhs_cto[ind] -= 1.0;
913  for (unsigned j = 0; j < _num_sp; ++j)
914  for (unsigned k = 0; k < _num_intnl; ++k)
915  rhs_cto[ind] -= ga * _Eij[b][j] * smoothed_q.d2g_di[j][k] * dintnl[k][a];
916  ind++;
917  }
918  // now b = _num_sp (that is, the yield function)
919  for (unsigned k = 0; k < _num_intnl; ++k)
920  rhs_cto[ind] -= smoothed_q.df_di[k] * dintnl[k][a];
921  ind++;
922  }
923 
924  // jac = d(-rhs)/d(var)
925  std::vector<double> jac((_num_sp + 1) * (_num_sp + 1));
926  dnRHSdVar(smoothed_q, dintnl, stress_params, gaE, jac);
927 
928  std::vector<PetscBLASInt> ipiv(_num_sp + 1);
929  PetscBLASInt info;
930  const PetscBLASInt gesv_num_rhs = _num_sp + 1;
931  const PetscBLASInt gesv_num_pq = _num_sp;
932  LAPACKgesv_(&gesv_num_rhs,
933  &gesv_num_pq,
934  &jac[0],
935  &gesv_num_rhs,
936  &ipiv[0],
937  &rhs_cto[0],
938  &gesv_num_rhs,
939  &info);
940  if (info != 0)
941  errorHandler("MultiParameterPlasticityStressUpdate: PETSC LAPACK gsev routine returned with "
942  "error code " +
944 
945  ind = 0;
946  std::vector<std::vector<Real>> dvarn_dtrialn(_num_sp + 1, std::vector<Real>(_num_sp, 0.0));
947  for (unsigned spt = 0; spt < _num_sp; ++spt) // loop over trial stress-param variables
948  {
949  for (unsigned v = 0; v < _num_sp; ++v) // loop over variables in NR procedure
950  {
951  dvarn_dtrialn[v][spt] = rhs_cto[ind];
952  ind++;
953  }
954  // the final NR variable is gaE
955  dvarn_dtrialn[_num_sp][spt] = rhs_cto[ind];
956  ind++;
957  }
958 
959  const std::vector<std::vector<Real>> dvar_dtrial_old = dvar_dtrial;
960 
961  for (unsigned v = 0; v < _num_sp; ++v) // loop over variables in NR procedure
962  {
963  for (unsigned spt = 0; spt < _num_sp; ++spt) // loop over trial stress-param variables
964  {
965  dvar_dtrial[v][spt] = step_size * dvarn_dtrialn[v][spt];
966  for (unsigned a = 0; a < _num_sp; ++a)
967  dvar_dtrial[v][spt] += dvarn_dtrialn[v][a] * dvar_dtrial_old[a][spt];
968  }
969  }
970  // for gaE the formulae are a little different
971  const unsigned v = _num_sp;
972  for (unsigned spt = 0; spt < _num_sp; ++spt)
973  {
974  dvar_dtrial[v][spt] += step_size * dvarn_dtrialn[v][spt]; // note +=
975  for (unsigned a = 0; a < _num_sp; ++a)
976  dvar_dtrial[v][spt] += dvarn_dtrialn[v][a] * dvar_dtrial_old[a][spt];
977  }
978 }
979 
980 bool
981 MultiParameterPlasticityStressUpdate::precisionLoss(const std::vector<Real> & solution,
982  const std::vector<Real> & stress_params,
983  Real gaE) const
984 {
985  if (std::abs(solution[_num_sp]) > 1E-13 * std::abs(gaE))
986  return false;
987  for (unsigned i = 0; i < _num_sp; ++i)
988  if (std::abs(solution[i]) > 1E-13 * std::abs(stress_params[i]))
989  return false;
990  return true;
991 }
const Real _smoothing_tol2
Square of the smoothing tolerance.
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.
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:
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...
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...
ADRealEigenVector< T, D, asd > sqrt(const ADRealEigenVector< T, D, asd > &)
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 mooseWarning(Args &&... args) const
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.
ADRealEigenVector< T, D, asd > abs(const ADRealEigenVector< T, D, asd > &)
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.
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
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) const
Sets inelastic strain increment from the returned configuration This is called after the return-map p...
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 ...
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.
MaterialProperty< RankTwoTensor > & _plastic_strain
plastic strain
virtual std::vector< RankFourTensor > d2stress_param_dstress(const RankTwoTensor &stress) const =0
d2(stress_param[i])/d(stress)/d(stress) at given stress
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)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
static const std::string v
Definition: NS.h:82
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])
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)
virtual std::vector< RankTwoTensor > dstress_param_dstress(const RankTwoTensor &stress) const =0
d(stress_param[i])/d(stress) at given stress
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...
bool precisionLoss(const std::vector< Real > &solution, const std::vector< Real > &stress_params, Real gaE) const
Check whether precision loss has occurred.
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:124
Real yieldF(const std::vector< Real > &stress_params, const std::vector< Real > &intnl) const
Computes the smoothed yield function.
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"...
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.