LCOV - code coverage report
Current view: top level - src/convergence - DefaultMultiAppFixedPointConvergence.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 106 112 94.6 %
Date: 2025-07-17 01:28:37 Functions: 7 7 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             : 
      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 : }

Generated by: LCOV version 1.14