LCOV - code coverage report
Current view: top level - src/convergence - DefaultMultiAppFixedPointConvergence.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 419b9d Lines: 112 118 94.9 %
Date: 2025-08-08 20:01:16 Functions: 8 8 100.0 %
Legend: Lines: hit not hit

          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 : }

Generated by: LCOV version 1.14