Nektar++
Classes | Public Types | Public Member Functions | Public Attributes | Private Types | Private Member Functions | Private Attributes | List of all members
Nektar::LibUtilities::Interpreter::ExpressionEvaluator Class Reference

Concrete implementation of the interface defined in Interpreter. More...

Classes

class  AnalyticExpression
 
struct  CopyState
 
struct  EvalAbs
 
struct  EvalAcos
 
struct  EvalAng
 
struct  EvalAsin
 
struct  EvalAtan
 
struct  EvalAtan2
 
struct  EvalAWGN
 
struct  EvalBessel
 
struct  EvalCeil
 
struct  EvalCos
 
struct  EvalCosh
 
struct  EvalDiv
 
struct  EvalExp
 
struct  EvalFabs
 
struct  EvalFloor
 
struct  EvalFmod
 
struct  EvalLog
 
struct  EvalLog10
 
struct  EvalLogicalEqual
 
struct  EvalLogicalGeq
 
struct  EvalLogicalGreater
 
struct  EvalLogicalLeq
 
struct  EvalLogicalLess
 
struct  EvalMax
 
struct  EvalMin
 
struct  EvalMod
 
struct  EvalMul
 
struct  EvalNeg
 
struct  EvalPow
 
struct  EvalRad
 
struct  EvalSign
 
struct  EvalSin
 
struct  EvalSinh
 
struct  EvalSqrt
 
struct  EvalSub
 
struct  EvalSum
 
struct  EvalTan
 
struct  EvalTanh
 
struct  EvaluationStep
 Function objects (functors) More...
 
struct  StoreConst
 
struct  StorePrm
 
struct  StoreVar
 

Public Types

typedef std::map< std::string, int > VariableMap
 
typedef std::map< std::string, int > ConstantMap
 
typedef std::map< std::string, int > ParameterMap
 
typedef std::map< std::string, int > ExpressionMap
 
typedef std::map< std::string, int > FunctionNameMap
 
typedef std::vector< EvaluationStep * > ExecutionStack
 
typedef std::pair< bool, NekDoublePrecomputedValue
 
typedef NekDouble(* OneArgFunc) (NekDouble)
 
typedef NekDouble(* TwoArgFunc) (NekDouble, NekDouble)
 
typedef bsp::tree_parse_info< std::string::const_iterator, bsp::node_val_data_factory< NekDouble > > ParsedTreeInfo
 
typedef bsp::tree_match< std::string::const_iterator, bsp::node_val_data_factory< NekDouble > >::tree_iterator ParsedTreeIterator
 
typedef std::vector< const Array< OneD, const NekDouble > * > VariableArray
 

Public Member Functions

 ExpressionEvaluator ()
 Initializes the evaluator. More...
 
 ~ExpressionEvaluator (void)
 Destructor that removes all entries from the execution stack. More...
 
void SetRandomSeed (unsigned int seed)
 Sets the random seed for the pseudorandom number generator. More...
 
void AddConstants (std::map< std::string, NekDouble > const &constants)
 Set constants to be evaluated. More...
 
int AddConstant (std::string const &name, NekDouble value)
 Set constants to be evaluated. More...
 
NekDouble GetConstant (std::string const &name)
 Return the value of a constant. More...
 
void SetParameters (std::map< std::string, NekDouble > const &params)
 Set parameter values. More...
 
void SetParameter (std::string const &name, NekDouble value)
 Set parameter values. More...
 
NekDouble GetParameter (std::string const &name)
 Get the value of a parameter. More...
 
NekDouble GetTime () const
 Returns the total walltime spent in evaluation procedures in seconds. More...
 
int DefineFunction (const std::string &vlist, const std::string &expr)
 Defines a function for the purposes of evaluation. More...
 
NekDouble Evaluate (const int id)
 Evaluate a function which depends only on constants and/or parameters. More...
 
NekDouble Evaluate (const int id, const NekDouble x, const NekDouble y, const NekDouble z, const NekDouble t)
 Evaluate a function which depends only on constants and/or parameters. More...
 
NekDouble EvaluateAtPoint (const int id, const std::vector< NekDouble > point)
 Evaluate a function which depends on zero or more variables. More...
 
void Evaluate (const int id, const Array< OneD, const NekDouble > &x, const Array< OneD, const NekDouble > &y, const Array< OneD, const NekDouble > &z, const Array< OneD, const NekDouble > &t, Array< OneD, NekDouble > &result)
 Evaluate a function which depends only on constants and/or parameters. More...
 
void Evaluate (const int id, const std::vector< Array< OneD, const NekDouble > > &points, Array< OneD, NekDouble > &result)
 Evaluate a function which depends only on constants and/or parameters. More...
 
PrecomputedValue PrepareExecutionAsYouParse (const ParsedTreeIterator &location, ExecutionStack &stack, VariableMap &variableMap, int stateIndex)
 Prepares an execution stack for the evaluation of a function. More...
 

Public Attributes

bsp::symbols< NekDoublem_constantsParser
 

Private Types

enum  EvaluationStepType {
  E_ABS , E_ASIN , E_ACOS , E_ATAN ,
  E_ATAN2 , E_ANG , E_CEIL , E_COS ,
  E_COSH , E_EXP , E_FABS , E_FLOOR ,
  E_FMOD , E_LOG , E_LOG10 , E_MAX ,
  E_MIN , E_POW , E_RAD , E_SIN ,
  E_SINH , E_SQRT , E_TAN , E_TANH ,
  E_SIGN , E_AWGN , E_BESSEL
}
 
typedef std::vector< NekDouble > & vr
 Short names to minimise the infractructural code mess in defining functors below. More...
 
typedef const std::vector< NekDouble > & cvr
 
typedef const int ci
 
typedef std::mt19937 & rgt
 

Private Member Functions

template<typename StepType >
EvaluationStepmakeStep (ci dest, ci src_left=0, ci src_right=0)
 Factory method which makes code little less messy. More...
 

Private Attributes

ExpressionMap m_parsedMapExprToExecStackId
 These vector and map store pre-processed evaluation sequences for the analytic expressions. Each ExecutionStack is an ordered container of steps of sequential execution process which evaluates an analytic expression. More...
 
std::vector< ExecutionStackm_executionStack
 
std::vector< VariableMapm_stackVariableMap
 Keeping map of variables individually per each analytic expression allows correctly handling expressions which depend on different number of variables. More...
 
ParameterMap m_parameterMapNameToId
 The following data structures hold input data to be used on evaluation stage. There are three types of input data: More...
 
ConstantMap m_constantMapNameToId
 
VariableMap m_expressionVariableMap
 
std::vector< NekDoublem_parameter
 
std::vector< NekDoublem_constant
 
std::vector< NekDoublem_variable
 
std::vector< NekDoublem_state
 This vector stores the execution state (memory) used by the sequential execution process. More...
 
std::vector< int > m_state_sizes
 Vector of state sizes per each. More...
 
int m_state_size
 This counter is used by PrepareExecutionAsYouParse for finding the minimal state size necessary for evaluation of function parsed. More...
 
Timer m_timer
 Timer and sum of evaluation times. More...
 
NekDouble m_total_eval_time
 
std::mt19937 m_generator
 
FunctionNameMap m_functionMapNameToInstanceType
 
std::map< int, OneArgFuncm_function
 
std::map< int, TwoArgFuncm_function2
 

Detailed Description

Concrete implementation of the interface defined in Interpreter.

