void FiniteStrainPlasticBase::checkJacobian() { _console << "\n ++++++++++++++ \nChecking the Jacobian\n"; outputAndCheckDebugParameters(); RankFourTensor E_inv = _elasticity_tensor[_qp].invSymm(); RankTwoTensor delta_dp = -E_inv*_fspb_debug_stress; std::vector<std::vector<Real> > jac; calculateJacobian(_fspb_debug_stress, _fspb_debug_intnl, _fspb_debug_pm, E_inv, jac); std::vector<std::vector<Real> > fdjac; fdJacobian(_fspb_debug_stress, _intnl_old[_qp], _fspb_debug_intnl, _fspb_debug_pm, delta_dp, E_inv, fdjac); _console << "Hand-coded Jacobian:\n"; for (unsigned row = 0 ; row < jac.size() ; ++row) { for (unsigned col = 0 ; col < jac.size() ; ++col) _console << jac[row][col] << " "; _console << "\n"; } _console << "Finite difference Jacobian:\n"; for (unsigned row = 0 ; row < fdjac.size() ; ++row) { for (unsigned col = 0 ; col < fdjac.size() ; ++col) _console << fdjac[row][col] << " "; _console << "\n"; } }
void MultiPlasticityDebugger::checkJacobian(const RankFourTensor & E_inv, const std::vector<Real> & intnl_old) { Moose::err << "\n\n+++++++++++++++++++++\nChecking the Jacobian\n+++++++++++++++++++++\n"; outputAndCheckDebugParameters(); std::vector<bool> act; act.assign(_num_surfaces, true); std::vector<bool> deactivated_due_to_ld; deactivated_due_to_ld.assign(_num_surfaces, false); RankTwoTensor delta_dp = -E_inv * _fspb_debug_stress; std::vector<std::vector<Real>> jac; calculateJacobian(_fspb_debug_stress, _fspb_debug_intnl, _fspb_debug_pm, E_inv, act, deactivated_due_to_ld, jac); std::vector<std::vector<Real>> fdjac; fdJacobian(_fspb_debug_stress, intnl_old, _fspb_debug_intnl, _fspb_debug_pm, delta_dp, E_inv, false, fdjac); Real L2_numer = 0; Real L2_denom = 0; for (unsigned row = 0; row < jac.size(); ++row) for (unsigned col = 0; col < jac.size(); ++col) { L2_numer += Utility::pow<2>(jac[row][col] - fdjac[row][col]); L2_denom += Utility::pow<2>(jac[row][col] + fdjac[row][col]); } Moose::err << "\nRelative L2norm = " << std::sqrt(L2_numer / L2_denom) / 0.5 << "\n"; Moose::err << "\nHand-coded Jacobian:\n"; for (unsigned row = 0; row < jac.size(); ++row) { for (unsigned col = 0; col < jac.size(); ++col) Moose::err << jac[row][col] << " "; Moose::err << "\n"; } Moose::err << "Finite difference Jacobian:\n"; for (unsigned row = 0; row < fdjac.size(); ++row) { for (unsigned col = 0; col < fdjac.size(); ++col) Moose::err << fdjac[row][col] << " "; Moose::err << "\n"; } }
void MultiPlasticityDebugger::checkSolution(const RankFourTensor & E_inv) { Moose::err << "\n\n+++++++++++++++++++++\nChecking the Solution\n"; Moose::err << "(Ie, checking Ax = b)\n+++++++++++++++++++++\n"; outputAndCheckDebugParameters(); std::vector<bool> act; act.assign(_num_surfaces, true); std::vector<bool> deactivated_due_to_ld; deactivated_due_to_ld.assign(_num_surfaces, false); RankTwoTensor delta_dp = -E_inv * _fspb_debug_stress; std::vector<Real> orig_rhs; calculateRHS(_fspb_debug_stress, _fspb_debug_intnl, _fspb_debug_intnl, _fspb_debug_pm, delta_dp, orig_rhs, act, true, deactivated_due_to_ld); Moose::err << "\nb = "; for (unsigned i = 0; i < orig_rhs.size(); ++i) Moose::err << orig_rhs[i] << " "; Moose::err << "\n\n"; std::vector<std::vector<Real>> jac_coded; calculateJacobian(_fspb_debug_stress, _fspb_debug_intnl, _fspb_debug_pm, E_inv, act, deactivated_due_to_ld, jac_coded); Moose::err << "Before checking Ax=b is correct, check that the Jacobians given below are equal.\n"; Moose::err << "The hand-coded Jacobian is used in calculating the solution 'x', given 'b' above.\n"; Moose::err << "Note that this only includes degrees of freedom that aren't deactivated due to " "linear dependence.\n"; Moose::err << "Hand-coded Jacobian:\n"; for (unsigned row = 0; row < jac_coded.size(); ++row) { for (unsigned col = 0; col < jac_coded.size(); ++col) Moose::err << jac_coded[row][col] << " "; Moose::err << "\n"; } deactivated_due_to_ld.assign(_num_surfaces, false); // this potentially gets changed by nrStep, below RankTwoTensor dstress; std::vector<Real> dpm; std::vector<Real> dintnl; nrStep(_fspb_debug_stress, _fspb_debug_intnl, _fspb_debug_intnl, _fspb_debug_pm, E_inv, delta_dp, dstress, dpm, dintnl, act, deactivated_due_to_ld); std::vector<bool> active_not_deact(_num_surfaces); for (unsigned surface = 0; surface < _num_surfaces; ++surface) active_not_deact[surface] = !deactivated_due_to_ld[surface]; std::vector<Real> x; x.assign(orig_rhs.size(), 0); unsigned ind = 0; for (unsigned i = 0; i < 3; ++i) for (unsigned j = 0; j <= i; ++j) x[ind++] = dstress(i, j); for (unsigned surface = 0; surface < _num_surfaces; ++surface) if (active_not_deact[surface]) x[ind++] = dpm[surface]; for (unsigned model = 0; model < _num_models; ++model) if (anyActiveSurfaces(model, active_not_deact)) x[ind++] = dintnl[model]; mooseAssert(ind == orig_rhs.size(), "Incorrect extracting of changes from NR solution in the " "finite-difference checking of nrStep"); Moose::err << "\nThis yields x ="; for (unsigned i = 0; i < orig_rhs.size(); ++i) Moose::err << x[i] << " "; Moose::err << "\n"; std::vector<std::vector<Real>> jac_fd; fdJacobian(_fspb_debug_stress, _fspb_debug_intnl, _fspb_debug_intnl, _fspb_debug_pm, delta_dp, E_inv, true, jac_fd); Moose::err << "\nThe finite-difference Jacobian is used to multiply by this 'x',\n"; Moose::err << "in order to check that the solution is correct\n"; Moose::err << "Finite-difference Jacobian:\n"; for (unsigned row = 0; row < jac_fd.size(); ++row) { for (unsigned col = 0; col < jac_fd.size(); ++col) Moose::err << jac_fd[row][col] << " "; Moose::err << "\n"; } Real L2_numer = 0; Real L2_denom = 0; for (unsigned row = 0; row < jac_coded.size(); ++row) for (unsigned col = 0; col < jac_coded.size(); ++col) { L2_numer += Utility::pow<2>(jac_coded[row][col] - jac_fd[row][col]); L2_denom += Utility::pow<2>(jac_coded[row][col] + jac_fd[row][col]); } Moose::err << "Relative L2norm of the hand-coded and finite-difference Jacobian is " << std::sqrt(L2_numer / L2_denom) / 0.5 << "\n"; std::vector<Real> fd_times_x; fd_times_x.assign(orig_rhs.size(), 0); for (unsigned row = 0; row < orig_rhs.size(); ++row) for (unsigned col = 0; col < orig_rhs.size(); ++col) fd_times_x[row] += jac_fd[row][col] * x[col]; Moose::err << "\n(Finite-difference Jacobian)*x =\n"; for (unsigned i = 0; i < orig_rhs.size(); ++i) Moose::err << fd_times_x[i] << " "; Moose::err << "\n"; Moose::err << "Recall that b = \n"; for (unsigned i = 0; i < orig_rhs.size(); ++i) Moose::err << orig_rhs[i] << " "; Moose::err << "\n"; L2_numer = 0; L2_denom = 0; for (unsigned i = 0; i < orig_rhs.size(); ++i) { L2_numer += Utility::pow<2>(orig_rhs[i] - fd_times_x[i]); L2_denom += Utility::pow<2>(orig_rhs[i] + fd_times_x[i]); } Moose::err << "\nRelative L2norm of these is " << std::sqrt(L2_numer / L2_denom) / 0.5 << "\n"; }