Nektar++
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
Classes | Public Types | Public Member Functions | Private Types | Private Member Functions | Private Attributes | List of all members
Nektar::LibUtilities::AnalyticExpressionEvaluator Class Reference

This class defines evaluator of analytic (symbolic) mathematical expressions. Expressions are allowed to depend on a number of spatial-time variables and parameters. Pre-processing and evaluation stages are split. At evaluation stage one specifies values for each variable, resulting expression value is returned. Vectorized evaluator (evaluate expression at a set of points) is available. More...

#include <AnalyticExpressionEvaluator.hpp>

Collaboration diagram for Nektar::LibUtilities::AnalyticExpressionEvaluator:
Collaboration graph
[legend]

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  EvalLog
 
struct  EvalLog10
 
struct  EvalLogicalEqual
 
struct  EvalLogicalGeq
 
struct  EvalLogicalGreater
 
struct  EvalLogicalLeq
 
struct  EvalLogicalLess
 
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,
NekDouble
PrecomputedValue
 
typedef NekDouble(* OneArgFunc )(NekDouble)
 
typedef NekDouble(* TwoArgFunc )(NekDouble, NekDouble)
 
typedef
boost_spirit::tree_parse_info
< std::string::const_iterator,
boost_spirit::node_val_data_factory
< NekDouble > > 
ParsedTreeInfo
 
typedef
boost_spirit::tree_match
< std::string::const_iterator,
boost_spirit::node_val_data_factory
< NekDouble > >::tree_iterator 
ParsedTreeIterator
 
typedef std::vector< const
Array< OneD, const NekDouble > * > 
VariableArray
 
typedef boost::mt19937 RandomGeneratorType
 

Public Member Functions

 AnalyticExpressionEvaluator (void)
 Initializes the evaluator to a state where it is ready to accept input from the DefineFunction function. More...
 
 ~AnalyticExpressionEvaluator (void)
 Destroys the execution stack. More...
 
void SetRandomSeed (unsigned int seed=123u)
 
void AddConstants (std::map< std::string, NekDouble > const &constants)
 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 map argument 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 and output the constants it couldn't add in the string exception. More...
 
int AddConstant (std::string const &name, NekDouble value)
 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. More...
 
NekDouble GetConstant (std::string const &name)
 If a constant with the specified name exists, it returns the NekDouble value that the constant stores. If the constant doesn't exist, it throws an exception. More...
 
void SetParameters (std::map< std::string, NekDouble > const &params)
 Parameters are like constants, but they are inserted into the function at the time Evaluate is called instead of when the function is parsed. This function can 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. More...
 
void SetParameter (std::string const &name, NekDouble value)
 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 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. More...
 
NekDouble GetParameter (std::string const &name)
 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. More...
 
NekDouble GetTime () const
 Returns the total time spent in evaluation procedures, seconds. More...
 
int DefineFunction (const std::string &vlist, const std::string &function)
 This function allows one to define a function to evaluate. The first argument (vlist) is a list of variables (separated by spaces) that the second argument (function) depends on. For example, if function = "x + y", then vlist should most likely be "x y", unless you are defining x or y as parameters with SetParameters. parsed expression ID. You will need this expression id to call evaluation methods below. More...
 
NekDouble Evaluate (const int AnalyticExpression_id)
 Evaluation method for expressions depending on parameters only. More...
 
NekDouble Evaluate (const int AnalyticExpression_id, const NekDouble, const NekDouble, const NekDouble, const NekDouble)
 Evaluation method for expressions depending on 4 variables (+parameters). More...
 
NekDouble EvaluateAtPoint (const int AnalyticExpression_id, std::vector< NekDouble > point)
 Evaluation method for expressions depending on unspecified number of variables. This suitable for expressions depending on more than 4 variables or for the dynamic setting some variables as parameters (there is currently no interface method for removing a variable from parameter map though). More...
 
void Evaluate (const int expression_id, const Array< OneD, const NekDouble > &, const Array< OneD, const NekDouble > &, const Array< OneD, const NekDouble > &, const Array< OneD, const NekDouble > &, Array< OneD, NekDouble > &result)
 Vectorized evaluation method for expressions depending on 4 variables. More...
 
void Evaluate (const int expression_id, const std::vector< Array< OneD, const NekDouble > > points, Array< OneD, NekDouble > &result)
 Vectorized evaluation method for expressions depending on unspecified number of variables. More...
 

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_LOG, E_LOG10, 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 RandomGeneratorTypergt
 

Private Member Functions

PrecomputedValue PrepareExecutionAsYouParse (const ParsedTreeIterator &root, ExecutionStack &stack, VariableMap &varMap, int stateIndex)
 This method prepares the execution stack (an ordered sequence of operators that perform the evaluation) for the parsed evaluation tree. More...
 
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

boost_spirit::symbols< NekDoublem_constantsParser
 
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
 
RandomGeneratorType m_generator
 
FunctionNameMap m_functionMapNameToInstanceType
 
std::map< int, OneArgFuncm_function
 
std::map< int, TwoArgFuncm_function2
 

Detailed Description

This class defines evaluator of analytic (symbolic) mathematical expressions. Expressions are allowed to depend on a number of spatial-time variables and parameters. Pre-processing and evaluation stages are split. At evaluation stage one specifies values for each variable, resulting expression value is returned. Vectorized evaluator (evaluate expression at a set of points) is available.

Internally this class uses boost::spirit to parse analytic expressions and unrolls their recursive bracketing structure into a sequence of evaluation steps (aka execution stack) with resolved data dependencies. Once an expression is pre-processed, its execution stack is stored internally in order to be re-used.

Definition at line 114 of file AnalyticExpressionEvaluator.hpp.

Member Typedef Documentation

Definition at line 469 of file AnalyticExpressionEvaluator.hpp.

Definition at line 125 of file AnalyticExpressionEvaluator.hpp.

Definition at line 468 of file AnalyticExpressionEvaluator.hpp.