Definition at line 156 of file Interpreter/Interpreter.cpp.

Member Typedef Documentation

◆ ci

Definition at line 1324 of file Interpreter/Interpreter.cpp.

◆ ConstantMap

Definition at line 163 of file Interpreter/Interpreter.cpp.

◆ cvr

Definition at line 1323 of file Interpreter/Interpreter.cpp.

◆ ExecutionStack

Definition at line 167 of file Interpreter/Interpreter.cpp.

◆ ExpressionMap

Definition at line 165 of file Interpreter/Interpreter.cpp.

◆ FunctionNameMap

Definition at line 166 of file Interpreter/Interpreter.cpp.

◆ OneArgFunc

typedef NekDouble(* Nektar::LibUtilities::Interpreter::ExpressionEvaluator::OneArgFunc) (NekDouble)

Definition at line 169 of file Interpreter/Interpreter.cpp.

◆ ParameterMap

Definition at line 164 of file Interpreter/Interpreter.cpp.

◆ ParsedTreeInfo

typedef bsp::tree_parse_info<std::string::const_iterator, bsp::node_val_data_factory<NekDouble> > Nektar::LibUtilities::Interpreter::ExpressionEvaluator::ParsedTreeInfo

Definition at line 174 of file Interpreter/Interpreter.cpp.

◆ ParsedTreeIterator

typedef bsp::tree_match<std::string::const_iterator,bsp::node_val_data_factory<NekDouble>>::tree_iterator Nektar::LibUtilities::Interpreter::ExpressionEvaluator::ParsedTreeIterator

Definition at line 177 of file Interpreter/Interpreter.cpp.

◆ PrecomputedValue

Definition at line 168 of file Interpreter/Interpreter.cpp.

◆ rgt

Definition at line 1325 of file Interpreter/Interpreter.cpp.

◆ TwoArgFunc

typedef NekDouble(* Nektar::LibUtilities::Interpreter::ExpressionEvaluator::TwoArgFunc) (NekDouble, NekDouble)

Definition at line 170 of file Interpreter/Interpreter.cpp.

◆ VariableArray

Definition at line 179 of file Interpreter/Interpreter.cpp.

◆ VariableMap

Definition at line 162 of file Interpreter/Interpreter.cpp.

◆ vr

Short names to minimise the infractructural code mess in defining functors below.

Definition at line 1322 of file Interpreter/Interpreter.cpp.

Member Enumeration Documentation

◆ EvaluationStepType

Enumerator
E_ABS 
E_ASIN 
E_ACOS 
E_ATAN 
E_ATAN2 
E_ANG 
E_CEIL 
E_COS 
E_COSH 
E_EXP 
E_FABS 
E_FLOOR 
E_FMOD 
E_LOG 
E_LOG10 
E_MAX 
E_MIN 
E_POW 
E_RAD 
E_SIN 
E_SINH 
E_SQRT 
E_TAN 
E_TANH 
E_SIGN 
E_AWGN 
E_BESSEL 

Definition at line 1335 of file Interpreter/Interpreter.cpp.

1336 {
1337 E_ABS,
1338 E_ASIN,
1339 E_ACOS,
1340 E_ATAN,
1341 E_ATAN2,
1342 E_ANG,
1343 E_CEIL,
1344 E_COS,
1345 E_COSH,
1346 E_EXP,
1347 E_FABS,
1348 E_FLOOR,
1349 E_FMOD,
1350 E_LOG,
1351 E_LOG10,
1352 E_MAX,
1353 E_MIN,
1354 E_POW,
1355 E_RAD,
1356 E_SIN,
1357 E_SINH,
1358 E_SQRT,
1359 E_TAN,
1360 E_TANH,
1361 E_SIGN,
1362 E_AWGN,
1363 E_BESSEL
1364 };

Constructor & Destructor Documentation

◆ ExpressionEvaluator()

Nektar::LibUtilities::Interpreter::ExpressionEvaluator::ExpressionEvaluator ( )
inline

Initializes the evaluator.

This routine will initialize the evaluator with some basic default constants,

Definition at line 187 of file Interpreter/Interpreter.cpp.

188 {
189 m_state_size = 1;
190
191 // Constant definitions.
192 AddConstant("MEANINGLESS", 0.0);
193 AddConstant("E", M_E); // Natural logarithm
194 AddConstant("LOG2E", M_LOG2E); // log_2 e
195 AddConstant("LOG10E", M_LOG10E); // log_10 e
196 AddConstant("LN2", M_LN2); // log_e 2
197 AddConstant("LN10", M_LN10); // log_e 10
198 AddConstant("PI", M_PI); // pi
199 AddConstant("PI_2", M_PI_2); // pi/2
200 AddConstant("PI_4", M_PI_4); // pi/4
201 AddConstant("1_PI", M_1_PI); // 1/pi
202 AddConstant("2_PI", M_2_PI); // 2/pi
203 AddConstant("2_SQRTPI", M_2_SQRTPI); // 2/sqrt(pi)
204 AddConstant("SQRT2", M_SQRT2); // sqrt(2)
205 AddConstant("SQRT1_2", M_SQRT1_2); // 1/sqrt(2)
206 AddConstant("GAMMA", 0.57721566490153286060); // Euler
207 AddConstant("DEG", 57.2957795130823208768); // deg/radian
208 AddConstant("PHI", 1.61803398874989484820); // golden ratio
209
210 // Function definitions.
239
241 m_function[E_ASIN] = asin;
242 m_function[E_ACOS] = acos;
243 m_function[E_ATAN] = atan;
244 m_function[E_CEIL] = ceil;
245 m_function[E_COS] = cos;
246 m_function[E_COSH] = cosh;
247 m_function[E_EXP] = exp;
248 m_function[E_FABS] = fabs;
249 m_function[E_FLOOR] = floor;
251 m_function[E_LOG10] = log10;
252 m_function2[E_MAX] = fmax;
253 m_function2[E_MIN] = fmin;
254 m_function[E_SIN] = sin;
255 m_function[E_SINH] = sinh;
257 m_function[E_TAN] = tan;
258 m_function[E_TANH] = tanh;
260 m_function2[E_ATAN2] = atan2;
263 m_function2[E_BESSEL] = boost::math::cyl_bessel_j;
264 m_function2[E_FMOD] = static_cast<double (*)(double, double)>(&fmod);
265
266 // Note that there is no entry in m_function that corresponds to the
267 // awgn function. This is intentional as this function need not be
268 // pre-evaluated once!
269 }
int AddConstant(std::string const &name, NekDouble value)
Set constants to be evaluated.
int m_state_size
This counter is used by PrepareExecutionAsYouParse for finding the minimal state size necessary for e...
static NekDouble rad(NekDouble x, NekDouble y)
static NekDouble ang(NekDouble x, NekDouble y)
NekDouble sign(NekDouble arg)
scalarT< T > abs(scalarT< T > in)
Definition: scalar.hpp:289
scalarT< T > log(scalarT< T > in)
Definition: scalar.hpp:294
scalarT< T > sqrt(scalarT< T > in)
Definition: scalar.hpp:285

References tinysimd::abs(), AddConstant(), Nektar::LibUtilities::ang(), E_ABS, E_ACOS, E_ANG, E_ASIN, E_ATAN, E_ATAN2, E_AWGN, E_BESSEL, E_CEIL, E_COS, E_COSH, E_EXP, E_FABS, E_FLOOR, E_FMOD, E_LOG, E_LOG10, E_MAX, E_MIN, E_RAD, E_SIGN, E_SIN, E_SINH, E_SQRT, E_TAN, E_TANH, tinysimd::log(), m_function, m_function2, m_functionMapNameToInstanceType, m_state_size, Nektar::LibUtilities::rad(), Nektar::LibUtilities::sign(), and tinysimd::sqrt().

