LCOV - code coverage report
Current view: top level - src/convergence - ParsedConvergence.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: #32971 (54bef8) with base c6cf66 Lines: 106 112 94.6 %
Date: 2026-05-29 20:35:17 Functions: 15 15 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 "ParsedConvergence.h"
      11             : #include "MooseUtils.h"
      12             : #include "Function.h"
      13             : #include "FEProblemBase.h"
      14             : 
      15             : registerMooseObject("MooseApp", ParsedConvergence);
      16             : 
      17             : InputParameters
      18        3206 : ParsedConvergence::validParams()
      19             : {
      20        3206 :   InputParameters params = Convergence::validParams();
      21        3206 :   params += FunctionParserUtils<false>::validParams();
      22             : 
      23        6412 :   params.addClassDescription("Evaluates convergence from a parsed expression.");
      24             : 
      25       19236 :   params.addRequiredCustomTypeParam<std::string>(
      26             :       "convergence_expression", "FunctionExpression", "Expression to parse for convergence");
      27       19236 :   params.addCustomTypeParam<std::string>(
      28             :       "divergence_expression", "FunctionExpression", "Expression to parse for divergence");
      29       12824 :   params.addParam<std::vector<std::string>>(
      30             :       "symbol_names", {}, "Symbol names to use in the parsed expressions");
      31        9618 :   params.addParam<std::vector<std::string>>(
      32             :       "symbol_values",
      33             :       {},
      34             :       "Values (Convergence names, Postprocessor names, Function names, and constants) "
      35             :       "corresponding to each entry in 'symbol_names'");
      36             : 
      37        3206 :   return params;
      38           0 : }
      39             : 
      40          77 : ParsedConvergence::ParsedConvergence(const InputParameters & parameters)
      41             :   : Convergence(parameters),
      42             :     FunctionParserUtils<false>(parameters),
      43         231 :     _fe_problem(*getCheckedPointerParam<FEProblemBase *>("_fe_problem_base")),
      44         154 :     _symbol_names(getParam<std::vector<std::string>>("symbol_names")),
      45         154 :     _symbol_values(getParam<std::vector<std::string>>("symbol_values")),
      46         154 :     _convergence_function_params(_symbol_names.size(), 0.0),
      47         308 :     _divergence_function_params(_symbol_names.size(), 0.0)
      48             : {
      49          77 :   if (_symbol_names.size() != _symbol_values.size())
      50           3 :     mooseError("The parameters 'symbol_names' and 'symbol_values' must have the same size.");
      51          74 : }
      52             : 
      53             : void
      54          74 : ParsedConvergence::initialSetup()
      55             : {
      56          74 :   Convergence::initialSetup();
      57             : 
      58          74 :   initializeSymbols();
      59             : 
      60         148 :   const auto convergence_expression = getParam<std::string>("convergence_expression");
      61          74 :   _convergence_function = makeParsedFunction(convergence_expression);
      62             : 
      63         148 :   const auto divergence_expression = isParamValid("divergence_expression")
      64          74 :                                          ? getParam<std::string>("divergence_expression")
      65         222 :                                          : MooseUtils::join(_convergence_symbol_names, "|");
      66          74 :   if (divergence_expression.size())
      67          74 :     _divergence_function = makeParsedFunction(divergence_expression);
      68          74 : }
      69             : 
      70             : void
      71          74 : ParsedConvergence::initializeSymbols()
      72             : {
      73         333 :   for (const auto i : index_range(_symbol_values))
      74             :   {
      75         259 :     ReporterName reporter_name(_symbol_values[i], "value");
      76         259 :     if (_fe_problem.getReporterData().hasReporterValue<PostprocessorValue>(reporter_name))
      77          61 :       initializePostprocessorSymbol(i);
      78         198 :     else if (_fe_problem.hasFunction(_symbol_values[i]))
      79          50 :       initializeFunctionSymbol(i);
      80         148 :     else if (_fe_problem.hasConvergence(_symbol_values[i]))
      81          98 :       initializeConvergenceSymbol(i);
      82             :     else
      83          50 :       initializeConstantSymbol(i);
      84         259 :   }
      85          74 : }
      86             : 
      87             : void
      88          61 : ParsedConvergence::initializePostprocessorSymbol(unsigned int i)
      89             : {
      90          61 :   const PostprocessorValue & pp_value = _fe_problem.getPostprocessorValueByName(_symbol_values[i]);
      91          61 :   _pp_values.push_back(&pp_value);
      92          61 :   _pp_indices.push_back(i);
      93          61 : }
      94             : 
      95             : void
      96          50 : ParsedConvergence::initializeFunctionSymbol(unsigned int i)
      97             : {
      98          50 :   Function & function = _fe_problem.getFunction(_symbol_values[i], _tid);
      99          50 :   _functions.push_back(&function);
     100          50 :   _function_indices.push_back(i);
     101          50 : }
     102             : 
     103             : void
     104          98 : ParsedConvergence::initializeConvergenceSymbol(unsigned int i)
     105             : {
     106          98 :   Convergence & convergence = _fe_problem.getConvergence(_symbol_values[i], _tid);
     107          98 :   _convergences.push_back(&convergence);
     108          98 :   _convergence_symbol_names.push_back(_symbol_names[i]);
     109          98 :   _convergence_indices.push_back(i);
     110          98 : }
     111             : 
     112             : void
     113          50 : ParsedConvergence::initializeConstantSymbol(unsigned int i)
     114             : {
     115             :   try
     116             :   {
     117          50 :     const Real value = MooseUtils::convert<Real>(_symbol_values[i], true);
     118          50 :     _convergence_function_params[i] = value;
     119          50 :     _divergence_function_params[i] = value;
     120             :   }
     121           0 :   catch (const std::invalid_argument & e)
     122             :   {
     123           0 :     mooseError(
     124             :         "The 'symbol_values' entry '",
     125           0 :         _symbol_values[i],
     126             :         "' is not a constant value or the name of a Convergence, Postprocessor, or Function.",
     127           0 :         e.what());
     128           0 :   }
     129          50 : }
     130             : 
     131             : ParsedConvergence::SymFunctionPtr
     132         148 : ParsedConvergence::makeParsedFunction(const std::string & expression)
     133             : {
     134             :   // Create parsed function
     135         148 :   auto sym_function = std::make_shared<SymFunction>();
     136        1184 :   parsedFunctionSetup(sym_function,
     137             :                       expression,
     138         740 :                       Moose::stringify(_symbol_names),
     139             :                       {"pi", "e"},
     140             :                       {std::to_string(libMesh::pi), std::to_string(std::exp(Real(1)))},
     141             :                       comm());
     142             : 
     143         148 :   return sym_function;
     144         148 : }
     145             : 
     146             : Convergence::MooseConvergenceStatus
     147         918 : ParsedConvergence::checkConvergence(unsigned int iter)
     148             : {
     149         918 :   updateSymbolValues(iter);
     150             : 
     151         918 :   const Real converged_real = evaluate(_convergence_function, _convergence_function_params, name());
     152             :   const Real diverged_real =
     153         918 :       _divergence_function ? evaluate(_divergence_function, _divergence_function_params, name())
     154         918 :                            : 0;
     155             : 
     156        1833 :   if (convertRealToBool(diverged_real, "divergence_expression"))
     157          18 :     return MooseConvergenceStatus::DIVERGED;
     158        1794 :   else if (convertRealToBool(converged_real, "convergence_expression"))
     159         114 :     return MooseConvergenceStatus::CONVERGED;
     160             :   else
     161         783 :     return MooseConvergenceStatus::ITERATING;
     162             : }
     163             : 
     164             : void
     165         918 : ParsedConvergence::updateSymbolValues(unsigned int iter)
     166             : {
     167         918 :   updatePostprocessorSymbolValues();
     168         918 :   updateFunctionSymbolValues();
     169         918 :   updateConvergenceSymbolValues(iter);
     170         918 : }
     171             : 
     172             : void
     173         918 : ParsedConvergence::updatePostprocessorSymbolValues()
     174             : {
     175        1802 :   for (const auto i : index_range(_pp_indices))
     176             :   {
     177         884 :     _convergence_function_params[_pp_indices[i]] = (*_pp_values[i]);
     178         884 :     _divergence_function_params[_pp_indices[i]] = (*_pp_values[i]);
     179             :   }
     180         918 : }
     181             : 
     182             : void
     183         918 : ParsedConvergence::updateFunctionSymbolValues()
     184             : {
     185        1028 :   for (const auto i : index_range(_function_indices))
     186             :   {
     187         110 :     const Real function_value = _functions[i]->value(_t, Point(0, 0, 0));
     188         110 :     _convergence_function_params[_function_indices[i]] = function_value;
     189         110 :     _divergence_function_params[_function_indices[i]] = function_value;
     190             :   }
     191         918 : }
     192             : 
     193             : void
     194         918 : ParsedConvergence::updateConvergenceSymbolValues(unsigned int iter)
     195             : {
     196        2644 :   for (const auto i : index_range(_convergence_indices))
     197             :   {
     198        1726 :     const auto status = _convergences[i]->checkConvergence(iter);
     199        1726 :     _convergence_function_params[_convergence_indices[i]] =
     200             :         status == MooseConvergenceStatus::CONVERGED;
     201        1726 :     _divergence_function_params[_convergence_indices[i]] =
     202             :         status == MooseConvergenceStatus::DIVERGED;
     203             :   }
     204         918 : }
     205             : 
     206             : bool
     207        1815 : ParsedConvergence::convertRealToBool(Real value, const std::string & param) const
     208             : {
     209        1815 :   if (MooseUtils::absoluteFuzzyEqual(value, 1.0))
     210         132 :     return true;
     211        1683 :   else if (MooseUtils::absoluteFuzzyEqual(value, 0.0))
     212        1680 :     return false;
     213             :   else
     214           3 :     mooseError("The expression parameter '",
     215             :                param,
     216             :                "' evaluated to the value ",
     217             :                value,
     218             :                ", but it must only evaluate to either 0 or 1.");
     219             : }

Generated by: LCOV version 1.14