void ReferenceResidualProblem::updateReferenceResidual() { NonlinearSystemBase & nonlinear_sys = getNonlinearSystemBase(); AuxiliarySystem & aux_sys = getAuxiliarySystem(); System & s = nonlinear_sys.system(); TransientExplicitSystem & as = aux_sys.sys(); for (unsigned int i = 0; i < _solnVars.size(); ++i) _resid[i] = s.calculate_norm(nonlinear_sys.RHS(), _solnVars[i], DISCRETE_L2); for (unsigned int i = 0; i < _refResidVars.size(); ++i) { const Real refResidual = as.calculate_norm(*as.current_local_solution, _refResidVars[i], DISCRETE_L2); _refResid[i] = refResidual * _scaling_factors[i]; } }
void ReferenceResidualProblem::initialSetup() { NonlinearSystemBase & nonlinear_sys = getNonlinearSystemBase(); AuxiliarySystem & aux_sys = getAuxiliarySystem(); System & s = nonlinear_sys.system(); TransientExplicitSystem & as = aux_sys.sys(); if (_solnVarNames.size() > 0 && _solnVarNames.size() != s.n_vars()) mooseError("In ReferenceResidualProblem, size of solution_variables (", _solnVarNames.size(), ") != number of variables in system (", s.n_vars(), ")"); _solnVars.clear(); for (unsigned int i = 0; i < _solnVarNames.size(); ++i) { bool foundMatch = false; for (unsigned int var_num = 0; var_num < s.n_vars(); var_num++) { if (_solnVarNames[i] == s.variable_name(var_num)) { _solnVars.push_back(var_num); _resid.push_back(0.0); foundMatch = true; break; } } if (!foundMatch) mooseError("Could not find solution variable '", _solnVarNames[i], "' in system"); } _refResidVars.clear(); for (unsigned int i = 0; i < _refResidVarNames.size(); ++i) { bool foundMatch = false; for (unsigned int var_num = 0; var_num < as.n_vars(); var_num++) { if (_refResidVarNames[i] == as.variable_name(var_num)) { _refResidVars.push_back(var_num); _refResid.push_back(0.0); foundMatch = true; break; } } if (!foundMatch) mooseError("Could not find variable '", _refResidVarNames[i], "' in auxiliary system"); } const unsigned int size_solnVars = _solnVars.size(); _scaling_factors.resize(size_solnVars); for (unsigned int i = 0; i < size_solnVars; ++i) if (nonlinear_sys.isScalarVariable(_solnVars[i])) _scaling_factors[i] = nonlinear_sys.getScalarVariable(0, _solnVars[i]).scalingFactor(); else _scaling_factors[i] = nonlinear_sys.getVariable(/*tid*/ 0, _solnVars[i]).scalingFactor(); FEProblemBase::initialSetup(); }
MooseNonlinearConvergenceReason ReferenceResidualProblem::checkNonlinearConvergence(std::string & msg, const PetscInt it, const Real xnorm, const Real snorm, const Real fnorm, const Real rtol, const Real stol, const Real abstol, const PetscInt nfuncs, const PetscInt max_funcs, const PetscBool force_iteration, const Real ref_resid, const Real /*div_threshold*/) { updateReferenceResidual(); if (_solnVars.size() > 0) { _console << "Solution, reference convergence variable norms:" << std::endl; unsigned int maxwsv = 0; unsigned int maxwrv = 0; for (unsigned int i = 0; i < _solnVars.size(); ++i) { if (_solnVarNames[i].size() > maxwsv) maxwsv = _solnVarNames[i].size(); if (_refResidVarNames[i].size() > maxwrv) maxwrv = _refResidVarNames[i].size(); } for (unsigned int i = 0; i < _solnVars.size(); ++i) _console << std::setw(maxwsv + 2) << std::left << _solnVarNames[i] + ":" << _resid[i] << " " << std::setw(maxwrv + 2) << _refResidVarNames[i] + ":" << _refResid[i] << std::endl; } NonlinearSystemBase & system = getNonlinearSystemBase(); MooseNonlinearConvergenceReason reason = MOOSE_NONLINEAR_ITERATING; std::stringstream oss; if (fnorm != fnorm) { oss << "Failed to converge, function norm is NaN\n"; reason = MOOSE_DIVERGED_FNORM_NAN; } else if (fnorm < abstol && (it || !force_iteration)) { oss << "Converged due to function norm " << fnorm << " < " << abstol << std::endl; reason = MOOSE_CONVERGED_FNORM_ABS; } else if (nfuncs >= max_funcs) { oss << "Exceeded maximum number of function evaluations: " << nfuncs << " > " << max_funcs << std::endl; reason = MOOSE_DIVERGED_FUNCTION_COUNT; } if (it && !reason) { if (checkConvergenceIndividVars(fnorm, abstol, rtol, ref_resid)) { if (_resid.size() > 0) oss << "Converged due to function norm " << " < " << " (relative tolerance) or (absolute tolerance) for all solution variables" << std::endl; else oss << "Converged due to function norm " << fnorm << " < " << " (relative tolerance)" << std::endl; reason = MOOSE_CONVERGED_FNORM_RELATIVE; } else if (it >= _accept_iters && checkConvergenceIndividVars( fnorm, abstol * _accept_mult, rtol * _accept_mult, ref_resid)) { if (_resid.size() > 0) oss << "Converged due to function norm " << " < " << " (acceptable relative tolerance) or (acceptable absolute tolerance) for all " "solution variables" << std::endl; else oss << "Converged due to function norm " << fnorm << " < " << " (acceptable relative tolerance)" << std::endl; _console << "ACCEPTABLE" << std::endl; reason = MOOSE_CONVERGED_FNORM_RELATIVE; } else if (snorm < stol * xnorm) { oss << "Converged due to small update length: " << snorm << " < " << stol << " * " << xnorm << std::endl; reason = MOOSE_CONVERGED_SNORM_RELATIVE; } } system._last_nl_rnorm = fnorm; system._current_nl_its = static_cast<unsigned int>(it); msg = oss.str(); return reason; }
MooseNonlinearConvergenceReason AugmentedLagrangianContactProblem::checkNonlinearConvergence(std::string & msg, const PetscInt it, const Real xnorm, const Real snorm, const Real fnorm, const Real rtol, const Real stol, const Real abstol, const PetscInt nfuncs, const PetscInt /*max_funcs*/, const PetscBool force_iteration, const Real ref_resid, const Real /*div_threshold*/) { Real my_max_funcs = std::numeric_limits<int>::max(); Real my_div_threshold = std::numeric_limits<Real>::max(); MooseNonlinearConvergenceReason reason = ReferenceResidualProblem::checkNonlinearConvergence(msg, it, xnorm, snorm, fnorm, rtol, stol, abstol, nfuncs, my_max_funcs, force_iteration, ref_resid, my_div_threshold); _console << "Augmented Lagrangian contact iteration " << _num_lagmul_iterations << "\n"; bool _augLM_repeat_step; if (reason > 0) { if (_num_lagmul_iterations < _max_lagmul_iters) { NonlinearSystemBase & nonlinear_sys = getNonlinearSystemBase(); nonlinear_sys.update(); const ConstraintWarehouse & constraints = nonlinear_sys.getConstraintWarehouse(); std::map<std::pair<unsigned int, unsigned int>, PenetrationLocator *> * penetration_locators = NULL; bool displaced = false; _augLM_repeat_step = false; if (getDisplacedProblem() == NULL) { GeometricSearchData & geom_search_data = geomSearchData(); penetration_locators = &geom_search_data._penetration_locators; } else { GeometricSearchData & displaced_geom_search_data = getDisplacedProblem()->geomSearchData(); penetration_locators = &displaced_geom_search_data._penetration_locators; displaced = true; } for (const auto & it : *penetration_locators) { PenetrationLocator & pen_loc = *(it.second); BoundaryID slave_boundary = pen_loc._slave_boundary; if (constraints.hasActiveNodeFaceConstraints(slave_boundary, displaced)) { const auto & ncs = constraints.getActiveNodeFaceConstraints(slave_boundary, displaced); for (const auto & nc : ncs) { if (std::dynamic_pointer_cast<MechanicalContactConstraint>(nc) == NULL) mooseError("AugmentedLagrangianContactProblem: dynamic cast of " "MechanicalContactConstraint object failed."); if (!(std::dynamic_pointer_cast<MechanicalContactConstraint>(nc)) ->AugmentedLagrangianContactConverged()) { (std::dynamic_pointer_cast<MechanicalContactConstraint>(nc)) ->updateAugmentedLagrangianMultiplier(false); _augLM_repeat_step = true; break; } } } } if (_augLM_repeat_step) { // force it to keep iterating reason = MOOSE_NONLINEAR_ITERATING; _console << "Augmented Lagrangian Multiplier needs updating." << std::endl; _num_lagmul_iterations++; } else _console << "Augmented Lagrangian contact constraint enforcement is satisfied." << std::endl; } else { // maxed out _console << "Maximum Augmented Lagrangian contact iterations have been reached." << std::endl; reason = MOOSE_DIVERGED_FUNCTION_COUNT; } } return reason; }