◆ ~ExpressionEvaluator()

Nektar::LibUtilities::Interpreter::ExpressionEvaluator::~ExpressionEvaluator ( void  )
inline

Destructor that removes all entries from the execution stack.

Definition at line 274 of file Interpreter/Interpreter.cpp.

275 {
276 for (auto &it_es : m_executionStack)
277 {
278 for (auto &it : it_es)
279 {
280 delete it;
281 }
282 it_es.clear();
283 }
284 m_executionStack.clear();
285 }

References m_executionStack.

Member Function Documentation

◆ AddConstant()

int Nektar::LibUtilities::Interpreter::ExpressionEvaluator::AddConstant ( std::string const &  name,
NekDouble  value 
)
inline

Set constants to be evaluated.

This function behaves in the same way as AddConstants, but it only adds one constant at a time. If the constant existed previously, an exception will be thrown stating the fact. If it did not exist previously, it will be added to the global constants and will be used the next time DefineFunction is called.

Returns
Total number of constants after this one has been added.

Definition at line 309 of file Interpreter/Interpreter.cpp.

310 {
311 ConstantMap::const_iterator it = m_constantMapNameToId.find(name);
312 if (it == m_constantMapNameToId.end())
313 {
314 // We are trying to avoid duplicating entries in m_constantParser
315 // and m_constants.
316 m_constantsParser.add(name.c_str(), value);
317 int index = m_constant.size();
319 m_constant.push_back(value);
320 return index;
321 }
322 else
323 {
324 if (m_constant[it->second] != value)
325 {
326 std::string errormsg =
327 "Attempt to add numerically different constants under the "
328 "same name: " +
329 name;
330 std::cout << errormsg << std::endl;
331 }
332 }
333 return it->second;
334 }

References m_constant, m_constantMapNameToId, m_constantsParser, and CellMLToNektar.pycml::name.

Referenced by AddConstants(), DefineFunction(), ExpressionEvaluator(), and PrepareExecutionAsYouParse().

◆ AddConstants()

void Nektar::LibUtilities::Interpreter::ExpressionEvaluator::AddConstants ( std::map< std::string, NekDouble > const &  constants)
inline

Set constants to be evaluated.

Constants are evaluated and inserted into the function at the time it is parsed when calling the DefineFunction function. After parsing, if a constant is changed, it will not be reflected in the function when Evaluate is called. This also means that if a function with an unknown constant is added, and then the constant is added, the function will not see the added constant and through an exception.

This function will add all of the constants in the constants parameter to the global internal constants. If a constant was already loaded previously, it will throw an exception stating which constants in the map had this issue. It will add all of the constants it can from constants and output the constants it couldn't add in the string exception.

Parameters
constantsA std::map with string names for the constants (which will be evalauted in the expression) and their NekDouble value.

Definition at line 298 of file Interpreter/Interpreter.cpp.

299 {
300 for (auto const &it : constants)
301 {
302 AddConstant(it.first, it.second);
303 }
304 }

References AddConstant().

◆ DefineFunction()

int Nektar::LibUtilities::Interpreter::ExpressionEvaluator::DefineFunction ( const std::string &  vlist,
const std::string &  expr 
)
inline

Defines a function for the purposes of evaluation.

This function allows one to define a function to evaluate. The vlist argument should define a list of space-separated variables that the expression defined in function is dependent upon. For example, if function is defined as the string x + y, then vlist should most likely be x y, unless you are defining x or y as parameters with the SetParameters function.

Parameters
vlistList of variable names separated with spaces.
exprString definition of the function to be evaluated.
Returns
An integer denoting the unique ID of this function. This should be passed into Evaluate functions for later evaluation.

Definition at line 397 of file Interpreter/Interpreter.cpp.

398 {
399 // If we have previously parsed an identical expression, return its ID.
400 auto it = m_parsedMapExprToExecStackId.find(expr);
401 if (it != m_parsedMapExprToExecStackId.end())
402 {
403 // If this function is already defined, don't do anything but return
404 // its ID.
405 return it->second;
406 }
407
408 // Otherwise, prepare an iterator that allows to walk along the string
409 // representing an analytic expression in the order that respects its
410 // recursive structure (thanks to boost::spirit).
411
412 // Parse the vlist input and separate the variables into ordered entries
413 // in a vector<string> object. These need to be ordered because this is
414 // the order the variables will get assigned to in the Map when
415 // Evaluate(...) is called.
416 std::vector<std::string> variableNames;
417 bsp::parse((char *)vlist.c_str(),
418 (*bsp::space_p >>
419 *(+(+bsp::graph_p)[bsp::push_back_a(variableNames)] >>
420 +bsp::space_p)));
421
422 // Set up our grammar.
423 AnalyticExpression myGrammar(&m_constantsParser, variableNames);
424
425 // Do the actual parsing with boost::spirit and alert the user if there
426 // was an error with an exception.
427 ParsedTreeInfo parseInfo =
428 bsp::ast_parse<bsp::node_val_data_factory<NekDouble>,
429 std::string::const_iterator, AnalyticExpression,
430 bsp::space_parser>(expr.begin(), expr.end(),
431 myGrammar, bsp::space_p);
432
433 ASSERTL1(parseInfo.full != false,
434 "Unable to fully parse function. Stopped just before: " +
435 std::string(parseInfo.stop, parseInfo.stop + 15));
436
437 if (!parseInfo.full)
438 {
439 throw std::runtime_error(
440 "Unable to fully parse function at: " +
441 std::string(parseInfo.stop, parseInfo.stop + 15));
442 }
443
444 // ----------------------------------------------
445 // Data parsed, start setting up internal data structures.
446 // ----------------------------------------------
447
448 ExecutionStack stack;
449 VariableMap variableMap;
450
451 int stackId = m_executionStack.size();
452 m_state_size = 1;
453
454 // Register all variables declared in the expression
455 for (int i = 0; i < variableNames.size(); i++)
456 {
457 variableMap[variableNames[i]] = i;
458 }
459
460 // Then prepare an execution stack. This method also calculates a
461 // length of internal state storage (m_state_size) for this function.
462 PrecomputedValue v = PrepareExecutionAsYouParse(parseInfo.trees.begin(),
463 stack, variableMap, 0);
464
465 // Constant expression, fully evaluated already.
466 if (true == v.first)
467 {
468 ASSERTL1(stack.size() == 0,
469 "Constant expression yeilds non-empty execution stack. "
470 "Bug in PrepareExecutionAsYouParse()");
471
472 int const_index = AddConstant(
473 std::string("EXPRESSION_") + std::to_string(stackId), v.second);
474 stack.push_back(makeStep<StoreConst>(0, const_index));
475 }
476
477 m_parsedMapExprToExecStackId[expr] = stackId;
478
479 // The execution stack and its corresponding variable index map are two
480 // parallel std::vectors that share their ids. This split helps to
481 // achieve some performance improvement.
482 m_executionStack.push_back(stack);
483 m_stackVariableMap.push_back(variableMap);
484 m_state_sizes.push_back(m_state_size);
485
486 return stackId;
487 }
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode....
Definition: ErrorUtil.hpp:242
std::vector< int > m_state_sizes
Vector of state sizes per each.
std::vector< VariableMap > m_stackVariableMap
Keeping map of variables individually per each analytic expression allows correctly handling expressi...
bsp::tree_parse_info< std::string::const_iterator, bsp::node_val_data_factory< NekDouble > > ParsedTreeInfo
PrecomputedValue PrepareExecutionAsYouParse(const ParsedTreeIterator &location, ExecutionStack &stack, VariableMap &variableMap, int stateIndex)
Prepares an execution stack for the evaluation of a function.
ExpressionMap m_parsedMapExprToExecStackId
These vector and map store pre-processed evaluation sequences for the analytic expressions....

