41 #include <boost/lexical_cast.hpp>
42 #include <boost/algorithm/string/trim.hpp>
43 #include <boost/random/detail/seed.hpp>
46 #include <boost/preprocessor/cat.hpp>
50 #define NEKTAR_MATH_NAME(x) BOOST_PP_CAT(_, x)
52 #define NEKTAR_MATH_NAME(x) x
55 #if( BOOST_VERSION / 100 % 1000 >= 36 )
56 using namespace boost::spirit::classic;
58 using namespace boost::spirit;
67 namespace LibUtilities
99 return (arg > 0.0) - (arg < 0.0);
109 boost::variate_generator<
111 boost::normal_distribution<>
112 > _normal(rng, boost::normal_distribution<>(0, sigma) );
152 template <
typename ScannerT>
155 expression = logical_or;
157 logical_or = logical_and >> *( (root_node_d[str_p(
"||")] >> logical_and) );
159 logical_and = equality >> *( (root_node_d[str_p(
"&&")] >> equality) );
161 equality = lt_gt >> *( (root_node_d[str_p(
"==")] >> lt_gt) );
164 *( (root_node_d[str_p(
"<=")] >> add_sub)
165 | (root_node_d[str_p(
">=")] >> add_sub)
166 | (root_node_d[ch_p(
'<')] >> add_sub)
167 | (root_node_d[ch_p(
'>')] >> add_sub)
170 add_sub = mult_div >>
171 *( (root_node_d[ch_p(
'+')] >> mult_div)
172 | (root_node_d[ch_p(
'-')] >> mult_div)
175 mult_div = exponential >>
176 *( (root_node_d[ch_p(
'*')] >> exponential)
177 | (root_node_d[ch_p(
'/')] >> exponential)
180 exponential = factor >>
181 *( (root_node_d[ch_p(
'^')] >> factor) );
188 | inner_node_d[ch_p(
'(') >> expression >> ch_p(
')')]
189 | (root_node_d[ch_p(
'-')] >> factor);
191 parameter = leaf_node_d[ lexeme_d[
192 (alpha_p |
'_' |
'$') >> *(alnum_p |
'_' |
'$')
196 infix_node_d[inner_node_d[ch_p(
'(') >> expression >> *(
',' >> expression) >> ch_p(
')')]];
198 variable = leaf_node_d[ lexeme_d[
202 number = leaf_node_d[ lexeme_d[
206 constant = leaf_node_d[ lexeme_d[
210 op = eps_p( end_p |
"||" |
"&&" |
"==" |
"<=" |
">=" |
'<' |
'>' |
'+' |
'-' |
'*' |
'/' |
'^' |
')' );
218 AnalyticExpressionEvaluator::AnalyticExpressionEvaluator():
307 for (std::map<std::string, NekDouble>::const_iterator it = constants.begin(); it != constants.end(); ++it)
329 std::string errormsg(
"Attempt to add numerically different constants under the same name: ");
331 std::cout << errormsg << std::endl;
342 ASSERTL1(value != NULL,
"Constant variable not found: " + name);
349 for (std::map<std::string, NekDouble>::const_iterator it = params.begin(); it != params.end(); it++)
412 std::vector<std::string> variableNames;
413 parse((
char*) vlist.c_str(), ( *space_p >>
415 +(+graph_p)[push_back_a(variableNames)]
425 node_val_data_factory<NekDouble>,
426 std::string::const_iterator,
430 (expr.begin(), expr.end(), myGrammar, space_p);
432 ASSERTL1(parseInfo.full !=
false,
"Unable to fully parse function. Stopped just before: "
433 + std::string(parseInfo.stop, parseInfo.stop + 15));
446 for (
int i = 0; i < variableNames.size(); i++)
448 variableMap[variableNames[i]] = i;
459 ASSERTL1(stack.size() == 0,
"Constant expression yeilds non-empty execution stack. Bug in PrepareExecutionAsYouParse()");
461 int const_index =
AddConstant(std::string(
"EXPRESSION_") + boost::lexical_cast<std::string>(stackId), v.second);
462 stack.push_back ( makeStep<StoreConst>( 0, const_index ) );
481 ASSERTL1(
m_executionStack.size() > expression_id,
"unknown analytic expression, it must first be defined with DefineFunction(...)");
486 for (
int i = 0; i < stack.size(); i++)
488 (*stack[i]).run_once();
498 const int expression_id,
506 ASSERTL1(
m_executionStack.size() > expression_id,
"unknown analytic expression, it must first be defined with DefineFunction(...)");
527 for (
int i = 0; i < stack.size(); i++)
529 (*stack[i]).run_once();
542 ASSERTL1(
m_executionStack.size() > expression_id,
"unknown analytic expression, it must first be defined with DefineFunction(...)");
547 ASSERTL1(point.size() == variableMap.size(),
"The number of variables used to define this expression should match the point dimensionality.");
552 VariableMap::const_iterator it;
553 for (it = variableMap.begin(); it != variableMap.end(); ++it)
558 for (
int i = 0; i < stack.size(); i++)
560 (*stack[i]).run_once();
571 const int expression_id,
572 const Array<OneD, const NekDouble>& x,
573 const Array<OneD, const NekDouble>& y,
574 const Array<OneD, const NekDouble>& z,
575 const Array<OneD, const NekDouble>& t,
576 Array<OneD, NekDouble>& result)
580 const int num_points = x.num_elements();
581 ASSERTL1(
m_executionStack.size() > expression_id,
"unknown analytic expression, it must first be defined with DefineFunction(...)");
582 ASSERTL1(result.num_elements() >= num_points,
"destination array must have enough capacity to store expression values at each given point");
590 const int max_chunk_size = 1024;
593 const int chunk_size = (std::min)(max_chunk_size, num_points);
602 if (result.num_elements() < num_points)
604 result = Array<OneD, NekDouble>(num_points, 0.0);
608 int work_left = num_points;
611 const int this_chunk_size = (std::min)(work_left, 1024);
612 for (
int i = 0; i < this_chunk_size; i++)
614 m_variable[i+this_chunk_size*0] = x[offset + i];
615 m_variable[i+this_chunk_size*1] = y[offset + i];
616 m_variable[i+this_chunk_size*2] = z[offset + i];
617 m_variable[i+this_chunk_size*3] = t[offset + i];
619 for (
int i = 0; i < stack.size(); i++)
621 (*stack[i]).run_many(this_chunk_size);
623 for (
int i = 0; i < this_chunk_size; i++)
625 result[offset + i] =
m_state[i];
627 work_left -= this_chunk_size;
628 offset += this_chunk_size;
636 const int expression_id,
637 const std::vector<Array<OneD, const NekDouble> > points,
638 Array<OneD, NekDouble>& result)
644 ASSERTL1(
m_executionStack.size() > expression_id,
"unknown analytic expression, it must first be defined with DefineFunction(...)");
649 const int num = points[0].num_elements();
655 for (
int i = 0; i < points.size(); i++)
657 for (VariableMap::const_iterator it = variableMap.begin(); it != variableMap.end(); ++it)
659 m_variable[it->second] = points[i][it->second];
662 for (
int j = 0; j < stack.size(); j++)
664 (*stack[j]).run_many(num);
666 for (
int i = 0; i < num; ++i)
683 std::string valueStr(location->value.begin(), location->value.end());
684 boost::algorithm::trim(valueStr);
686 const parser_id parserID = location->value.id();
687 #if defined(NEKTAR_DEBUG) || defined(NEKTAR_FULLDEBUG)
688 const int num_children = location->children.size();
693 ASSERTL1(num_children == 0,
"Illegal children under constant node: " + valueStr);
698 return std::make_pair(
true,
m_constant[it->second]);
702 ASSERTL1(num_children == 0,
"Illegal children under number node: " + valueStr);
703 return std::make_pair(
true, boost::lexical_cast<NekDouble>(valueStr.c_str()) );
707 ASSERTL1(num_children == 0,
"Illegal children under variable node: " + valueStr);
709 VariableMap::const_iterator it = variableMap.find(valueStr);
710 ASSERTL1(it != variableMap.end(),
"Unknown variable parsed: " + valueStr);
713 stack.push_back ( makeStep<StoreVar>( stateIndex, it->second ) );
714 return std::make_pair(
false, 0);
718 ASSERTL1(num_children == 0,
"Illegal children under parameter node: " + valueStr);
724 stack.push_back ( makeStep<StorePrm>( stateIndex, it->second ) );
725 return std::make_pair(
false, 0);
731 ASSERTL1(num_children == 1,
"Function " + valueStr +
" would like to have too few or too many arguments. This is not implemented yet");
738 int const_index =
AddConstant(std::string(
"SUB_EXPR_") + boost::lexical_cast<std::string>(
m_constant.size()), v.second);
739 stack.push_back ( makeStep<StoreConst>( stateIndex, const_index ) );
740 stack.push_back ( makeStep<EvalAWGN>( stateIndex, stateIndex ) );
741 return std::make_pair(
false,0);
747 return std::make_pair(
true,
m_function[it->second](v.second) );
756 stack.push_back ( makeStep<EvalAbs>( stateIndex, stateIndex) );
757 return std::make_pair(
false,0);
759 stack.push_back ( makeStep<EvalAsin>( stateIndex, stateIndex) );
760 return std::make_pair(
false,0);
762 stack.push_back ( makeStep<EvalAcos>( stateIndex, stateIndex ) );
763 return std::make_pair(
false,0);
765 stack.push_back ( makeStep<EvalAtan>( stateIndex, stateIndex ) );
766 return std::make_pair(
false,0);
768 stack.push_back ( makeStep<EvalCeil>( stateIndex, stateIndex ) );
769 return std::make_pair(
false,0);
771 stack.push_back ( makeStep<EvalCos>( stateIndex, stateIndex ) );
772 return std::make_pair(
false,0);
774 stack.push_back ( makeStep<EvalCosh>( stateIndex, stateIndex ) );
775 return std::make_pair(
false,0);
777 stack.push_back ( makeStep<EvalExp>( stateIndex, stateIndex ) );
778 return std::make_pair(
false,0);
780 stack.push_back ( makeStep<EvalFabs>( stateIndex, stateIndex ) );
781 return std::make_pair(
false,0);
783 stack.push_back ( makeStep<EvalFloor>( stateIndex, stateIndex ) );
784 return std::make_pair(
false,0);
786 stack.push_back ( makeStep<EvalLog>( stateIndex, stateIndex ) );
787 return std::make_pair(
false,0);
789 stack.push_back ( makeStep<EvalLog10>( stateIndex, stateIndex ) );
790 return std::make_pair(
false,0);
792 stack.push_back ( makeStep<EvalSin>( stateIndex, stateIndex ) );
793 return std::make_pair(
false,0);
795 stack.push_back ( makeStep<EvalSinh>( stateIndex, stateIndex ) );
796 return std::make_pair(
false,0);
798 stack.push_back ( makeStep<EvalSqrt>( stateIndex, stateIndex ) );
799 return std::make_pair(
false,0);
801 stack.push_back ( makeStep<EvalTan>( stateIndex, stateIndex ) );
802 return std::make_pair(
false,0);
804 stack.push_back ( makeStep<EvalTanh>( stateIndex, stateIndex ) );
805 return std::make_pair(
false,0);
807 stack.push_back ( makeStep<EvalSign>( stateIndex, stateIndex ) );
808 return std::make_pair(
false,0);
810 ASSERTL0(
false,
"Evaluation of " + valueStr +
" is not implemented yet");
812 return std::make_pair(
false,0);
816 ASSERTL1(*valueStr.begin() ==
'-',
"Illegal factor - it can only be '-' and it was: " + valueStr);
817 ASSERTL1(num_children == 1,
"Illegal number of children under factor node: " + valueStr);
824 return std::make_pair(
true, - v.second );
826 stack.push_back (makeStep<EvalNeg>( stateIndex, stateIndex) );
827 return std::make_pair(
false,0);
831 ASSERTL1(num_children == 2,
"Too few or too many arguments for mathematical operator: " + valueStr);
837 if ((
true == left.first) && (
true == right.first))
839 switch(*valueStr.begin())
842 return std::make_pair(
true, left.second + right.second );
844 return std::make_pair(
true, left.second - right.second );
846 return std::make_pair(
true, left.second * right.second );
848 return std::make_pair(
true, left.second / right.second );
850 return std::make_pair(
true, std::pow(left.second, right.second) );
852 return std::make_pair(
true, left.second == right.second );
854 if (*(valueStr.end()-1) ==
'=')
856 return std::make_pair(
true, left.second <= right.second );
860 return std::make_pair(
true, left.second < right.second );
862 return std::make_pair(
false,0);
864 if (*(valueStr.end()-1) ==
'=')
866 return std::make_pair(
true, left.second >= right.second );
870 return std::make_pair(
true, left.second > right.second );
872 return std::make_pair(
false,0);
874 ASSERTL0(
false,
"Invalid operator encountered: " + valueStr);
876 return std::make_pair(
false,0);
881 if (
true == left.first)
883 int const_index =
AddConstant(std::string(
"SUB_EXPR_") + boost::lexical_cast<std::string>(
m_constant.size()), left.second);
884 stack.push_back ( makeStep<StoreConst>( stateIndex, const_index ) );
886 if (
true == right.first)
888 int const_index =
AddConstant(std::string(
"SUB_EXPR_") + boost::lexical_cast<std::string>(
m_constant.size()), right.second);
889 stack.push_back ( makeStep<StoreConst>( stateIndex+1, const_index ) );
893 switch(*valueStr.begin())
896 stack.push_back (makeStep<EvalSum>( stateIndex, stateIndex, stateIndex+1 ) );
897 return std::make_pair(
false,0);
899 stack.push_back (makeStep<EvalSub> (stateIndex, stateIndex, stateIndex+1 ) );
900 return std::make_pair(
false,0);
902 stack.push_back (makeStep<EvalMul>( stateIndex, stateIndex, stateIndex+1 ) );
903 return std::make_pair(
false,0);
905 stack.push_back (makeStep<EvalDiv>( stateIndex, stateIndex, stateIndex+1 ) );
906 return std::make_pair(
false,0);
908 stack.push_back (makeStep<EvalPow>( stateIndex, stateIndex, stateIndex+1 ) );
909 return std::make_pair(
false,0);
911 stack.push_back (makeStep<EvalLogicalEqual>( stateIndex, stateIndex, stateIndex+1 ) );
912 return std::make_pair(
false,0);
914 if (*(valueStr.end()-1) ==
'=')
916 stack.push_back (makeStep<EvalLogicalLeq>( stateIndex, stateIndex, stateIndex+1 ) );
920 stack.push_back (makeStep<EvalLogicalLess>( stateIndex, stateIndex, stateIndex+1 ) );
922 return std::make_pair(
false,0);
925 if (*(valueStr.end()-1) ==
'=')
927 stack.push_back (makeStep<EvalLogicalGeq>( stateIndex, stateIndex, stateIndex+1 ) );
931 stack.push_back (makeStep<EvalLogicalGreater>( stateIndex, stateIndex, stateIndex+1 ) );
933 return std::make_pair(
false,0);
936 ASSERTL0(
false,
"Invalid operator encountered: " + valueStr);
938 return std::make_pair(
false,0);
940 ASSERTL0(
false,
"Illegal expression encountered: " + valueStr);
941 return std::make_pair(
false,0);