Definition at line 129 of file AnalyticExpressionEvaluator.hpp.

Definition at line 127 of file AnalyticExpressionEvaluator.hpp.

Definition at line 128 of file AnalyticExpressionEvaluator.hpp.

typedef NekDouble(* Nektar::LibUtilities::AnalyticExpressionEvaluator::OneArgFunc)(NekDouble)

Definition at line 131 of file AnalyticExpressionEvaluator.hpp.

Definition at line 126 of file AnalyticExpressionEvaluator.hpp.

typedef boost_spirit::tree_parse_info< std::string::const_iterator, boost_spirit::node_val_data_factory<NekDouble> > Nektar::LibUtilities::AnalyticExpressionEvaluator::ParsedTreeInfo

Definition at line 137 of file AnalyticExpressionEvaluator.hpp.

typedef boost_spirit::tree_match< std::string::const_iterator, boost_spirit::node_val_data_factory<NekDouble> >::tree_iterator Nektar::LibUtilities::AnalyticExpressionEvaluator::ParsedTreeIterator

Definition at line 141 of file AnalyticExpressionEvaluator.hpp.

Definition at line 130 of file AnalyticExpressionEvaluator.hpp.

Definition at line 145 of file AnalyticExpressionEvaluator.hpp.

Definition at line 470 of file AnalyticExpressionEvaluator.hpp.

typedef NekDouble(* Nektar::LibUtilities::AnalyticExpressionEvaluator::TwoArgFunc)(NekDouble, NekDouble)

Definition at line 132 of file AnalyticExpressionEvaluator.hpp.

Definition at line 143 of file AnalyticExpressionEvaluator.hpp.

Definition at line 119 of file AnalyticExpressionEvaluator.hpp.

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

Definition at line 467 of file AnalyticExpressionEvaluator.hpp.

Member Enumeration Documentation

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_LOG 
E_LOG10 
E_POW 
E_RAD 
E_SIN 
E_SINH 
E_SQRT 
E_TAN 
E_TANH 
E_SIGN 
E_AWGN 
E_BESSEL 

Definition at line 479 of file AnalyticExpressionEvaluator.hpp.

480  {
485  };

Constructor & Destructor Documentation

Nektar::LibUtilities::AnalyticExpressionEvaluator::AnalyticExpressionEvaluator ( void  )

Initializes the evaluator to a state where it is ready to accept input from the DefineFunction function.

Definition at line 220 of file AnalyticExpressionEvaluator.cpp.

References 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_LOG, E_LOG10, E_RAD, E_SIGN, E_SIN, E_SINH, E_SQRT, E_TAN, E_TANH, m_function, m_function2, m_functionMapNameToInstanceType, m_state_size, Nektar::LibUtilities::rad(), and Nektar::LibUtilities::sign().

220  :
221  m_timer(),
223  {
224  m_state_size = 1;
225 
226  AddConstant("MEANINGLESS", 0.0);
227  AddConstant("E", 2.71828182845904523536); // Natural logarithm
228  AddConstant("LOG2E", 1.4426950408889634074); // log_2 e
229  AddConstant("LOG10E", 0.43429448190325182765); // log_10 e
230  AddConstant("LN2", 0.69314718055994530942); // log_e 2
231  AddConstant("LN10", 2.30258509299404568402); // log_e 10
232  AddConstant("PI", 3.14159265358979323846); // pi
233  AddConstant("PI_2", 1.57079632679489661923); // pi/2
234  AddConstant("PI_4", 0.78539816339744830962); // pi/4
235  AddConstant("1_PI", 0.31830988618379067154); // 1/pi
236  AddConstant("2_PI", 0.63661977236758134308); // 2/pi
237  AddConstant("2_SQRTPI", 1.12837916709551257390); // 2/sqrt(pi)
238  AddConstant("SQRT2", 1.41421356237309504880); // sqrt(2)
239  AddConstant("SQRT1_2", 0.70710678118654752440); // 1/sqrt(2)
240  AddConstant("GAMMA", 0.57721566490153286060); // Euler
241  AddConstant("DEG", 57.2957795130823208768); // deg/radian
242  AddConstant("PHI", 1.61803398874989484820); // golden ratio
243 
267 
268  m_function[ E_ABS ] = std::abs;
269  m_function[ E_ASIN ] = asin;
270  m_function[ E_ACOS ] = acos;
271  m_function[ E_ATAN ] = atan;
272  m_function[ E_CEIL ] = ceil;
273  m_function[ E_COS ] = cos;
274  m_function[ E_COSH ] = cosh;
275  m_function[ E_EXP ] = exp;
276  m_function[ E_FABS ] = fabs;
277  m_function[ E_FLOOR] = floor;
278  m_function[ E_LOG ] = log;
279  m_function[ E_LOG10] = log10;
280  m_function[ E_SIN ] = sin;
281  m_function[ E_SINH ] = sinh;
282  m_function[ E_SQRT ] = sqrt;
283  m_function[ E_TAN ] = tan;
284  m_function[ E_TANH ] = tanh;
285  m_function[ E_SIGN ] = sign;
286  m_function2[E_ATAN2] = atan2;
287  m_function2[E_ANG] = ang;
288  m_function2[E_RAD] = rad;
289  m_function2[E_BESSEL] = boost::math::cyl_bessel_j;
290 
291  // there is no entry to m_function that correspond to awgn function.
292  // this is made in purpose. This function need not be pre-evaluated once!
293  }
static NekDouble ang(NekDouble x, NekDouble y)
int AddConstant(std::string const &name, NekDouble value)
This function behaves in the same way as AddConstants, but it only adds one constant at a time...
NekDouble sign(NekDouble arg)
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)
Nektar::LibUtilities::AnalyticExpressionEvaluator::~AnalyticExpressionEvaluator ( void  )

Destroys the execution stack.

Definition at line 296 of file AnalyticExpressionEvaluator.cpp.