References AddConstant(), ASSERTL1, m_constantsParser, m_executionStack, m_parsedMapExprToExecStackId, m_stackVariableMap, m_state_size, m_state_sizes, and PrepareExecutionAsYouParse().

◆ Evaluate() [1/4]

NekDouble Nektar::LibUtilities::Interpreter::ExpressionEvaluator::Evaluate ( const int  id)
inline

Evaluate a function which depends only on constants and/or parameters.

Parameters
idThe ID returned from DefineFunction representing the function to be evaluated.

Definition at line 492 of file Interpreter/Interpreter.cpp.

493 {
494 m_timer.Start();
495
496 ASSERTL1(m_executionStack.size() > id,
497 "unknown analytic expression, it must first be defined "
498 "with DefineFunction(...)");
499
500 ExecutionStack &stack = m_executionStack[id];
501
502 m_state.resize(m_state_sizes[id]);
503 for (int i = 0; i < stack.size(); i++)
504 {
505 (*stack[i]).run_once();
506 }
507
508 m_timer.Stop();
510
511 return m_state[0];
512 }
std::vector< NekDouble > m_state
This vector stores the execution state (memory) used by the sequential execution process.
NekDouble TimePerTest(unsigned int n)
Returns amount of seconds per iteration in a test with n iterations.
Definition: Timer.cpp:65

References ASSERTL1, m_executionStack, m_state, m_state_sizes, m_timer, m_total_eval_time, Nektar::LibUtilities::Timer::Start(), Nektar::LibUtilities::Timer::Stop(), and Nektar::LibUtilities::Timer::TimePerTest().

Referenced by Evaluate().

◆ Evaluate() [2/4]

void Nektar::LibUtilities::Interpreter::ExpressionEvaluator::Evaluate ( const int  id,
const Array< OneD, const NekDouble > &  x,
const Array< OneD, const NekDouble > &  y,
const Array< OneD, const NekDouble > &  z,
const Array< OneD, const NekDouble > &  t,
Array< OneD, NekDouble > &  result 
)
inline

Evaluate a function which depends only on constants and/or parameters.

Parameters
idThe ID returned from DefineFunction representing the function to be evaluated.

Definition at line 599 of file Interpreter/Interpreter.cpp.

604 {
605 std::vector<Array<OneD, const NekDouble>> points = {x, y, z, t};
606 Evaluate(id, points, result);
607 }
NekDouble Evaluate(const int id)
Evaluate a function which depends only on constants and/or parameters.
std::vector< double > z(NPUPPER)

References Evaluate(), and Nektar::UnitTests::z().

◆ Evaluate() [3/4]

NekDouble Nektar::LibUtilities::Interpreter::ExpressionEvaluator::Evaluate ( const int  id,
const NekDouble  x,
const NekDouble  y,
const NekDouble  z,
const NekDouble  t 
)
inline

Evaluate a function which depends only on constants and/or parameters.

Parameters
idThe ID returned from DefineFunction representing the function to be evaluated.

Definition at line 517 of file Interpreter/Interpreter.cpp.

519 {
520 m_timer.Start();
521
522 ASSERTL1(m_executionStack.size() > id,
523 "unknown analytic expression, it must first be defined with "
524 "DefineFunction(...)");
525
526 ExecutionStack &stack = m_executionStack[id];
527
528 // initialise internal vector of variable values
529 m_state.resize(m_state_sizes[id]);
530
531 if (m_variable.size() < 4)
532 {
533 m_variable.resize(4);
534 }
535
536 // no flexibility, no change of variable ordering in m_variable
537 // container depending on their names ordering in the input vlist
538 // argument of DefineFunction. Ordering convention (x,y,z,t) is assumed.
539 m_variable[0] = x;
540 m_variable[1] = y;
541 m_variable[2] = z;
542 m_variable[3] = t;
543
544 // main execution cycle is hidden here
545 for (int i = 0; i < stack.size(); i++)
546 {
547 (*stack[i]).run_once();
548 }
549
550 m_timer.Stop();
552
553 return m_state[0];
554 }

References ASSERTL1, m_executionStack, m_state, m_state_sizes, m_timer, m_total_eval_time, m_variable, Nektar::LibUtilities::Timer::Start(), Nektar::LibUtilities::Timer::Stop(), Nektar::LibUtilities::Timer::TimePerTest(), and Nektar::UnitTests::z().

◆ Evaluate() [4/4]

void Nektar::LibUtilities::Interpreter::ExpressionEvaluator::Evaluate ( const int  id,
const std::vector< Array< OneD, const NekDouble > > &  points,
Array< OneD, NekDouble > &  result 
)
inline

Evaluate a function which depends only on constants and/or parameters.

Parameters
idThe ID returned from DefineFunction representing the function to be evaluated.

If number of points tends to 10^6, one may end up with up to ~0.5Gb data allocated for m_state only. Lets split the work into cache-sized chunks. Ahtung, magic constant!

Definition at line 612 of file Interpreter/Interpreter.cpp.

615 {
616 m_timer.Start();
617
618 const int num_points = points[0].size();
619 ASSERTL1(m_executionStack.size() > id,
620 "unknown analytic expression, it must first be defined "
621 "with DefineFunction(...)");
622 ASSERTL1(result.size() >= num_points,
623 "destination array must have enough capacity to store "
624 "expression values at each given point");
625
626 ExecutionStack &stack = m_executionStack[id];
627
628 /// If number of points tends to 10^6, one may end up with up to ~0.5Gb
629 /// data allocated for m_state only. Lets split the work into
630 /// cache-sized chunks. Ahtung, magic constant!
631 const int max_chunk_size = 1024;
632 const int nvals = points.size();
633 const int chunk_size = (std::min)(max_chunk_size, num_points);
634
635 if (m_state.size() < chunk_size * m_state_sizes[id])
636 {
637 m_state.resize(m_state_sizes[id] * chunk_size, 0.0);
638 }
639 if (m_variable.size() < nvals * chunk_size)
640 {
641 m_variable.resize(nvals * chunk_size, 0.0);
642 }
643 if (result.size() < num_points)
644 {
645 result = Array<OneD, NekDouble>(num_points, 0.0);
646 }
647
648 int offset = 0;
649 int work_left = num_points;
650 while (work_left > 0)
651 {
652 const int this_chunk_size = (std::min)(work_left, 1024);
653 for (int i = 0; i < this_chunk_size; i++)
654 {
655 for (int j = 0; j < nvals; ++j)
656 {
657 m_variable[i + this_chunk_size * j] = points[j][offset + i];
658 }
659 }
660 for (int i = 0; i < stack.size(); i++)
661 {
662 (*stack[i]).run_many(this_chunk_size);
663 }
664 for (int i = 0; i < this_chunk_size; i++)
665 {
666 result[offset + i] = m_state[i];
667 }
668 work_left -= this_chunk_size;
669 offset += this_chunk_size;
670 }
671 m_timer.Stop();
673 }

