www.mooseframework.org
FunctionParserUtils.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://www.mooseframework.org
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 "FunctionParserUtils.h"
11 
12 // MOOSE includes
13 #include "InputParameters.h"
14 #include "MooseEnum.h"
15 
16 template <bool is_ad>
19 {
21 
22  params.addParam<bool>(
23  "enable_jit",
24 #ifdef LIBMESH_HAVE_FPARSER_JIT
25  true,
26 #else
27  false,
28 #endif
29  "Enable just-in-time compilation of function expressions for faster evaluation");
30  params.addParam<bool>(
31  "enable_ad_cache", true, "Enable caching of function derivatives for faster startup time");
32  params.addParam<bool>(
33  "enable_auto_optimize", true, "Enable automatic immediate optimization of derivatives");
34  params.addParam<bool>(
35  "disable_fpoptimizer", false, "Disable the function parser algebraic optimizer");
36  MooseEnum evalerror("nan nan_warning error exception", "nan");
37  params.addParam<MooseEnum>("evalerror_behavior",
38  evalerror,
39  "What to do if evaluation error occurs. Options are to pass a nan, "
40  "pass a nan with a warning, throw a error, or throw an exception");
41 
42  params.addParamNamesToGroup(
43  "enable_jit enable_ad_cache enable_auto_optimize disable_fpoptimizer evalerror_behavior",
44  "Advanced");
45 
46  return params;
47 }
48 
49 template <bool is_ad>
51  "Unknown",
52  "Division by zero",
53  "Square root of a negative value",
54  "Logarithm of negative value",
55  "Trigonometric error (asin or acos of illegal value)",
56  "Maximum recursion level reached"};
57 
58 template <bool is_ad>
60  : _enable_jit(parameters.isParamValid("enable_jit") && parameters.get<bool>("enable_jit")),
61  _enable_ad_cache(parameters.get<bool>("enable_ad_cache")),
62  _disable_fpoptimizer(parameters.get<bool>("disable_fpoptimizer")),
63  _enable_auto_optimize(parameters.get<bool>("enable_auto_optimize") && !_disable_fpoptimizer),
64  _evalerror_behavior(parameters.get<MooseEnum>("evalerror_behavior").getEnum<FailureMethod>()),
65  _quiet_nan(std::numeric_limits<Real>::quiet_NaN())
66 {
67 #ifndef LIBMESH_HAVE_FPARSER_JIT
68  if (_enable_jit)
69  {
70  mooseWarning("Tried to enable FParser JIT but libmesh does not have it compiled in.");
71  _enable_jit = false;
72  }
73 #endif
74 }
75 
76 template <bool is_ad>
77 void
79 {
80  parser->SetADFlags(SymFunction::ADCacheDerivatives, _enable_ad_cache);
81  parser->SetADFlags(SymFunction::ADAutoOptimize, _enable_auto_optimize);
82 }
83 
84 template <bool is_ad>
86 FunctionParserUtils<is_ad>::evaluate(SymFunctionPtr & parser, const std::string & name)
87 {
88  // null pointer is a shortcut for vanishing derivatives, see functionsOptimize()
89  if (parser == NULL)
90  return 0.0;
91 
92  // evaluate expression
93  auto result = parser->Eval(_func_params.data());
94 
95  // fetch fparser evaluation error (set to unknown if the JIT result is nan)
96  int error_code = _enable_jit ? (std::isnan(result) ? -1 : 0) : parser->EvalError();
97 
98  // no error
99  if (error_code == 0)
100  return result;
101 
102  // hard fail or return not a number
103  switch (_evalerror_behavior)
104  {
105  case FailureMethod::nan:
106  return _quiet_nan;
107 
108  case FailureMethod::nan_warning:
109  mooseWarning("In ",
110  name,
111  ": Parsed function evaluation encountered an error: ",
112  _eval_error_msg[(error_code < 0 || error_code > 5) ? 0 : error_code]);
113  return _quiet_nan;
114 
115  case FailureMethod::error:
116  mooseError("In ",
117  name,
118  ": Parsed function evaluation encountered an error: ",
119  _eval_error_msg[(error_code < 0 || error_code > 5) ? 0 : error_code]);
120 
121  case FailureMethod::exception:
122  mooseException("In ",
123  name,
124  ": Parsed function evaluation encountered an error: ",
125  _eval_error_msg[(error_code < 0 || error_code > 5) ? 0 : error_code],
126  "\n Cutting timestep");
127  }
128 
129  return _quiet_nan;
130 }
131 
132 template <bool is_ad>
133 void
135  SymFunctionPtr & parser,
136  const std::vector<std::string> & constant_names,
137  const std::vector<std::string> & constant_expressions)
138 {
139  // check constant vectors
140  unsigned int nconst = constant_expressions.size();
141  if (nconst != constant_names.size())
142  mooseError("The parameter vectors constant_names and constant_values must have equal length.");
143 
144  // previously evaluated constant_expressions may be used in following constant_expressions
145  std::vector<Real> constant_values(nconst);
146 
147  for (unsigned int i = 0; i < nconst; ++i)
148  {
149  // no need to use dual numbers for the constant expressions
150  auto expression = std::make_shared<FunctionParserADBase<Real>>();
151 
152  // add previously evaluated constants
153  for (unsigned int j = 0; j < i; ++j)
154  if (!expression->AddConstant(constant_names[j], constant_values[j]))
155  mooseError("Invalid constant name in ParsedMaterialHelper");
156 
157  // build the temporary constant expression function
158  if (expression->Parse(constant_expressions[i], "") >= 0)
159  mooseError("Invalid constant expression\n",
160  constant_expressions[i],
161  "\n in parsed function object.\n",
162  expression->ErrorMsg());
163 
164  constant_values[i] = expression->Eval(NULL);
165 
166  if (!parser->AddConstant(constant_names[i], constant_values[i]))
167  mooseError("Invalid constant name in parsed function object");
168  }
169 }
170 
171 template <>
172 void
173 FunctionParserUtils<false>::functionsOptimize(SymFunctionPtr & parsed_function)
174 {
175  // base function
177  parsed_function->Optimize();
178  if (_enable_jit && !parsed_function->JITCompile())
179  mooseInfo("Failed to JIT compile expression, falling back to byte code interpretation.");
180 }
181 
182 template <>
183 void
185 {
186  // base function
187  if (!_disable_fpoptimizer)
188  parsed_function->Optimize();
189  if (!_enable_jit || !parsed_function->JITCompile())
190  mooseError("AD parsed objects require JIT compilation to be enabled and working.");
191 }
192 
193 // explicit instantiation
194 template class FunctionParserUtils<false>;
195 template class FunctionParserUtils<true>;
std::string name(const ElemQuality q)
GenericReal< is_ad > evaluate(SymFunctionPtr &, const std::string &object_name="")
Evaluate FParser object and check EvalError.
std::shared_ptr< SymFunction > SymFunctionPtr
Shorthand for an smart pointer to an autodiff function parser object.
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:284
FunctionParserUtils(const InputParameters &parameters)
void mooseWarning(Args &&... args)
Emit a warning message with the given stringified, concatenated args.
Definition: MooseError.h:296
T * get(const std::unique_ptr< T > &u)
The MooseUtils::get() specializations are used to support making forwards-compatible code changes fro...
Definition: MooseUtils.h:1147
virtual void functionsOptimize(SymFunctionPtr &parsed_function)
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
void addFParserConstants(SymFunctionPtr &parser, const std::vector< std::string > &constant_names, const std::vector< std::string > &constant_expressions)
add constants (which can be complex expressions) to the parser object
InputParameters emptyInputParameters()
void mooseInfo(Args &&... args)
Emit an informational message with the given stringified, concatenated args.
Definition: MooseError.h:329
FailureMethod
Enum for failure method.
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Definition: MooseEnum.h:31
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
static InputParameters validParams()
void addParam(const std::string &name, const S &value, const std::string &doc_string)
These methods add an option parameter and a documentation string to the InputParameters object...
typename Moose::GenericType< Real, is_ad > GenericReal
Definition: MooseTypes.h:559
void setParserFeatureFlags(SymFunctionPtr &)
apply input paramters to internal feature flags of the parser object
void addParamNamesToGroup(const std::string &space_delim_names, const std::string group_name)
This method takes a space delimited list of parameter names and adds them to the specified group name...