bool FrictionalContactProblem::calculateSlip(const NumericVector<Number>& ghosted_solution, std::vector<SlipData> * iterative_slip) { NonlinearSystem & nonlinear_sys = getNonlinearSystem(); unsigned int dim = nonlinear_sys.subproblem().mesh().dimension(); MooseVariable * residual_x_var = &getVariable(0,_residual_x); MooseVariable * residual_y_var = &getVariable(0,_residual_y); MooseVariable * residual_z_var = NULL; MooseVariable * diag_stiff_x_var = &getVariable(0,_diag_stiff_x); MooseVariable * diag_stiff_y_var = &getVariable(0,_diag_stiff_y); MooseVariable * diag_stiff_z_var = NULL; MooseVariable * inc_slip_x_var = &getVariable(0,_inc_slip_x); MooseVariable * inc_slip_y_var = &getVariable(0,_inc_slip_y); MooseVariable * inc_slip_z_var = NULL; if (dim == 3) { residual_z_var = &getVariable(0,_residual_z); diag_stiff_z_var = &getVariable(0,_diag_stiff_z); inc_slip_z_var = &getVariable(0,_inc_slip_z); } bool updatedSolution = false; _slip_residual = 0.0; _it_slip_norm = 0.0; _inc_slip_norm = 0.0; TransientNonlinearImplicitSystem & system = getNonlinearSystem().sys(); if (iterative_slip) iterative_slip->clear(); if (getDisplacedProblem() && _interaction_params.size() > 0) { computeResidual(system, ghosted_solution, *system.rhs); _num_contact_nodes = 0; _num_slipping = 0; _num_slipped_too_far = 0; GeometricSearchData & displaced_geom_search_data = getDisplacedProblem()->geomSearchData(); std::map<std::pair<unsigned int, unsigned int>, PenetrationLocator *> * penetration_locators = &displaced_geom_search_data._penetration_locators; AuxiliarySystem & aux_sys = getAuxiliarySystem(); const NumericVector<Number> & aux_solution = *aux_sys.currentSolution(); for (std::map<std::pair<unsigned int, unsigned int>, PenetrationLocator *>::iterator plit = penetration_locators->begin(); plit != penetration_locators->end(); ++plit) { PenetrationLocator & pen_loc = *plit->second; std::set<dof_id_type> & has_penetrated = pen_loc._has_penetrated; bool frictional_contact_this_interaction = false; std::map<std::pair<int,int>,InteractionParams>::iterator ipit; std::pair<int,int> ms_pair(pen_loc._master_boundary,pen_loc._slave_boundary); ipit = _interaction_params.find(ms_pair); if (ipit != _interaction_params.end()) frictional_contact_this_interaction = true; if (frictional_contact_this_interaction) { InteractionParams & interaction_params = ipit->second; Real slip_factor = interaction_params._slip_factor; Real slip_too_far_factor = interaction_params._slip_too_far_factor; Real friction_coefficient = interaction_params._friction_coefficient; std::vector<dof_id_type> & slave_nodes = pen_loc._nearest_node._slave_nodes; for (unsigned int i=0; i<slave_nodes.size(); i++) { dof_id_type slave_node_num = slave_nodes[i]; if (pen_loc._penetration_info[slave_node_num]) { PenetrationInfo & info = *pen_loc._penetration_info[slave_node_num]; const Node * node = info._node; if (node->processor_id() == processor_id()) { std::set<dof_id_type>::iterator hpit = has_penetrated.find(slave_node_num); if (hpit != has_penetrated.end()) { _num_contact_nodes++; VectorValue<dof_id_type> residual_dofs(node->dof_number(aux_sys.number(), residual_x_var->number(), 0), node->dof_number(aux_sys.number(), residual_y_var->number(), 0), (residual_z_var ? node->dof_number(aux_sys.number(), residual_z_var->number(), 0) : 0)); VectorValue<dof_id_type> diag_stiff_dofs(node->dof_number(aux_sys.number(), diag_stiff_x_var->number(), 0), node->dof_number(aux_sys.number(), diag_stiff_y_var->number(), 0), (diag_stiff_z_var ? node->dof_number(aux_sys.number(), diag_stiff_z_var->number(), 0) : 0)); VectorValue<dof_id_type> inc_slip_dofs(node->dof_number(aux_sys.number(), inc_slip_x_var->number(), 0), node->dof_number(aux_sys.number(), inc_slip_y_var->number(), 0), (inc_slip_z_var ? node->dof_number(aux_sys.number(), inc_slip_z_var->number(), 0) : 0)); RealVectorValue res_vec; RealVectorValue stiff_vec; RealVectorValue slip_inc_vec; for (unsigned int i=0; i<dim; ++i) { res_vec(i) = aux_solution(residual_dofs(i)); stiff_vec(i) = aux_solution(diag_stiff_dofs(i)); slip_inc_vec(i) = aux_solution(inc_slip_dofs(i)); } RealVectorValue slip_iterative(0.0,0.0,0.0); Real interaction_slip_residual = 0.0; // _console<<"inc slip: "<<slip_inc_vec<<std::endl; // _console<<"info slip: "<<info._incremental_slip<<std::endl; // ContactState state = calculateInteractionSlip(slip_iterative, interaction_slip_residual, info._normal, res_vec, info._incremental_slip, stiff_vec, friction_coefficient, slip_factor, slip_too_far_factor, dim); ContactState state = calculateInteractionSlip(slip_iterative, interaction_slip_residual, info._normal, res_vec, slip_inc_vec, stiff_vec, friction_coefficient, slip_factor, slip_too_far_factor, dim); // _console<<"iter slip: "<<slip_iterative<<std::endl; _slip_residual += interaction_slip_residual*interaction_slip_residual; if (state == SLIPPING || state == SLIPPED_TOO_FAR) { _num_slipping++; if (state == SLIPPED_TOO_FAR) _num_slipped_too_far++; for (unsigned int i=0; i<dim; ++i) { SlipData sd(node,i,slip_iterative(i)); if (iterative_slip) iterative_slip->push_back(sd); _it_slip_norm += slip_iterative(i)*slip_iterative(i); _inc_slip_norm += (slip_inc_vec(i)+slip_iterative(i))*(slip_inc_vec(i)+slip_iterative(i)); } } } } } } } } _communicator.sum(_num_contact_nodes); _communicator.sum(_num_slipping); _communicator.sum(_num_slipped_too_far); _communicator.sum(_slip_residual); _slip_residual = std::sqrt(_slip_residual); _communicator.sum(_it_slip_norm); _it_slip_norm = std::sqrt(_it_slip_norm); _communicator.sum(_inc_slip_norm); _inc_slip_norm = std::sqrt(_inc_slip_norm); if (_num_slipping > 0) updatedSolution = true; } return updatedSolution; }
bool FrictionalContactProblem::updateSolution(NumericVector<Number>& vec_solution, NumericVector<Number>& ghosted_solution) { bool solution_modified(false); solution_modified |= enforceRateConstraint(vec_solution, ghosted_solution); unsigned int nfc = numLocalFrictionalConstraints(); std::vector<SlipData> iterative_slip; unsigned int dim = getNonlinearSystem().subproblem().mesh().dimension(); iterative_slip.reserve(nfc*dim); if (_do_slip_update) { updateReferenceResidual(); updateContactReferenceResidual(); _console<<"Slip Update: "<<_num_slip_iterations<<std::endl; _console<<"Iter #Cont #Slip #TooFar Slip resid Inc Slip It Slip"<<std::endl; for (int i=0; i<_slip_updates_per_iter; i++) { _console<<std::left<<std::setw(6)<<i+1; bool updated_this_iter = calculateSlip(ghosted_solution, &iterative_slip); _console<<std::setw(10)<<_num_contact_nodes <<std::setw(10)<<_num_slipping <<std::setw(10)<<_num_slipped_too_far <<std::setprecision(4)<<std::setw(12)<<_slip_residual <<std::setw(12)<<_inc_slip_norm <<std::setw(12)<<_it_slip_norm; if (updated_this_iter) { if (_slip_residual < _target_contact_residual || _slip_residual < _target_relative_contact_residual*_refResidContact) { _console<<" Converged: Slip resid < tolerance, not applying this slip update"<<std::endl; break; } else { _console<<std::endl; applySlip(vec_solution, ghosted_solution, iterative_slip); } } else { _console<<" Converged: No slipping nodes"<<std::endl; break; } solution_modified |= updated_this_iter; } _num_slip_iterations++; _do_slip_update = false; _num_nl_its_since_contact_update = 0; } return solution_modified; }
bool FrictionalContactProblem::enforceRateConstraint(NumericVector<Number>& vec_solution, NumericVector<Number>& ghosted_solution) { NonlinearSystem & nonlinear_sys = getNonlinearSystem(); unsigned int dim = nonlinear_sys.subproblem().mesh().dimension(); _displaced_problem->updateMesh(ghosted_solution, *_aux.currentSolution()); MooseVariable * disp_x_var = &getVariable(0,_disp_x); MooseVariable * disp_y_var = &getVariable(0,_disp_y); MooseVariable * disp_z_var = NULL; if (dim == 3) disp_z_var = &getVariable(0,_disp_z); bool updatedSolution = false; if (getDisplacedProblem() && _interaction_params.size() > 0) { GeometricSearchData & displaced_geom_search_data = getDisplacedProblem()->geomSearchData(); std::map<std::pair<unsigned int, unsigned int>, PenetrationLocator *> * penetration_locators = &displaced_geom_search_data._penetration_locators; for (std::map<std::pair<unsigned int, unsigned int>, PenetrationLocator *>::iterator plit = penetration_locators->begin(); plit != penetration_locators->end(); ++plit) { PenetrationLocator & pen_loc = *plit->second; std::set<dof_id_type> & has_penetrated = pen_loc._has_penetrated; bool frictional_contact_this_interaction = false; std::map<std::pair<int,int>,InteractionParams>::iterator ipit; std::pair<int,int> ms_pair(pen_loc._master_boundary,pen_loc._slave_boundary); ipit = _interaction_params.find(ms_pair); if (ipit != _interaction_params.end()) frictional_contact_this_interaction = true; if (frictional_contact_this_interaction) { std::vector<dof_id_type> & slave_nodes = pen_loc._nearest_node._slave_nodes; for (unsigned int i=0; i<slave_nodes.size(); i++) { dof_id_type slave_node_num = slave_nodes[i]; if (pen_loc._penetration_info[slave_node_num]) { PenetrationInfo & info = *pen_loc._penetration_info[slave_node_num]; std::set<dof_id_type>::iterator hpit = has_penetrated.find(slave_node_num); if (hpit != has_penetrated.end()) { // _console<<"Slave node: "<<slave_node_num<<std::endl; const Node * node = info._node; VectorValue<dof_id_type> solution_dofs(node->dof_number(nonlinear_sys.number(), disp_x_var->number(), 0), node->dof_number(nonlinear_sys.number(), disp_y_var->number(), 0), (disp_z_var ? node->dof_number(nonlinear_sys.number(), disp_z_var->number(), 0) : 0)); //Get old parametric coords from info //get old element from info //Apply current configuration to that element and find xyz coords of that point //find xyz coords of current point from original coords and displacement vector //calculate difference between those two point coordinates to get correction // std::vector<Point>points(1); // points[0] = info._starting_closest_point_ref; // Elem *side = (info._starting_elem->build_side(info._starting_side_num,false)).release(); // FEBase &fe = *(pen_loc._fe[0]); // fe.reinit(side, &points); // RealVectorValue correction = starting_point[0] - current_coords; // RealVectorValue current_coords = *node; // RealVectorValue correction = info._closest_point - current_coords; const Node & undisp_node = _mesh.node(node->id()); RealVectorValue solution = info._closest_point - undisp_node; for (unsigned int i=0; i<dim; ++i) { // vec_solution.add(solution_dofs(i), correction(i)); vec_solution.set(solution_dofs(i), solution(i)); } info._distance = 0.0; } } } } updatedSolution = true; } vec_solution.close(); _communicator.max(updatedSolution); if (updatedSolution) { ghosted_solution = vec_solution; ghosted_solution.close(); } } return updatedSolution; }
void FrictionalContactProblem::updateIncrementalSlip() { AuxiliarySystem & aux_sys = getAuxiliarySystem(); NumericVector<Number> & aux_solution = aux_sys.solution(); MooseVariable * inc_slip_x_var = &getVariable(0,_inc_slip_x); MooseVariable * inc_slip_y_var = &getVariable(0,_inc_slip_y); MooseVariable * inc_slip_z_var = NULL; unsigned int dim = getNonlinearSystem().subproblem().mesh().dimension(); if (dim == 3) { inc_slip_z_var = &getVariable(0,_inc_slip_z); } GeometricSearchData & displaced_geom_search_data = getDisplacedProblem()->geomSearchData(); std::map<std::pair<unsigned int, unsigned int>, PenetrationLocator *> * penetration_locators = &displaced_geom_search_data._penetration_locators; for (std::map<std::pair<unsigned int, unsigned int>, PenetrationLocator *>::iterator plit = penetration_locators->begin(); plit != penetration_locators->end(); ++plit) { PenetrationLocator & pen_loc = *plit->second; bool frictional_contact_this_interaction = false; std::map<std::pair<int,int>,InteractionParams>::iterator ipit; std::pair<int,int> ms_pair(pen_loc._master_boundary,pen_loc._slave_boundary); ipit = _interaction_params.find(ms_pair); if (ipit != _interaction_params.end()) frictional_contact_this_interaction = true; if (frictional_contact_this_interaction) { std::vector<dof_id_type> & slave_nodes = pen_loc._nearest_node._slave_nodes; for (unsigned int i=0; i<slave_nodes.size(); i++) { dof_id_type slave_node_num = slave_nodes[i]; if (pen_loc._penetration_info[slave_node_num]) { PenetrationInfo & info = *pen_loc._penetration_info[slave_node_num]; if (info.isCaptured()) { const Node * node = info._node; VectorValue<dof_id_type> inc_slip_dofs(node->dof_number(aux_sys.number(), inc_slip_x_var->number(), 0), node->dof_number(aux_sys.number(), inc_slip_y_var->number(), 0), (inc_slip_z_var ? node->dof_number(aux_sys.number(), inc_slip_z_var->number(), 0) : 0)); RealVectorValue inc_slip = info._incremental_slip; for (unsigned int i=0; i<dim; ++i) { aux_solution.set(inc_slip_dofs(i), inc_slip(i)); } } } } } } aux_solution.close(); }
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); }
void FrictionalContactProblem::applySlip(NumericVector<Number>& vec_solution, NumericVector<Number>& ghosted_solution, std::vector<SlipData> & iterative_slip) { NonlinearSystem & nonlinear_sys = getNonlinearSystem(); unsigned int dim = nonlinear_sys.subproblem().mesh().dimension(); AuxiliarySystem & aux_sys = getAuxiliarySystem(); NumericVector<Number> & aux_solution = aux_sys.solution(); MooseVariable * disp_x_var = &getVariable(0,_disp_x); MooseVariable * disp_y_var = &getVariable(0,_disp_y); MooseVariable * disp_z_var = NULL; MooseVariable * inc_slip_x_var = &getVariable(0,_inc_slip_x); MooseVariable * inc_slip_y_var = &getVariable(0,_inc_slip_y); MooseVariable * inc_slip_z_var = NULL; if (dim == 3) { disp_z_var = &getVariable(0,_disp_z); inc_slip_z_var = &getVariable(0,_inc_slip_z); } MooseVariable * disp_var; MooseVariable * inc_slip_var; for (unsigned int iislip=0; iislip<iterative_slip.size(); ++iislip) { const Node * node = iterative_slip[iislip]._node; const unsigned int dof = iterative_slip[iislip]._dof; const Real slip = iterative_slip[iislip]._slip; if (dof == 0) { disp_var = disp_x_var; inc_slip_var = inc_slip_x_var; } else if (dof == 1) { disp_var = disp_y_var; inc_slip_var = inc_slip_y_var; } else { disp_var = disp_z_var; inc_slip_var = inc_slip_z_var; } dof_id_type solution_dof = node->dof_number(nonlinear_sys.number(), disp_var->number(), 0), inc_slip_dof = node->dof_number(aux_sys.number(), inc_slip_var->number(), 0); vec_solution.add(solution_dof, slip); aux_solution.add(inc_slip_dof, slip); } aux_solution.close(); vec_solution.close(); unsigned int num_slipping_nodes = iterative_slip.size(); _communicator.sum(num_slipping_nodes); if (num_slipping_nodes > 0) { ghosted_solution = vec_solution; ghosted_solution.close(); updateContactPoints(ghosted_solution,false); enforceRateConstraint(vec_solution, ghosted_solution); } }
FrictionalContactProblem::FrictionalContactProblem(const InputParameters & params) : ReferenceResidualProblem(params), _refResidContact(0.0), _slip_residual(0.0), _do_slip_update(false), _num_slip_iterations(0), _target_contact_residual(0.0), _target_relative_contact_residual(0.0), _num_nl_its_since_contact_update(0), _num_contact_nodes(0), _num_slipping(0), _num_slipped_too_far(0), _inc_slip_norm(0.0), _it_slip_norm(0.0) { std::vector<int> master = params.get<std::vector<int> >("master"); std::vector<int> slave = params.get<std::vector<int> >("slave"); std::vector<Real> friction_coefficient = params.get<std::vector<Real> >("friction_coefficient"); std::vector<Real> slip_factor = params.get<std::vector<Real> >("slip_factor"); std::vector<Real> slip_too_far_factor = params.get<std::vector<Real> >("slip_too_far_factor"); unsigned int dim = getNonlinearSystem().subproblem().mesh().dimension(); _disp_x = params.get<NonlinearVariableName>("disp_x"); _residual_x = params.get<AuxVariableName>("residual_x"); _diag_stiff_x = params.get<AuxVariableName>("diag_stiff_x"); _inc_slip_x = params.get<AuxVariableName>("inc_slip_x"); _disp_y = params.get<NonlinearVariableName>("disp_y"); _residual_y = params.get<AuxVariableName>("residual_y"); _diag_stiff_y = params.get<AuxVariableName>("diag_stiff_y"); _inc_slip_y = params.get<AuxVariableName>("inc_slip_y"); if (dim == 3) { if (!params.isParamValid("disp_z")) mooseError("Missing disp_z in FrictionalContactProblem"); if (!params.isParamValid("residual_z")) mooseError("Missing residual_z in FrictionalContactProblem"); if (!params.isParamValid("diag_stiff_z")) mooseError("Missing diag_stiff_z in FrictionalContactProblem"); if (!params.isParamValid("inc_slip_z")) mooseError("Missing inc_slip_z in FrictionalContactProblem"); _disp_z = params.get<NonlinearVariableName>("disp_z"); _residual_z = params.get<AuxVariableName>("residual_z"); _diag_stiff_z = params.get<AuxVariableName>("diag_stiff_z"); _inc_slip_z = params.get<AuxVariableName>("inc_slip_z"); } unsigned int num_interactions = master.size(); if (num_interactions != slave.size()) mooseError("Sizes of master surface and slave surface lists must match in FrictionalContactProblem"); if (num_interactions != friction_coefficient.size()) mooseError("Must have friction coefficient defined for every interaction in FrictionalContactProblem"); if (num_interactions != slip_factor.size()) mooseError("Must have slip factor defined for every interaction in FrictionalContactProblem"); if (num_interactions != slip_too_far_factor.size()) mooseError("Must have slip too far factor defined for every interaction in FrictionalContactProblem"); for (unsigned int i=0; i<master.size(); ++i) { std::pair<int,int> ms_pair(master[i],slave[i]); InteractionParams ip; ip._friction_coefficient = friction_coefficient[i]; ip._slip_factor = slip_factor[i]; ip._slip_too_far_factor = slip_too_far_factor[i]; _interaction_params[ms_pair] = ip; } _min_slip_iters = params.get<int>("minimum_slip_iterations"); _max_slip_iters = params.get<int>("maximum_slip_iterations"); _slip_updates_per_iter = params.get<int>("slip_updates_per_iteration"); bool have_target = false; bool have_target_relative = false; if (params.isParamValid("target_contact_residual")) { _target_contact_residual = params.get<Real>("target_contact_residual"); have_target = true; } if (params.isParamValid("target_relative_contact_residual")) { _target_relative_contact_residual = params.get<Real>("target_relative_contact_residual"); have_target_relative = true; } if (!(have_target || have_target_relative)) mooseError("Must specify either target_contact_residual or target_relative_contact_residual"); _contact_slip_tol_factor = params.get<Real>("contact_slip_tolerance_factor"); if (params.isParamValid("contact_reference_residual_variables")) _contactRefResidVarNames = params.get<std::vector<std::string> >("contact_reference_residual_variables"); }
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 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; } } 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; _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(); // _console<<msg<<std::endl; //Print convergence diagnostic message return(reason); }