References Nektar::iterator, and m_executionStack.

297  {
298  for (std::vector<ExecutionStack>::iterator it_es = m_executionStack.begin(); it_es != m_executionStack.end(); ++it_es)
299  {
300  for (std::vector<EvaluationStep*>::iterator it = (*it_es).begin(); it != (*it_es).end(); ++it)
301  {
302  delete *it;
303  }
304  (*it_es).clear();
305  }
306  m_executionStack.clear();
307  }
StandardMatrixTag boost::call_traits< LhsDataType >::const_reference rhs typedef NekMatrix< LhsDataType, StandardMatrixTag >::iterator iterator

Member Function Documentation

int Nektar::LibUtilities::AnalyticExpressionEvaluator::AddConstant ( std::string const &  name,
NekDouble  value 
)

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.

Definition at line 324 of file AnalyticExpressionEvaluator.cpp.

References m_constant, m_constantMapNameToId, and m_constantsParser.

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

325  {
326  ConstantMap::const_iterator it = m_constantMapNameToId.find(name);
327  if (it == m_constantMapNameToId.end())
328  {
329  // we are trying to avoid duplicating entries in m_constantParser and m_constants
330  m_constantsParser.add(name.c_str(), value);
331  int index = m_constant.size();
332  m_constantMapNameToId[name] = index;
333  m_constant.push_back(value);
334  return index;
335  }
336  else
337  {
338  if(m_constant[it->second] != value)
339  {
340  std::string errormsg("Attempt to add numerically different constants under the same name: ");
341  errormsg += name;
342  std::cout << errormsg << std::endl;
343  }
344  //ASSERTL1(m_constant[it->second] == value, "Attempt to add numerically different constants under the same name: " + name);
345  }
346  return it->second;
347  }
void Nektar::LibUtilities::AnalyticExpressionEvaluator::AddConstants ( std::map< std::string, NekDouble > const &  constants)

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 map argument 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 and output the constants it couldn't add in the string exception.

Definition at line 316 of file AnalyticExpressionEvaluator.cpp.

References AddConstant().

Referenced by Nektar::LibUtilities::Equation::SetConstants().

317  {
318  for (std::map<std::string, NekDouble>::const_iterator it = constants.begin(); it != constants.end(); ++it)
319  {
320  AddConstant(it->first, it->second);
321  }
322  }
int AddConstant(std::string const &name, NekDouble value)
This function behaves in the same way as AddConstants, but it only adds one constant at a time...
int Nektar::LibUtilities::AnalyticExpressionEvaluator::DefineFunction ( const std::string &  vlist,
const std::string &  function 
)

This function allows one to define a function to evaluate. The first argument (vlist) is a list of variables (separated by spaces) that the second argument (function) depends on. For example, if function = "x + y", then vlist should most likely be "x y", unless you are defining x or y as parameters with SetParameters. parsed expression ID. You will need this expression id to call evaluation methods below.

Definition at line 402 of file AnalyticExpressionEvaluator.cpp.

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

Referenced by Nektar::NekMeshUtils::CurveMesh::CurveMesh(), Nektar::LibUtilities::Equation::Equation(), Nektar::NekMeshUtils::Generator2D::Process(), Nektar::Utilities::ProcessScalar::Process(), Nektar::SpatialDomains::MeshGraph::ReadCurves(), Nektar::SpatialDomains::MeshGraph::ReadGeometry(), and Nektar::Utilities::ProcessCurve::v_GenerateEdgeNodes().

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

Evaluation method for expressions depending on parameters only.

Definition at line 494 of file AnalyticExpressionEvaluator.cpp.

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

Referenced by Nektar::LibUtilities::Equation::Evaluate(), Evaluate(), Nektar::Utilities::ProcessCurve::EvaluateCoordinate(), Nektar::NekMeshUtils::Generator2D::MakeBL(), Nektar::SpatialDomains::MeshGraph::ReadCurves(), and Nektar::SpatialDomains::MeshGraph::ReadGeometry().

