Nektar++
Interpreter.h
Go to the documentation of this file.
1///////////////////////////////////////////////////////////////////////////////
2//
3// File: Interpreter.h
4//
5// For more information, please see: http://www.nektar.info
6//
7// The MIT License
8//
9// Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
10// Department of Aeronautics, Imperial College London (UK), and Scientific
11// Computing and Imaging Institute, University of Utah (USA).
12//
13// License for the specific language governing rights and limitations under
14// Permission is hereby granted, free of charge, to any person obtaining a
15// copy of this software and associated documentation files (the "Software"),
16// to deal in the Software without restriction, including without limitation
17// the rights to use, copy, modify, merge, publish, distribute, sublicense,
18// and/or sell copies of the Software, and to permit persons to whom the
19// Software is furnished to do so, subject to the following conditions:
20//
21// The above copyright notice and this permission notice shall be included
22// in all copies or substantial portions of the Software.
23//
24// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
25// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
27// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30// DEALINGS IN THE SOFTWARE.
31//
32// Description: Parser and evaluator of analytic expressions.
33//
34///////////////////////////////////////////////////////////////////////////////
35
36#ifndef NEKTAR_LIBUTILITIES_INTERPRETER_INTERPRETER_H
37#define NEKTAR_LIBUTILITIES_INTERPRETER_INTERPRETER_H
38
39#include <memory>
40#include <string>
41
43
45{
46
47/**
48 * @brief Interpreter class for the evaluation of mathematical expressions.
49 *
50 * The Interpreter class uses the boost::spirit parser framework in order to
51 * construct a simple grammar for the evaluation of mathematical
52 * expressions. Primarily this is used within LibUtilities::SessionReader to
53 * evaluate functions defined using strings, but can be used generically
54 * anywhere within the framework in order to provide parsing functionality.
55 *
56 * The interpreter supports:
57 * - classical mathematical binary operators of addition `+`, subtraction `-`,
58 * multiplication `*`, division `/` and exponentiation `^`, evaluated in the
59 * appropriate manner and with use of parentheses;
60 * - logical operators `&&`, `||`, `==`, `<=` and `>=`;
61 * - several predefined constants such as `PI` and other related constants from
62 * the `cmath` header assigned by the #AddConstant function;
63 * - various mathematical functions including trigonometric functions (`sin`,
64 * `cos`, etc), `pow`, `log` and `exp`;
65 * - noise generation with the `awgn` function;
66 * - the evaluation of spatially-constant parameters, controlled by the
67 * #SetParameters function;
68 * - support for either single-value or multiple-value variables, in order to
69 * e.g. support the evaluation of spatially-variable expressions.
70 *
71 * Note that this class exposes the interface of the Interpreter class only in
72 * order to reduce compile-time includes. The implementation itself can be found
73 * in Interpreter::ExpressionEvaluator.
74 */
76{
77public:
78 /**
79 * @brief Default constructor.
80 */
82
83 /**
84 * @brief Default destructor.
85 */
87
88 /**
89 * @brief Default move constructor.
90 */
92
93 /**
94 * @brief Default assignment operator.
95 */
97
98 /**
99 * @brief Sets the random seed for the pseudorandom number generator.
100 *
101 * This allows for e.g. different ranks to be given different seeds to
102 * ensure appropriate entropy in noise generation.
103 */
104 LIB_UTILITIES_EXPORT void SetRandomSeed(unsigned int seed = 123u);
105
106 /**
107 * @brief Set constants to be evaluated.
108 *
109 * Constants are evaluated and inserted into the function at the time it is
110 * parsed when calling the #DefineFunction function. After parsing, if a
111 * constant is changed, it will not be reflected in the function when
112 * Evaluate is called. This also means that if a function with an unknown
113 * constant is added, and then the constant is added, the function will not
114 * see the added constant and through an exception.
115 *
116 * This function will add all of the constants in the @p constants parameter
117 * to the global internal constants. If a constant was already loaded
118 * previously, it will throw an exception stating which constants in the map
119 * had this issue. It will add all of the constants it can from @p constants
120 * and output the constants it couldn't add in the string exception.
121 *
122 * @param constants A std::map with string names for the constants (which
123 * will be evalauted in the expression) and their
124 * NekDouble value.
125 */
127 std::map<std::string, NekDouble> const &constants);
128
129 /**
130 * @brief Set constants to be evaluated.
131 *
132 * This function behaves in the same way as #AddConstants, but it only adds
133 * one constant at a time. If the constant existed previously, an exception
134 * will be thrown stating the fact. If it did not exist previously, it will
135 * be added to the global constants and will be used the next time
136 * #DefineFunction is called.
137 *
138 * @return Total number of constants after this one has been added.
139 */
140 LIB_UTILITIES_EXPORT int AddConstant(std::string const &name,
141 NekDouble value);
142
143 /**
144 * @brief Return the value of a constant.
145 *
146 * If a constant with the specified name @p name exists, this function
147 * returns the NekDouble value that the constant stores. If the constant
148 * doesn't exist, this throws an exception.
149 *
150 * @param name Name of constant to return.
151 */
153
154 /**
155 * @brief Set parameter values.
156 *
157 * Parameters are functionally similar to constants, but they are inserted
158 * into the function at the time that #Evaluate is called, instead of when
159 * the function is parsed. This function can therefore be called at any
160 * time, and it will take effect in the next call to #Evaluate. This
161 * function will delete all of the parameters, and replace all of them with
162 * only the ones in the map argument.
163 */
165 std::map<std::string, NekDouble> const &params);
166
167 /**
168 * @brief Set parameter values.
169 *
170 * This function behaves in the same way as #SetParameters, but it only adds
171 * one parameter and it does not delete the others. If the parameter @p name
172 * existed previously, it will be overridden and replaced with the new
173 * value. If it did not exist previously, it will be added to the current
174 * parameters.
175 *
176 * @param name Name of the parameter to define.
177 * @param value The parameter's value.
178 */
179 LIB_UTILITIES_EXPORT void SetParameter(std::string const &name,
180 NekDouble value);
181
182 /**
183 * @brief Get the value of a parameter
184 *
185 * If a parameter with the specified @p name exists, it returns the
186 * NekDouble value that the parameter stores. If the parameter doesn't
187 * exist, it throws an exception.
188 *
189 * @param name Name of the parameter to query.
190 */
192
193 /**
194 * @brief Returns the total walltime spent in evaluation procedures in
195 * seconds.
196 */
198
199 // ======================================================
200 // Parsing and evaluation methods
201 // ======================================================
202
203 /**
204 * @brief Defines a function for the purposes of evaluation.
205 *
206 * This function allows one to define a function to evaluate. The @p vlist
207 * argument should define a list of space-separated variables that the
208 * expression defined in @p function is dependent upon. For example, if @p
209 * function is defined as the string `x + y`, then vlist should most likely
210 * be `x y`, unless you are defining `x` or `y` as parameters with the
211 * #SetParameters function.
212 *
213 * @param vlist List of variable names separated with spaces.
214 * @param expr String definition of the function to be evaluated.
215 *
216 * @return An integer denoting the unique ID of this function. This should
217 * be passed into #Evaluate functions for later evaluation.
218 */
219 LIB_UTILITIES_EXPORT int DefineFunction(const std::string &vlist,
220 const std::string &expr);
221
222 /**
223 * @brief Evaluate a function which depends only on constants and/or
224 * parameters.
225 *
226 * @param id The ID returned from #DefineFunction representing the function
227 * to be evaluated.
228 */
230
231 /**
232 * @brief Evaluate a function which depends on four variables: typically
233 * space \f$ (x, y, z) \f$ and time \f$ t\f$.
234 *
235 * @param id The ID returned from #DefineFunction representing the function
236 * to be evaluated.
237 * @param x The value of variable 1 (typically \f$ x \f$).
238 * @param y The value of variable 2 (typically \f$ y \f$).
239 * @param z The value of variable 3 (typically \f$ z \f$).
240 * @param t The value of variable 4 (typically \f$ t \f$).
241 */
242 LIB_UTILITIES_EXPORT NekDouble Evaluate(const int id, const NekDouble x,
243 const NekDouble y,
244 const NekDouble z,
245 const NekDouble t);
246
247 /**
248 * @brief Evaluate a function which depends on zero or more variables.
249 *
250 * This is suitable for expressions depending on more than 4 variables or
251 * for the dynamic setting of some variables as parameters (there is
252 * currently no interface method for removing a variable from parameter map
253 * however).
254 *
255 * @param id The ID returned from #DefineFunction representing the
256 * function to be evaluated.
257 * @param point A std::vector of points to be evaluated.
258 */
260 EvaluateAtPoint(const int id, std::vector<NekDouble> point);
261
262 /**
263 * @brief Evaluate a function which depends on four variables: typically
264 * space \f$ (x, y, z) \f$ and time \f$ t\f$ in a vectorised manner.
265 *
266 * This is a vectorised version of the evaluation method that will allow the
267 * same function to be evaluated many times for each of the entries in the
268 * input variable arrays @p x, @p y, @p z and @p t. Note that this is
269 * typically far quicker than the use of a loop with many calls to the
270 * single-variable variants in this class.
271 *
272 * @note All parameters @p x, @p y, @p z and @p t should be Arrays of the
273 * same length.
274 *
275 * @param id The ID returned from #DefineFunction representing the
276 * function to be evaluated.
277 * @param x An Array of values for variable 1 (typically \f$ x\f$).
278 * @param y An Array of values for variable 2 (typically \f$ y\f$).
279 * @param z An Array of values for variable 3 (typically \f$ z\f$).
280 * @param t An Array of values for variable 4 (typically \f$ t\f$).
281 * @param result An Array containing the evaluation of the function for each
282 * of the variable values.
283 */
284 LIB_UTILITIES_EXPORT void Evaluate(const int id,
289 Array<OneD, NekDouble> &result);
290
291 /**
292 * @brief Evaluate a function which depends on zero or more variables.
293 *
294 * This is a vectorised version of the evaluation method that will allow the
295 * same function to be evaluated many times for each of the entries in the
296 * input variable arrays within @p points. Note that this is typically far
297 * quicker than the use of a loop with many calls to the single-variable
298 * variants in this class.
299 *
300 * @note All entries of the input array @p points should be of the same
301 * length.
302 *
303 * @param id The ID returned from #DefineFunction representing the
304 * function to be evaluated.
305 * @param points An Array in which the i-th entry corresponds to values of
306 * variable \f$ i\f$.
307 * @param result An Array containing the evaluation of the function for each
308 * of the variable values.
309 */
311 const int expression_id,
312 const std::vector<Array<OneD, const NekDouble>> &points,
313 Array<OneD, NekDouble> &result);
314
315private:
316 /// Forward declaration of evaluator to avoid boost::spirit includes.
318 /// Concrete implementation of the above API calls.
319 std::unique_ptr<ExpressionEvaluator> m_impl;
320};
321
322typedef std::shared_ptr<Interpreter> InterpreterSharedPtr;
323
324} // namespace Nektar::LibUtilities
325
326#endif
#define LIB_UTILITIES_EXPORT
Concrete implementation of the interface defined in Interpreter.
Interpreter class for the evaluation of mathematical expressions.
Definition: Interpreter.h:76
NekDouble GetTime() const
Returns the total walltime spent in evaluation procedures in seconds.
void AddConstants(std::map< std::string, NekDouble > const &constants)
Set constants to be evaluated.
std::unique_ptr< ExpressionEvaluator > m_impl
Concrete implementation of the above API calls.
Definition: Interpreter.h:319
Interpreter & operator=(Interpreter &&)
Default assignment operator.
NekDouble GetConstant(std::string const &name)
Return the value of a constant.
int AddConstant(std::string const &name, NekDouble value)
Set constants to be evaluated.
NekDouble EvaluateAtPoint(const int id, std::vector< NekDouble > point)
Evaluate a function which depends on zero or more variables.
int DefineFunction(const std::string &vlist, const std::string &expr)
Defines a function for the purposes of evaluation.
void SetParameters(std::map< std::string, NekDouble > const &params)
Set parameter values.
void SetParameter(std::string const &name, NekDouble value)
Set parameter values.
NekDouble Evaluate(const int id)
Evaluate a function which depends only on constants and/or parameters.
NekDouble GetParameter(std::string const &name)
Get the value of a parameter.
void SetRandomSeed(unsigned int seed=123u)
Sets the random seed for the pseudorandom number generator.
std::shared_ptr< Interpreter > InterpreterSharedPtr
Definition: Interpreter.h:322
std::vector< double > z(NPUPPER)
double NekDouble