References ASSERTL1, m_executionStack, m_state, m_state_sizes, m_timer, m_total_eval_time, m_variable, Nektar::LibUtilities::Timer::Start(), Nektar::LibUtilities::Timer::Stop(), and Nektar::LibUtilities::Timer::TimePerTest().

◆ EvaluateAtPoint()

NekDouble Nektar::LibUtilities::Interpreter::ExpressionEvaluator::EvaluateAtPoint ( const int  id,
const std::vector< NekDouble point 
)
inline

Evaluate a function which depends on zero or more variables.

This is suitable for expressions depending on more than 4 variables or for the dynamic setting of some variables as parameters (there is currently no interface method for removing a variable from parameter map however).

Parameters
idThe ID returned from DefineFunction representing the function to be evaluated.
pointA std::vector of points to be evaluated.

Definition at line 559 of file Interpreter/Interpreter.cpp.

560 {
561 m_timer.Start();
562
563 ASSERTL1(m_executionStack.size() > id,
564 "unknown analytic expression, it must first be defined with "
565 "DefineFunction(...)");
566
567 ExecutionStack &stack = m_executionStack[id];
568 VariableMap &variableMap = m_stackVariableMap[id];
569
570 ASSERTL1(point.size() == variableMap.size(),
571 "The number of variables used to define this expression should"
572 " match the point dimensionality.");
573
574 // initialise internal vector of variable values
575 m_state.resize(m_state_sizes[id]);
576 m_variable.resize(point.size());
577 VariableMap::const_iterator it;
578
579 for (it = variableMap.begin(); it != variableMap.end(); ++it)
580 {
581 m_variable[it->second] = point[it->second];
582 }
583
584 // main execution cycle is hidden here
585 for (int i = 0; i < stack.size(); i++)
586 {
587 (*stack[i]).run_once();
588 }
589
590 m_timer.Stop();
592
593 return m_state[0];
594 }

References ASSERTL1, m_executionStack, m_stackVariableMap, m_state, m_state_sizes, m_timer, m_total_eval_time, m_variable, Nektar::LibUtilities::Timer::Start(), Nektar::LibUtilities::Timer::Stop(), and Nektar::LibUtilities::Timer::TimePerTest().

◆ GetConstant()

NekDouble Nektar::LibUtilities::Interpreter::ExpressionEvaluator::GetConstant ( std::string const &  name)
inline

Return the value of a constant.

If a constant with the specified name name exists, this function returns the NekDouble value that the constant stores. If the constant doesn't exist, this throws an exception.

Parameters
nameName of constant to return.

Definition at line 339 of file Interpreter/Interpreter.cpp.

340 {
341 NekDouble *value = find(m_constantsParser, name.c_str());
342 ASSERTL1(value != nullptr, "Constant variable not found: " + name);
343 return *value;
344 }
InputIterator find(InputIterator first, InputIterator last, InputIterator startingpoint, const EqualityComparable &value)
Definition: StdRegions.hpp:475
double NekDouble

References ASSERTL1, Nektar::StdRegions::find(), m_constantsParser, and CellMLToNektar.pycml::name.

◆ GetParameter()

NekDouble Nektar::LibUtilities::Interpreter::ExpressionEvaluator::GetParameter ( std::string const &  name)
inline

Get the value of a parameter.

If a parameter with the specified name exists, it returns the NekDouble value that the parameter stores. If the parameter doesn't exist, it throws an exception.

Parameters
nameName of the parameter to query.

Definition at line 378 of file Interpreter/Interpreter.cpp.

379 {
380 ParameterMap::const_iterator it = m_parameterMapNameToId.find(name);
382 "Parameter not found: " + name);
383 return m_parameter[it->second];
384 }
ParameterMap m_parameterMapNameToId
The following data structures hold input data to be used on evaluation stage. There are three types o...

References ASSERTL1, m_parameter, m_parameterMapNameToId, and CellMLToNektar.pycml::name.

◆ GetTime()

NekDouble Nektar::LibUtilities::Interpreter::ExpressionEvaluator::GetTime ( ) const
inline

Returns the total walltime spent in evaluation procedures in seconds.

Definition at line 389 of file Interpreter/Interpreter.cpp.

390 {
391 return m_total_eval_time;
392 }

References m_total_eval_time.

◆ makeStep()

template<typename StepType >
EvaluationStep * Nektar::LibUtilities::Interpreter::ExpressionEvaluator::makeStep ( ci  dest,
ci  src_left = 0,
ci  src_right = 0 
)
inlineprivate

Factory method which makes code little less messy.

Definition at line 1329 of file Interpreter/Interpreter.cpp.

1330 {
1331 return (new StepType(m_generator, m_state, m_constant, m_parameter,
1332 m_variable, dest, src_left, src_right));
1333 }

References m_constant, m_generator, m_parameter, m_state, and m_variable.

◆ PrepareExecutionAsYouParse()

PrecomputedValue Nektar::LibUtilities::Interpreter::ExpressionEvaluator::PrepareExecutionAsYouParse ( const ParsedTreeIterator location,
ExecutionStack stack,
VariableMap variableMap,
int  stateIndex 
)
inline

Prepares an execution stack for the evaluation of a function.

This method prepares the execution stack (an ordered sequence of operators that perform the evaluation) for the parsed evaluation tree. In order to do this, it unrolls the binary tree representing the recursive evaluation into an ordered sequence of commands. That ordered sequence of commands is equivalent to a bottom-up walk up the evaluation tree, but this allows not to form tree explicitly.

This approach requires to introduce explicitly an execution state (memory) shared by commands in the evaluation sequence: recursively dependent commands need to pass data between each other. Such state for the recursive evaluation is passed via return values of a recursive evaluation function — which is bad if one wants to implement vectorized evaluator.

On the other hand, to run through a sequential container of functors is faster than to walk the tree and at each node to check the node type.

Parameters
rootIterator generated by boost::spirit.
stackInitially empty sequential container of evaluation steps.
varMapMaps variable names to their ids.
stateIndexAn index in the state[] array where an evaluation step corresponding to the current tree node is allowed to write.
Returns
A std::pair<bool, NekDouble> which encodes fully pre-evaluated NekDouble values as (true, value) if all sub-tree down the current node evaluates to constant, or flags the opposite via (false, 0).

Definition at line 712 of file Interpreter/Interpreter.cpp.

