LCOV - code coverage report
Current view: top level - src/convergence - DefaultMultiAppFixedPointConvergence.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: #33416 (b10b36) with base 9fbd27 Lines: 114 120 95.0 %
Date: 2026-07-23 16:15:30 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      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 : }

Generated by: LCOV version 1.14