Line data Source code
1 : //* This file is part of the MOOSE framework 2 : //* https://mooseframework.inl.gov 3 : //* 4 : //* All rights reserved, see COPYRIGHT for full restrictions 5 : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT 6 : //* 7 : //* Licensed under LGPL 2.1, please see LICENSE for details 8 : //* https://www.gnu.org/licenses/lgpl-2.1.html 9 : 10 : #include "DefaultMultiAppFixedPointConvergence.h" 11 : #include "FEProblemBase.h" 12 : #include "FixedPointSolve.h" 13 : #include "Console.h" 14 : #include "SteffensenSolve.h" 15 : #include "ConvergenceIterationTypes.h" 16 : 17 : registerMooseObject("MooseApp", DefaultMultiAppFixedPointConvergence); 18 : 19 : InputParameters 20 144316 : DefaultMultiAppFixedPointConvergence::validParams() 21 : { 22 144316 : InputParameters params = DefaultConvergenceBase::validParams(); 23 144316 : params += FixedPointSolve::fixedPointDefaultConvergenceParams(); 24 144316 : params.addClassDescription("Default fixed point convergence criteria."); 25 144316 : return params; 26 0 : } 27 : 28 68045 : DefaultMultiAppFixedPointConvergence::DefaultMultiAppFixedPointConvergence( 29 68045 : const InputParameters & parameters) 30 : : DefaultConvergenceBase(parameters), 31 68045 : _min_fixed_point_its(getSharedExecutionerParam<unsigned int>("fixed_point_min_its")), 32 68045 : _max_fixed_point_its(getSharedExecutionerParam<unsigned int>("fixed_point_max_its")), 33 68045 : _has_fixed_point_norm( 34 68045 : !getSharedExecutionerParam<bool>("disable_fixed_point_residual_norm_check")), 35 68045 : _fixed_point_force_norms(getSharedExecutionerParam<bool>("fixed_point_force_norms")), 36 68045 : _accept_max_it(getSharedExecutionerParam<bool>("accept_on_max_fixed_point_iteration")), 37 68045 : _fixed_point_rel_tol(getSharedExecutionerParam<Real>("fixed_point_rel_tol")), 38 68045 : _fixed_point_abs_tol(getSharedExecutionerParam<Real>("fixed_point_abs_tol")), 39 68045 : _custom_pp_rel_tol(getSharedExecutionerParam<Real>("custom_rel_tol")), 40 68045 : _custom_pp_abs_tol(getSharedExecutionerParam<Real>("custom_abs_tol")), 41 68045 : _fixed_point_custom_pp(isParamValid("custom_pp") ? &getPostprocessorValue("custom_pp") 42 : : nullptr), 43 68045 : _fixed_point_custom_pp_old(isParamValid("custom_pp") ? &getPostprocessorValueOld("custom_pp") 44 : : nullptr), 45 68045 : _pp_previous(0.0), 46 68045 : _pp_current(std::numeric_limits<Real>::max()), 47 68045 : _pp_scaling(1.0), 48 68045 : _fe_problem(*getCheckedPointerParam<FEProblemBase *>("_fe_problem_base")), 49 272180 : _fp_solve(getMooseApp().getExecutioner()->fixedPointSolve()) 50 : { 51 68045 : if (_min_fixed_point_its > _max_fixed_point_its) 52 0 : paramError("fixed_point_min_its", 53 : "The minimum number of fixed point iterations may not exceed the maximum."); 54 68045 : if (!_has_fixed_point_norm && parameters.isParamSetByUser("fixed_point_rel_tol")) 55 4 : paramWarning( 56 : "disable_fixed_point_residual_norm_check", 57 : "fixed_point_rel_tol will be ignored because the fixed point residual check is disabled."); 58 68041 : if (!_has_fixed_point_norm && parameters.isParamSetByUser("fixed_point_abs_tol")) 59 4 : paramWarning( 60 : "disable_fixed_point_residual_norm_check", 61 : "fixed_point_abs_tol will be ignored because the fixed point residual check is disabled."); 62 68037 : if (!_has_fixed_point_norm && parameters.isParamSetByUser("fixed_point_force_norms")) 63 4 : paramWarning("disable_fixed_point_residual_norm_check", 64 : "fixed_point_force_norms will be ignored because the fixed point residual check " 65 : "is disabled."); 66 : 67 68033 : if (dynamic_cast<SteffensenSolve *>(&_fp_solve) && _fe_problem.hasMultiApps()) 68 : { 69 : // Steffensen method uses half-steps 70 0 : if (!parameters.isParamSetByAddParam("fixed_point_min_its")) 71 0 : _min_fixed_point_its *= 2; 72 0 : _max_fixed_point_its *= 2; 73 : } 74 68033 : } 75 : 76 : void 77 1561 : DefaultMultiAppFixedPointConvergence::checkIterationType(IterationType it_type) const 78 : { 79 1561 : DefaultConvergenceBase::checkIterationType(it_type); 80 : 81 1561 : if (it_type != ConvergenceIterationTypes::MULTIAPP_FIXED_POINT) 82 4 : mooseError( 83 : "DefaultMultiAppFixedPointConvergence can only be used with MultiApp fixed point solves."); 84 1557 : } 85 : 86 : void 87 12189 : DefaultMultiAppFixedPointConvergence::initialize() 88 : { 89 12189 : DefaultConvergenceBase::initialize(); 90 : 91 12189 : _fixed_point_timestep_begin_norm.clear(); 92 12189 : _fixed_point_timestep_end_norm.clear(); 93 12189 : _fixed_point_timestep_begin_norm.resize(_max_fixed_point_its); 94 12189 : _fixed_point_timestep_end_norm.resize(_max_fixed_point_its); 95 : 96 12189 : _pp_history.str(""); 97 : 98 : // compute residual norm before iteration loop 99 12189 : if (_has_fixed_point_norm) 100 : { 101 12087 : _fixed_point_initial_norm = _fe_problem.computeResidualL2Norm(); 102 12087 : _console << COLOR_MAGENTA << "Initial fixed point residual norm: " << COLOR_DEFAULT; 103 12087 : if (_fixed_point_initial_norm == std::numeric_limits<Real>::max()) 104 0 : _console << " MAX "; 105 : else 106 12087 : _console << std::scientific << _fixed_point_initial_norm; 107 12087 : _console << COLOR_DEFAULT << "\n" << std::endl; 108 : } 109 12189 : } 110 : 111 : void 112 60796 : DefaultMultiAppFixedPointConvergence::preExecute() 113 : { 114 60796 : DefaultConvergenceBase::preExecute(); 115 : 116 : // compute TIMESTEP_BEGIN residual norm; this should be executed after TIMESTEP_BEGIN 117 : // but before the solve 118 121112 : if (_has_fixed_point_norm && 119 121112 : (_fe_problem.hasMultiApps(EXEC_TIMESTEP_BEGIN) || _fixed_point_force_norms)) 120 : { 121 43090 : const auto iter = _fp_solve.numFixedPointIts() - 1; 122 43090 : _fixed_point_timestep_begin_norm[iter] = _fe_problem.computeResidualL2Norm(); 123 : 124 : Real begin_norm_old = 125 43090 : (iter > 0 ? _fixed_point_timestep_begin_norm[iter - 1] : std::numeric_limits<Real>::max()); 126 : 127 43090 : outputResidualNorm("TIMESTEP_BEGIN", begin_norm_old, _fixed_point_timestep_begin_norm[iter]); 128 : } 129 60796 : } 130 : 131 : Convergence::MooseConvergenceStatus 132 60796 : DefaultMultiAppFixedPointConvergence::checkConvergence(unsigned int iter) 133 : { 134 60796 : TIME_SECTION(_perfid_check_convergence); 135 : 136 60796 : if (_fixed_point_custom_pp) 137 392 : computeCustomConvergencePostprocessor(iter); 138 : 139 : // compute TIMESTEP_END residual norm; this should be executed between TIMESTEP_END 140 : // and TIMESTEP_BEGIN 141 60796 : if (_has_fixed_point_norm) 142 60316 : if (_fe_problem.hasMultiApps(EXEC_TIMESTEP_END) || _fixed_point_force_norms) 143 : { 144 12207 : _fixed_point_timestep_end_norm[iter] = _fe_problem.computeResidualL2Norm(); 145 : 146 : Real end_norm_old = 147 12207 : (iter > 0 ? _fixed_point_timestep_end_norm[iter - 1] : std::numeric_limits<Real>::max()); 148 : 149 12207 : outputResidualNorm("TIMESTEP_END", end_norm_old, _fixed_point_timestep_end_norm[iter]); 150 : } 151 : 152 : // print residual norm history 153 60796 : if (_has_fixed_point_norm) 154 60316 : _fp_solve.printFixedPointConvergenceHistory(_fixed_point_initial_norm, 155 60316 : _fixed_point_timestep_begin_norm, 156 60316 : _fixed_point_timestep_end_norm); 157 : 158 60796 : if (iter + 2 > _min_fixed_point_its) 159 : { 160 : Real max_norm = 161 55242 : std::max(_fixed_point_timestep_begin_norm[iter], _fixed_point_timestep_end_norm[iter]); 162 : 163 55242 : Real max_relative_drop = max_norm / _fixed_point_initial_norm; 164 : 165 55242 : if (_has_fixed_point_norm && max_norm < _fixed_point_abs_tol) 166 : { 167 3703 : _fp_solve.setFixedPointStatus( 168 : FixedPointSolve::MooseFixedPointConvergenceReason::CONVERGED_ABS); 169 3703 : return MooseConvergenceStatus::CONVERGED; 170 : } 171 51539 : if (_has_fixed_point_norm && max_relative_drop < _fixed_point_rel_tol) 172 : { 173 8039 : _fp_solve.setFixedPointStatus( 174 : FixedPointSolve::MooseFixedPointConvergenceReason::CONVERGED_RELATIVE); 175 8039 : return MooseConvergenceStatus::CONVERGED; 176 : } 177 : 178 43500 : if (std::abs(_pp_current - _pp_previous) < _custom_pp_abs_tol) 179 : { 180 23 : _fp_solve.setFixedPointStatus( 181 : FixedPointSolve::MooseFixedPointConvergenceReason::CONVERGED_PP); 182 23 : return MooseConvergenceStatus::CONVERGED; 183 : } 184 43477 : if (std::abs((_pp_current - _pp_previous) / _pp_scaling) < _custom_pp_rel_tol) 185 : { 186 21 : _fp_solve.setFixedPointStatus( 187 : FixedPointSolve::MooseFixedPointConvergenceReason::CONVERGED_PP); 188 21 : return MooseConvergenceStatus::CONVERGED; 189 : } 190 : } 191 : 192 49010 : if (iter + 1 == _max_fixed_point_its) 193 : { 194 378 : if (_accept_max_it) 195 : { 196 81 : _fp_solve.setFixedPointStatus( 197 : FixedPointSolve::MooseFixedPointConvergenceReason::REACH_MAX_ITS); 198 81 : return MooseConvergenceStatus::CONVERGED; 199 : } 200 : else 201 : { 202 297 : _fp_solve.setFixedPointStatus( 203 : FixedPointSolve::MooseFixedPointConvergenceReason::DIVERGED_MAX_ITS); 204 297 : return MooseConvergenceStatus::DIVERGED; 205 : } 206 : } 207 : 208 48632 : return MooseConvergenceStatus::ITERATING; 209 60796 : } 210 : 211 : void 212 55297 : DefaultMultiAppFixedPointConvergence::outputResidualNorm(const std::string & execute_on_str, 213 : Real old_norm, 214 : Real new_norm) const 215 : { 216 55297 : _console << COLOR_MAGENTA << "Fixed point residual norm after " << execute_on_str 217 55297 : << " MultiApps: " << Console::outputNorm(old_norm, new_norm) << std::endl; 218 55297 : } 219 : 220 : void 221 392 : DefaultMultiAppFixedPointConvergence::computeCustomConvergencePostprocessor(unsigned int iter) 222 : { 223 392 : if (!getParam<bool>("direct_pp_value")) 224 55 : _pp_previous = iter > 0 ? _pp_current : *_fixed_point_custom_pp_old; 225 : 226 392 : if ((iter == 0 && getParam<bool>("direct_pp_value")) || !getParam<bool>("direct_pp_value")) 227 148 : _pp_scaling = *_fixed_point_custom_pp; 228 392 : _pp_current = *_fixed_point_custom_pp; 229 : 230 392 : const auto pp_name = getParam<PostprocessorName>("custom_pp"); 231 392 : _pp_history << std::setw(2) << iter + 1 << " fixed point " << pp_name << " = " 232 392 : << Console::outputNorm(std::numeric_limits<Real>::max(), _pp_current, 8) << std::endl; 233 392 : _console << _pp_history.str() << std::flush; 234 392 : }