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
44namespace Nektar
45{
46namespace LibUtilities
47{
48
49/**
50 * @brief Interpreter class for the evaluation of mathematical expressions.
51 *
52 * The Interpreter class uses the boost::spirit parser framework in order to
53 * construct a simple grammar for the evaluation of mathematical
54 * expressions. Primarily this is used within LibUtilities::SessionReader to
55 * evaluate functions defined using strings, but can be used generically
56 * anywhere within the framework in order to provide parsing functionality.
57 *
58 * The interpreter supports:
59 * - classical mathematical binary operators of addition `+`, subtraction `-`,
60 * multiplication `*`, division `/` and exponentiation `^`, evaluated in the
61 * appropriate manner and with use of parentheses;
62 * - logical operators `&&`, `||`, `==`, `<=` and `>=`;
63 * - several predefined constants such as `PI` and other related constants from
64 * the `cmath` header assigned by the #AddConstant function;
65 * - various mathematical functions including trigonometric functions (`sin`,
66 * `cos`, etc), `pow`, `log` and `exp`;
67 * - noise generation with the `awgn` function;
68 * - the evaluation of spatially-constant parameters, controlled by the
69 * #SetParameters function;
70 * - support for either single-value or multiple-value variables, in order to
71 * e.g. support the evaluation of spatially-variable expressions.
72 *
73 * Note that this class exposes the interface of the Interpreter class only in
74 * order to reduce compile-time includes. The implementation itself can be found
75 * in Interpreter::ExpressionEvaluator.
76 */
78{
79public:
80 /**
81 * @brief Default constructor.
82 */
84
85 /**
86 * @brief Default destructor.
87 */
89
90 /**
91 * @brief Default move constructor.
92 */
94
95 /**
96 * @brief Default assignment operator.
97 */
99
100 /**
101 * @brief Sets the random seed for the pseudorandom number generator.
102 *
103 * This allows for e.g. different ranks to be given different seeds to
104 * ensure appropriate entropy in noise generation.
105 */
106 LIB_UTILITIES_EXPORT void SetRandomSeed(unsigned int seed = 123u);
107
108 /**
109 * @brief Set constants to be evaluated.
110 *
111 * Constants are evaluated and inserted into the function at the time it is
112 * parsed when calling the #DefineFunction function. After parsing, if a
113 * constant is changed, it will not be reflected in the function when
114 * Evaluate is called. This also means that if a function with an unknown
115 * constant is added, and then the constant is added, the function will not
116 * see the added constant and through an exception.
117 *
118 * This function will add all of the constants in the @p constants parameter
119 * to the global internal constants. If a constant was already loaded
120 * previously, it will throw an exception stating which constants in the map
121 * had this issue. It will add all of the constants it can from @p constants
122 * and output the constants it couldn't add in the string exception.
123 *
124 * @param constants A std::map with string names for the constants (which
125 * will be evalauted in the expression) and their
126 * NekDouble value.
127 */
129 std::map<std::string, NekDouble> const &constants);
130
131 /**
132 * @brief Set constants to be evaluated.
133 *
134 * This function behaves in the same way as #AddConstants, but it only adds
135 * one constant at a time. If the constant existed previously, an exception
136 * will be thrown stating the fact. If it did not exist previously, it will
137 * be added to the global constants and will be used the next time
138 * #DefineFunction is called.
139 *
140 * @return Total number of constants after this one has been added.
141 */
142 LIB_UTILITIES_EXPORT int AddConstant(std::string const &name,
143 NekDouble value);
144
145 /**
146 * @brief Return the value of a constant.
147 *
148 * If a constant with the specified name @p name exists, this function
149 * returns the NekDouble value that the constant stores. If the constant
150 * doesn't exist, this throws an exception.
151 *
152 * @param name Name of constant to return.
153 */
155
156 /**
157 * @brief Set parameter values.
158 *
159 * Parameters are functionally similar to constants, but they are inserted
160 * into the function at the time that #Evaluate is called, instead of when
161 * the function is parsed. This function can therefore be called at any
162 * time, and it will take effect in the next call to #Evaluate. This
163 * function will delete all of the parameters, and replace all of them with
164 * only the ones in the map argument.
165 */
167 std::map<std::string, NekDouble> const &params);
168
169 /**
170 * @brief Set parameter values.
171 *
172 * This function behaves in the same way as #SetParameters, but it only adds
173 * one parameter and it does not delete the others. If the parameter @p name
174 * existed previously, it will be overridden and replaced with the new
175 * value. If it did not exist previously, it will be added to the current
176 * parameters.
177 *
178 * @param name Name of the parameter to define.
179 * @param value The parameter's value.
180 */
181 LIB_UTILITIES_EXPORT void SetParameter(std::string const &name,
182 NekDouble value);
183
184 /**
185 * @brief Get the value of a parameter
186 *
187 * If a parameter with the specified @p name exists, it returns the
188 * NekDouble value that the parameter stores. If the parameter doesn't
189 * exist, it throws an exception.
190 *
191 * @param name Name of the parameter to query.
192 */
194
195 /**
196 * @brief Returns the total walltime spent in evaluation procedures in
197 * seconds.
198 */
200
201 // ======================================================
202 // Parsing and evaluation methods
203 // ======================================================
204
205 /**
206 * @brief Defines a function for the purposes of evaluation.
207 *
208 * This function allows one to define a function to evaluate. The @p vlist
209 * argument should define a list of space-separated variables that the
210 * expression defined in @p function is dependent upon. For example, if @p
211 * function is defined as the string `x + y`, then vlist should most likely
212 * be `x y`, unless you are defining `x` or `y` as parameters with the
213 * #SetParameters function.
214 *
215 * @param vlist List of variable names separated with spaces.
216 * @param expr String definition of the function to be evaluated.
217 *
218 * @return An integer denoting the unique ID of this function. This should
219 * be passed into #Evaluate functions for later evaluation.
220 */
221 LIB_UTILITIES_EXPORT int DefineFunction(const std::string &vlist,
222 const std::string &expr);
223
224 /**
225 * @brief Evaluate a function which depends only on constants and/or
226 * parameters.
227 *
228 * @param id The ID returned from #DefineFunction representing the function
229 * to be evaluated.
230 */
232
233 /**
234 * @brief Evaluate a function which depends on four variables: typically
235 * space \f$ (x, y, z) \f$ and time \f$ t\f$.
236 *
237 * @param id The ID returned from #DefineFunction representing the function
238 * to be evaluated.
239 * @param x The value of variable 1 (typically \f$ x \f$).
240 * @param y The value of variable 2 (typically \f$ y \f$).
241 * @param z The value of variable 3 (typically \f$ z \f$).
242 * @param t The value of variable 4 (typically \f$ t \f$).
243 */
244 LIB_UTILITIES_EXPORT NekDouble Evaluate(const int id, const NekDouble x,
245 const NekDouble y,
246 const NekDouble z,
247 const NekDouble t);
248
249 /**
250 * @brief Evaluate a function which depends on zero or more variables.
251 *
252 * This is suitable for expressions depending on more than 4 variables or
253 * for the dynamic setting of some variables as parameters (there is
254 * currently no interface method for removing a variable from parameter map
255 * however).
256 *
257 * @param id The ID returned from #DefineFunction representing the
258 * function to be evaluated.
259 * @param point A std::vector of points to be evaluated.
260 */
262 EvaluateAtPoint(const int id, std::vector<NekDouble> point);
263
264 /**
265 * @brief Evaluate a function which depends on four variables: typically
266 * space \f$ (x, y, z) \f$ and time \f$ t\f$ in a vectorised manner.
267 *
268 * This is a vectorised version of the evaluation method that will allow the
269 * same function to be evaluated many times for each of the entries in the
270 * input variable arrays @p x, @p y, @p z and @p t. Note that this is
271 * typically far quicker than the use of a loop with many calls to the
272 * single-variable variants in this class.
273 *
274 * @note All parameters @p x, @p y, @p z and @p t should be Arrays of the
275 * same length.
276 *
277 * @param id The ID returned from #DefineFunction representing the
278 * function to be evaluated.
279 * @param x An Array of values for variable 1 (typically \f$ x\f$).
280 * @param y An Array of values for variable 2 (typically \f$ y\f$).
281 * @param z An Array of values for variable 3 (typically \f$ z\f$).
282 * @param t An Array of values for variable 4 (typically \f$ t\f$).
283 * @param result An Array containing the evaluation of the function for each
284 * of the variable values.
285 */
286 LIB_UTILITIES_EXPORT void Evaluate(const int id,
291 Array<OneD, NekDouble> &result);
292
293 /**
294 * @brief Evaluate a function which depends on zero or more variables.
295 *
296 * This is a vectorised version of the evaluation method that will allow the
297 * same function to be evaluated many times for each of the entries in the
298 * input variable arrays within @p points. Note that this is typically far
299 * quicker than the use of a loop with many calls to the single-variable
300 * variants in this class.
301 *
302 * @note All entries of the input array @p points should be of the same
303 * length.
304 *
305 * @param id The ID returned from #DefineFunction representing the
306 * function to be evaluated.
307 * @param points An Array in which the i-th entry corresponds to values of
308 * variable \f$ i\f$.
309 * @param result An Array containing the evaluation of the function for each
310 * of the variable values.
311 */
313 const int expression_id,
314 const std::vector<Array<OneD, const NekDouble>> &points,
315 Array<OneD, NekDouble> &result);
316
317private:
318 /// Forward declaration of evaluator to avoid boost::spirit includes.
320 /// Concrete implementation of the above API calls.
321 std::unique_ptr<ExpressionEvaluator> m_impl;
322};
323
324typedef std::shared_ptr<Interpreter> InterpreterSharedPtr;
325
326} // namespace LibUtilities
327} // namespace Nektar
328
329#endif
#define LIB_UTILITIES_EXPORT
Concrete implementation of the interface defined in Interpreter.
Interpreter class for the evaluation of mathematical expressions.
Definition: Interpreter.h:78
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:321
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:324
std::vector< double > z(NPUPPER)
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:2
double NekDouble