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 133968 : DefaultMultiAppFixedPointConvergence::validParams() 21 : { 22 133968 : InputParameters params = DefaultConvergenceBase::validParams(); 23 133968 : params += FixedPointSolve::fixedPointDefaultConvergenceParams(); 24 133968 : params.addClassDescription("Default fixed point convergence criteria."); 25 133968 : return params; 26 0 : } 27 : 28 68735 : DefaultMultiAppFixedPointConvergence::DefaultMultiAppFixedPointConvergence( 29 68735 : const InputParameters & parameters) 30 : : DefaultConvergenceBase(parameters), 31 68735 : _min_fixed_point_its(getSharedExecutionerParam<unsigned int>("fixed_point_min_its")), 32 137470 : _max_fixed_point_its(getSharedExecutionerParam<unsigned int>("fixed_point_max_its")), 33 68735 : _has_fixed_point_norm( 34 137470 : !getSharedExecutionerParam<bool>("disable_fixed_point_residual_norm_check")), 35 137470 : _fixed_point_force_norms(getSharedExecutionerParam<bool>("fixed_point_force_norms")), 36 137470 : _accept_max_it(getSharedExecutionerParam<bool>("accept_on_max_fixed_point_iteration")), 37 137470 : _fixed_point_rel_tol(getSharedExecutionerParam<Real>("fixed_point_rel_tol")), 38 137470 : _fixed_point_abs_tol(getSharedExecutionerParam<Real>("fixed_point_abs_tol")), 39 137470 : _custom_pp_rel_tol(getSharedExecutionerParam<Real>("custom_rel_tol")), 40 137470 : _custom_pp_abs_tol(getSharedExecutionerParam<Real>("custom_abs_tol")), 41 137586 : _fixed_point_custom_pp(isParamValid("custom_pp") ? &getPostprocessorValue("custom_pp") 42 : : nullptr), 43 137586 : _fixed_point_custom_pp_old(isParamValid("custom_pp") ? &getPostprocessorValueOld("custom_pp") 44 : : nullptr), 45 68735 : _pp_previous(0.0), 46 68735 : _pp_current(std::numeric_limits<Real>::max()), 47 68735 : _pp_scaling(1.0), 48 274940 : _fe_problem(*getCheckedPointerParam<FEProblemBase *>("_fe_problem_base")), 49 274940 : _fp_solve(getMooseApp().getExecutioner()->fixedPointSolve()) 50 : { 51 68735 : 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 68863 : if (!_has_fixed_point_norm && parameters.isParamSetByUser("fixed_point_rel_tol")) 55 6 : 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 68854 : if (!_has_fixed_point_norm && parameters.isParamSetByUser("fixed_point_abs_tol")) 59 6 : 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 68845 : if (!_has_fixed_point_norm && parameters.isParamSetByUser("fixed_point_force_norms")) 63 6 : 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 68726 : 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 68726 : } 75 : 76 : void 77 1463 : DefaultMultiAppFixedPointConvergence::checkIterationType(IterationType it_type) const 78 : { 79 1463 : DefaultConvergenceBase::checkIterationType(it_type); 80 : 81 1463 : if (it_type != ConvergenceIterationTypes::MULTIAPP_FIXED_POINT) 82 3 : mooseError( 83 : "DefaultMultiAppFixedPointConvergence can only be used with MultiApp fixed point solves."); 84 1460 : } 85 : 86 : void 87 11134 : DefaultMultiAppFixedPointConvergence::initialize() 88 : { 89 11134 : DefaultConvergenceBase::initialize(); 90 : 91 11134 : _fixed_point_timestep_begin_norm.clear(); 92 11134 : _fixed_point_timestep_end_norm.clear(); 93 11134 : _fixed_point_timestep_begin_norm.resize(_max_fixed_point_its); 94 11134 : _fixed_point_timestep_end_norm.resize(_max_fixed_point_its); 95 : 96 22268 : _pp_history.str(""); 97 : 98 : // compute residual norm before iteration loop 99 11134 : if (_has_fixed_point_norm) 100 : { 101 11041 : _fixed_point_initial_norm = _fe_problem.computeResidualL2Norm(); 102 11041 : _console << COLOR_MAGENTA << "Initial fixed point residual norm: " << COLOR_DEFAULT; 103 11041 : if (_fixed_point_initial_norm == std::numeric_limits<Real>::max()) 104 0 : _console << " MAX "; 105 : else 106 11041 : _console << std::scientific << _fixed_point_initial_norm; 107 11041 : _console << COLOR_DEFAULT << "\n" << std::endl; 108 : } 109 11134 : } 110 : 111 : void 112 56736 : DefaultMultiAppFixedPointConvergence::preExecute() 113 : { 114 56736 : DefaultConvergenceBase::preExecute(); 115 : 116 : // compute TIMESTEP_BEGIN residual norm; this should be executed after TIMESTEP_BEGIN 117 : // but before the solve 118 113036 : if (_has_fixed_point_norm && 119 113036 : (_fe_problem.hasMultiApps(EXEC_TIMESTEP_BEGIN) || _fixed_point_force_norms)) 120 : { 121 39918 : const auto iter = _fp_solve.numFixedPointIts() - 1; 122 39918 : _fixed_point_timestep_begin_norm[iter] = _fe_problem.computeResidualL2Norm(); 123 : 124 : Real begin_norm_old = 125 39918 : (iter > 0 ? _fixed_point_timestep_begin_norm[iter - 1] : std::numeric_limits<Real>::max()); 126 : 127 119754 : outputResidualNorm("TIMESTEP_BEGIN", begin_norm_old, _fixed_point_timestep_begin_norm[iter]); 128 : } 129 56736 : } 130 : 131 : Convergence::MooseConvergenceStatus 132 56736 : DefaultMultiAppFixedPointConvergence::checkConvergence(unsigned int n_iter) 133 : { 134 56736 : TIME_SECTION(_perfid_check_convergence); 135 : 136 : // index of the iteration, starting at 0; n_iter is number of iterations performed. 137 56736 : const auto iter = n_iter - 1; 138 : 139 56736 : if (_fixed_point_custom_pp) 140 357 : computeCustomConvergencePostprocessor(iter); 141 : 142 : // compute TIMESTEP_END residual norm; this should be executed between TIMESTEP_END 143 : // and TIMESTEP_BEGIN 144 56736 : if (_has_fixed_point_norm) 145 56300 : if (_fe_problem.hasMultiApps(EXEC_TIMESTEP_END) || _fixed_point_force_norms) 146 : { 147 11773 : auto & end_norm = _fixed_point_timestep_end_norm[iter]; 148 11773 : end_norm = _fe_problem.computeResidualL2Norm(); 149 : 150 : Real end_norm_old = 151 11773 : (iter > 0 ? _fixed_point_timestep_end_norm[iter - 1] : std::numeric_limits<Real>::max()); 152 : 153 35319 : outputResidualNorm("TIMESTEP_END", end_norm_old, end_norm); 154 : } 155 : 156 : // print residual norm history 157 56736 : if (_has_fixed_point_norm) 158 56300 : _fp_solve.printFixedPointConvergenceHistory(_fixed_point_initial_norm, 159 56300 : _fixed_point_timestep_begin_norm, 160 56300 : _fixed_point_timestep_end_norm); 161 : 162 56736 : if (n_iter >= _min_fixed_point_its) 163 : { 164 : Real max_norm = 165 51614 : std::max(_fixed_point_timestep_begin_norm[iter], _fixed_point_timestep_end_norm[iter]); 166 : 167 51614 : Real max_relative_drop = max_norm / _fixed_point_initial_norm; 168 : 169 51614 : if (_has_fixed_point_norm && max_norm < _fixed_point_abs_tol) 170 : { 171 3405 : _fp_solve.setFixedPointStatus( 172 : FixedPointSolve::MooseFixedPointConvergenceReason::CONVERGED_ABS); 173 3405 : return MooseConvergenceStatus::CONVERGED; 174 : } 175 48209 : if (_has_fixed_point_norm && max_relative_drop < _fixed_point_rel_tol) 176 : { 177 7339 : _fp_solve.setFixedPointStatus( 178 : FixedPointSolve::MooseFixedPointConvergenceReason::CONVERGED_RELATIVE); 179 7339 : return MooseConvergenceStatus::CONVERGED; 180 : } 181 : 182 40870 : if (std::abs(_pp_current - _pp_previous) < _custom_pp_abs_tol) 183 : { 184 21 : _fp_solve.setFixedPointStatus( 185 : FixedPointSolve::MooseFixedPointConvergenceReason::CONVERGED_PP); 186 21 : return MooseConvergenceStatus::CONVERGED; 187 : } 188 40849 : if (std::abs((_pp_current - _pp_previous) / _pp_scaling) < _custom_pp_rel_tol) 189 : { 190 19 : _fp_solve.setFixedPointStatus( 191 : FixedPointSolve::MooseFixedPointConvergenceReason::CONVERGED_PP); 192 19 : return MooseConvergenceStatus::CONVERGED; 193 : } 194 : } 195 : 196 45952 : if (n_iter == _max_fixed_point_its) 197 : { 198 338 : if (_accept_max_it) 199 : { 200 74 : _fp_solve.setFixedPointStatus( 201 : FixedPointSolve::MooseFixedPointConvergenceReason::REACH_MAX_ITS); 202 74 : return MooseConvergenceStatus::CONVERGED; 203 : } 204 : else 205 : { 206 264 : _fp_solve.setFixedPointStatus( 207 : FixedPointSolve::MooseFixedPointConvergenceReason::DIVERGED_MAX_ITS); 208 264 : return MooseConvergenceStatus::DIVERGED; 209 : } 210 : } 211 : 212 45614 : return MooseConvergenceStatus::ITERATING; 213 56736 : } 214 : 215 : void 216 51691 : DefaultMultiAppFixedPointConvergence::outputResidualNorm(const std::string & execute_on_str, 217 : Real old_norm, 218 : Real new_norm) const 219 : { 220 51691 : _console << COLOR_MAGENTA << "Fixed point residual norm after " << execute_on_str 221 51691 : << " MultiApps: " << Console::outputNorm(old_norm, new_norm) << std::endl; 222 51691 : } 223 : 224 : void 225 357 : DefaultMultiAppFixedPointConvergence::computeCustomConvergencePostprocessor(unsigned int iter) 226 : { 227 1071 : if (!getParam<bool>("direct_pp_value")) 228 50 : _pp_previous = iter > 0 ? _pp_current : *_fixed_point_custom_pp_old; 229 : 230 1091 : if ((iter == 0 && getParam<bool>("direct_pp_value")) || !getParam<bool>("direct_pp_value")) 231 135 : _pp_scaling = *_fixed_point_custom_pp; 232 357 : _pp_current = *_fixed_point_custom_pp; 233 : 234 714 : const auto pp_name = getParam<PostprocessorName>("custom_pp"); 235 357 : _pp_history << std::setw(2) << iter + 1 << " fixed point " << pp_name << " = " 236 357 : << Console::outputNorm(std::numeric_limits<Real>::max(), _pp_current, 8) << std::endl; 237 357 : _console << _pp_history.str() << std::flush; 238 357 : }