495  {
496  m_timer.Start();
497 
498  ASSERTL1(m_executionStack.size() > expression_id, "unknown analytic expression, it must first be defined with DefineFunction(...)");
499 
500  ExecutionStack &stack = m_executionStack[expression_id];
501 
502  m_state.resize(m_state_sizes[expression_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.
void Stop()
Definition: Timer.cpp:62
std::vector< int > m_state_sizes
Vector of state sizes per each.
void Start()
Definition: Timer.cpp:51
NekDouble TimePerTest(unsigned int n)
Returns amount of seconds per iteration in a test with n iterations.
Definition: Timer.cpp:108
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode...
Definition: ErrorUtil.hpp:228
NekDouble Nektar::LibUtilities::AnalyticExpressionEvaluator::Evaluate ( const int  AnalyticExpression_id,
const NekDouble  x,
const NekDouble  y,
const NekDouble  z,
const NekDouble  t 
)

Evaluation method for expressions depending on 4 variables (+parameters).

Definition at line 514 of file AnalyticExpressionEvaluator.cpp.

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

520  {
521  m_timer.Start();
522 
523  ASSERTL1(m_executionStack.size() > expression_id, "unknown analytic expression, it must first be defined with DefineFunction(...)");
524 
525  ExecutionStack &stack = m_executionStack[expression_id];
526 
527  // initialise internal vector of variable values
528  m_state.resize(m_state_sizes[expression_id]);
529 
530  if (m_variable.size() < 4)
531  {
532  m_variable.resize(4);
533  }
534 
535  // no flexibility, no change of variable ordering in m_variable
536  // container depending on their names ordering in the input vlist
537  // argument of DefineFunction. Ordering convention (x,y,z,t) is assumed.
538  m_variable[0] = x;
539  m_variable[1] = y;
540  m_variable[2] = z;
541  m_variable[3] = t;
542 
543  // main execution cycle is hidden here
544  for (int i = 0; i < stack.size(); i++)
545  {
546  (*stack[i]).run_once();
547  }
548 
549  m_timer.Stop();
551 
552  return m_state[0];
553  }
std::vector< NekDouble > m_state
This vector stores the execution state (memory) used by the sequential execution process.
void Stop()
Definition: Timer.cpp:62
std::vector< int > m_state_sizes
Vector of state sizes per each.
void Start()
Definition: Timer.cpp:51
NekDouble TimePerTest(unsigned int n)
Returns amount of seconds per iteration in a test with n iterations.
Definition: Timer.cpp:108
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode...
Definition: ErrorUtil.hpp:228
void Nektar::LibUtilities::AnalyticExpressionEvaluator::Evaluate ( const int  expression_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 
)

Vectorized evaluation method for expressions depending on 4 variables.

Definition at line 588 of file AnalyticExpressionEvaluator.cpp.

References Evaluate(), m_timer, m_total_eval_time, Nektar::Timer::Start(), Nektar::Timer::Stop(), and Nektar::Timer::TimePerTest().

595  {
596  m_timer.Start();
597 
598  std::vector<Array<OneD, const NekDouble> >points;
599 
600  points.push_back(x);
601  points.push_back(y);
602  points.push_back(z);
603  points.push_back(t);
604 
605  Evaluate(expression_id,points,result);
606 
607  m_timer.Stop();
609  }
NekDouble Evaluate(const int AnalyticExpression_id)
Evaluation method for expressions depending on parameters only.
void Stop()
Definition: Timer.cpp:62
void Start()
Definition: Timer.cpp:51
NekDouble TimePerTest(unsigned int n)
Returns amount of seconds per iteration in a test with n iterations.
Definition: Timer.cpp:108
void Nektar::LibUtilities::AnalyticExpressionEvaluator::Evaluate ( const int  expression_id,
const std::vector< Array< OneD, const NekDouble > >  points,
Array< OneD, NekDouble > &  result 
)

Vectorized evaluation method for expressions depending on unspecified number of variables.

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 AnalyticExpressionEvaluator.cpp.

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

616  {
617  m_timer.Start();
618 
619  const int num_points = points[0].num_elements();
620  ASSERTL1(m_executionStack.size() > expression_id,
621  "unknown analytic expression, it must first be defined "
622  "with DefineFunction(...)");
623  ASSERTL1(result.num_elements() >= num_points,
624  "destination array must have enough capacity to store "
625  "expression values at each given point");
626 
627  ExecutionStack &stack = m_executionStack[expression_id];
628 
629  /// If number of points tends to 10^6, one may end up
630  /// with up to ~0.5Gb data allocated for m_state only.
631  /// Lets split the work into cache-sized chunks.
632  /// Ahtung, magic constant!
633  const int max_chunk_size = 1024;
634  const int nvals = points.size();
635  const int chunk_size = (std::min)(max_chunk_size, num_points);
636 
637  if (m_state.size() < chunk_size * m_state_sizes[expression_id])
638  {
639  m_state.resize(m_state_sizes[expression_id] * chunk_size, 0.0);
640  }
641  if (m_variable.size() < nvals * chunk_size)
642  {
643  m_variable.resize( nvals * chunk_size, 0.0);
644  }
645  if (result.num_elements() < num_points)
646  {
647  result = Array<OneD, NekDouble>(num_points, 0.0);
648  }
649 
650  int offset = 0;
651  int work_left = num_points;
652  while(work_left > 0)
653  {
654  const int this_chunk_size = (std::min)(work_left, 1024);
655  for (int i = 0; i < this_chunk_size; i++)
656  {
657  for(int j = 0; j < nvals; ++j)
658  {
659  m_variable[i+this_chunk_size*j] = points[j][offset + i];
660  }
661  }
662  for (int i = 0; i < stack.size(); i++)
663  {
664  (*stack[i]).run_many(this_chunk_size);
665  }
666  for (int i = 0; i < this_chunk_size; i++)
667  {
668  result[offset + i] = m_state[i];
669  }
670  work_left -= this_chunk_size;
671  offset += this_chunk_size;
672  }
673  m_timer.Stop();
675  }
std::vector< NekDouble > m_state
This vector stores the execution state (memory) used by the sequential execution process.
void Stop()
Definition: Timer.cpp:62
std::vector< int > m_state_sizes
Vector of state sizes per each.
void Start()
Definition: Timer.cpp:51
NekDouble TimePerTest(unsigned int n)
Returns amount of seconds per iteration in a test with n iterations.
Definition: Timer.cpp:108
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode...
Definition: ErrorUtil.hpp:228
NekDouble Nektar::LibUtilities::AnalyticExpressionEvaluator::EvaluateAtPoint ( const int  AnalyticExpression_id,
std::vector< NekDouble point 
)

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

Definition at line 555 of file AnalyticExpressionEvaluator.cpp.

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

556  {
557  m_timer.Start();
558 
559  ASSERTL1(m_executionStack.size() > expression_id, "unknown analytic expression, it must first be defined with DefineFunction(...)");
560 
561  ExecutionStack& stack = m_executionStack[expression_id];
562  VariableMap& variableMap = m_stackVariableMap[expression_id];
563 
564  ASSERTL1(point.size() == variableMap.size(), "The number of variables used to define this expression should match the point dimensionality.");
565 
566  // initialise internal vector of variable values
567  m_state.resize(m_state_sizes[expression_id]);
568  m_variable.resize(point.size());
569  VariableMap::const_iterator it;
570  for (it = variableMap.begin(); it != variableMap.end(); ++it)
571  {
572  m_variable[it->second] = point[it->second];
573  }
574  // main execution cycle is hidden here
575  for (int i = 0; i < stack.size(); i++)
576  {
577  (*stack[i]).run_once();
578  }
579 
580  m_timer.Stop();
582 
583  return m_state[0];
584  }
std::vector< VariableMap > m_stackVariableMap
Keeping map of variables individually per each analytic expression allows correctly handling expressi...
std::vector< NekDouble > m_state
This vector stores the execution state (memory) used by the sequential execution process.
void Stop()
Definition: Timer.cpp:62
std::vector< int > m_state_sizes
Vector of state sizes per each.
void Start()
Definition: Timer.cpp:51
NekDouble TimePerTest(unsigned int n)
Returns amount of seconds per iteration in a test with n iterations.
Definition: Timer.cpp:108
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode...
Definition: ErrorUtil.hpp:228
NekDouble Nektar::LibUtilities::AnalyticExpressionEvaluator::GetConstant ( std::string const &  name)

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

Definition at line 349 of file AnalyticExpressionEvaluator.cpp.

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

350  {
351  NekDouble* value = find(m_constantsParser, name.c_str());
352 
353  ASSERTL1(value != NULL, "Constant variable not found: " + name);
354 
355  return *value;
356  }
double NekDouble
InputIterator find(InputIterator first, InputIterator last, InputIterator startingpoint, const EqualityComparable &value)
Definition: StdRegions.hpp:316
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode...
Definition: ErrorUtil.hpp:228
NekDouble Nektar::LibUtilities::AnalyticExpressionEvaluator::GetParameter ( std::string const &  name)

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.

Definition at line 382 of file AnalyticExpressionEvaluator.cpp.

References ASSERTL1, m_parameter, and m_parameterMapNameToId.

383  {
384  ParameterMap::const_iterator it = m_parameterMapNameToId.find(name);
385 
386  ASSERTL1(it != m_parameterMapNameToId.end(), "Parameter not found: " + name);
387 
388  return m_parameter[ it->second ];
389  }
ParameterMap m_parameterMapNameToId
The following data structures hold input data to be used on evaluation stage. There are three types o...
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode...
Definition: ErrorUtil.hpp:228
NekDouble Nektar::LibUtilities::AnalyticExpressionEvaluator::GetTime ( ) const

Returns the total time spent in evaluation procedures, seconds.

Definition at line 392 of file AnalyticExpressionEvaluator.cpp.

References m_total_eval_time.

Referenced by Nektar::LibUtilities::Equation::GetTime().

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

Factory method which makes code little less messy.

Definition at line 474 of file AnalyticExpressionEvaluator.hpp.

475  {
476  return ( new StepType ( m_generator,m_state,m_constant,m_parameter,m_variable,dest,src_left,src_right ) );
477  }
std::vector< NekDouble > m_state
This vector stores the execution state (memory) used by the sequential execution process.
#define dest(otri, vertexptr)
AnalyticExpressionEvaluator::PrecomputedValue Nektar::LibUtilities::AnalyticExpressionEvaluator::PrepareExecutionAsYouParse ( const ParsedTreeIterator root,
ExecutionStack stack,
VariableMap varMap,
int  stateIndex 
)
private

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 binary tree representing the recursive evaluation into an ordered sequence of commands. That ordered sequence of commands is equivalent to 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.

root - iterator generated by boost::spirit; stack - initially empty sequential container of evaluation steps; varMap - maps variable names to their ids; stateIndex - an index in state[] array where an evaluation step corresponding to the current tree node is allowed to write. an std::pair<bool, NekDouble> which encodes fully pre-evaluated NekDouble value as pair <true, value> if all sub-tree down the current node evaluates to constant, or flags the opposite via pair <false,0>.

Definition at line 678 of file AnalyticExpressionEvaluator.cpp.

References AddConstant(), ASSERTL0, ASSERTL1, Nektar::LibUtilities::AnalyticExpressionEvaluator::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_LOG, E_LOG10, E_RAD, E_SIGN, E_SIN, E_SINH, E_SQRT, E_TAN, E_TANH, Nektar::LibUtilities::AnalyticExpressionEvaluator::AnalyticExpression::factorID, Nektar::LibUtilities::AnalyticExpressionEvaluator::AnalyticExpression::functionID, m_constant, m_constantMapNameToId, m_function, m_function2, m_functionMapNameToInstanceType, m_parameterMapNameToId, m_state_size, Nektar::LibUtilities::AnalyticExpressionEvaluator::AnalyticExpression::numberID, Nektar::LibUtilities::AnalyticExpressionEvaluator::AnalyticExpression::operatorID, Nektar::LibUtilities::AnalyticExpressionEvaluator::AnalyticExpression::parameterID, and Nektar::LibUtilities::AnalyticExpressionEvaluator::AnalyticExpression::variableID.

Referenced by DefineFunction().

683  {
684  std::string valueStr(location->value.begin(), location->value.end());
685  boost::algorithm::trim(valueStr);
686 
687  const parser_id parserID = location->value.id();
688 #if defined(NEKTAR_DEBUG) || defined(NEKTAR_FULLDEBUG)
689  const int num_children = location->children.size();
690 #endif
691 
692  if (parserID == AnalyticExpression::constantID)
693  {
694  ASSERTL1(num_children == 0, "Illegal children under constant node: " + valueStr);
695 
696  ConstantMap::const_iterator it = m_constantMapNameToId.find(valueStr);
697  ASSERTL1(it != m_constantMapNameToId.end(), "Cannot find the value for the specified constant: " + valueStr);
698 
699  return std::make_pair(true, m_constant[it->second]);
700  }
701  else if (parserID == AnalyticExpression::numberID)
702  {
703  ASSERTL1(num_children == 0, "Illegal children under number node: " + valueStr);
704  return std::make_pair(true, boost::lexical_cast<NekDouble>(valueStr.c_str()) );
705  }
706  else if (parserID == AnalyticExpression::variableID)
707  {
708  ASSERTL1(num_children == 0, "Illegal children under variable node: " + valueStr);
709 
710  VariableMap::const_iterator it = variableMap.find(valueStr);
711  ASSERTL1(it != variableMap.end(), "Unknown variable parsed: " + valueStr);
712 
713  // Variables are not defined at the time of this parse.
714  stack.push_back ( makeStep<StoreVar>( stateIndex, it->second ) );
715  return std::make_pair(false, 0);
716  }
717  else if (parserID == AnalyticExpression::parameterID)
718  {
719  ASSERTL1(num_children == 0, "Illegal children under parameter node: " + valueStr);
720 
721  ParameterMap::const_iterator it = m_parameterMapNameToId.find(valueStr);
722  ASSERTL1(it != m_parameterMapNameToId.end(), "Unknown parameter parsed: " + valueStr);
723 
724  // Parameters may change in between of evalutions.
725  stack.push_back ( makeStep<StorePrm>( stateIndex, it->second ) );
726  return std::make_pair(false, 0);
727  }
728  else if (parserID == AnalyticExpression::functionID)
729  {
730  FunctionNameMap::const_iterator it = m_functionMapNameToInstanceType.find(valueStr);
731  ASSERTL1(it != m_functionMapNameToInstanceType.end(), "Invalid function specified: " + valueStr);
732  ASSERTL1(num_children == 1 || num_children == 2, "Function " + valueStr + " would like to have too few or too many arguments. This is not implemented yet");
733 
734  if (location->children.size() == 1)
735  {
736  PrecomputedValue v = PrepareExecutionAsYouParse(location->children.begin(), stack, variableMap, stateIndex);
737 
738  // additive white gaussian noise function
739  if (it->second == E_AWGN)
740  {
741  int const_index = AddConstant(std::string("SUB_EXPR_") + boost::lexical_cast<std::string>(m_constant.size()), v.second);
742  stack.push_back ( makeStep<StoreConst>( stateIndex, const_index ) );
743  stack.push_back ( makeStep<EvalAWGN>( stateIndex, stateIndex ) );
744  return std::make_pair(false,0);
745  }
746 
747  if (true == v.first)
748  {
749  return std::make_pair( true, m_function[it->second](v.second) );
750  }
751  }
752  else
753  {
754  PrecomputedValue v1 = PrepareExecutionAsYouParse(location->children.begin()+0, stack, variableMap, stateIndex);
755  PrecomputedValue v2 = PrepareExecutionAsYouParse(location->children.begin()+1, stack, variableMap, stateIndex+1);
756  m_state_size++;
757 
758  if (true == v1.first && true == v2.first)
759  {
760  return std::make_pair( true, m_function2[it->second](v1.second, v2.second) );
761  }
762  }
763 
764  // if somewhere down the parse tree there is a variable or parameter, set up an
765  // evaluation sequence.
766  switch (it->second)
767  {
768  case E_ABS:
769  stack.push_back ( makeStep<EvalAbs>( stateIndex, stateIndex) );
770  return std::make_pair(false,0);
771  case E_ASIN:
772  stack.push_back ( makeStep<EvalAsin>( stateIndex, stateIndex) );
773  return std::make_pair(false,0);
774  case E_ACOS:
775  stack.push_back ( makeStep<EvalAcos>( stateIndex, stateIndex ) );
776  return std::make_pair(false,0);
777  case E_ATAN:
778  stack.push_back ( makeStep<EvalAtan>( stateIndex, stateIndex ) );
779  return std::make_pair(false,0);
780  case E_ATAN2:
781  stack.push_back ( makeStep<EvalAtan2>( stateIndex, stateIndex, stateIndex+1 ) );
782  return std::make_pair(false,0);
783  case E_ANG:
784  stack.push_back ( makeStep<EvalAng>( stateIndex, stateIndex, stateIndex+1 ) );
785  return std::make_pair(false,0);
786  case E_BESSEL:
787  stack.push_back ( makeStep<EvalBessel>( stateIndex, stateIndex, stateIndex+1 ) );
788  return std::make_pair(false,0);
789  case E_CEIL:
790  stack.push_back ( makeStep<EvalCeil>( stateIndex, stateIndex ) );
791  return std::make_pair(false,0);
792  case E_COS:
793  stack.push_back ( makeStep<EvalCos>( stateIndex, stateIndex ) );
794  return std::make_pair(false,0);
795  case E_COSH:
796  stack.push_back ( makeStep<EvalCosh>( stateIndex, stateIndex ) );
797  return std::make_pair(false,0);
798  case E_EXP:
799  stack.push_back ( makeStep<EvalExp>( stateIndex, stateIndex ) );
800  return std::make_pair(false,0);
801  case E_FABS:
802  stack.push_back ( makeStep<EvalFabs>( stateIndex, stateIndex ) );
803  return std::make_pair(false,0);
804  case E_FLOOR:
805  stack.push_back ( makeStep<EvalFloor>( stateIndex, stateIndex ) );
806  return std::make_pair(false,0);
807  case E_LOG:
808  stack.push_back ( makeStep<EvalLog>( stateIndex, stateIndex ) );
809  return std::make_pair(false,0);
810  case E_LOG10:
811  stack.push_back ( makeStep<EvalLog10>( stateIndex, stateIndex ) );
812  return std::make_pair(false,0);
813  case E_RAD:
814  stack.push_back ( makeStep<EvalRad>( stateIndex, stateIndex, stateIndex+1 ) );
815  return std::make_pair(false,0);
816  case E_SIN:
817  stack.push_back ( makeStep<EvalSin>( stateIndex, stateIndex ) );
818  return std::make_pair(false,0);
819  case E_SINH:
820  stack.push_back ( makeStep<EvalSinh>( stateIndex, stateIndex ) );
821  return std::make_pair(false,0);
822  case E_SQRT:
823  stack.push_back ( makeStep<EvalSqrt>( stateIndex, stateIndex ) );
824  return std::make_pair(false,0);
825  case E_TAN:
826  stack.push_back ( makeStep<EvalTan>( stateIndex, stateIndex ) );
827  return std::make_pair(false,0);
828  case E_TANH:
829  stack.push_back ( makeStep<EvalTanh>( stateIndex, stateIndex ) );
830  return std::make_pair(false,0);
831  case E_SIGN:
832  stack.push_back ( makeStep<EvalSign>( stateIndex, stateIndex ) );
833  return std::make_pair(false,0);
834  default:
835  ASSERTL0(false, "Evaluation of " + valueStr + " is not implemented yet");
836  }
837  return std::make_pair(false,0);
838  }
839  else if (parserID == AnalyticExpression::factorID)
840  {
841  ASSERTL1(*valueStr.begin() == '-', "Illegal factor - it can only be '-' and it was: " + valueStr);
842  ASSERTL1(num_children == 1, "Illegal number of children under factor node: " + valueStr);
843 
844  PrecomputedValue v = PrepareExecutionAsYouParse(location->children.begin(), stack, variableMap, stateIndex);
845 
846  // if precomputed value is valid, process it further.
847  if (true == v.first)
848  {
849  return std::make_pair( true, - v.second );
850  }
851  stack.push_back (makeStep<EvalNeg>( stateIndex, stateIndex) );
852  return std::make_pair(false,0);
853  }
854  else if (parserID == AnalyticExpression::operatorID)
855  {
856  ASSERTL1(num_children == 2, "Too few or too many arguments for mathematical operator: " + valueStr);
857  PrecomputedValue left = PrepareExecutionAsYouParse(location->children.begin()+0, stack, variableMap, stateIndex);
858  PrecomputedValue right = PrepareExecutionAsYouParse(location->children.begin()+1, stack, variableMap, stateIndex+1);
859  m_state_size++;
860 
861  // if both precomputed values are valid, process them further.
862  if ((true == left.first) && (true == right.first))
863  {
864  switch(*valueStr.begin())
865  {
866  case '+':
867  return std::make_pair( true, left.second + right.second );
868  case '-':
869  return std::make_pair( true, left.second - right.second );
870  case '*':
871  return std::make_pair( true, left.second * right.second );
872  case '/':
873  return std::make_pair( true, left.second / right.second );
874  case '^':
875  return std::make_pair( true, std::pow(left.second, right.second) );
876  case '=':
877  return std::make_pair( true, left.second == right.second );
878  case '<':
879  if (*(valueStr.end()-1) == '=')
880  {
881  return std::make_pair( true, left.second <= right.second );
882  }
883  else
884  {
885  return std::make_pair( true, left.second < right.second );
886  }
887  return std::make_pair(false,0);
888  case '>':
889  if (*(valueStr.end()-1) == '=')
890  {
891  return std::make_pair( true, left.second >= right.second );
892  }
893  else
894  {
895  return std::make_pair( true, left.second > right.second );
896  }
897  return std::make_pair(false,0);
898  default:
899  ASSERTL0(false, "Invalid operator encountered: " + valueStr);
900  }
901  return std::make_pair(false,0);
902  }
903 
904  // either operator argument is not fully evaluated
905  // add pre-evaluated value to the contaner of constants
906  if (true == left.first)
907  {
908  int const_index = AddConstant(std::string("SUB_EXPR_") + boost::lexical_cast<std::string>(m_constant.size()), left.second);
909  stack.push_back ( makeStep<StoreConst>( stateIndex, const_index ) );
910  }
911  if (true == right.first)
912  {
913  int const_index = AddConstant(std::string("SUB_EXPR_") + boost::lexical_cast<std::string>(m_constant.size()), right.second);
914  stack.push_back ( makeStep<StoreConst>( stateIndex+1, const_index ) );
915  }
916 
917 
918  switch(*valueStr.begin())
919  {
920  case '+':
921  stack.push_back (makeStep<EvalSum>( stateIndex, stateIndex, stateIndex+1 ) );
922  return std::make_pair(false,0);
923  case '-':
924  stack.push_back (makeStep<EvalSub> (stateIndex, stateIndex, stateIndex+1 ) );
925  return std::make_pair(false,0);
926  case '*':
927  stack.push_back (makeStep<EvalMul>( stateIndex, stateIndex, stateIndex+1 ) );
928  return std::make_pair(false,0);
929  case '/':
930  stack.push_back (makeStep<EvalDiv>( stateIndex, stateIndex, stateIndex+1 ) );
931  return std::make_pair(false,0);
932  case '^':
933  stack.push_back (makeStep<EvalPow>( stateIndex, stateIndex, stateIndex+1 ) );
934  return std::make_pair(false,0);
935  case '=':
936  stack.push_back (makeStep<EvalLogicalEqual>( stateIndex, stateIndex, stateIndex+1 ) );
937  return std::make_pair(false,0);
938  case '<':
939  if (*(valueStr.end()-1) == '=')
940  {
941  stack.push_back (makeStep<EvalLogicalLeq>( stateIndex, stateIndex, stateIndex+1 ) );
942  }
943  else
944  {
945  stack.push_back (makeStep<EvalLogicalLess>( stateIndex, stateIndex, stateIndex+1 ) );
946  }
947  return std::make_pair(false,0);
948 
949  case '>':
950  if (*(valueStr.end()-1) == '=')
951  {
952  stack.push_back (makeStep<EvalLogicalGeq>( stateIndex, stateIndex, stateIndex+1 ) );
953  }
954  else
955  {
956  stack.push_back (makeStep<EvalLogicalGreater>( stateIndex, stateIndex, stateIndex+1 ) );
957  }
958  return std::make_pair(false,0);
959 
960  default:
961  ASSERTL0(false, "Invalid operator encountered: " + valueStr);
962  }
963  return std::make_pair(false,0);
964  }
965  ASSERTL0(false, "Illegal expression encountered: " + valueStr);
966  return std::make_pair(false,0);
967  }
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:198
int AddConstant(std::string const &name, NekDouble value)
This function behaves in the same way as AddConstants, but it only adds one constant at a time...
PrecomputedValue PrepareExecutionAsYouParse(const ParsedTreeIterator &root, ExecutionStack &stack, VariableMap &varMap, int stateIndex)
This method prepares the execution stack (an ordered sequence of operators that perform the evaluatio...
int m_state_size
This counter is used by PrepareExecutionAsYouParse for finding the minimal state size necessary for e...
ParameterMap m_parameterMapNameToId
The following data structures hold input data to be used on evaluation stage. There are three types o...
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode...
Definition: ErrorUtil.hpp:228
void Nektar::LibUtilities::AnalyticExpressionEvaluator::SetParameter ( std::string const &  name,
NekDouble  value 
)

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 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.

Definition at line 366 of file AnalyticExpressionEvaluator.cpp.

References m_parameter, and m_parameterMapNameToId.

Referenced by Nektar::LibUtilities::Equation::SetParameter(), and SetParameters().

367  {
368  ParameterMap::const_iterator it = m_parameterMapNameToId.find(name);
369  if (it == m_parameterMapNameToId.end())
370  {
371  m_parameterMapNameToId[name] = m_parameter.size();
372  m_parameter.push_back(value);
373  }
374  else
375  {
376  // if parameter is known, change its value
377  m_parameter[ it->second ] = value;
378  }
379  }
ParameterMap m_parameterMapNameToId
The following data structures hold input data to be used on evaluation stage. There are three types o...
void Nektar::LibUtilities::AnalyticExpressionEvaluator::SetParameters ( std::map< std::string, NekDouble > const &  params)

Parameters are like constants, but they are inserted into the function at the time Evaluate is called instead of when the function is parsed. This function can 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 358 of file AnalyticExpressionEvaluator.cpp.

References SetParameter().

359  {
360  for (std::map<std::string, NekDouble>::const_iterator it = params.begin(); it != params.end(); it++)
361  {
362  SetParameter(it->first, it->second);
363  }
364  }
void SetParameter(std::string const &name, NekDouble value)
This function behaves in the same way as SetParameters, but it only adds one parameter and it does no...
void Nektar::LibUtilities::AnalyticExpressionEvaluator::SetRandomSeed ( unsigned int  seed = 123u)

Definition at line 310 of file AnalyticExpressionEvaluator.cpp.

References m_generator.

311  {
312  m_generator.seed(seed);
313  }

Member Data Documentation

std::vector<NekDouble> Nektar::LibUtilities::AnalyticExpressionEvaluator::m_constant
private

Definition at line 426 of file AnalyticExpressionEvaluator.hpp.

Referenced by AddConstant(), and PrepareExecutionAsYouParse().

ConstantMap Nektar::LibUtilities::AnalyticExpressionEvaluator::m_constantMapNameToId
private

Definition at line 422 of file AnalyticExpressionEvaluator.hpp.

Referenced by AddConstant(), and PrepareExecutionAsYouParse().

boost_spirit::symbols<NekDouble> Nektar::LibUtilities::AnalyticExpressionEvaluator::m_constantsParser
private

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 313 of file AnalyticExpressionEvaluator.hpp.

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

std::vector<ExecutionStack> Nektar::LibUtilities::AnalyticExpressionEvaluator::m_executionStack
private
VariableMap Nektar::LibUtilities::AnalyticExpressionEvaluator::m_expressionVariableMap
private

Definition at line 423 of file AnalyticExpressionEvaluator.hpp.

std::map<int, OneArgFunc> Nektar::LibUtilities::AnalyticExpressionEvaluator::m_function
private
std::map<int, TwoArgFunc> Nektar::LibUtilities::AnalyticExpressionEvaluator::m_function2
private
FunctionNameMap Nektar::LibUtilities::AnalyticExpressionEvaluator::m_functionMapNameToInstanceType
private
RandomGeneratorType Nektar::LibUtilities::AnalyticExpressionEvaluator::m_generator
private

Definition at line 447 of file AnalyticExpressionEvaluator.hpp.

Referenced by SetRandomSeed().

std::vector<NekDouble> Nektar::LibUtilities::AnalyticExpressionEvaluator::m_parameter
private

Definition at line 425 of file AnalyticExpressionEvaluator.hpp.

Referenced by GetParameter(), and SetParameter().

ParameterMap Nektar::LibUtilities::AnalyticExpressionEvaluator::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 421 of file AnalyticExpressionEvaluator.hpp.

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

ExpressionMap Nektar::LibUtilities::AnalyticExpressionEvaluator::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 395 of file AnalyticExpressionEvaluator.hpp.

Referenced by DefineFunction().

std::vector<VariableMap> Nektar::LibUtilities::AnalyticExpressionEvaluator::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 402 of file AnalyticExpressionEvaluator.hpp.

Referenced by DefineFunction(), and EvaluateAtPoint().

std::vector<NekDouble> Nektar::LibUtilities::AnalyticExpressionEvaluator::m_state
private

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

Definition at line 432 of file AnalyticExpressionEvaluator.hpp.

Referenced by Evaluate(), and EvaluateAtPoint().

int Nektar::LibUtilities::AnalyticExpressionEvaluator::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 439 of file AnalyticExpressionEvaluator.hpp.

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

std::vector<int> Nektar::LibUtilities::AnalyticExpressionEvaluator::m_state_sizes
private

Vector of state sizes per each.

Definition at line 435 of file AnalyticExpressionEvaluator.hpp.

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

Timer Nektar::LibUtilities::AnalyticExpressionEvaluator::m_timer
private

Timer and sum of evaluation times.

Definition at line 443 of file AnalyticExpressionEvaluator.hpp.

Referenced by Evaluate(), and EvaluateAtPoint().

NekDouble Nektar::LibUtilities::AnalyticExpressionEvaluator::m_total_eval_time
private

Definition at line 444 of file AnalyticExpressionEvaluator.hpp.

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

std::vector<NekDouble> Nektar::LibUtilities::AnalyticExpressionEvaluator::m_variable
private

Definition at line 427 of file AnalyticExpressionEvaluator.hpp.

Referenced by Evaluate(), and EvaluateAtPoint().