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