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 "ParsedOptimizationFunction.h"
11 :
12 : // MOOSE includes
13 : #include "MooseUtils.h"
14 :
15 : registerMooseObject("OptimizationApp", ParsedOptimizationFunction);
16 :
17 : InputParameters
18 721 : ParsedOptimizationFunction::validParams()
19 : {
20 721 : InputParameters params = OptimizationFunction::validParams();
21 721 : params.addClassDescription(
22 : "Function used for optimization that uses a parsed expression with parameter dependence.");
23 :
24 1442 : params.addRequiredCustomTypeParam<std::string>(
25 : "expression", "FunctionExpression", "The user defined function.");
26 1442 : params.addRequiredParam<std::vector<std::string>>(
27 : "param_symbol_names", "Names of parameters in 'expression' being optimized.");
28 1442 : params.addRequiredParam<ReporterName>(
29 : "param_vector_name", "Reporter or VectorPostprocessor vector containing parameter values.");
30 721 : params.addParam<std::vector<std::string>>(
31 : "constant_symbol_names",
32 721 : 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 721 : params.addParam<std::vector<Real>>(
36 721 : "constant_symbol_values", std::vector<Real>(), "Constant numeric values for vars.");
37 721 : return params;
38 0 : }
39 :
40 364 : ParsedOptimizationFunction::ParsedOptimizationFunction(const InputParameters & parameters)
41 : : OptimizationFunction(parameters),
42 : ReporterInterface(this),
43 364 : _expression(getParam<std::string>("expression")),
44 728 : _param_names(getParam<std::vector<std::string>>("param_symbol_names")),
45 364 : _params(getReporterValue<std::vector<Real>>("param_vector_name")),
46 728 : _symbol_names(getParam<std::vector<std::string>>("constant_symbol_names")),
47 1092 : _symbol_values(getParam<std::vector<Real>>("constant_symbol_values"))
48 : {
49 364 : if (_symbol_names.size() != _symbol_values.size())
50 0 : 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 364 : "use and must not be declared.";
55 1005 : for (const auto & var : _param_names)
56 641 : if (var.find_first_of("xyzt") != std::string::npos && var.size() == 1)
57 0 : paramError("param_names", msg);
58 364 : for (const auto & var : _symbol_names)
59 0 : if (var.find_first_of("xyzt") != std::string::npos && var.size() == 1)
60 0 : paramError("symbol_names", msg);
61 :
62 : // Create parser
63 728 : _parser = std::make_unique<FunctionParserADBase<Real>>();
64 :
65 : // Add basic and user-defined constants
66 728 : _parser->AddConstant("NaN", std::numeric_limits<Real>::quiet_NaN());
67 728 : _parser->AddConstant("pi", libMesh::pi);
68 364 : _parser->AddConstant("e", std::exp(1.0));
69 364 : for (const auto & i : index_range(_symbol_names))
70 0 : _parser->AddConstant(_symbol_names[i], _symbol_values[i]);
71 :
72 : // Join xyzt and parameters to give to FParser as variables
73 364 : std::vector<std::string> all_vars = {"x", "y", "z", "t"};
74 364 : all_vars.insert(all_vars.end(), _param_names.begin(), _param_names.end());
75 :
76 : // Parse expression and error if something goes wrong
77 728 : if (_parser->Parse(_expression, MooseUtils::join(all_vars, ",")) != -1)
78 0 : paramError("expression", "Unable to parse expression\n", _parser->ErrorMsg());
79 : _parser->SetADFlags(FunctionParserADBase<Real>::ADAutoOptimize);
80 364 : _parser->Optimize();
81 :
82 : // Add parsers for each derivative we are taking, including xyzt
83 364 : _derivative_parsers.resize(all_vars.size());
84 2461 : for (const auto & i : index_range(all_vars))
85 : {
86 4194 : _derivative_parsers[i] = std::make_unique<FunctionParserADBase<Real>>(*_parser);
87 2097 : if (_derivative_parsers[i]->AutoDiff(all_vars[i]) != -1)
88 0 : paramError("expression",
89 : "Unable to take derivative with respect to ",
90 : all_vars[i],
91 : "\n",
92 : _derivative_parsers[i]->ErrorMsg());
93 : }
94 728 : }
95 :
96 : Real
97 5671728 : ParsedOptimizationFunction::value(Real t, const Point & p) const
98 : {
99 11343456 : return evaluateExpression(*_parser, t, p);
100 : }
101 :
102 : RealGradient
103 0 : ParsedOptimizationFunction::gradient(Real t, const Point & p) const
104 : {
105 : RealGradient result;
106 0 : result(0) = evaluateExpression(*_derivative_parsers[0], t, p, "gradient");
107 0 : result(1) = evaluateExpression(*_derivative_parsers[1], t, p, "gradient");
108 0 : result(2) = evaluateExpression(*_derivative_parsers[2], t, p, "gradient");
109 0 : return result;
110 : }
111 :
112 : Real
113 0 : ParsedOptimizationFunction::timeDerivative(Real t, const Point & p) const
114 : {
115 0 : return evaluateExpression(*_derivative_parsers[3], t, p, "time derivative");
116 : }
117 :
118 : std::vector<Real>
119 136426 : ParsedOptimizationFunction::parameterGradient(Real t, const Point & p) const
120 : {
121 136426 : std::vector<Real> result(_param_names.size());
122 292662 : for (const auto & i : index_range(result))
123 156236 : result[i] =
124 312474 : evaluateExpression(*_derivative_parsers[4 + i], t, p, _param_names[i] + " derivative");
125 136424 : return result;
126 0 : }
127 :
128 : Real
129 5827966 : ParsedOptimizationFunction::evaluateExpression(FunctionParserADBase<Real> & parser,
130 : Real t,
131 : const Point & p,
132 : std::string name) const
133 : {
134 5827966 : if (_params.size() != _param_names.size())
135 2 : 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 5827964 : std::vector<Real> parser_var_values(4 + _param_names.size());
143 5827964 : parser_var_values[0] = p(0);
144 5827964 : parser_var_values[1] = p(1);
145 5827964 : parser_var_values[2] = p(2);
146 5827964 : parser_var_values[3] = t;
147 11867884 : for (const auto & i : index_range(_param_names))
148 6039920 : parser_var_values[4 + i] = _params[i];
149 :
150 5827964 : Real result = parser.Eval(parser_var_values.data());
151 :
152 5827964 : auto err = parser.EvalError();
153 5827964 : if (err)
154 : {
155 0 : std::string msg = "Error evaluating function " + name + "\n";
156 0 : 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 0 : paramError("expression", msg);
176 : }
177 :
178 5827964 : return result;
179 5827964 : }
|