12 #include "libmesh/utility.h" 18 MooseEnum debug_fspb_type(
"none crash jacobian jacobian_and_linear_system",
"none");
21 "Debug types for use by developers when creating new " 22 "plasticity models, not for general use. 2 = debug Jacobian " 23 "entries, 3 = check the entire Jacobian, and check Ax=b");
26 "Debug Jacobian entries at this stress. For use by developers");
27 params.
addParam<std::vector<Real>>(
"debug_jac_at_pm",
28 "Debug Jacobian entries at these plastic multipliers");
29 params.
addParam<std::vector<Real>>(
"debug_jac_at_intnl",
30 "Debug Jacobian entries at these internal parameters");
32 "debug_stress_change", 1.0,
"Debug finite differencing parameter for the stress");
34 "debug_pm_change",
"Debug finite differencing parameters for the plastic multipliers");
36 "debug_intnl_change",
"Debug finite differencing parameters for the internal parameters");
44 _fspb_debug_pm(_params.
get<
std::vector<
Real>>(
"debug_jac_at_pm")),
45 _fspb_debug_intnl(_params.
get<
std::vector<
Real>>(
"debug_jac_at_intnl")),
46 _fspb_debug_stress_change(_params.
get<
Real>(
"debug_stress_change")),
47 _fspb_debug_pm_change(_params.
get<
std::vector<
Real>>(
"debug_pm_change")),
48 _fspb_debug_intnl_change(_params.
get<
std::vector<
Real>>(
"debug_intnl_change"))
55 Moose::err <<
"Debug Parameters are as follows\n";
56 Moose::err <<
"stress = \n";
62 mooseError(
"The debug parameters have the wrong size\n");
64 Moose::err <<
"plastic multipliers =\n";
65 for (
unsigned surface = 0; surface <
_num_surfaces; ++surface)
68 Moose::err <<
"internal parameters =\n";
72 Moose::err <<
"finite-differencing parameter for stress-changes:\n" 74 Moose::err <<
"finite-differencing parameter(s) for plastic-multiplier(s):\n";
75 for (
unsigned surface = 0; surface <
_num_surfaces; ++surface)
77 Moose::err <<
"finite-differencing parameter(s) for internal-parameter(s):\n";
81 Moose::err << std::flush;
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();
159 Moose::err << std::flush;
164 const std::vector<Real> & intnl_old)
166 Moose::err <<
"\n\n+++++++++++++++++++++\nChecking the Jacobian\n+++++++++++++++++++++\n";
169 std::vector<bool> act;
171 std::vector<bool> deactivated_due_to_ld;
176 std::vector<std::vector<Real>> jac;
182 deactivated_due_to_ld,
185 std::vector<std::vector<Real>> fdjac;
197 for (
unsigned row = 0; row < jac.size(); ++row)
198 for (
unsigned col = 0; col < jac.size(); ++col)
200 L2_numer += Utility::pow<2>(jac[row][col] - fdjac[row][col]);
201 L2_denom += Utility::pow<2>(jac[row][col] + fdjac[row][col]);
203 Moose::err <<
"\nRelative L2norm = " <<
std::sqrt(L2_numer / L2_denom) / 0.5 <<
"\n";
205 Moose::err <<
"\nHand-coded Jacobian:\n";
206 for (
unsigned row = 0; row < jac.size(); ++row)
208 for (
unsigned col = 0; col < jac.size(); ++col)
209 Moose::err << jac[row][col] <<
" ";
213 Moose::err <<
"Finite difference Jacobian:\n";
214 for (
unsigned row = 0; row < fdjac.size(); ++row)
216 for (
unsigned col = 0; col < fdjac.size(); ++col)
217 Moose::err << fdjac[row][col] <<
" ";
221 Moose::err << std::flush;
226 const std::vector<Real> & intnl_old,
227 const std::vector<Real> & intnl,
228 const std::vector<Real> & pm,
232 std::vector<std::vector<Real>> & jac)
234 std::vector<bool> active;
237 std::vector<bool> deactivated_due_to_ld;
238 std::vector<bool> deactivated_due_to_ld_ep;
240 std::vector<Real> orig_rhs;
249 deactivated_due_to_ld);
253 unsigned int system_size =
255 jac.resize(system_size);
256 for (
unsigned row = 0; row < system_size; ++row)
257 jac[row].assign(system_size, 0);
259 std::vector<Real> rhs_ep;
265 for (
unsigned i = 0; i < 3; ++i)
266 for (
unsigned j = 0;
j <= i; ++
j)
269 stressep(i,
j) += ep;
271 stressep(
j, i) += ep;
272 delta_dpep = delta_dp;
273 for (
unsigned k = 0;
k < 3; ++
k)
274 for (
unsigned l = 0; l < 3; ++l)
276 delta_dpep(
k, l) -= E_inv(
k, l, i,
j) * ep;
278 delta_dpep(
k, l) -= E_inv(
k, l,
j, i) * ep;
289 deactivated_due_to_ld_ep);
291 for (
unsigned dof = 0; dof < whole_system_size; ++dof)
295 -(rhs_ep[dof] - orig_rhs[row]) / ep;
301 std::vector<Real> pmep;
303 for (
unsigned surface = 0; surface <
_num_surfaces; ++surface)
304 pmep[surface] = pm[surface];
305 for (
unsigned surface = 0; surface <
_num_surfaces; ++surface)
313 stress, intnl_old, intnl, pmep, delta_dp, rhs_ep, active,
false, deactivated_due_to_ld_ep);
315 for (
unsigned dof = 0; dof < whole_system_size; ++dof)
319 -(rhs_ep[dof] - orig_rhs[row]) / ep;
326 std::vector<Real> intnlep;
335 intnlep[
model] += ep;
338 stress, intnl_old, intnlep, pm, delta_dp, rhs_ep, active,
false, deactivated_due_to_ld_ep);
340 for (
unsigned dof = 0; dof < whole_system_size; ++dof)
344 -(rhs_ep[dof] - orig_rhs[row]) / ep;
347 intnlep[
model] -= ep;
354 const std::vector<bool> & deactivated_due_to_ld)
356 if (dof <
unsigned(6))
359 unsigned eff_dof = dof - 6;
362 return !deactivated_due_to_ld[eff_dof];
365 for (
unsigned surface = 0; surface <
_num_surfaces; ++surface)
366 active_surface[surface] = !deactivated_due_to_ld[surface];
373 Moose::err <<
"\n\n+++++++++++++++++++++\nChecking the Solution\n";
374 Moose::err <<
"(Ie, checking Ax = b)\n+++++++++++++++++++++\n";
377 std::vector<bool> act;
379 std::vector<bool> deactivated_due_to_ld;
384 std::vector<Real> orig_rhs;
393 deactivated_due_to_ld);
395 Moose::err <<
"\nb = ";
396 for (
unsigned i = 0; i < orig_rhs.size(); ++i)
397 Moose::err << orig_rhs[i] <<
" ";
398 Moose::err <<
"\n\n";
400 std::vector<std::vector<Real>> jac_coded;
406 deactivated_due_to_ld,
410 <<
"Before checking Ax=b is correct, check that the Jacobians given below are equal.\n";
412 <<
"The hand-coded Jacobian is used in calculating the solution 'x', given 'b' above.\n";
413 Moose::err <<
"Note that this only includes degrees of freedom that aren't deactivated due to " 414 "linear dependence.\n";
415 Moose::err <<
"Hand-coded Jacobian:\n";
416 for (
unsigned row = 0; row < jac_coded.size(); ++row)
418 for (
unsigned col = 0; col < jac_coded.size(); ++col)
419 Moose::err << jac_coded[row][col] <<
" ";
426 std::vector<Real> dpm;
427 std::vector<Real> dintnl;
438 deactivated_due_to_ld);
441 for (
unsigned surface = 0; surface <
_num_surfaces; ++surface)
442 active_not_deact[surface] = !deactivated_due_to_ld[surface];
445 x.assign(orig_rhs.size(), 0);
447 for (
unsigned i = 0; i < 3; ++i)
448 for (
unsigned j = 0;
j <= i; ++
j)
449 x[ind++] = dstress(i,
j);
450 for (
unsigned surface = 0; surface <
_num_surfaces; ++surface)
451 if (active_not_deact[surface])
452 x[ind++] = dpm[surface];
457 mooseAssert(ind == orig_rhs.size(),
458 "Incorrect extracting of changes from NR solution in the " 459 "finite-difference checking of nrStep");
461 Moose::err <<
"\nThis yields x =";
462 for (
unsigned i = 0; i < orig_rhs.size(); ++i)
463 Moose::err <<
x[i] <<
" ";
466 std::vector<std::vector<Real>> jac_fd;
476 Moose::err <<
"\nThe finite-difference Jacobian is used to multiply by this 'x',\n";
477 Moose::err <<
"in order to check that the solution is correct\n";
478 Moose::err <<
"Finite-difference Jacobian:\n";
479 for (
unsigned row = 0; row < jac_fd.size(); ++row)
481 for (
unsigned col = 0; col < jac_fd.size(); ++col)
482 Moose::err << jac_fd[row][col] <<
" ";
488 for (
unsigned row = 0; row < jac_coded.size(); ++row)
489 for (
unsigned col = 0; col < jac_coded.size(); ++col)
491 L2_numer += Utility::pow<2>(jac_coded[row][col] - jac_fd[row][col]);
492 L2_denom += Utility::pow<2>(jac_coded[row][col] + jac_fd[row][col]);
494 Moose::err <<
"Relative L2norm of the hand-coded and finite-difference Jacobian is " 495 <<
std::sqrt(L2_numer / L2_denom) / 0.5 <<
"\n";
497 std::vector<Real> fd_times_x;
498 fd_times_x.assign(orig_rhs.size(), 0);
499 for (
unsigned row = 0; row < orig_rhs.size(); ++row)
500 for (
unsigned col = 0; col < orig_rhs.size(); ++col)
501 fd_times_x[row] += jac_fd[row][col] *
x[col];
503 Moose::err <<
"\n(Finite-difference Jacobian)*x =\n";
504 for (
unsigned i = 0; i < orig_rhs.size(); ++i)
505 Moose::err << fd_times_x[i] <<
" ";
507 Moose::err <<
"Recall that b = \n";
508 for (
unsigned i = 0; i < orig_rhs.size(); ++i)
509 Moose::err << orig_rhs[i] <<
" ";
514 for (
unsigned i = 0; i < orig_rhs.size(); ++i)
516 L2_numer += Utility::pow<2>(orig_rhs[i] - fd_times_x[i]);
517 L2_denom += Utility::pow<2>(orig_rhs[i] + fd_times_x[i]);
519 Moose::err <<
"\nRelative L2norm of these is " <<
std::sqrt(L2_numer / L2_denom) / 0.5
525 const std::vector<Real> & intnl,
526 std::vector<RankTwoTensor> & df_dstress)
530 std::vector<bool> act;
535 std::vector<Real> fep, fep_minus;
536 for (
unsigned i = 0; i < 3; ++i)
537 for (
unsigned j = 0;
j < 3; ++
j)
542 stressep(i,
j) += ep / 2.0;
544 stressep(i,
j) -= ep;
546 for (
unsigned surface = 0; surface <
_num_surfaces; ++surface)
547 df_dstress[surface](i,
j) = (fep[surface] - fep_minus[surface]) / ep;
553 const std::vector<Real> & intnl,
554 std::vector<Real> & df_dintnl)
558 std::vector<bool> act;
561 std::vector<Real> origf;
564 std::vector<Real> intnlep;
569 std::vector<Real> fep;
571 for (
unsigned surface = 0; surface <
_num_surfaces; ++surface)
575 intnlep[
model] += ep;
577 df_dintnl[surface] = (fep[surface] - origf[surface]) / ep;
578 intnlep[
model] -= ep;
584 const std::vector<Real> & intnl,
585 std::vector<RankFourTensor> & dr_dstress)
589 std::vector<bool> act;
594 std::vector<RankTwoTensor> rep, rep_minus;
595 for (
unsigned i = 0; i < 3; ++i)
596 for (
unsigned j = 0;
j < 3; ++
j)
600 stressep(i,
j) += ep / 2.0;
602 stressep(i,
j) -= ep;
604 for (
unsigned surface = 0; surface <
_num_surfaces; ++surface)
605 for (
unsigned k = 0;
k < 3; ++
k)
606 for (
unsigned l = 0; l < 3; ++l)
607 dr_dstress[surface](
k, l, i,
j) = (rep[surface](
k, l) - rep_minus[surface](
k, l)) / ep;
613 const std::vector<Real> & intnl,
614 std::vector<RankTwoTensor> & dr_dintnl)
618 std::vector<bool> act;
621 std::vector<RankTwoTensor> origr;
624 std::vector<Real> intnlep;
629 std::vector<RankTwoTensor> rep;
631 for (
unsigned surface = 0; surface <
_num_surfaces; ++surface)
635 intnlep[
model] += ep;
637 dr_dintnl[surface] = (rep[surface] - origr[surface]) / ep;
638 intnlep[
model] -= ep;
void fddyieldFunction_dintnl(const RankTwoTensor &stress, const std::vector< Real > &intnl, std::vector< Real > &df_dintnl)
The finite-difference derivative of yield function(s) with respect to internal parameter(s) ...
virtual void fdJacobian(const RankTwoTensor &stress, const std::vector< Real > &intnl_old, const std::vector< Real > &intnl, const std::vector< Real > &pm, const RankTwoTensor &delta_dp, const RankFourTensor &E_inv, bool eliminate_ld, std::vector< std::vector< Real >> &jac)
The Jacobian calculated using finite differences.
void fddyieldFunction_dstress(const RankTwoTensor &stress, const std::vector< Real > &intnl, std::vector< RankTwoTensor > &df_dstress)
The finite-difference derivative of yield function(s) with respect to stress.
virtual void calculateRHS(const RankTwoTensor &stress, const std::vector< Real > &intnl_old, const std::vector< Real > &intnl, const std::vector< Real > &pm, const RankTwoTensor &delta_dp, std::vector< Real > &rhs, const std::vector< bool > &active, bool eliminate_ld, std::vector< bool > &deactivated_due_to_ld)
Calculate the RHS which is rhs = -(epp(0,0), epp(1,0), epp(1,1), epp(2,0), epp(2,1), epp(2,2), f[0], f[1], ..., f[num_f], ic[0], ic[1], ..., ic[num_ic])
virtual void dyieldFunction_dstress(const RankTwoTensor &stress, const std::vector< Real > &intnl, const std::vector< bool > &active, std::vector< RankTwoTensor > &df_dstress)
The derivative of the active yield function(s) with respect to stress.
unsigned int modelNumber(unsigned int surface)
returns the model number, given the surface number
void mooseError(Args &&... args)
void print(std::ostream &stm=Moose::out) const
virtual void calculateJacobian(const RankTwoTensor &stress, const std::vector< Real > &intnl, const std::vector< Real > &pm, const RankFourTensor &E_inv, const std::vector< bool > &active, const std::vector< bool > &deactivated_due_to_ld, std::vector< std::vector< Real >> &jac)
d(rhs)/d(dof)
Real _fspb_debug_stress_change
Debug finite-differencing parameter for the stress.
virtual void fddflowPotential_dintnl(const RankTwoTensor &stress, const std::vector< Real > &intnl, std::vector< RankTwoTensor > &dr_dintnl)
The finite-difference derivative of the flow potentials with respect to internal parameters.
static InputParameters validParams()
ADRealEigenVector< T, D, asd > sqrt(const ADRealEigenVector< T, D, asd > &)
std::vector< Real > _fspb_debug_intnl_change
Debug finite-differencing parameters for the internal parameters.
virtual void yieldFunction(const RankTwoTensor &stress, const std::vector< Real > &intnl, const std::vector< bool > &active, std::vector< Real > &f)
The active yield function(s)
virtual void fddflowPotential_dstress(const RankTwoTensor &stress, const std::vector< Real > &intnl, std::vector< RankFourTensor > &dr_dstress)
The finite-difference derivative of the flow potential(s) with respect to stress. ...
std::vector< Real > _fspb_debug_intnl
Debug the Jacobian entires at these internal parameters.
MultiPlasticityLinearSystem computes the linear system and handles linear-dependence removal for use ...
TensorValue< Real > RealTensorValue
unsigned int _num_surfaces
Number of surfaces within the plastic models.
const std::vector< double > x
void outputAndCheckDebugParameters()
Outputs the debug parameters: _fspb_debug_stress, _fspd_debug_pm, etc and checks that they are sized ...
virtual void dflowPotential_dintnl(const RankTwoTensor &stress, const std::vector< Real > &intnl, const std::vector< bool > &active, std::vector< RankTwoTensor > &dr_dintnl)
The derivative of the active flow potentials with respect to the active internal parameters The UserO...
void checkSolution(const RankFourTensor &E_inv)
Checks that Ax does equal b in the NR procedure.
void checkDerivatives()
Checks the derivatives, eg dyieldFunction_dstress by using finite difference approximations.
RankTwoTensor _fspb_debug_stress
Debug the Jacobian entries at this stress.
bool anyActiveSurfaces(int model, const std::vector< bool > &active)
returns true if any internal surfaces of the given model are active according to 'active' ...
virtual void flowPotential(const RankTwoTensor &stress, const std::vector< Real > &intnl, const std::vector< bool > &active, std::vector< RankTwoTensor > &r)
The active flow potential(s) - one for each yield function.
const PertinentGeochemicalSystem model(database, {"H2O", "H+", "HCO3-", "O2(aq)", "Ca++", ">(s)FeOH", "radius_neg1", "radius_neg1.5"}, {"Calcite"}, {}, {"Calcite_asdf"}, {"CH4(aq)"}, {">(s)FeOCa+"}, "O2(aq)", "e-")
bool dof_included(unsigned int dof, const std::vector< bool > &deactivated_due_to_ld)
static InputParameters validParams()
std::vector< Real > _fspb_debug_pm_change
Debug finite-differencing parameters for the plastic multipliers.
unsigned int _num_models
Number of plastic models for this material.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
virtual void dflowPotential_dstress(const RankTwoTensor &stress, const std::vector< Real > &intnl, const std::vector< bool > &active, std::vector< RankFourTensor > &dr_dstress)
The derivative of the active flow potential(s) with respect to stress.
std::vector< Real > _fspb_debug_pm
Debug the Jacobian entires at these plastic multipliers.
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
virtual void dyieldFunction_dintnl(const RankTwoTensor &stress, const std::vector< Real > &intnl, const std::vector< bool > &active, std::vector< Real > &df_dintnl)
The derivative of active yield function(s) with respect to their internal parameters (the user object...
MultiPlasticityDebugger(const MooseObject *moose_object)
virtual void nrStep(const RankTwoTensor &stress, const std::vector< Real > &intnl_old, const std::vector< Real > &intnl, const std::vector< Real > &pm, const RankFourTensor &E_inv, const RankTwoTensor &delta_dp, RankTwoTensor &dstress, std::vector< Real > &dpm, std::vector< Real > &dintnl, const std::vector< bool > &active, std::vector< bool > &deactivated_due_to_ld)
Performs one Newton-Raphson step.
static const std::string k
const Elem & get(const ElemType type_in)
void checkJacobian(const RankFourTensor &E_inv, const std::vector< Real > &intnl_old)
Checks the full Jacobian, which is just certain linear combinations of the dyieldFunction_dstress, etc, by using finite difference approximations.