https://mooseframework.inl.gov
ParsedOptimizationFunction.C
Go to the documentation of this file.
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 
11 
12 // MOOSE includes
13 #include "MooseUtils.h"
14 
16 
19 {
21  params.addClassDescription(
22  "Function used for optimization that uses a parsed expression with parameter dependence.");
23 
24  params.addRequiredCustomTypeParam<std::string>(
25  "expression", "FunctionExpression", "The user defined function.");
26  params.addRequiredParam<std::vector<std::string>>(
27  "param_symbol_names", "Names of parameters in 'expression' being optimized.");
29  "param_vector_name", "Reporter or VectorPostprocessor vector containing parameter values.");
30  params.addParam<std::vector<std::string>>(
31  "constant_symbol_names",
32  std::vector<std::string>(),
33  "Variables (excluding t,x,y,z) that are bound to the values provided by the corresponding "
34  "items in the symbol_values vector.");
35  params.addParam<std::vector<Real>>(
36  "constant_symbol_values", std::vector<Real>(), "Constant numeric values for vars.");
37  return params;
38 }
39 
41  : OptimizationFunction(parameters),
42  ReporterInterface(this),
43  _expression(getParam<std::string>("expression")),
44  _param_names(getParam<std::vector<std::string>>("param_symbol_names")),
45  _params(getReporterValue<std::vector<Real>>("param_vector_name")),
46  _symbol_names(getParam<std::vector<std::string>>("constant_symbol_names")),
47  _symbol_values(getParam<std::vector<Real>>("constant_symbol_values"))
48 {
49  if (_symbol_names.size() != _symbol_values.size())
50  paramError("symbol_names", "Number of vars must match the number of vals for a ", type(), "!");
51 
52  // Loop through the variables assigned by the user and give an error if x,y,z,t are used
53  std::string msg = "The variables \"x, y, z, and t\" in the ParsedFunction are pre-declared for "
54  "use and must not be declared.";
55  for (const auto & var : _param_names)
56  if (var.find_first_of("xyzt") != std::string::npos && var.size() == 1)
57  paramError("param_names", msg);
58  for (const auto & var : _symbol_names)
59  if (var.find_first_of("xyzt") != std::string::npos && var.size() == 1)
60  paramError("symbol_names", msg);
61 
62  // Create parser
63  _parser = std::make_unique<FunctionParserADBase<Real>>();
64 
65  // Add basic and user-defined constants
66  _parser->AddConstant("NaN", std::numeric_limits<Real>::quiet_NaN());
67  _parser->AddConstant("pi", libMesh::pi);
68  _parser->AddConstant("e", std::exp(1.0));
69  for (const auto & i : index_range(_symbol_names))
70  _parser->AddConstant(_symbol_names[i], _symbol_values[i]);
71 
72  // Join xyzt and parameters to give to FParser as variables
73  std::vector<std::string> all_vars = {"x", "y", "z", "t"};
74  all_vars.insert(all_vars.end(), _param_names.begin(), _param_names.end());
75 
76  // Parse expression and error if something goes wrong
77  if (_parser->Parse(_expression, MooseUtils::join(all_vars, ",")) != -1)
78  paramError("expression", "Unable to parse expression\n", _parser->ErrorMsg());
79  _parser->SetADFlags(FunctionParserADBase<Real>::ADAutoOptimize);
80  _parser->Optimize();
81 
82  // Add parsers for each derivative we are taking, including xyzt
83  _derivative_parsers.resize(all_vars.size());
84  for (const auto & i : index_range(all_vars))
85  {
86  _derivative_parsers[i] = std::make_unique<FunctionParserADBase<Real>>(*_parser);
87  if (_derivative_parsers[i]->AutoDiff(all_vars[i]) != -1)
88  paramError("expression",
89  "Unable to take derivative with respect to ",
90  all_vars[i],
91  "\n",
92  _derivative_parsers[i]->ErrorMsg());
93  }
94 }
95 
96 Real
97 ParsedOptimizationFunction::value(Real t, const Point & p) const
98 {
99  return evaluateExpression(*_parser, t, p);
100 }
101 
103 ParsedOptimizationFunction::gradient(Real t, const Point & p) const
104 {
105  RealGradient result;
106  result(0) = evaluateExpression(*_derivative_parsers[0], t, p, "gradient");
107  result(1) = evaluateExpression(*_derivative_parsers[1], t, p, "gradient");
108  result(2) = evaluateExpression(*_derivative_parsers[2], t, p, "gradient");
109  return result;
110 }
111 
112 Real
113 ParsedOptimizationFunction::timeDerivative(Real t, const Point & p) const
114 {
115  return evaluateExpression(*_derivative_parsers[3], t, p, "time derivative");
116 }
117 
118 std::vector<Real>
119 ParsedOptimizationFunction::parameterGradient(Real t, const Point & p) const
120 {
121  std::vector<Real> result(_param_names.size());
122  for (const auto & i : index_range(result))
123  result[i] =
124  evaluateExpression(*_derivative_parsers[4 + i], t, p, _param_names[i] + " derivative");
125  return result;
126 }
127 
128 Real
129 ParsedOptimizationFunction::evaluateExpression(FunctionParserADBase<Real> & parser,
130  Real t,
131  const Point & p,
132  std::string name) const
133 {
134  if (_params.size() != _param_names.size())
135  paramError("param_vector_name",
136  "Size of vector (",
137  _params.size(),
138  ") does not match number of specified 'param_names' (",
139  _param_names.size(),
140  ").");
141 
142  std::vector<Real> parser_var_values(4 + _param_names.size());
143  parser_var_values[0] = p(0);
144  parser_var_values[1] = p(1);
145  parser_var_values[2] = p(2);
146  parser_var_values[3] = t;
147  for (const auto & i : index_range(_param_names))
148  parser_var_values[4 + i] = _params[i];
149 
150  Real result = parser.Eval(parser_var_values.data());
151 
152  auto err = parser.EvalError();
153  if (err)
154  {
155  std::string msg = "Error evaluating function " + name + "\n";
156  switch (err)
157  {
158  case 1:
159  msg += "Division by zero";
160  break;
161  case 2:
162  msg += "Square Root error (negative value)";
163  break;
164  case 3:
165  msg += "Log error (negative value)";
166  break;
167  case 4:
168  msg += "Trigonometric error (asin or acos of illegal value)";
169  break;
170  case 5:
171  msg += "Maximum recursion level reached";
172  break;
173  }
174 
175  paramError("expression", msg);
176  }
177 
178  return result;
179 }
OStreamProxy err
std::string join(Iterator begin, Iterator end, const std::string &delimiter)
registerMooseObject("OptimizationApp", ParsedOptimizationFunction)
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
std::vector< std::unique_ptr< FunctionParserADBase< Real > > > _derivative_parsers
Pointers to parsed function objects representing derivative (first four are xyzt) ...
const std::vector< std::string > & _param_names
Parameters passed to FParser.
virtual Real value(Real t, const Point &p) const override
const std::vector< Real > & _symbol_values
Values passed by the user, they may be Reals for Postprocessors.
Real evaluateExpression(FunctionParserADBase< Real > &parser, Real t, const Point &p, std::string name="") const
Function to evaluate an inputted parser.
virtual const std::string & name() const
void addRequiredParam(const std::string &name, const std::string &doc_string)
const std::vector< std::string > & _symbol_names
Variables passed to FParser.
const std::string & _expression
Function expression passed to FParser.
ParsedOptimizationFunction(const InputParameters &parameters)
const std::string name
Definition: Setup.h:20
virtual RealGradient gradient(Real t, const Point &p) const override
const std::string & type() const
std::unique_ptr< FunctionParserADBase< Real > > _parser
Pointer to parsed function object.
void paramError(const std::string &param, Args... args) const
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
Base class for functions used in inverse optimization The parameterDerivative function is used in adj...
void addRequiredCustomTypeParam(const std::string &name, const std::string &custom_type, const std::string &doc_string)
void addClassDescription(const std::string &doc_string)
virtual std::vector< Real > parameterGradient(Real t, const Point &p) const override
static InputParameters validParams()
const std::vector< Real > & _params
Vector containing parameter values.
virtual Real timeDerivative(Real t, const Point &p) const override
static InputParameters validParams()
auto index_range(const T &sizable)
const Real pi