MooseNonlinearConvergenceReason ReferenceResidualProblem::checkNonlinearConvergence(std::string &msg, const int it, const Real xnorm, const Real snorm, const Real fnorm, const Real rtol, const Real stol, const Real abstol, const int nfuncs, const int max_funcs, const Real ref_resid, const Real /*div_threshold*/) { updateReferenceResidual(); if (_solnVars.size() > 0) { Moose::out<<"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) { Moose::out<<std::setw(maxwsv+2)<<std::left<<_solnVarNames[i]+":"<<_resid[i]<<" "<<std::setw(maxwrv+2)<<_refResidVarNames[i]+":"<<_refResid[i]<<std::endl; } } NonlinearSystem & system = getNonlinearSystem(); 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) { 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; Moose::out<<"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 = it; msg = oss.str(); // Moose::out<<msg<<std::endl; //Print convergence diagnostic message return(reason); }
MooseNonlinearConvergenceReason FrictionalContactProblem::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 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, ref_resid, my_div_threshold); _refResidContact = ref_resid; //use initial residual if no reference variables are specified updateContactReferenceResidual(); int min_nl_its_since_contact_update = 1; ++_num_nl_its_since_contact_update; if ((reason > 0) || //converged (reason == MOOSE_NONLINEAR_ITERATING && //iterating and converged within factor (fnorm < abstol*_contact_slip_tol_factor || checkConvergenceIndividVars(fnorm, abstol*_contact_slip_tol_factor, rtol*_contact_slip_tol_factor, ref_resid)))) { _console<<"Slip iteration "<<_num_slip_iterations<<" "; if (_num_slip_iterations < _min_slip_iters) { //force another iteration, and do a slip update reason = MOOSE_NONLINEAR_ITERATING; _do_slip_update = true; _console<<"Force slip update < min slip iterations"<<std::endl; } else if (_num_slip_iterations < _max_slip_iters) { //do a slip update if there is another iteration if (_num_nl_its_since_contact_update >= min_nl_its_since_contact_update) { _do_slip_update = true; NonlinearSystem & nonlinear_sys = getNonlinearSystem(); nonlinear_sys.update(); const NumericVector<Number>*& ghosted_solution = nonlinear_sys.currentSolution(); calculateSlip(*ghosted_solution, NULL); //Just to calculate slip residual if (_slip_residual > _target_contact_residual && _slip_residual > _target_relative_contact_residual*_refResidContact) { //force it to keep iterating reason = MOOSE_NONLINEAR_ITERATING; _console<<"Force slip update slip_resid > target: "<<_slip_residual<<std::endl; } else { //_do_slip_update = false; //maybe we want to do this _console<<"Not forcing slip update slip_resid <= target: "<<_slip_residual<<std::endl; } } else { if (_slip_residual > _target_contact_residual && _slip_residual > _target_relative_contact_residual*_refResidContact) { //force it to keep iterating reason = MOOSE_NONLINEAR_ITERATING; _console<<"Forcing another nonlinear iteration before slip iteration: " <<_num_nl_its_since_contact_update <<std::endl; } } } else { //maxed out _console<<"Max slip iterations"<<std::endl; reason = MOOSE_DIVERGED_FUNCTION_COUNT; } } return(reason); }