715 {
716 std::string valueStr(location->value.begin(), location->value.end());
717 boost::algorithm::trim(valueStr);
718
719 const bsp::parser_id parserID = location->value.id();
720#if defined(NEKTAR_DEBUG) || defined(NEKTAR_FULLDEBUG)
721 const int num_children = location->children.size();
722#endif
723
724 if (parserID == AnalyticExpression::constantID)
725 {
726 ASSERTL1(num_children == 0,
727 "Illegal children under constant node: " + valueStr);
728
729 auto it = m_constantMapNameToId.find(valueStr);
731 "Cannot find the value for the specified constant: " +
732 valueStr);
733
734 return std::make_pair(true, m_constant[it->second]);
735 }
736 else if (parserID == AnalyticExpression::numberID)
737 {
738 ASSERTL1(num_children == 0,
739 "Illegal children under number node: " + valueStr);
740 return std::make_pair(true, std::stod(valueStr.c_str()));
741 }
742 else if (parserID == AnalyticExpression::variableID)
743 {
744 ASSERTL1(num_children == 0,
745 "Illegal children under variable node: " + valueStr);
746
747 VariableMap::const_iterator it = variableMap.find(valueStr);
748 ASSERTL1(it != variableMap.end(),
749 "Unknown variable parsed: " + valueStr);
750
751 // Variables are not defined at the time of this parse.
752 stack.push_back(makeStep<StoreVar>(stateIndex, it->second));
753 return std::make_pair(false, 0);
754 }
755 else if (parserID == AnalyticExpression::parameterID)
756 {
757 ASSERTL1(num_children == 0,
758 "Illegal children under parameter node: " + valueStr);
759
760 auto it = m_parameterMapNameToId.find(valueStr);
762 "Unknown parameter parsed: " + valueStr);
763
764 // Parameters may change in between of evalutions.
765 stack.push_back(makeStep<StorePrm>(stateIndex, it->second));
766 return std::make_pair(false, 0);
767 }
768 else if (parserID == AnalyticExpression::functionID)
769 {
770 auto it = m_functionMapNameToInstanceType.find(valueStr);
772 "Invalid function specified: " + valueStr);
773 ASSERTL1(num_children == 1 || num_children == 2,
774 "Function " + valueStr +
775 " has neither one or two "
776 "arguments: this is not implemented yet.");
777
778 if (location->children.size() == 1)
779 {
781 location->children.begin(), stack, variableMap, stateIndex);
782
783 // additive white gaussian noise function
784 if (it->second == E_AWGN)
785 {
786 int const_index =
787 AddConstant(std::string("SUB_EXPR_") +
788 std::to_string(m_constant.size()),
789 v.second);
790 stack.push_back(
791 makeStep<StoreConst>(stateIndex, const_index));
792 stack.push_back(makeStep<EvalAWGN>(stateIndex, stateIndex));
793 return std::make_pair(false, 0);
794 }
795
796 if (true == v.first)
797 {
798 return std::make_pair(true,
799 m_function[it->second](v.second));
800 }
801 }
802 else
803 {
805 PrepareExecutionAsYouParse(location->children.begin() + 0,
806 stack, variableMap, stateIndex);
808 location->children.begin() + 1, stack, variableMap,
809 stateIndex + 1);
810 m_state_size++;
811
812 if (true == v1.first && true == v2.first)
813 {
814 return std::make_pair(
815 true, m_function2[it->second](v1.second, v2.second));
816 }
817 }
818
819 // if somewhere down the parse tree there is a variable or
820 // parameter, set up an evaluation sequence.
821 switch (it->second)
822 {
823 case E_ABS:
824 stack.push_back(makeStep<EvalAbs>(stateIndex, stateIndex));
825 return std::make_pair(false, 0);
826 case E_ASIN:
827 stack.push_back(makeStep<EvalAsin>(stateIndex, stateIndex));
828 return std::make_pair(false, 0);
829 case E_ACOS:
830 stack.push_back(makeStep<EvalAcos>(stateIndex, stateIndex));
831 return std::make_pair(false, 0);
832 case E_ATAN:
833 stack.push_back(makeStep<EvalAtan>(stateIndex, stateIndex));
834 return std::make_pair(false, 0);
835 case E_ATAN2:
836 stack.push_back(makeStep<EvalAtan2>(stateIndex, stateIndex,
837 stateIndex + 1));
838 return std::make_pair(false, 0);
839 case E_ANG:
840 stack.push_back(makeStep<EvalAng>(stateIndex, stateIndex,
841 stateIndex + 1));
842 return std::make_pair(false, 0);
843 case E_BESSEL:
844 stack.push_back(makeStep<EvalBessel>(stateIndex, stateIndex,
845 stateIndex + 1));
846 return std::make_pair(false, 0);
847 case E_CEIL:
848 stack.push_back(makeStep<EvalCeil>(stateIndex, stateIndex));
849 return std::make_pair(false, 0);
850 case E_COS:
851 stack.push_back(makeStep<EvalCos>(stateIndex, stateIndex));
852 return std::make_pair(false, 0);
853 case E_COSH:
854 stack.push_back(makeStep<EvalCosh>(stateIndex, stateIndex));
855 return std::make_pair(false, 0);
856 case E_EXP:
857 stack.push_back(makeStep<EvalExp>(stateIndex, stateIndex));
858 return std::make_pair(false, 0);
859 case E_FABS:
860 stack.push_back(makeStep<EvalFabs>(stateIndex, stateIndex));
861 return std::make_pair(false, 0);
862 case E_FLOOR:
863 stack.push_back(
864 makeStep<EvalFloor>(stateIndex, stateIndex));
865 return std::make_pair(false, 0);
866 case E_FMOD:
867 stack.push_back(makeStep<EvalFmod>(stateIndex, stateIndex,
868 stateIndex + 1));
869 return std::make_pair(false, 0);
870 case E_LOG:
871 stack.push_back(makeStep<EvalLog>(stateIndex, stateIndex));
872 return std::make_pair(false, 0);
873 case E_LOG10:
874 stack.push_back(
875 makeStep<EvalLog10>(stateIndex, stateIndex));
876 return std::make_pair(false, 0);
877 case E_MAX:
878 stack.push_back(makeStep<EvalMax>(stateIndex, stateIndex,
879 stateIndex + 1));
880 return std::make_pair(false, 0);
881 case E_MIN:
882 stack.push_back(makeStep<EvalMin>(stateIndex, stateIndex,
883 stateIndex + 1));
884 return std::make_pair(false, 0);
885 case E_RAD:
886 stack.push_back(makeStep<EvalRad>(stateIndex, stateIndex,
887 stateIndex + 1));
888 return std::make_pair(false, 0);
889 case E_SIN:
890 stack.push_back(makeStep<EvalSin>(stateIndex, stateIndex));
891 return std::make_pair(false, 0);
892 case E_SINH:
893 stack.push_back(makeStep<EvalSinh>(stateIndex, stateIndex));
894 return std::make_pair(false, 0);
895 case E_SQRT:
896 stack.push_back(makeStep<EvalSqrt>(stateIndex, stateIndex));
897 return std::make_pair(false, 0);
898 case E_TAN:
899 stack.push_back(makeStep<EvalTan>(stateIndex, stateIndex));
900 return std::make_pair(false, 0);
901 case E_TANH:
902 stack.push_back(makeStep<EvalTanh>(stateIndex, stateIndex));
903 return std::make_pair(false, 0);
904 case E_SIGN:
905 stack.push_back(makeStep<EvalSign>(stateIndex, stateIndex));
906 return std::make_pair(false, 0);
907 default:
908 ASSERTL0(false, "Evaluation of " + valueStr +
909 " is not implemented yet");
910 }
911 return std::make_pair(false, 0);
912 }
913 else if (parserID == AnalyticExpression::unaryID)
914 {
915 ASSERTL1(*valueStr.begin() == '-',
916 "Illegal factor - it can only be '-' and it was: " +
917 valueStr);
918 ASSERTL1(num_children == 1,
919 "Illegal number of children under factor node: " +
920 valueStr);
922 location->children.begin(), stack, variableMap, stateIndex);
923
924 // if precomputed value is valid, process it further.
925 if (true == v.first)
926 {
927 return std::make_pair(true, -v.second);
928 }
929 stack.push_back(makeStep<EvalNeg>(stateIndex, stateIndex));
930 return std::make_pair(false, 0);
931 }
932 else if (parserID == AnalyticExpression::operatorID)
933 {
934 ASSERTL1(
935 num_children == 2,
936 "Too few or too many arguments for mathematical operator: " +
937 valueStr);
939 location->children.begin() + 0, stack, variableMap, stateIndex);
940 PrecomputedValue right =
941 PrepareExecutionAsYouParse(location->children.begin() + 1,
942 stack, variableMap, stateIndex + 1);
943 m_state_size++;
944
945 // if both precomputed values are valid, process them further.
946 if ((left.first == true) && (right.first == true))
947 {
948 switch (*valueStr.begin())
949 {
950 case '+':
951 return std::make_pair(true, left.second + right.second);
952 case '-':
953 return std::make_pair(true, left.second - right.second);
954 case '*':
955 return std::make_pair(true, left.second * right.second);
956 case '/':
957 return std::make_pair(true, left.second / right.second);
958 case '%':
959 return std::make_pair(
960 true, std::fmod(left.second, right.second));
961 case '^':
962 return std::make_pair(
963 true, std::pow(left.second, right.second));
964 case '=':
965 return std::make_pair(true,
966 left.second == right.second);
967 case '<':
968 if (*(valueStr.end() - 1) == '=')
969 {
970 return std::make_pair(true,
971 left.second <= right.second);
972 }
973 else
974 {
975 return std::make_pair(true,
976 left.second < right.second);
977 }
978 case '>':
979 if (*(valueStr.end() - 1) == '=')
980 {
981 return std::make_pair(true,
982 left.second >= right.second);
983 }
984 else
985 {
986 return std::make_pair(true,
987 left.second > right.second);
988 }
989 default:
990 ASSERTL0(false,
991 "Invalid operator encountered: " + valueStr);
992 }
993 return std::make_pair(false, 0);
994 }
995
996 // either operator argument is not fully evaluated
997 // add pre-evaluated value to the contaner of constants
998 if (true == left.first)
999 {
1000 int const_index =
1001 AddConstant(std::string("SUB_EXPR_") +
1002 std::to_string(m_constant.size()),
1003 left.second);
1004 stack.push_back(makeStep<StoreConst>(stateIndex, const_index));
1005 }
1006 if (true == right.first)
1007 {
1008 int const_index =
1009 AddConstant(std::string("SUB_EXPR_") +
1010 std::to_string(m_constant.size()),
1011 right.second);
1012 stack.push_back(
1013 makeStep<StoreConst>(stateIndex + 1, const_index));
1014 }
1015
1016 switch (*valueStr.begin())
1017 {
1018 case '+':
1019 stack.push_back(makeStep<EvalSum>(stateIndex, stateIndex,
1020 stateIndex + 1));
1021 return std::make_pair(false, 0);
1022 case '-':
1023 stack.push_back(makeStep<EvalSub>(stateIndex, stateIndex,
1024 stateIndex + 1));
1025 return std::make_pair(false, 0);
1026 case '*':
1027 stack.push_back(makeStep<EvalMul>(stateIndex, stateIndex,
1028 stateIndex + 1));
1029 return std::make_pair(false, 0);
1030 case '/':
1031 stack.push_back(makeStep<EvalDiv>(stateIndex, stateIndex,
1032 stateIndex + 1));
1033 return std::make_pair(false, 0);
1034 case '%':
1035 stack.push_back(makeStep<EvalMod>(stateIndex, stateIndex,
1036 stateIndex + 1));
1037 return std::make_pair(false, 0);
1038 case '^':
1039 stack.push_back(makeStep<EvalPow>(stateIndex, stateIndex,
1040 stateIndex + 1));
1041 return std::make_pair(false, 0);
1042 case '=':
1043 stack.push_back(makeStep<EvalLogicalEqual>(
1044 stateIndex, stateIndex, stateIndex + 1));
1045 return std::make_pair(false, 0);
1046 case '<':
1047 if (*(valueStr.end() - 1) == '=')
1048 {
1049 stack.push_back(makeStep<EvalLogicalLeq>(
1050 stateIndex, stateIndex, stateIndex + 1));
1051 }
1052 else
1053 {
1054 stack.push_back(makeStep<EvalLogicalLess>(
1055 stateIndex, stateIndex, stateIndex + 1));
1056 }
1057 return std::make_pair(false, 0);
1058
1059 case '>':
1060 if (*(valueStr.end() - 1) == '=')
1061 {
1062 stack.push_back(makeStep<EvalLogicalGeq>(
1063 stateIndex, stateIndex, stateIndex + 1));
1064 }
1065 else
1066 {
1067 stack.push_back(makeStep<EvalLogicalGreater>(
1068 stateIndex, stateIndex, stateIndex + 1));
1069 }
1070 return std::make_pair(false, 0);
1071
1072 default:
1073 ASSERTL0(false,
1074 "Invalid operator encountered: " + valueStr);
1075 }
1076 return std::make_pair(false, 0);
1077 }
1078 else if (parserID == AnalyticExpression::operatorID)
1079 {
1080 ASSERTL1(
1081 false,
1082 "Too few or too many arguments for mathematical operator: " +
1083 valueStr);
1084 }
1085 ASSERTL0(false, "Illegal expression encountered: " + valueStr);
1086 return std::make_pair(false, 0);
1087 }
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:208

