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 : 16 : registerMooseObject("MooseApp", DefaultMultiAppFixedPointConvergence); 17 : 18 : InputParameters 19 135259 : DefaultMultiAppFixedPointConvergence::validParams() 20 : { 21 135259 : InputParameters params = DefaultConvergenceBase::validParams(); 22 135259 : params += FixedPointSolve::fixedPointDefaultConvergenceParams(); 23 135259 : params.addClassDescription("Default fixed point convergence criteria."); 24 135259 : return params; 25 0 : } 26 : 27 63493 : DefaultMultiAppFixedPointConvergence::DefaultMultiAppFixedPointConvergence( 28 63493 : const InputParameters & parameters) 29 : : DefaultConvergenceBase(parameters), 30 63493 : _min_fixed_point_its(getSharedExecutionerParam<unsigned int>("fixed_point_min_its")), 31 63493 : _max_fixed_point_its(getSharedExecutionerParam<unsigned int>("fixed_point_max_its")), 32 63493 : _has_fixed_point_norm( 33 63493 : !getSharedExecutionerParam<bool>("disable_fixed_point_residual_norm_check")), 34 63493 : _fixed_point_force_norms(getSharedExecutionerParam<bool>("fixed_point_force_norms")), 35 63493 : _accept_max_it(getSharedExecutionerParam<bool>("accept_on_max_fixed_point_iteration")), 36 63493 : _fixed_point_rel_tol(getSharedExecutionerParam<Real>("fixed_point_rel_tol")), 37 63493 : _fixed_point_abs_tol(getSharedExecutionerParam<Real>("fixed_point_abs_tol")), 38 63493 : _custom_pp_rel_tol(getSharedExecutionerParam<Real>("custom_rel_tol")), 39 63493 : _custom_pp_abs_tol(getSharedExecutionerParam<Real>("custom_abs_tol")), 40 63493 : _fixed_point_custom_pp(isParamValid("custom_pp") ? &getPostprocessorValue("custom_pp") 41 : : nullptr), 42 63493 : _pp_old(0.0), 43 63493 : _pp_new(std::numeric_limits<Real>::max()), 44 63493 : _pp_scaling(1.0), 45 63493 : _fe_problem(*getCheckedPointerParam<FEProblemBase *>("_fe_problem_base")), 46 253972 : _fp_solve(getMooseApp().getExecutioner()->fixedPointSolve()) 47 : { 48 63493 : if (_min_fixed_point_its > _max_fixed_point_its) 49 0 : paramError("fixed_point_min_its", 50 : "The minimum number of fixed point iterations may not exceed the maximum."); 51 63493 : if (!_has_fixed_point_norm && parameters.isParamSetByUser("fixed_point_rel_tol")) 52 4 : paramWarning( 53 : "disable_fixed_point_residual_norm_check", 54 : "fixed_point_rel_tol will be ignored because the fixed point residual check is disabled."); 55 63489 : if (!_has_fixed_point_norm && parameters.isParamSetByUser("fixed_point_abs_tol")) 56 4 : paramWarning( 57 : "disable_fixed_point_residual_norm_check", 58 : "fixed_point_abs_tol will be ignored because the fixed point residual check is disabled."); 59 63485 : if (!_has_fixed_point_norm && parameters.isParamSetByUser("fixed_point_force_norms")) 60 4 : paramWarning("disable_fixed_point_residual_norm_check", 61 : "fixed_point_force_norms will be ignored because the fixed point residual check " 62 : "is disabled."); 63 : 64 63481 : if (dynamic_cast<SteffensenSolve *>(&_fp_solve) && _fe_problem.hasMultiApps()) 65 : { 66 : // Steffensen method uses half-steps 67 0 : if (!parameters.isParamSetByAddParam("fixed_point_min_its")) 68 0 : _min_fixed_point_its *= 2; 69 0 : _max_fixed_point_its *= 2; 70 : } 71 63481 : } 72 : 73 : void 74 11275 : DefaultMultiAppFixedPointConvergence::initialize() 75 : { 76 11275 : DefaultConvergenceBase::initialize(); 77 : 78 11275 : _fixed_point_timestep_begin_norm.clear(); 79 11275 : _fixed_point_timestep_end_norm.clear(); 80 11275 : _fixed_point_timestep_begin_norm.resize(_max_fixed_point_its); 81 11275 : _fixed_point_timestep_end_norm.resize(_max_fixed_point_its); 82 : 83 11275 : _pp_history.str(""); 84 : 85 : // compute residual norm before iteration loop 86 11275 : if (_has_fixed_point_norm) 87 : { 88 11180 : _fixed_point_initial_norm = _fe_problem.computeResidualL2Norm(); 89 11180 : _console << COLOR_MAGENTA << "Initial fixed point residual norm: " << COLOR_DEFAULT; 90 11180 : if (_fixed_point_initial_norm == std::numeric_limits<Real>::max()) 91 0 : _console << " MAX "; 92 : else 93 11180 : _console << std::scientific << _fixed_point_initial_norm; 94 11180 : _console << COLOR_DEFAULT << "\n" << std::endl; 95 : } 96 11275 : } 97 : 98 : void 99 56048 : DefaultMultiAppFixedPointConvergence::preExecute() 100 : { 101 56048 : DefaultConvergenceBase::preExecute(); 102 : 103 : // compute TIMESTEP_BEGIN residual norm; this should be executed after TIMESTEP_BEGIN 104 : // but before the solve 105 111641 : if (_has_fixed_point_norm && 106 111641 : (_fe_problem.hasMultiApps(EXEC_TIMESTEP_BEGIN) || _fixed_point_force_norms)) 107 : { 108 40000 : const auto iter = _fp_solve.numFixedPointIts() - 1; 109 40000 : _fixed_point_timestep_begin_norm[iter] = _fe_problem.computeResidualL2Norm(); 110 : 111 : Real begin_norm_old = 112 40000 : (iter > 0 ? _fixed_point_timestep_begin_norm[iter - 1] : std::numeric_limits<Real>::max()); 113 : 114 40000 : outputResidualNorm("TIMESTEP_BEGIN", begin_norm_old, _fixed_point_timestep_begin_norm[iter]); 115 : } 116 56048 : } 117 : 118 : Convergence::MooseConvergenceStatus 119 56048 : DefaultMultiAppFixedPointConvergence::checkConvergence(unsigned int iter) 120 : { 121 56048 : TIME_SECTION(_perfid_check_convergence); 122 : 123 56048 : if (_fixed_point_custom_pp) 124 366 : computeCustomConvergencePostprocessor(iter); 125 : 126 : // compute TIMESTEP_END residual norm; this should be executed between TIMESTEP_END 127 : // and TIMESTEP_BEGIN 128 56048 : if (_has_fixed_point_norm) 129 55593 : if (_fe_problem.hasMultiApps(EXEC_TIMESTEP_END) || _fixed_point_force_norms) 130 : { 131 11032 : _fixed_point_timestep_end_norm[iter] = _fe_problem.computeResidualL2Norm(); 132 : 133 : Real end_norm_old = 134 11032 : (iter > 0 ? _fixed_point_timestep_end_norm[iter - 1] : std::numeric_limits<Real>::max()); 135 : 136 11032 : outputResidualNorm("TIMESTEP_END", end_norm_old, _fixed_point_timestep_end_norm[iter]); 137 : } 138 : 139 : // print residual norm history 140 56048 : if (_has_fixed_point_norm) 141 55593 : _fp_solve.printFixedPointConvergenceHistory(_fixed_point_initial_norm, 142 55593 : _fixed_point_timestep_begin_norm, 143 55593 : _fixed_point_timestep_end_norm); 144 : 145 56048 : if (iter + 2 > _min_fixed_point_its) 146 : { 147 : Real max_norm = 148 50946 : std::max(_fixed_point_timestep_begin_norm[iter], _fixed_point_timestep_end_norm[iter]); 149 : 150 50946 : Real max_relative_drop = max_norm / _fixed_point_initial_norm; 151 : 152 50946 : if (_has_fixed_point_norm && max_norm < _fixed_point_abs_tol) 153 : { 154 3336 : _fp_solve.setFixedPointStatus( 155 : FixedPointSolve::MooseFixedPointConvergenceReason::CONVERGED_ABS); 156 3336 : return MooseConvergenceStatus::CONVERGED; 157 : } 158 47610 : if (_has_fixed_point_norm && max_relative_drop < _fixed_point_rel_tol) 159 : { 160 7411 : _fp_solve.setFixedPointStatus( 161 : FixedPointSolve::MooseFixedPointConvergenceReason::CONVERGED_RELATIVE); 162 7411 : return MooseConvergenceStatus::CONVERGED; 163 : } 164 : 165 40199 : if (std::abs(_pp_new - _pp_old) < _custom_pp_abs_tol) 166 : { 167 21 : _fp_solve.setFixedPointStatus( 168 : FixedPointSolve::MooseFixedPointConvergenceReason::CONVERGED_PP); 169 21 : return MooseConvergenceStatus::CONVERGED; 170 : } 171 40178 : if (std::abs((_pp_new - _pp_old) / _pp_scaling) < _custom_pp_rel_tol) 172 : { 173 20 : _fp_solve.setFixedPointStatus( 174 : FixedPointSolve::MooseFixedPointConvergenceReason::CONVERGED_PP); 175 20 : return MooseConvergenceStatus::CONVERGED; 176 : } 177 : } 178 : 179 45260 : if (iter + 1 == _max_fixed_point_its) 180 : { 181 462 : if (_accept_max_it) 182 : { 183 75 : _fp_solve.setFixedPointStatus( 184 : FixedPointSolve::MooseFixedPointConvergenceReason::REACH_MAX_ITS); 185 75 : return MooseConvergenceStatus::CONVERGED; 186 : } 187 : else 188 : { 189 387 : _fp_solve.setFixedPointStatus( 190 : FixedPointSolve::MooseFixedPointConvergenceReason::DIVERGED_MAX_ITS); 191 387 : return MooseConvergenceStatus::DIVERGED; 192 : } 193 : } 194 : 195 44798 : return MooseConvergenceStatus::ITERATING; 196 56048 : } 197 : 198 : void 199 51032 : DefaultMultiAppFixedPointConvergence::outputResidualNorm(const std::string & execute_on_str, 200 : Real old_norm, 201 : Real new_norm) const 202 : { 203 51032 : _console << COLOR_MAGENTA << "Fixed point residual norm after " << execute_on_str 204 51032 : << " MultiApps: " << Console::outputNorm(old_norm, new_norm) << std::endl; 205 51032 : } 206 : 207 : void 208 366 : DefaultMultiAppFixedPointConvergence::computeCustomConvergencePostprocessor(unsigned int iter) 209 : { 210 366 : if (iter > 0 && !getParam<bool>("direct_pp_value")) 211 40 : _pp_old = _pp_new; 212 : 213 366 : if ((iter == 0 && getParam<bool>("direct_pp_value")) || !getParam<bool>("direct_pp_value")) 214 136 : _pp_scaling = *_fixed_point_custom_pp; 215 366 : _pp_new = *_fixed_point_custom_pp; 216 : 217 366 : const auto pp_name = getParam<PostprocessorName>("custom_pp"); 218 366 : _pp_history << std::setw(2) << iter + 1 << " fixed point " << pp_name << " = " 219 366 : << Console::outputNorm(std::numeric_limits<Real>::max(), _pp_new, 8) << std::endl; 220 366 : _console << _pp_history.str() << std::flush; 221 366 : }