Ejemplo n.º 1
0
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);
}
Ejemplo n.º 2
0
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);
}