References AddConstant(), ASSERTL0, ASSERTL1, Nektar::LibUtilities::Interpreter::ExpressionEvaluator::AnalyticExpression::constantID, E_ABS, E_ACOS, E_ANG, E_ASIN, E_ATAN, E_ATAN2, E_AWGN, E_BESSEL, E_CEIL, E_COS, E_COSH, E_EXP, E_FABS, E_FLOOR, E_FMOD, E_LOG, E_LOG10, E_MAX, E_MIN, E_RAD, E_SIGN, E_SIN, E_SINH, E_SQRT, E_TAN, E_TANH, Nektar::LibUtilities::Interpreter::ExpressionEvaluator::AnalyticExpression::functionID, m_constant, m_constantMapNameToId, m_function, m_function2, m_functionMapNameToInstanceType, m_parameterMapNameToId, m_state_size, Nektar::LibUtilities::Interpreter::ExpressionEvaluator::AnalyticExpression::numberID, Nektar::LibUtilities::Interpreter::ExpressionEvaluator::AnalyticExpression::operatorID, Nektar::LibUtilities::Interpreter::ExpressionEvaluator::AnalyticExpression::parameterID, PrepareExecutionAsYouParse(), Nektar::LibUtilities::Interpreter::ExpressionEvaluator::AnalyticExpression::unaryID, and Nektar::LibUtilities::Interpreter::ExpressionEvaluator::AnalyticExpression::variableID.

Referenced by DefineFunction(), and PrepareExecutionAsYouParse().

◆ SetParameter()

void Nektar::LibUtilities::Interpreter::ExpressionEvaluator::SetParameter ( std::string const &  name,
NekDouble  value 
)
inline

Set parameter values.

This function behaves in the same way as SetParameters, but it only adds one parameter and it does not delete the others. If the parameter name existed previously, it will be overridden and replaced with the new value. If it did not exist previously, it will be added to the current parameters.

Parameters
nameName of the parameter to define.
valueThe parameter's value.

Definition at line 360 of file Interpreter/Interpreter.cpp.

361 {
362 ParameterMap::const_iterator it = m_parameterMapNameToId.find(name);
363 if (it == m_parameterMapNameToId.end())
364 {
366 m_parameter.push_back(value);
367 }
368 else
369 {
370 // If parameter is known, change its value.
371 m_parameter[it->second] = value;
372 }
373 }

