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 145910 : DefaultMultiAppFixedPointConvergence::validParams() 21 : { 22 145910 : InputParameters params = DefaultConvergenceBase::validParams(); 23 145910 : params += FixedPointSolve::fixedPointDefaultConvergenceParams(); 24 145910 : params.addClassDescription("Default fixed point convergence criteria."); 25 145910 : return params; 26 0 : } 27 : 28 68881 : DefaultMultiAppFixedPointConvergence::DefaultMultiAppFixedPointConvergence( 29 68881 : const InputParameters & parameters) 30 : : DefaultConvergenceBase(parameters), 31 68881 : _min_fixed_point_its(getSharedExecutionerParam<unsigned int>("fixed_point_min_its")), 32 137762 : _max_fixed_point_its(getSharedExecutionerParam<unsigned int>("fixed_point_max_its")), 33 68881 : _has_fixed_point_norm( 34 137762 : !getSharedExecutionerParam<bool>("disable_fixed_point_residual_norm_check")), 35 137762 : _fixed_point_force_norms(getSharedExecutionerParam<bool>("fixed_point_force_norms")), 36 137762 : _accept_max_it(getSharedExecutionerParam<bool>("accept_on_max_fixed_point_iteration")), 37 137762 : _fixed_point_rel_tol(getSharedExecutionerParam<Real>("fixed_point_rel_tol")), 38 137762 : _fixed_point_abs_tol(getSharedExecutionerParam<Real>("fixed_point_abs_tol")), 39 137762 : _custom_pp_rel_tol(getSharedExecutionerParam<Real>("custom_rel_tol")), 40 137762 : _custom_pp_abs_tol(getSharedExecutionerParam<Real>("custom_abs_tol")), 41 137888 : _fixed_point_custom_pp(isParamValid("custom_pp") ? &getPostprocessorValue("custom_pp") 42 : : nullptr), 43 137888 : _fixed_point_custom_pp_old(isParamValid("custom_pp") ? &getPostprocessorValueOld("custom_pp") 44 : : nullptr), 45 68881 : _pp_previous(0.0), 46 68881 : _pp_current(std::numeric_limits<Real>::max()), 47 68881 : _pp_scaling(1.0), 48 275524 : _fe_problem(*getCheckedPointerParam<FEProblemBase *>("_fe_problem_base")), 49 275524 : _fp_solve(getMooseApp().getExecutioner()->fixedPointSolve()) 50 : { 51 68881 : 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 69025 : if (!_has_fixed_point_norm && parameters.isParamSetByUser("fixed_point_rel_tol")) 55 8 : 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 69013 : if (!_has_fixed_point_norm && parameters.isParamSetByUser("fixed_point_abs_tol")) 59 8 : 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 69001 : if (!_has_fixed_point_norm && parameters.isParamSetByUser("fixed_point_force_norms")) 63 8 : 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 68869 : 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 68869 : } 75 : 76 : void 77 1574 : DefaultMultiAppFixedPointConvergence::checkIterationType(IterationType it_type) const 78 : { 79 1574 : DefaultConvergenceBase::checkIterationType(it_type); 80 : 81 1574 : if (it_type != ConvergenceIterationTypes::MULTIAPP_FIXED_POINT) 82 4 : mooseError( 83 : "DefaultMultiAppFixedPointConvergence can only be used with MultiApp fixed point solves."); 84 1570 : } 85 : 86 : void 87 12201 : DefaultMultiAppFixedPointConvergence::initialize() 88 : { 89 12201 : DefaultConvergenceBase::initialize(); 90 : 91 12201 : _fixed_point_timestep_begin_norm.clear(); 92 12201 : _fixed_point_timestep_end_norm.clear(); 93 12201 : _fixed_point_timestep_begin_norm.resize(_max_fixed_point_its); 94 12201 : _fixed_point_timestep_end_norm.resize(_max_fixed_point_its); 95 : 96 24402 : _pp_history.str(""); 97 : 98 : // compute residual norm before iteration loop 99 12201 : if (_has_fixed_point_norm) 100 : { 101 12099 : _fixed_point_initial_norm = _fe_problem.computeResidualL2Norm(); 102 12099 : _console << COLOR_MAGENTA << "Initial fixed point residual norm: " << COLOR_DEFAULT; 103 12099 : if (_fixed_point_initial_norm == std::numeric_limits<Real>::max()) 104 0 : _console << " MAX "; 105 : else 106 12099 : _console << std::scientific << _fixed_point_initial_norm; 107 12099 : _console << COLOR_DEFAULT << "\n" << std::endl; 108 : } 109 12201 : } 110 : 111 : void 112 60820 : DefaultMultiAppFixedPointConvergence::preExecute() 113 : { 114 60820 : DefaultConvergenceBase::preExecute(); 115 : 116 : // compute TIMESTEP_BEGIN residual norm; this should be executed after TIMESTEP_BEGIN 117 : // but before the solve 118 121160 : if (_has_fixed_point_norm && 119 121160 : (_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 129270 : outputResidualNorm("TIMESTEP_BEGIN", begin_norm_old, _fixed_point_timestep_begin_norm[iter]); 128 : } 129 60820 : } 130 : 131 : Convergence::MooseConvergenceStatus 132 60820 : DefaultMultiAppFixedPointConvergence::checkConvergence(unsigned int iter) 133 : { 134 60820 : TIME_SECTION(_perfid_check_convergence); 135 : 136 60820 : 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 60820 : if (_has_fixed_point_norm) 142 60340 : if (_fe_problem.hasMultiApps(EXEC_TIMESTEP_END) || _fixed_point_force_norms) 143 : { 144 12231 : _fixed_point_timestep_end_norm[iter] = _fe_problem.computeResidualL2Norm(); 145 : 146 : Real end_norm_old = 147 12231 : (iter > 0 ? _fixed_point_timestep_end_norm[iter - 1] : std::numeric_limits<Real>::max()); 148 : 149 36693 : outputResidualNorm("TIMESTEP_END", end_norm_old, _fixed_point_timestep_end_norm[iter]); 150 : } 151 : 152 : // print residual norm history 153 60820 : if (_has_fixed_point_norm) 154 60340 : _fp_solve.printFixedPointConvergenceHistory(_fixed_point_initial_norm, 155 60340 : _fixed_point_timestep_begin_norm, 156 60340 : _fixed_point_timestep_end_norm); 157 : 158 60820 : if (iter + 2 > _min_fixed_point_its) 159 : { 160 : Real max_norm = 161 55254 : std::max(_fixed_point_timestep_begin_norm[iter], _fixed_point_timestep_end_norm[iter]); 162 : 163 55254 : Real max_relative_drop = max_norm / _fixed_point_initial_norm; 164 : 165 55254 : 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 51551 : if (_has_fixed_point_norm && max_relative_drop < _fixed_point_rel_tol) 172 : { 173 8051 : _fp_solve.setFixedPointStatus( 174 : FixedPointSolve::MooseFixedPointConvergenceReason::CONVERGED_RELATIVE); 175 8051 : 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 49022 : 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 48644 : return MooseConvergenceStatus::ITERATING; 209 60820 : } 210 : 211 : void 212 55321 : DefaultMultiAppFixedPointConvergence::outputResidualNorm(const std::string & execute_on_str, 213 : Real old_norm, 214 : Real new_norm) const 215 : { 216 55321 : _console << COLOR_MAGENTA << "Fixed point residual norm after " << execute_on_str 217 55321 : << " MultiApps: " << Console::outputNorm(old_norm, new_norm) << std::endl; 218 55321 : } 219 : 220 : void 221 392 : DefaultMultiAppFixedPointConvergence::computeCustomConvergencePostprocessor(unsigned int iter) 222 : { 223 1176 : if (!getParam<bool>("direct_pp_value")) 224 55 : _pp_previous = iter > 0 ? _pp_current : *_fixed_point_custom_pp_old; 225 : 226 1198 : 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 784 : 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 : }