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 <string>
40 #include <memory>
41 
43 
44 namespace Nektar
45 {
46 namespace 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 {
79 public:
80  /**
81  * @brief Default constructor.
82  */
84 
85  /**
86  * @brief Default destructor.
87  */
89 
90  /**
91  * @brief Default move constructor.
92  */
93  LIB_UTILITIES_EXPORT Interpreter(Interpreter &&);
94 
95  /**
96  * @brief Default assignment operator.
97  */
98  LIB_UTILITIES_EXPORT Interpreter &operator=(Interpreter &&);
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  */
143  std::string const& name, 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  */
154  LIB_UTILITIES_EXPORT NekDouble GetConstant(std::string const& name);
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  */
182  std::string const& name, 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  */
193  LIB_UTILITIES_EXPORT NekDouble GetParameter(std::string const& name);
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  */
222  const std::string& vlist, 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$ x \f$).
241  * @param z The value of variable 3 (typically \f$ x \f$).
242  * @param t The value of variable 4 (typically \f$ x \f$).
243  */
245  const int id, const NekDouble x, const NekDouble y, const NekDouble z,
246  const NekDouble t);
247 
248  /**
249  * @brief Evaluate a function which depends on zero or more variables.
250  *
251  * This is suitable for expressions depending on more than 4 variables or
252  * for the dynamic setting of some variables as parameters (there is
253  * currently no interface method for removing a variable from parameter map
254  * however).
255  *
256  * @param id The ID returned from #DefineFunction representing the
257  * function to be evaluated.
258  * @param point A std::vector of points to be evaluated.
259  */
261  const int id,
262  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  */
287  const int id,
292  Array<OneD, NekDouble>& result);
293 
294  /**
295  * @brief Evaluate a function which depends on zero or more variables.
296  *
297  * This is a vectorised version of the evaluation method that will allow the
298  * same function to be evaluated many times for each of the entries in the
299  * input variable arrays within @p points. Note that this is typically far
300  * quicker than the use of a loop with many calls to the single-variable
301  * variants in this class.
302  *
303  * @note All entries of the input array @p points should be of the same
304  * length.
305  *
306  * @param id The ID returned from #DefineFunction representing the
307  * function to be evaluated.
308  * @param points An Array in which the i-th entry corresponds to values of
309  * variable \f$ i\f$.
310  * @param result An Array containing the evaluation of the function for each
311  * of the variable values.
312  */
314  const int expression_id,
315  const std::vector<Array<OneD, const NekDouble> > &points,
316  Array<OneD, NekDouble>& result);
317 
318 private:
319  /// Forward declaration of evaluator to avoid boost::spirit includes.
321  /// Concrete implementation of the above API calls.
322  std::unique_ptr<ExpressionEvaluator> m_impl;
323 };
324 
325 typedef std::shared_ptr<Interpreter> InterpreterSharedPtr;
326 
327 }
328 }
329 
330 #endif
~Interpreter()
Default destructor.
int DefineFunction(const std::string &vlist, const std::string &expr)
Defines a function for the purposes of evaluation.
NekDouble Evaluate(const int id)
Evaluate a function which depends only on constants and/or parameters.
Interpreter()
Default constructor.
NekDouble GetParameter(std::string const &name)
Get the value of a parameter.
Interpreter & operator=(Interpreter &&)
Default assignment operator.
void SetParameters(std::map< std::string, NekDouble > const &params)
Set parameter values.
Concrete implementation of the interface defined in Interpreter.
std::unique_ptr< ExpressionEvaluator > m_impl
Concrete implementation of the above API calls.
Definition: Interpreter.h:320
int AddConstant(std::string const &name, NekDouble value)
Set constants to be evaluated.
#define LIB_UTILITIES_EXPORT
void AddConstants(std::map< std::string, NekDouble > const &constants)
Set constants to be evaluated.
std::shared_ptr< Interpreter > InterpreterSharedPtr
Definition: Interpreter.h:325
double NekDouble
NekDouble GetTime() const
Returns the total walltime spent in evaluation procedures in seconds.
void SetParameter(std::string const &name, NekDouble value)
Set parameter values.
void SetRandomSeed(unsigned int seed=123u)
Sets the random seed for the pseudorandom number generator.
Interpreter class for the evaluation of mathematical expressions.
Definition: Interpreter.h:77
bg::model::point< double, 3, bg::cs::cartesian > point
Definition: BLMesh.cpp:53
NekDouble EvaluateAtPoint(const int id, std::vector< NekDouble > point)
Evaluate a function which depends on zero or more variables.
NekDouble GetConstant(std::string const &name)
Return the value of a constant.