References m_parameter, m_parameterMapNameToId, and CellMLToNektar.pycml::name.

Referenced by SetParameters().

◆ SetParameters()

void Nektar::LibUtilities::Interpreter::ExpressionEvaluator::SetParameters ( std::map< std::string, NekDouble > const &  params)
inline

Set parameter values.

Parameters are functionally similar to constants, but they are inserted into the function at the time that Evaluate is called, instead of when the function is parsed. This function can therefore be called at any time, and it will take effect in the next call to Evaluate. This function will delete all of the parameters, and replace all of them with only the ones in the map argument.

Definition at line 349 of file Interpreter/Interpreter.cpp.

350 {
351 for (auto const &it : params)
352 {
353 SetParameter(it.first, it.second);
354 }
355 }
void SetParameter(std::string const &name, NekDouble value)
Set parameter values.

References SetParameter().

◆ SetRandomSeed()

void Nektar::LibUtilities::Interpreter::ExpressionEvaluator::SetRandomSeed ( unsigned int  seed)
inline

Sets the random seed for the pseudorandom number generator.

This allows for e.g. different ranks to be given different seeds to ensure appropriate entropy in noise generation.

Definition at line 290 of file Interpreter/Interpreter.cpp.

291 {
292 m_generator.seed(seed);
293 }

References m_generator.

Member Data Documentation

◆ m_constant

std::vector<NekDouble> Nektar::LibUtilities::Interpreter::ExpressionEvaluator::m_constant
private

Definition at line 1288 of file Interpreter/Interpreter.cpp.

Referenced by AddConstant(), makeStep(), and PrepareExecutionAsYouParse().

◆ m_constantMapNameToId

ConstantMap Nektar::LibUtilities::Interpreter::ExpressionEvaluator::m_constantMapNameToId
private

Definition at line 1284 of file Interpreter/Interpreter.cpp.

Referenced by AddConstant(), and PrepareExecutionAsYouParse().

◆ m_constantsParser

bsp::symbols<NekDouble> Nektar::LibUtilities::Interpreter::ExpressionEvaluator::m_constantsParser

This is a parser for spirit that parses the CONSTANT values. The default constants are those that are in math.h without the M_ prefix and they are initialized in the AnalyticExpressionEvaluator constructor.

Definition at line 1097 of file Interpreter/Interpreter.cpp.

Referenced by AddConstant(), DefineFunction(), and GetConstant().

◆ m_executionStack

std::vector<ExecutionStack> Nektar::LibUtilities::Interpreter::ExpressionEvaluator::m_executionStack
private

◆ m_expressionVariableMap

VariableMap Nektar::LibUtilities::Interpreter::ExpressionEvaluator::m_expressionVariableMap
private

Definition at line 1285 of file Interpreter/Interpreter.cpp.

◆ m_function

std::map<int, OneArgFunc> Nektar::LibUtilities::Interpreter::ExpressionEvaluator::m_function
private

◆ m_function2

std::map<int, TwoArgFunc> Nektar::LibUtilities::Interpreter::ExpressionEvaluator::m_function2
private

◆ m_functionMapNameToInstanceType

FunctionNameMap Nektar::LibUtilities::Interpreter::ExpressionEvaluator::m_functionMapNameToInstanceType
private

◆ m_generator

std::mt19937 Nektar::LibUtilities::Interpreter::ExpressionEvaluator::m_generator
private

Definition at line 1306 of file Interpreter/Interpreter.cpp.

Referenced by makeStep(), and SetRandomSeed().

◆ m_parameter

std::vector<NekDouble> Nektar::LibUtilities::Interpreter::ExpressionEvaluator::m_parameter
private

Definition at line 1287 of file Interpreter/Interpreter.cpp.

Referenced by GetParameter(), makeStep(), and SetParameter().

◆ m_parameterMapNameToId

ParameterMap Nektar::LibUtilities::Interpreter::ExpressionEvaluator::m_parameterMapNameToId
private

The following data structures hold input data to be used on evaluation stage. There are three types of input data:

  • constants (never change their value)
  • parameters are allowed to change their values between evaluations (compared to constants)
  • variables always change their values at every evaluation call. First map looks like <parameter_name, parameter_id> while the second is <parameter_id, parameter_value>. The map is used at a preparation stage when the analytic expression is parsed. This associates an integer id with a parameter name in its string form. On evaluation stage the id and a std::vector constant lookup time make evaluation faster compared to permanent std::map<std::string, NekDouble> lookup.

Definition at line 1283 of file Interpreter/Interpreter.cpp.

Referenced by GetParameter(), PrepareExecutionAsYouParse(), and SetParameter().

◆ m_parsedMapExprToExecStackId

ExpressionMap Nektar::LibUtilities::Interpreter::ExpressionEvaluator::m_parsedMapExprToExecStackId
private

These vector and map store pre-processed evaluation sequences for the analytic expressions. Each ExecutionStack is an ordered container of steps of sequential execution process which evaluates an analytic expression.

Definition at line 1257 of file Interpreter/Interpreter.cpp.

Referenced by DefineFunction().

◆ m_stackVariableMap

std::vector<VariableMap> Nektar::LibUtilities::Interpreter::ExpressionEvaluator::m_stackVariableMap
private

Keeping map of variables individually per each analytic expression allows correctly handling expressions which depend on different number of variables.

Definition at line 1264 of file Interpreter/Interpreter.cpp.

Referenced by DefineFunction(), and EvaluateAtPoint().

◆ m_state

std::vector<NekDouble> Nektar::LibUtilities::Interpreter::ExpressionEvaluator::m_state
private

This vector stores the execution state (memory) used by the sequential execution process.

Definition at line 1293 of file Interpreter/Interpreter.cpp.

Referenced by Evaluate(), EvaluateAtPoint(), and makeStep().

◆ m_state_size

int Nektar::LibUtilities::Interpreter::ExpressionEvaluator::m_state_size
private

This counter is used by PrepareExecutionAsYouParse for finding the minimal state size necessary for evaluation of function parsed.

Definition at line 1300 of file Interpreter/Interpreter.cpp.

Referenced by DefineFunction(), ExpressionEvaluator(), and PrepareExecutionAsYouParse().

◆ m_state_sizes

std::vector<int> Nektar::LibUtilities::Interpreter::ExpressionEvaluator::m_state_sizes
private

Vector of state sizes per each.

Definition at line 1296 of file Interpreter/Interpreter.cpp.

Referenced by DefineFunction(), Evaluate(), and EvaluateAtPoint().

◆ m_timer

Timer Nektar::LibUtilities::Interpreter::ExpressionEvaluator::m_timer
private

Timer and sum of evaluation times.

Definition at line 1303 of file Interpreter/Interpreter.cpp.

Referenced by Evaluate(), and EvaluateAtPoint().

◆ m_total_eval_time

NekDouble Nektar::LibUtilities::Interpreter::ExpressionEvaluator::m_total_eval_time
private

Definition at line 1304 of file Interpreter/Interpreter.cpp.

Referenced by Evaluate(), EvaluateAtPoint(), and GetTime().

◆ m_variable

std::vector<NekDouble> Nektar::LibUtilities::Interpreter::ExpressionEvaluator::m_variable
private

Definition at line 1289 of file Interpreter/Interpreter.cpp.

Referenced by Evaluate(), EvaluateAtPoint(), and makeStep().