11 #include "RankFourTensor.h"
12 #include "libmesh/utility.h"
20 MooseEnum debug_fspb_type(
"none crash jacobian jacobian_and_linear_system",
"none");
21 params.addParam<MooseEnum>(
"debug_fspb",
23 "Debug types for use by developers when creating new "
24 "plasticity models, not for general use. 2 = debug Jacobian "
25 "entries, 3 = check the entire Jacobian, and check Ax=b");
26 params.addParam<RealTensorValue>(
"debug_jac_at_stress",
28 "Debug Jacobian entries at this stress. For use by developers");
29 params.addParam<std::vector<Real>>(
"debug_jac_at_pm",
30 "Debug Jacobian entries at these plastic multipliers");
31 params.addParam<std::vector<Real>>(
"debug_jac_at_intnl",
32 "Debug Jacobian entries at these internal parameters");
33 params.addParam<Real>(
34 "debug_stress_change", 1.0,
"Debug finite differencing parameter for the stress");
35 params.addParam<std::vector<Real>>(
36 "debug_pm_change",
"Debug finite differencing parameters for the plastic multipliers");
37 params.addParam<std::vector<Real>>(
38 "debug_intnl_change",
"Debug finite differencing parameters for the internal parameters");
44 _fspb_debug(_params.get<MooseEnum>(
"debug_fspb")),
45 _fspb_debug_stress(_params.get<RealTensorValue>(
"debug_jac_at_stress")),
46 _fspb_debug_pm(_params.get<std::vector<Real>>(
"debug_jac_at_pm")),
47 _fspb_debug_intnl(_params.get<std::vector<Real>>(
"debug_jac_at_intnl")),
48 _fspb_debug_stress_change(_params.get<Real>(
"debug_stress_change")),
49 _fspb_debug_pm_change(_params.get<std::vector<Real>>(
"debug_pm_change")),
50 _fspb_debug_intnl_change(_params.get<std::vector<Real>>(
"debug_intnl_change"))
57 Moose::err <<
"Debug Parameters are as follows\n";
58 Moose::err <<
"stress = \n";
64 mooseError(
"The debug parameters have the wrong size\n");
66 Moose::err <<
"plastic multipliers =\n";
67 for (
unsigned surface = 0; surface <
_num_surfaces; ++surface)
70 Moose::err <<
"internal parameters =\n";
71 for (
unsigned model = 0; model <
_num_models; ++model)
74 Moose::err <<
"finite-differencing parameter for stress-changes:\n"
76 Moose::err <<
"finite-differencing parameter(s) for plastic-multiplier(s):\n";
77 for (
unsigned surface = 0; surface <
_num_surfaces; ++surface)
79 Moose::err <<
"finite-differencing parameter(s) for internal-parameter(s):\n";
80 for (
unsigned model = 0; model <
_num_models; ++model)
88 <<
"\n\n++++++++++++++++++++++++\nChecking the derivatives\n++++++++++++++++++++++++\n";
91 std::vector<bool> act;
94 Moose::err <<
"\ndyieldFunction_dstress. Relative L2 norms.\n";
95 std::vector<RankTwoTensor> df_dstress;
96 std::vector<RankTwoTensor> fddf_dstress;
99 for (
unsigned surface = 0; surface <
_num_surfaces; ++surface)
101 Moose::err <<
"surface = " << surface <<
" Relative L2norm = "
102 << 2 * (df_dstress[surface] - fddf_dstress[surface]).
L2norm() /
103 (df_dstress[surface] + fddf_dstress[surface]).
L2norm()
105 Moose::err <<
"Coded:\n";
106 df_dstress[surface].print();
107 Moose::err <<
"Finite difference:\n";
108 fddf_dstress[surface].print();
111 Moose::err <<
"\ndyieldFunction_dintnl.\n";
112 std::vector<Real> df_dintnl;
114 Moose::err <<
"Coded:\n";
115 for (
unsigned surface = 0; surface <
_num_surfaces; ++surface)
116 Moose::err << df_dintnl[surface] <<
" ";
118 std::vector<Real> fddf_dintnl;
120 Moose::err <<
"Finite difference:\n";
121 for (
unsigned surface = 0; surface <
_num_surfaces; ++surface)
122 Moose::err << fddf_dintnl[surface] <<
" ";
125 Moose::err <<
"\ndflowPotential_dstress. Relative L2 norms.\n";
126 std::vector<RankFourTensor> dr_dstress;
127 std::vector<RankFourTensor> fddr_dstress;
130 for (
unsigned surface = 0; surface <
_num_surfaces; ++surface)
132 Moose::err <<
"surface = " << surface <<
" Relative L2norm = "
133 << 2 * (dr_dstress[surface] - fddr_dstress[surface]).
L2norm() /
134 (dr_dstress[surface] + fddr_dstress[surface]).
L2norm()
136 Moose::err <<
"Coded:\n";
137 dr_dstress[surface].print();
138 Moose::err <<
"Finite difference:\n";
139 fddr_dstress[surface].print();
142 Moose::err <<
"\ndflowPotential_dintnl. Relative L2 norms.\n";
143 std::vector<RankTwoTensor> dr_dintnl;
144 std::vector<RankTwoTensor> fddr_dintnl;
147 for (
unsigned surface = 0; surface <
_num_surfaces; ++surface)
149 Moose::err <<
"surface = " << surface <<
" Relative L2norm = "
150 << 2 * (dr_dintnl[surface] - fddr_dintnl[surface]).
L2norm() /
151 (dr_dintnl[surface] + fddr_dintnl[surface]).
L2norm()
153 Moose::err <<
"Coded:\n";
154 dr_dintnl[surface].print();
155 Moose::err <<
"Finite difference:\n";
156 fddr_dintnl[surface].print();
162 const std::vector<Real> & intnl_old)
164 Moose::err <<
"\n\n+++++++++++++++++++++\nChecking the Jacobian\n+++++++++++++++++++++\n";
167 std::vector<bool> act;
169 std::vector<bool> deactivated_due_to_ld;
174 std::vector<std::vector<Real>> jac;
180 deactivated_due_to_ld,
183 std::vector<std::vector<Real>> fdjac;
195 for (
unsigned row = 0; row < jac.size(); ++row)
196 for (
unsigned col = 0; col < jac.size(); ++col)
198 L2_numer += Utility::pow<2>(jac[row][col] - fdjac[row][col]);
199 L2_denom += Utility::pow<2>(jac[row][col] + fdjac[row][col]);
201 Moose::err <<
"\nRelative L2norm = " << std::sqrt(L2_numer / L2_denom) / 0.5 <<
"\n";
203 Moose::err <<
"\nHand-coded Jacobian:\n";
204 for (
unsigned row = 0; row < jac.size(); ++row)
206 for (
unsigned col = 0; col < jac.size(); ++col)
207 Moose::err << jac[row][col] <<
" ";
211 Moose::err <<
"Finite difference Jacobian:\n";
212 for (
unsigned row = 0; row < fdjac.size(); ++row)
214 for (
unsigned col = 0; col < fdjac.size(); ++col)
215 Moose::err << fdjac[row][col] <<
" ";
222 const std::vector<Real> & intnl_old,
223 const std::vector<Real> & intnl,
224 const std::vector<Real> & pm,
228 std::vector<std::vector<Real>> & jac)
230 std::vector<bool> active;
233 std::vector<bool> deactivated_due_to_ld;
234 std::vector<bool> deactivated_due_to_ld_ep;
236 std::vector<Real> orig_rhs;
245 deactivated_due_to_ld);
249 unsigned int system_size =
251 jac.resize(system_size);
252 for (
unsigned row = 0; row < system_size; ++row)
253 jac[row].assign(system_size, 0);
255 std::vector<Real> rhs_ep;
261 for (
unsigned i = 0; i < 3; ++i)
262 for (
unsigned j = 0; j <= i; ++j)
265 stressep(i, j) += ep;
267 stressep(j, i) += ep;
268 delta_dpep = delta_dp;
269 for (
unsigned k = 0; k < 3; ++k)
270 for (
unsigned l = 0; l < 3; ++l)
272 delta_dpep(k, l) -= E_inv(k, l, i, j) * ep;
274 delta_dpep(k, l) -= E_inv(k, l, j, i) * ep;
285 deactivated_due_to_ld_ep);
287 for (
unsigned dof = 0; dof < whole_system_size; ++dof)
291 -(rhs_ep[dof] - orig_rhs[row]) / ep;
297 std::vector<Real> pmep;
299 for (
unsigned surface = 0; surface <
_num_surfaces; ++surface)
300 pmep[surface] = pm[surface];
301 for (
unsigned surface = 0; surface <
_num_surfaces; ++surface)
309 stress, intnl_old, intnl, pmep, delta_dp, rhs_ep, active,
false, deactivated_due_to_ld_ep);
311 for (
unsigned dof = 0; dof < whole_system_size; ++dof)
315 -(rhs_ep[dof] - orig_rhs[row]) / ep;
322 std::vector<Real> intnlep;
324 for (
unsigned model = 0; model <
_num_models; ++model)
325 intnlep[model] = intnl[model];
326 for (
unsigned model = 0; model <
_num_models; ++model)
331 intnlep[model] += ep;
334 stress, intnl_old, intnlep, pm, delta_dp, rhs_ep, active,
false, deactivated_due_to_ld_ep);
336 for (
unsigned dof = 0; dof < whole_system_size; ++dof)
340 -(rhs_ep[dof] - orig_rhs[row]) / ep;
343 intnlep[model] -= ep;
350 const std::vector<bool> & deactivated_due_to_ld)
352 if (dof <
unsigned(6))
355 unsigned eff_dof = dof - 6;
358 return !deactivated_due_to_ld[eff_dof];
361 for (
unsigned surface = 0; surface <
_num_surfaces; ++surface)
362 active_surface[surface] = !deactivated_due_to_ld[surface];
369 Moose::err <<
"\n\n+++++++++++++++++++++\nChecking the Solution\n";
370 Moose::err <<
"(Ie, checking Ax = b)\n+++++++++++++++++++++\n";
373 std::vector<bool> act;
375 std::vector<bool> deactivated_due_to_ld;
380 std::vector<Real> orig_rhs;
389 deactivated_due_to_ld);
391 Moose::err <<
"\nb = ";
392 for (
unsigned i = 0; i < orig_rhs.size(); ++i)
393 Moose::err << orig_rhs[i] <<
" ";
394 Moose::err <<
"\n\n";
396 std::vector<std::vector<Real>> jac_coded;
402 deactivated_due_to_ld,
406 <<
"Before checking Ax=b is correct, check that the Jacobians given below are equal.\n";
408 <<
"The hand-coded Jacobian is used in calculating the solution 'x', given 'b' above.\n";
409 Moose::err <<
"Note that this only includes degrees of freedom that aren't deactivated due to "
410 "linear dependence.\n";
411 Moose::err <<
"Hand-coded Jacobian:\n";
412 for (
unsigned row = 0; row < jac_coded.size(); ++row)
414 for (
unsigned col = 0; col < jac_coded.size(); ++col)
415 Moose::err << jac_coded[row][col] <<
" ";
422 std::vector<Real> dpm;
423 std::vector<Real> dintnl;
434 deactivated_due_to_ld);
437 for (
unsigned surface = 0; surface <
_num_surfaces; ++surface)
438 active_not_deact[surface] = !deactivated_due_to_ld[surface];
441 x.assign(orig_rhs.size(), 0);
443 for (
unsigned i = 0; i < 3; ++i)
444 for (
unsigned j = 0; j <= i; ++j)
445 x[ind++] = dstress(i, j);
446 for (
unsigned surface = 0; surface <
_num_surfaces; ++surface)
447 if (active_not_deact[surface])
448 x[ind++] = dpm[surface];
449 for (
unsigned model = 0; model <
_num_models; ++model)
451 x[ind++] = dintnl[model];
453 mooseAssert(ind == orig_rhs.size(),
454 "Incorrect extracting of changes from NR solution in the "
455 "finite-difference checking of nrStep");
457 Moose::err <<
"\nThis yields x =";
458 for (
unsigned i = 0; i < orig_rhs.size(); ++i)
459 Moose::err << x[i] <<
" ";
462 std::vector<std::vector<Real>> jac_fd;
472 Moose::err <<
"\nThe finite-difference Jacobian is used to multiply by this 'x',\n";
473 Moose::err <<
"in order to check that the solution is correct\n";
474 Moose::err <<
"Finite-difference Jacobian:\n";
475 for (
unsigned row = 0; row < jac_fd.size(); ++row)
477 for (
unsigned col = 0; col < jac_fd.size(); ++col)
478 Moose::err << jac_fd[row][col] <<
" ";
484 for (
unsigned row = 0; row < jac_coded.size(); ++row)
485 for (
unsigned col = 0; col < jac_coded.size(); ++col)
487 L2_numer += Utility::pow<2>(jac_coded[row][col] - jac_fd[row][col]);
488 L2_denom += Utility::pow<2>(jac_coded[row][col] + jac_fd[row][col]);
490 Moose::err <<
"Relative L2norm of the hand-coded and finite-difference Jacobian is "
491 << std::sqrt(L2_numer / L2_denom) / 0.5 <<
"\n";
493 std::vector<Real> fd_times_x;
494 fd_times_x.assign(orig_rhs.size(), 0);
495 for (
unsigned row = 0; row < orig_rhs.size(); ++row)
496 for (
unsigned col = 0; col < orig_rhs.size(); ++col)
497 fd_times_x[row] += jac_fd[row][col] * x[col];
499 Moose::err <<
"\n(Finite-difference Jacobian)*x =\n";
500 for (
unsigned i = 0; i < orig_rhs.size(); ++i)
501 Moose::err << fd_times_x[i] <<
" ";
503 Moose::err <<
"Recall that b = \n";
504 for (
unsigned i = 0; i < orig_rhs.size(); ++i)
505 Moose::err << orig_rhs[i] <<
" ";
510 for (
unsigned i = 0; i < orig_rhs.size(); ++i)
512 L2_numer += Utility::pow<2>(orig_rhs[i] - fd_times_x[i]);
513 L2_denom += Utility::pow<2>(orig_rhs[i] + fd_times_x[i]);
515 Moose::err <<
"\nRelative L2norm of these is " << std::sqrt(L2_numer / L2_denom) / 0.5 <<
"\n";
520 const std::vector<Real> & intnl,
521 std::vector<RankTwoTensor> & df_dstress)
525 std::vector<bool> act;
530 std::vector<Real> fep, fep_minus;
531 for (
unsigned i = 0; i < 3; ++i)
532 for (
unsigned j = 0; j < 3; ++j)
537 stressep(i, j) += ep / 2.0;
539 stressep(i, j) -= ep;
541 for (
unsigned surface = 0; surface <
_num_surfaces; ++surface)
542 df_dstress[surface](i, j) = (fep[surface] - fep_minus[surface]) / ep;
548 const std::vector<Real> & intnl,
549 std::vector<Real> & df_dintnl)
553 std::vector<bool> act;
556 std::vector<Real> origf;
559 std::vector<Real> intnlep;
561 for (
unsigned model = 0; model <
_num_models; ++model)
562 intnlep[model] = intnl[model];
564 std::vector<Real> fep;
566 for (
unsigned surface = 0; surface <
_num_surfaces; ++surface)
570 intnlep[model] += ep;
572 df_dintnl[surface] = (fep[surface] - origf[surface]) / ep;
573 intnlep[model] -= ep;
579 const std::vector<Real> & intnl,
580 std::vector<RankFourTensor> & dr_dstress)
584 std::vector<bool> act;
589 std::vector<RankTwoTensor> rep, rep_minus;
590 for (
unsigned i = 0; i < 3; ++i)
591 for (
unsigned j = 0; j < 3; ++j)
595 stressep(i, j) += ep / 2.0;
597 stressep(i, j) -= ep;
599 for (
unsigned surface = 0; surface <
_num_surfaces; ++surface)
600 for (
unsigned k = 0; k < 3; ++k)
601 for (
unsigned l = 0; l < 3; ++l)
602 dr_dstress[surface](k, l, i, j) = (rep[surface](k, l) - rep_minus[surface](k, l)) / ep;
608 const std::vector<Real> & intnl,
609 std::vector<RankTwoTensor> & dr_dintnl)
613 std::vector<bool> act;
616 std::vector<RankTwoTensor> origr;
619 std::vector<Real> intnlep;
621 for (
unsigned model = 0; model <
_num_models; ++model)
622 intnlep[model] = intnl[model];
624 std::vector<RankTwoTensor> rep;
626 for (
unsigned surface = 0; surface <
_num_surfaces; ++surface)
630 intnlep[model] += ep;
632 dr_dintnl[surface] = (rep[surface] - origr[surface]) / ep;
633 intnlep[model] -= ep;