11 #include "Conversion.h"
12 #include "MooseEnum.h"
15 #include "libmesh/utility.h"
18 #include <petscblaslapack.h>
26 params.addClassDescription(
"Return-map and Jacobian algorithms for plastic models where the "
27 "yield function and flow directions depend on multiple functions of "
29 params.addRangeCheckedParam<
unsigned int>(
32 "max_NR_iterations>0",
33 "Maximum number of Newton-Raphson iterations allowed during the return-map algorithm");
34 params.addParam<
bool>(
"perform_finite_strain_rotations",
36 "Tensors are correctly rotated "
37 "in finite-strain simulations. "
38 "For optimal performance you can "
39 "set this to 'false' if you are "
40 "only ever using small strains");
41 params.addRequiredParam<Real>(
43 "Intersections of the yield surfaces will be smoothed by this amount (this "
44 "is measured in units of stress). Often this is related to other physical "
45 "parameters (eg, 0.1*cohesion) but it is important to set this small enough "
46 "so that the individual yield surfaces do not mix together in the smoothing "
47 "process to produce a result where no stress is admissible (for example, "
48 "mixing together tensile and compressive failure envelopes).");
49 params.addRequiredParam<Real>(
"yield_function_tol",
50 "The return-map process will be deemed to have converged if all "
51 "yield functions are within yield_function_tol of zero. If this "
52 "is set very low then precision-loss might be encountered: if the "
53 "code detects precision loss then it also deems the return-map "
54 "process has converged.");
55 MooseEnum tangent_operator(
"elastic nonlinear",
"nonlinear");
56 params.addParam<Real>(
"min_step_size",
58 "In order to help the Newton-Raphson procedure, the applied strain "
59 "increment may be applied in sub-increments of size greater than this "
60 "value. Usually it is better for Moose's nonlinear convergence to "
61 "increase max_NR_iterations rather than decrease this parameter.");
62 params.addParam<
bool>(
"warn_about_precision_loss",
64 "Output a message to the console every "
65 "time precision-loss is encountered "
66 "during the Newton-Raphson process");
67 params.addParam<std::vector<Real>>(
"admissible_stress",
68 "A single admissible value of the value of the stress "
69 "parameters for internal parameters = 0. This is used "
70 "to initialize the return-mapping algorithm during the first "
71 "nonlinear iteration. If not given then it is assumed that "
72 "stress parameters = 0 is admissible.");
73 MooseEnum smoother_fcn_enum(
"cos poly1 poly2 poly3",
"cos");
74 params.addParam<MooseEnum>(
"smoother_function_type",
76 "Type of smoother function to use. 'cos' means (-a/pi)cos(pi x/2/a), "
77 "'polyN' means a polynomial of degree 2N+2");
78 params.addParamNamesToGroup(
"smoother_function_type",
"Advanced");
83 const InputParameters & parameters,
unsigned num_sp,
unsigned num_yf,
unsigned num_intnl)
86 _definitely_ok_sp(isParamValid(
"admissible_stress")
87 ? getParam<std::vector<Real>>(
"admissible_stress")
88 : std::vector<Real>(_num_sp, 0.0)),
89 _Eij(num_sp, std::vector<Real>(num_sp)),
91 _Cij(num_sp, std::vector<Real>(num_sp)),
93 _num_intnl(num_intnl),
94 _max_nr_its(getParam<unsigned>(
"max_NR_iterations")),
95 _perform_finite_strain_rotations(getParam<bool>(
"perform_finite_strain_rotations")),
96 _smoothing_tol(getParam<Real>(
"smoothing_tol")),
97 _smoothing_tol2(Utility::
pow<2>(getParam<Real>(
"smoothing_tol"))),
98 _f_tol(getParam<Real>(
"yield_function_tol")),
99 _f_tol2(Utility::
pow<2>(getParam<Real>(
"yield_function_tol"))),
100 _min_step_size(getParam<Real>(
"min_step_size")),
101 _step_one(declareRestartableData<bool>(
"step_one", true)),
102 _warn_about_precision_loss(getParam<bool>(
"warn_about_precision_loss")),
104 _plastic_strain(declareProperty<
RankTwoTensor>(_base_name +
"plastic_strain")),
105 _plastic_strain_old(getMaterialPropertyOld<
RankTwoTensor>(_base_name +
"plastic_strain")),
106 _intnl(declareProperty<std::vector<Real>>(_base_name +
"plastic_internal_parameter")),
108 getMaterialPropertyOld<std::vector<Real>>(_base_name +
"plastic_internal_parameter")),
109 _yf(declareProperty<std::vector<Real>>(_base_name +
"plastic_yield_function")),
110 _iter(declareProperty<Real>(_base_name +
111 "plastic_NR_iterations")),
113 _max_iter_used(declareProperty<Real>(
114 _base_name +
"max_plastic_NR_iterations")),
116 _max_iter_used_old(getMaterialPropertyOld<Real>(_base_name +
"max_plastic_NR_iterations")),
118 declareProperty<Real>(_base_name +
"plastic_linesearch_needed")),
125 _dvar_dtrial(num_sp + 1, std::vector<Real>(num_sp, 0.0)),
127 _ok_intnl(num_intnl),
128 _del_stress_params(num_sp),
130 _current_intnl(num_intnl),
131 _smoother_function_type(
135 mooseError(
"MultiParameterPlasticityStressUpdate: admissible_stress parameter must consist of ",
167 bool compute_full_tangent_operator,
196 inelastic_strain_increment.zero();
197 if (_fe_problem.currentlyComputingJacobian())
198 tangent_operator = elasticity_tensor;
237 for (
unsigned i = 0; i <
_num_sp; ++i)
240 Real step_taken = 0.0;
242 Real step_size = 1.0;
243 Real gaE_total = 0.0;
251 bool smoothed_q_calculated =
false;
255 if (1.0 - step_taken < step_size)
257 step_size = 1.0 - step_taken;
260 for (
unsigned i = 0; i <
_num_sp; ++i)
272 unsigned step_iter = 0;
281 smoothed_q_calculated =
false;
290 smoothed_q_calculated =
true;
295 while (res2 >
_f_tol2 && step_iter <
_max_nr_its && nr_failure == 0 && ls_failure == 0)
307 Moose::err <<
"MultiParameterPlasticityStressUpdate: precision-loss in element "
308 << _current_elem->id() <<
" quadpoint=" << _qp <<
". Stress_params =";
309 for (
unsigned i = 0; i <
_num_sp; ++i)
311 Moose::err <<
" gaE = " << gaE <<
"\n";
330 if (res2 <=
_f_tol2 && step_iter <
_max_nr_its && nr_failure == 0 && ls_failure == 0 &&
336 step_taken += step_size;
347 compute_full_tangent_operator,
349 if (static_cast<Real>(step_iter) >
_iter[_qp])
350 _iter[_qp] = static_cast<Real>(step_iter);
363 errorHandler(
"MultiParameterPlasticityStressUpdate: Minimum step-size violated");
369 if (!smoothed_q_calculated)
380 inelastic_strain_increment);
382 strain_increment = strain_increment - inelastic_strain_increment;
385 if (_fe_problem.currentlyComputingJacobian())
394 compute_full_tangent_operator,
401 const std::vector<Real> & intnl)
const
430 std::size_t res_f = 0;
432 for (std::size_t a = 1; a < all_q.size(); ++a)
446 const Real f_diff = all_q[res_f].f - all_q[a].f;
452 for (
unsigned i = 0; i <
_num_sp; ++i)
454 for (
unsigned j = 0; j <
_num_sp; ++j)
455 all_q[res_f].d2g[i][j] =
456 0.5 * (all_q[res_f].d2g[i][j] + all_q[a].d2g[i][j]) +
457 dsm * (all_q[res_f].df[j] - all_q[a].df[j]) * (all_q[res_f].dg[i] - all_q[a].dg[i]) +
458 sm * (all_q[res_f].d2g[i][j] - all_q[a].d2g[i][j]);
460 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]) +
461 dsm * (all_q[res_f].df_di[j] - all_q[a].df_di[j]) *
462 (all_q[res_f].dg[i] - all_q[a].dg[i]) +
463 sm * (all_q[res_f].d2g_di[i][j] - all_q[a].d2g_di[i][j]);
465 for (
unsigned i = 0; i <
_num_sp; ++i)
467 all_q[res_f].df[i] = 0.5 * (all_q[res_f].df[i] + all_q[a].df[i]) +
468 sm * (all_q[res_f].df[i] - all_q[a].df[i]);
471 all_q[res_f].dg[i] = 0.5 * (all_q[res_f].dg[i] + all_q[a].dg[i]) +
472 sm * (all_q[res_f].dg[i] - all_q[a].dg[i]);
475 all_q[res_f].df_di[i] = 0.5 * (all_q[res_f].df_di[i] + all_q[a].df_di[i]) +
476 sm * (all_q[res_f].df_di[i] - all_q[a].df_di[i]);
477 all_q[res_f].f = 0.5 * (all_q[res_f].f + all_q[a].f +
_smoothing_tol) + ism;
554 std::vector<Real> & stress_params,
556 const std::vector<Real> & trial_stress_params,
558 const std::vector<Real> & intnl_ok,
559 std::vector<Real> & intnl,
560 std::vector<Real> & rhs,
561 Real & linesearch_needed)
const
563 const Real res2_old = res2;
564 const std::vector<Real> sp_params_old = stress_params;
565 const Real gaE_old = gaE;
566 const std::vector<Real> delta_nr_params = rhs;
569 const Real lam_min = 1E-10;
570 const Real slope = -2.0 * res2_old;
580 for (
unsigned i = 0; i <
_num_sp; ++i)
581 stress_params[i] = sp_params_old[i] + lam * delta_nr_params[i];
582 gaE = gaE_old + lam * delta_nr_params[
_num_sp];
590 calculateRHS(trial_stress_params, stress_params, gaE, smoothed_q, rhs);
594 if (res2 < res2_old + 1E-4 * lam * slope)
596 else if (lam < lam_min)
601 tmp_lam = -0.5 * slope / (res2 - res2_old - slope);
606 const Real rhs1 = res2 - res2_old - lam * slope;
607 const Real rhs2 = f2 - res2_old - lam2 * slope;
608 const Real a = (rhs1 / Utility::pow<2>(lam) - rhs2 / Utility::pow<2>(lam2)) / (lam - lam2);
610 (-lam2 * rhs1 / Utility::pow<2>(lam) + lam * rhs2 / Utility::pow<2>(lam2)) / (lam - lam2);
612 tmp_lam = -slope / (2.0 * b);
615 const Real disc = Utility::pow<2>(b) - 3.0 * a * slope;
619 tmp_lam = (-b + std::sqrt(disc)) / (3.0 * a);
621 tmp_lam = -slope / (b + std::sqrt(disc));
623 if (tmp_lam > 0.5 * lam)
628 lam = std::max(tmp_lam, 0.1 * lam);
632 linesearch_needed = 1.0;
638 const std::vector<Real> & trial_stress_params,
639 const std::vector<Real> & stress_params,
640 const std::vector<Real> & intnl,
642 std::vector<Real> & rhs)
const
648 dnRHSdVar(smoothed_q, dintnl, stress_params, gaE, jac);
652 std::vector<int> ipiv(
_num_sp + 1);
654 const int gesv_num_rhs =
_num_sp + 1;
656 &gesv_num_rhs, &nrhs, &jac[0], &gesv_num_rhs, &ipiv[0], &rhs[0], &gesv_num_rhs, &info);
663 throw MooseException(message);
679 const std::vector<Real> & ,
681 const std::vector<Real> & ,
682 const std::vector<Real> & ,
689 const std::vector<Real> & intnl)
const
691 std::vector<Real> yfs(
_num_yf);
700 for (std::size_t i = 1; i < yfs.size(); ++i)
714 const std::vector<Real> & intnl_old,
715 std::vector<Real> & stress_params,
717 std::vector<Real> & intnl)
const
720 std::copy(trial_stress_params.begin(), trial_stress_params.end(), stress_params.begin());
721 std::copy(intnl_old.begin(), intnl_old.end(), intnl.begin());
727 const std::vector<Real> & ,
729 const std::vector<Real> & ,
733 bool compute_full_tangent_operator,
734 const std::vector<std::vector<Real>> & dvar_dtrial,
737 cto = elasticity_tensor;
738 if (!compute_full_tangent_operator)
741 const Real ga = gaE /
_En;
746 for (
unsigned a = 0; a <
_num_sp; ++a)
748 for (
unsigned b = 0; b <
_num_sp; ++b)
752 for (
unsigned c = 0; c <
_num_sp; ++c)
753 s -= dsp[b] *
_Cij[b][c] * dvar_dtrial[c][a];
754 s = elasticity_tensor * s;
755 cto -= s.outerProduct(t);
761 for (
unsigned i = 0; i <
_num_sp; ++i)
762 Tijab += smoothed_q.
dg[i] * d2sp[i];
763 Tijab = ga * elasticity_tensor * Tijab;
768 inv = inv.transposeMajor().invSymm();
770 catch (
const MooseException & e)
774 mooseWarning(
"MultiParameterPlasticityStressUpdate: Cannot invert 1+T in consistent tangent "
775 "operator computation at quadpoint ",
778 _current_elem->id());
782 cto = (cto.transposeMajor() * inv).transposeMajor();
796 for (
unsigned i = 0; i <
_num_sp; ++i)
797 inelastic_strain_increment += smoothed_q.
dg[i] * dsp_dstress[i];
798 inelastic_strain_increment *= gaE /
_En;
805 for (
const auto & r : rhs)
812 const std::vector<Real> & stress_params,
815 std::vector<Real> & rhs)
const
817 const Real ga = gaE /
_En;
818 for (
unsigned i = 0; i <
_num_sp; ++i)
820 rhs[i] = stress_params[i] - trial_stress_params[i];
821 for (
unsigned j = 0; j <
_num_sp; ++j)
822 rhs[i] += ga *
_Eij[i][j] * smoothed_q.
dg[j];
829 const std::vector<std::vector<Real>> & dintnl,
830 const std::vector<Real> & ,
832 std::vector<double> & jac)
const
834 for (
auto & jac_entry : jac)
837 const Real ga = gaE /
_En;
840 for (
unsigned var = 0; var <
_num_sp; ++var)
842 for (
unsigned rhs = 0; rhs <
_num_sp; ++rhs)
846 for (
unsigned j = 0; j <
_num_sp; ++j)
848 jac[ind] -= ga *
_Eij[rhs][j] * smoothed_q.
d2g[j][var];
850 jac[ind] -= ga *
_Eij[rhs][j] * smoothed_q.
d2g_di[j][k] * dintnl[k][var];
855 jac[ind] -= smoothed_q.
df[var];
857 jac[ind] -= smoothed_q.
df_di[k] * dintnl[k][var];
862 for (
unsigned rhs = 0; rhs <
_num_sp; ++rhs)
864 for (
unsigned j = 0; j <
_num_sp; ++j)
865 jac[ind] -= (1.0 /
_En) *
_Eij[rhs][j] * smoothed_q.
dg[j];
874 const std::vector<Real> & trial_stress_params,
875 const std::vector<Real> & stress_params,
877 const std::vector<Real> & intnl,
880 bool compute_full_tangent_operator,
881 std::vector<std::vector<Real>> & dvar_dtrial)
const
883 if (!_fe_problem.currentlyComputingJacobian())
886 if (!compute_full_tangent_operator)
892 for (
unsigned v = 0; v <
_num_sp; ++v)
893 dvar_dtrial[v][v] += step_size;
897 const Real ga = gaE /
_En;
908 for (
unsigned a = 0; a <
_num_sp; ++a)
911 for (
unsigned b = 0; b <
_num_sp; ++b)
915 for (
unsigned j = 0; j <
_num_sp; ++j)
917 rhs_cto[ind] -= ga *
_Eij[b][j] * smoothed_q.
d2g_di[j][k] * dintnl[k][a];
922 rhs_cto[ind] -= smoothed_q.
df_di[k] * dintnl[k][a];
928 dnRHSdVar(smoothed_q, dintnl, stress_params, gaE, jac);
930 std::vector<int> ipiv(
_num_sp + 1);
932 const int gesv_num_rhs =
_num_sp + 1;
933 const int gesv_num_pq =
_num_sp;
934 LAPACKgesv_(&gesv_num_rhs,
943 errorHandler(
"MultiParameterPlasticityStressUpdate: PETSC LAPACK gsev routine returned with "
945 Moose::stringify(info));
948 std::vector<std::vector<Real>> dvarn_dtrialn(
_num_sp + 1, std::vector<Real>(
_num_sp, 0.0));
949 for (
unsigned spt = 0; spt <
_num_sp; ++spt)
951 for (
unsigned v = 0; v <
_num_sp; ++v)
953 dvarn_dtrialn[v][spt] = rhs_cto[ind];
957 dvarn_dtrialn[
_num_sp][spt] = rhs_cto[ind];
961 const std::vector<std::vector<Real>> dvar_dtrial_old = dvar_dtrial;
963 for (
unsigned v = 0; v <
_num_sp; ++v)
965 for (
unsigned spt = 0; spt <
_num_sp; ++spt)
967 dvar_dtrial[v][spt] = step_size * dvarn_dtrialn[v][spt];
968 for (
unsigned a = 0; a <
_num_sp; ++a)
969 dvar_dtrial[v][spt] += dvarn_dtrialn[v][a] * dvar_dtrial_old[a][spt];
974 for (
unsigned spt = 0; spt <
_num_sp; ++spt)
976 dvar_dtrial[v][spt] += step_size * dvarn_dtrialn[v][spt];
977 for (
unsigned a = 0; a <
_num_sp; ++a)
978 dvar_dtrial[v][spt] += dvarn_dtrialn[v][a] * dvar_dtrial_old[a][spt];
984 const std::vector<Real> & stress_params,
987 if (std::abs(solution[
_num_sp]) > 1E-13 * std::abs(gaE))
989 for (
unsigned i = 0; i <
_num_sp; ++i)
990 if (std::abs(solution[i]) > 1E-13 * std::abs(stress_params[i]))