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 1327 of file Interpreter/Interpreter.cpp.

◆ ConstantMap

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

◆ cvr

Definition at line 1326 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 1328 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 1325 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 1338 of file Interpreter/Interpreter.cpp.

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

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:298
scalarT< T > log(scalarT< T > in)
Definition: scalar.hpp:303
scalarT< T > sqrt(scalarT< T > in)
Definition: scalar.hpp:294

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:447
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 1332 of file Interpreter/Interpreter.cpp.

1333 {
1334 return (new StepType(m_generator, m_state, m_constant, m_parameter,
1335 m_variable, dest, src_left, src_right));
1336 }

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

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

◆ m_constantMapNameToId

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

Definition at line 1287 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 1100 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 1288 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 1309 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 1290 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 1286 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 1260 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 1267 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 1296 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 1303 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 1299 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 1306 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 1307 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 1292 of file Interpreter/Interpreter.cpp.

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