LCOV - code coverage report
Current view: top level - src/convergence - ParsedConvergence.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 106 112 94.6 %
Date: 2025-07-17 01:28:37 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       14394 : ParsedConvergence::validParams()
      19             : {
      20       14394 :   InputParameters params = Convergence::validParams();
      21       14394 :   params += FunctionParserUtils<false>::validParams();
      22             : 
      23       14394 :   params.addClassDescription("Evaluates convergence from a parsed expression.");
      24             : 
      25       14394 :   params.addRequiredCustomTypeParam<std::string>(
      26             :       "convergence_expression", "FunctionExpression", "Expression to parse for convergence");
      27       14394 :   params.addCustomTypeParam<std::string>(
      28             :       "divergence_expression", "FunctionExpression", "Expression to parse for divergence");
      29       14394 :   params.addParam<std::vector<std::string>>(
      30             :       "symbol_names", {}, "Symbol names to use in the parsed expressions");
      31       14394 :   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       14394 :   return params;
      38           0 : }
      39             : 
      40          69 : ParsedConvergence::ParsedConvergence(const InputParameters & parameters)
      41             :   : Convergence(parameters),
      42             :     FunctionParserUtils<false>(parameters),
      43          69 :     _fe_problem(*getCheckedPointerParam<FEProblemBase *>("_fe_problem_base")),
      44          69 :     _symbol_names(getParam<std::vector<std::string>>("symbol_names")),
      45          69 :     _symbol_values(getParam<std::vector<std::string>>("symbol_values")),
      46          69 :     _convergence_function_params(_symbol_names.size(), 0.0),
      47         207 :     _divergence_function_params(_symbol_names.size(), 0.0)
      48             : {
      49          69 :   if (_symbol_names.size() != _symbol_values.size())
      50           4 :     mooseError("The parameters 'symbol_names' and 'symbol_values' must have the same size.");
      51          65 : }
      52             : 
      53             : void
      54          65 : ParsedConvergence::initialSetup()
      55             : {
      56          65 :   Convergence::initialSetup();
      57             : 
      58          65 :   initializeSymbols();
      59             : 
      60          65 :   const auto convergence_expression = getParam<std::string>("convergence_expression");
      61          65 :   _convergence_function = makeParsedFunction(convergence_expression);
      62             : 
      63         130 :   const auto divergence_expression = isParamValid("divergence_expression")
      64          65 :                                          ? getParam<std::string>("divergence_expression")
      65          65 :                                          : MooseUtils::join(_convergence_symbol_names, "|");
      66          65 :   if (divergence_expression.size())
      67          65 :     _divergence_function = makeParsedFunction(divergence_expression);
      68          65 : }
      69             : 
      70             : void
      71          65 : ParsedConvergence::initializeSymbols()
      72             : {
      73         313 :   for (const auto i : index_range(_symbol_values))
      74             :   {
      75         248 :     ReporterName reporter_name(_symbol_values[i], "value");
      76         248 :     if (_fe_problem.getReporterData().hasReporterValue<PostprocessorValue>(reporter_name))
      77          65 :       initializePostprocessorSymbol(i);
      78         183 :     else if (_fe_problem.hasFunction(_symbol_values[i]))
      79          53 :       initializeFunctionSymbol(i);
      80         130 :     else if (_fe_problem.hasConvergence(_symbol_values[i]))
      81          77 :       initializeConvergenceSymbol(i);
      82             :     else
      83          53 :       initializeConstantSymbol(i);
      84         248 :   }
      85          65 : }
      86             : 
      87             : void
      88          65 : ParsedConvergence::initializePostprocessorSymbol(unsigned int i)
      89             : {
      90          65 :   const PostprocessorValue & pp_value = _fe_problem.getPostprocessorValueByName(_symbol_values[i]);
      91          65 :   _pp_values.push_back(&pp_value);
      92          65 :   _pp_indices.push_back(i);
      93          65 : }
      94             : 
      95             : void
      96          53 : ParsedConvergence::initializeFunctionSymbol(unsigned int i)
      97             : {
      98          53 :   Function & function = _fe_problem.getFunction(_symbol_values[i], _tid);
      99          53 :   _functions.push_back(&function);
     100          53 :   _function_indices.push_back(i);
     101          53 : }
     102             : 
     103             : void
     104          77 : ParsedConvergence::initializeConvergenceSymbol(unsigned int i)
     105             : {
     106          77 :   Convergence & convergence = _fe_problem.getConvergence(_symbol_values[i], _tid);
     107          77 :   _convergences.push_back(&convergence);
     108          77 :   _convergence_symbol_names.push_back(_symbol_names[i]);
     109          77 :   _convergence_indices.push_back(i);
     110          77 : }
     111             : 
     112             : void
     113          53 : ParsedConvergence::initializeConstantSymbol(unsigned int i)
     114             : {
     115             :   try
     116             :   {
     117          53 :     const Real value = MooseUtils::convert<Real>(_symbol_values[i], true);
     118          53 :     _convergence_function_params[i] = value;
     119          53 :     _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          53 : }
     130             : 
     131             : ParsedConvergence::SymFunctionPtr
     132         130 : ParsedConvergence::makeParsedFunction(const std::string & expression)
     133             : {
     134             :   // Create parsed function
     135         130 :   auto sym_function = std::make_shared<SymFunction>();
     136        1300 :   parsedFunctionSetup(sym_function,
     137             :                       expression,
     138         260 :                       Moose::stringify(_symbol_names),
     139             :                       {"pi", "e"},
     140             :                       {std::to_string(libMesh::pi), std::to_string(std::exp(Real(1)))},
     141             :                       comm());
     142             : 
     143         130 :   return sym_function;
     144         390 : }
     145             : 
     146             : Convergence::MooseConvergenceStatus
     147         954 : ParsedConvergence::checkConvergence(unsigned int iter)
     148             : {
     149         954 :   updateSymbolValues(iter);
     150             : 
     151         954 :   const Real converged_real = evaluate(_convergence_function, _convergence_function_params, name());
     152             :   const Real diverged_real =
     153         954 :       _divergence_function ? evaluate(_divergence_function, _divergence_function_params, name())
     154         954 :                            : 0;
     155             : 
     156         954 :   if (convertRealToBool(diverged_real, "divergence_expression"))
     157          20 :     return MooseConvergenceStatus::DIVERGED;
     158         930 :   else if (convertRealToBool(converged_real, "convergence_expression"))
     159         110 :     return MooseConvergenceStatus::CONVERGED;
     160             :   else
     161         820 :     return MooseConvergenceStatus::ITERATING;
     162             : }
     163             : 
     164             : void
     165         954 : ParsedConvergence::updateSymbolValues(unsigned int iter)
     166             : {
     167         954 :   updatePostprocessorSymbolValues();
     168         954 :   updateFunctionSymbolValues();
     169         954 :   updateConvergenceSymbolValues(iter);
     170         954 : }
     171             : 
     172             : void
     173         954 : ParsedConvergence::updatePostprocessorSymbolValues()
     174             : {
     175        1908 :   for (const auto i : index_range(_pp_indices))
     176             :   {
     177         954 :     _convergence_function_params[_pp_indices[i]] = (*_pp_values[i]);
     178         954 :     _divergence_function_params[_pp_indices[i]] = (*_pp_values[i]);
     179             :   }
     180         954 : }
     181             : 
     182             : void
     183         954 : ParsedConvergence::updateFunctionSymbolValues()
     184             : {
     185        1072 :   for (const auto i : index_range(_function_indices))
     186             :   {
     187         118 :     const Real function_value = _functions[i]->value(_t, Point(0, 0, 0));
     188         118 :     _convergence_function_params[_function_indices[i]] = function_value;
     189         118 :     _divergence_function_params[_function_indices[i]] = function_value;
     190             :   }
     191         954 : }
     192             : 
     193             : void
     194         954 : ParsedConvergence::updateConvergenceSymbolValues(unsigned int iter)
     195             : {
     196        2744 :   for (const auto i : index_range(_convergence_indices))
     197             :   {
     198        1790 :     const auto status = _convergences[i]->checkConvergence(iter);
     199        1790 :     _convergence_function_params[_convergence_indices[i]] =
     200             :         status == MooseConvergenceStatus::CONVERGED;
     201        1790 :     _divergence_function_params[_convergence_indices[i]] =
     202             :         status == MooseConvergenceStatus::DIVERGED;
     203             :   }
     204         954 : }
     205             : 
     206             : bool
     207        1884 : ParsedConvergence::convertRealToBool(Real value, const std::string & param) const
     208             : {
     209        1884 :   if (MooseUtils::absoluteFuzzyEqual(value, 1.0))
     210         130 :     return true;
     211        1754 :   else if (MooseUtils::absoluteFuzzyEqual(value, 0.0))
     212        1750 :     return false;
     213             :   else
     214           4 :     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