From f493e329c1a0e67f81772260a00a228e835f57bd Mon Sep 17 00:00:00 2001 From: Timo Heister Date: Mon, 24 Feb 2014 18:46:25 +0000 Subject: [PATCH] function_parser formatting and documentation changes git-svn-id: https://svn.dealii.org/branches/branch_muparser@32537 0785d39b-7218-0410-832d-ea1e28bc413d --- .../include/deal.II/base/function_parser.h | 840 ++++++++---------- 1 file changed, 388 insertions(+), 452 deletions(-) diff --git a/deal.II/include/deal.II/base/function_parser.h b/deal.II/include/deal.II/base/function_parser.h index 276b8ca931..0bc81fb36b 100644 --- a/deal.II/include/deal.II/base/function_parser.h +++ b/deal.II/include/deal.II/base/function_parser.h @@ -49,206 +49,205 @@ template class Vector; * * The following examples shows how to use this class: * @code - // set up problem: - std::string variables = "x,y"; - std::string expression = "cos(x)+sqrt(y)"; - std::map constants; - - // FunctionParser with 2 variables and 1 component: - FunctionParser<2> fp(1); - fp.initialize(variables, - expression, - constants); - - // Point at which we want to evaluate the function - Point<2> point(0.0, 4.0); - - // evaluate the expression at 'point': - double result = fp.value(point); - - deallog << "Function '" << expression << "'" - << " @ " << point - << " is " << result << std::endl; -@endcode -* The second example is a bit more complex: -* @code - // Define some constants that will be used by the function parser - std::map constants; - constants["pi"] = numbers::PI; - - // Define the variables that will be used inside the expressions - std::string variables = "x,y,z"; - - // Define the expressions of the individual components of a - // vector valued function with two components: - std::vector expressions(2); - expressions[0] = "sin(2*pi*x)+sinh(pi*z)"; - expressions[1] = "sin(2*pi*y)*exp(x^2)"; - - // function parser with 3 variables and 2 components - FunctionParser<3> vector_function(2); - - // And populate it with the newly created objects. - vector_function.initialize(variables, - expressions, - constants); - - // Point at which we want to evaluate the function - Point<3> point(0.0, 1.0, 1.0); - - // This Vector will store the result - Vector result(2); - - // Fill 'result' by evaluating the function - vector_function.vector_value(point, result); - - // We can also only evaluate the 2nd component: - double c = vector_function.value(point, 1); - - // Output the evaluated function - deallog << "Function '" << expressions[0] << "," << expressions[1] << "'" - << " @ " << point - << " is " << result << std::endl; - * @endcode - * - * This class overloads the virtual methods value() and - * vector_value() of the Function base class with the byte compiled versions - * of the expressions given to the initialize() methods. Note that the class - * will not work unless you first call the initialize() method that accepts - * the text description of the function as an argument (among other - * things). - * - * The syntax to describe a function follows usual programming practice, - * and is explained in this snippet from the fparser.txt file: - @verbatim - The function string understood by the class is very similar to the C-syntax. - Arithmetic float expressions can be created from float literals, variables - or functions using the following operators in this order of precedence: - - -A unary minus - A^B exponentiation (A raised to the power B) - A*B A/B A%B multiplication, division and modulo - A+B A-B addition and subtraction - A==B AB comparison between A and B (result is either 0 or 1) - A&&B A||B logical 'and' and 'or' - A&B A|B same, implemented for compatibility - - Since the unary minus has higher precedence than any other operator, for - example the following expression is valid: x*-y - - Note that the '==' comparison can be inaccurate due to floating point - precision problems, so it should be avoided (eg. "sqrt(100)=10" probably - returns 0, not 1). - - The class supports these functions: - - abs(A) : Absolute value of A. If A is negative, returns -A otherwise - returns A. - acos(A) : Arc-cosine of A. Returns the angle, measured in radians, - whose cosine is A. - acosh(A) : Same as acos() but for hyperbolic cosine. - asin(A) : Arc-sine of A. Returns the angle, measured in radians, whose - sine is A. - asinh(A) : Same as asin() but for hyperbolic sine. - atan(A) : Arc-tangent of (A). Returns the angle, measured in radians, - whose tangent is (A). - atan2(A,B): Arc-tangent of A/B. The two main differences to atan() is - that it will return the right angle depending on the signs of - A and B (atan() can only return values between -pi/2 and pi/2), - and that the return value of pi/2 and -pi/2 are possible. - atanh(A) : Same as atan() but for hyperbolic tangent. - ceil(A) : Ceiling of A. Returns the smallest integer greater than A. - Rounds up to the next higher integer. - cos(A) : Cosine of A. Returns the cosine of the angle A, where A is - measured in radians. - cosh(A) : Same as cos() but for hyperbolic cosine. - cot(A) : Cotangent of A (equivalent to 1/tan(A)). - csc(A) : Cosecant of A (equivalent to 1/sin(A)). - exp(A) : Exponential of A. Returns the value of e raised to the power - A where e is the base of the natural logarithm, i.e. the - non-repeating value approximately equal to 2.71828182846. - floor(A) : Floor of A. Returns the largest integer less than A. Rounds - down to the next lower integer. - if(A,B,C) : If int(A) differs from 0, the return value of this function is B, - else C. Only the parameter which needs to be evaluated is - evaluated, the other parameter is skipped; this makes it safe to - use eval() in them. - int(A) : Rounds A to the closest integer. 0.5 is rounded to 1. - log(A) : Natural (base e) logarithm of A. - log10(A) : Base 10 logarithm of A. - max(A,B) : If A>B, the result is A, else B. - min(A,B) : If A constants; + * + * // FunctionParser with 2 variables and 1 component: + * FunctionParser<2> fp(1); + * fp.initialize(variables, + * expression, + * constants); + * + * // Point at which we want to evaluate the function + * Point<2> point(0.0, 4.0); + * + * // evaluate the expression at 'point': + * double result = fp.value(point); + * + * deallog << "Function '" << expression << "'" + * << " @ " << point + * << " is " << result << std::endl; + * @endcode + * The second example is a bit more complex: + * @code + * // Define some constants that will be used by the function parser + * std::map constants; + * constants["pi"] = numbers::PI; + * + * // Define the variables that will be used inside the expressions + * std::string variables = "x,y,z"; + * + * // Define the expressions of the individual components of a + * // vector valued function with two components: + * std::vector expressions(2); + * expressions[0] = "sin(2*pi*x)+sinh(pi*z)"; + * expressions[1] = "sin(2*pi*y)*exp(x^2)"; + * + * // function parser with 3 variables and 2 components + * FunctionParser<3> vector_function(2); + * + * // And populate it with the newly created objects. + * vector_function.initialize(variables, + * expressions, + * constants); + * + * // Point at which we want to evaluate the function + * Point<3> point(0.0, 1.0, 1.0); + * + * // This Vector will store the result + * Vector result(2); + * + * // Fill 'result' by evaluating the function + * vector_function.vector_value(point, result); + * + * // We can also only evaluate the 2nd component: + * double c = vector_function.value(point, 1); + * + * // Output the evaluated function + * deallog << "Function '" << expressions[0] << "," << expressions[1] << "'" + * << " @ " << point + * << " is " << result << std::endl; + * @endcode + * + * This class overloads the virtual methods value() and vector_value() of the + * Function base class with the byte compiled versions of the expressions + * given to the initialize() methods. Note that the class will not work unless + * you first call the initialize() method that accepts the text description of + * the function as an argument (among other things). + * + * The syntax to describe a function follows usual programming practice, and + * is explained in this snippet from the fparser.txt file: + * @verbatim + * The function string understood by the class is very similar to the C-syntax. + * Arithmetic float expressions can be created from float literals, variables + * or functions using the following operators in this order of precedence: + * + * -A unary minus + * A^B exponentiation (A raised to the power B) + * A*B A/B A%B multiplication, division and modulo + * A+B A-B addition and subtraction + * A==B AB comparison between A and B (result is either 0 or 1) + * A&&B A||B logical 'and' and 'or' + * A&B A|B same, implemented for compatibility + * + * Since the unary minus has higher precedence than any other operator, for + * example the following expression is valid: x*-y + * + * Note that the '==' comparison can be inaccurate due to floating point + * precision problems, so it should be avoided (eg. "sqrt(100)=10" probably + * returns 0, not 1). + * + * The class supports these functions: + * + * abs(A) : Absolute value of A. If A is negative, returns -A otherwise + * returns A. + * acos(A) : Arc-cosine of A. Returns the angle, measured in radians, + * whose cosine is A. + * acosh(A) : Same as acos() but for hyperbolic cosine. + * asin(A) : Arc-sine of A. Returns the angle, measured in radians, whose + * sine is A. + * asinh(A) : Same as asin() but for hyperbolic sine. + * atan(A) : Arc-tangent of (A). Returns the angle, measured in radians, + * whose tangent is (A). + * atan2(A,B): Arc-tangent of A/B. The two main differences to atan() is + * that it will return the right angle depending on the signs of + * A and B (atan() can only return values between -pi/2 and pi/2), + * and that the return value of pi/2 and -pi/2 are possible. + * atanh(A) : Same as atan() but for hyperbolic tangent. + * ceil(A) : Ceiling of A. Returns the smallest integer greater than A. + * Rounds up to the next higher integer. + * cos(A) : Cosine of A. Returns the cosine of the angle A, where A is + * measured in radians. + * cosh(A) : Same as cos() but for hyperbolic cosine. + * cot(A) : Cotangent of A (equivalent to 1/tan(A)). + * csc(A) : Cosecant of A (equivalent to 1/sin(A)). + * exp(A) : Exponential of A. Returns the value of e raised to the power + * A where e is the base of the natural logarithm, i.e. the + * non-repeating value approximately equal to 2.71828182846. + * floor(A) : Floor of A. Returns the largest integer less than A. Rounds + * down to the next lower integer. + * if(A,B,C) : If int(A) differs from 0, the return value of this function is B, + * else C. Only the parameter which needs to be evaluated is + * evaluated, the other parameter is skipped; this makes it safe to + * use eval() in them. + * int(A) : Rounds A to the closest integer. 0.5 is rounded to 1. + * log(A) : Natural (base e) logarithm of A. + * log10(A) : Base 10 logarithm of A. + * max(A,B) : If A>B, the result is A, else B. + * min(A,B) : If A constants; - - // Variables that will be used inside the expressions - std::string variables = "x,y,t"; - - // Define the expression of the scalar time dependent function. - std::string expression = "exp(y*x)*exp(-t)"; - - // Generate an empty scalar function - FunctionParser<2> function; - - // And populate it with the newly created objects. - function.initialize(variables, - expression, - constants, - true); // This tells the parser that - // it is a time-dependent function - // and there is another variable - // to be taken into account (t). - - @endcode - - * The following is another example of how to instantiate a - * vector valued function by using a single string: - @code - - // Empty constants object - std::map constants; - - // Variables that will be used inside the expressions - std::string variables = "x,y"; - - // Define the expression of the vector valued function. - std::string expression = "cos(2*pi*x)*y^2; sin(2*pi*x)*exp(y)"; - - // Generate an empty vector valued function - FunctionParser<2> function(2); - - // And populate it with the newly created objects. - function.initialize(variables, - expression, - constants); - - @endcode + * @code + * + * // Empty constants object + * std::map constants; + * + * // Variables that will be used inside the expressions + * std::string variables = "x,y,t"; + * + * // Define the expression of the scalar time dependent function. + * std::string expression = "exp(y*x)*exp(-t)"; + * + * // Generate an empty scalar function + * FunctionParser<2> function; + * + * // And populate it with the newly created objects. + * function.initialize(variables, + * expression, + * constants, + * true); // This tells the parser that + * // it is a time-dependent function + * // and there is another variable + * // to be taken into account (t). + * + * @endcode + * + * The following is another example of how to instantiate a vector valued + * function by using a single string: + * @code + * + * // Empty constants object + * std::map constants; + * + * // Variables that will be used inside the expressions + * std::string variables = "x,y"; + * + * // Define the expression of the vector valued function. + * std::string expression = "cos(2*pi*x)*y^2; sin(2*pi*x)*exp(y)"; + * + * // Generate an empty vector valued function + * FunctionParser<2> function(2); + * + * // And populate it with the newly created objects. + * function.initialize(variables, + * expression, + * constants); + * + * @endcode * * * @ingroup functions @@ -257,243 +256,189 @@ template class Vector; template class FunctionParser : public Function { -public: - /** - * Constructor for Parsed - * functions. Its arguments are - * the same of the base class - * Function. The only difference - * is that this object needs to - * be initialized with - * initialize() method before you - * can use it. If an attempt to - * use this function is made - * before the initialize() method - * has been called, then an - * exception is thrown. - */ - FunctionParser (const unsigned int n_components = 1, - const double initial_time = 0.0); - - /** - * Destructor. Explicitly delete - * the FunctionParser objects - * (there is one for each - * component of the function). - */ - ~FunctionParser(); - - /** - * Type for the constant - * map. Used by the initialize() - * method. - */ - typedef std::map ConstMap; - - /** - * Iterator for the constants - * map. Used by the initialize() - * method. - */ - typedef ConstMap::iterator ConstMapIterator; - - /** - * Initialize the function. This methods - * accepts the following parameters: - * - * vars: a string with - * the variables that will be used by the - * expressions to be evaluated. Note that - * the variables can have any name (of - * course different from the function - * names defined above!), but the order - * IS important. The first variable will - * correspond to the first component of - * the point in which the function is - * evaluated, the second variable to the - * second component and so forth. If this - * function is also time dependent, then - * it is necessary to specify it by - * setting the time_dependent parameter - * to true. An exception is thrown if - * the number of variables specified here - * is different from dim (if this - * function is not time-dependent) or - * from dim+1 (if it is time-dependent). - * - * expressions: a list of strings - * containing the expressions that will - * be byte compiled by the internal - * parser (FunctionParser). Note that the - * size of this vector must match exactly - * the number of components of the - * FunctionParser, as declared in the - * constructor. If this is not the case, - * an exception is thrown. - * - * - * constants: a map of constants - * used to pass any necessary constant - * that we want to specify in our - * expressions (in the example above the - * number pi). An expression is valid if - * and only if it contains only defined - * variables and defined constants (other - * than the functions specified - * above). If a constant is given whose - * name is not valid (eg: - * constants["sin"] = 1.5;) an - * exception is thrown. - * - * time_dependent. If this is a - * time dependent function, then the last - * variable declared in vars is - * assumed to be the time variable, and - * this->get_time() is used to initialize - * it when evaluating the - * function. Naturally the number of - * variables parsed by the initialize() - * method in this case is dim+1. The - * value of this parameter defaults to - * false, i.e. do not consider time. - */ - void initialize (const std::string &vars, - const std::vector &expressions, - const ConstMap &constants, - const bool time_dependent = false); + public: + /** + * Constructor for Parsed functions. Its arguments are the same of the + * base class Function. The only difference is that this object needs to + * be initialized with initialize() method before you can use it. If an + * attempt to use this function is made before the initialize() method has + * been called, then an exception is thrown. + */ + FunctionParser (const unsigned int n_components = 1, + const double initial_time = 0.0); + + /** + * Destructor. Explicitly delete the FunctionParser objects (there is one + * for each component of the function). + */ + ~FunctionParser(); + + /** + * Type for the constant map. Used by the initialize() method. + */ + typedef std::map ConstMap; + + /** + * Iterator for the constants map. Used by the initialize() method. + */ + typedef ConstMap::iterator ConstMapIterator; /** - * Same as above, but with an additional parameter: - * use_degrees. Parameter to decide if the trigonometric functions - * work in radians or degrees. The default for this parameter is false, - * i.e. use radians and not degrees. + * Initialize the function. This methods accepts the following + * parameters: + * + * vars: a string with the variables that will be used by the + * expressions to be evaluated. Note that the variables can have any name + * (of course different from the function names defined above!), but the + * order IS important. The first variable will correspond to the first + * component of the point in which the function is evaluated, the second + * variable to the second component and so forth. If this function is also + * time dependent, then it is necessary to specify it by setting the + * time_dependent parameter to true. An exception is thrown if + * the number of variables specified here is different from dim (if this + * function is not time-dependent) or from dim+1 (if it is time- + * dependent). + * + * expressions: a list of strings containing the expressions that + * will be byte compiled by the internal parser (FunctionParser). Note + * that the size of this vector must match exactly the number of + * components of the FunctionParser, as declared in the constructor. If + * this is not the case, an exception is thrown. + * + * + * constants: a map of constants used to pass any necessary + * constant that we want to specify in our expressions (in the example + * above the number pi). An expression is valid if and only if it contains + * only defined variables and defined constants (other than the functions + * specified above). If a constant is given whose name is not valid (eg: + * constants["sin"] = 1.5;) an exception is thrown. + * + * time_dependent. If this is a time dependent function, then the + * last variable declared in vars is assumed to be the time + * variable, and this->get_time() is used to initialize it when evaluating + * the function. Naturally the number of variables parsed by the + * initialize() method in this case is dim+1. The value of this parameter + * defaults to false, i.e. do not consider time. + */ + void initialize (const std::string &vars, + const std::vector &expressions, + const ConstMap &constants, + const bool time_dependent = false); + + /** + * Same as above, but with an additional parameter: use_degrees. + * Parameter to decide if the trigonometric functions work in radians or + * degrees. The default for this parameter is false, i.e. use radians and + * not degrees. * * @note: this function is deprecated. Use the function without this * argument instead (which has the default use_degrees=false). */ void initialize (const std::string &vars, - const std::vector &expressions, - const ConstMap &constants, - const bool time_dependent, - const bool use_degrees) DEAL_II_DEPRECATED; - - - /** - * Initialize the function. Same as - * above, but with an additional argument - * units - a map of units passed to - * FunctionParser via AddUnint. - * - * Can be used as "3cm". - * Have higher precedence in parsing, i.e. - * if cm=10 then 3/2cm is 3 /(2*10). - * See contrib/functionparser/fparser.txt - * for more details. - */ - void initialize (const std::string &vars, - const std::vector &expressions, - const ConstMap &constants, - const ConstMap &units, - const bool time_dependent = false, - const bool use_degrees = false) DEAL_II_DEPRECATED; - - /** - * Initialize the function. Same as - * above, but accepts a string rather - * than a vector of strings. If this is a - * vector valued function, its - * components are expected to be - * separated by a semicolon. An exception - * is thrown if this method is called and - * the number of components successfully - * parsed does not match the number of - * components of the base function. - */ - void initialize (const std::string &vars, - const std::string &expression, - const ConstMap &constants, - const bool time_dependent = false); + const std::vector &expressions, + const ConstMap &constants, + const bool time_dependent, + const bool use_degrees) DEAL_II_DEPRECATED; + /** - * Same as above, but with an additional parameter: - * use_degrees. Parameter to decide if the trigonometric functions - * work in radians or degrees. The default for this parameter is false, - * i.e. use radians and not degrees. + * Initialize the function. Same as above, but with an additional argument + * units - a map of units passed to FunctionParser via AddUnint. + * + * Can be used as "3cm". Have higher precedence in parsing, i.e. if cm=10 + * then 3/2cm is 3 /(2*10). See contrib/functionparser/fparser.txt for + * more details. + */ + void initialize (const std::string &vars, + const std::vector &expressions, + const ConstMap &constants, + const ConstMap &units, + const bool time_dependent = false, + const bool use_degrees = false) DEAL_II_DEPRECATED; + + /** + * Initialize the function. Same as above, but accepts a string rather + * than a vector of strings. If this is a vector valued function, its + * components are expected to be separated by a semicolon. An exception is + * thrown if this method is called and the number of components + * successfully parsed does not match the number of components of the base + * function. + */ + void initialize (const std::string &vars, + const std::string &expression, + const ConstMap &constants, + const bool time_dependent = false); + + /** + * Same as above, but with an additional parameter: use_degrees. + * Parameter to decide if the trigonometric functions work in radians or + * degrees. The default for this parameter is false, i.e. use radians and + * not degrees. * * @note: this function is deprecated. Use the function without this * argument instead (which has the default use_degrees=false). */ - void initialize (const std::string &vars, - const std::string &expression, - const ConstMap &constants, - const bool time_dependent, - const bool use_degrees) DEAL_II_DEPRECATED; - /** - * Initialize the function. Same as - * above, but with units. - */ - - void initialize (const std::string &vars, - const std::string &expression, - const ConstMap &constants, - const ConstMap &units, - const bool time_dependent = false, - const bool use_degrees = false) DEAL_II_DEPRECATED; - - /** - * A function that returns - * default names for variables, - * to be used in the first - * argument of the initialize() - * functions: it returns "x" in - * 1d, "x,y" in 2d, and "x,y,z" - * in 3d. - */ - static - std::string - default_variable_names (); - - /** - * Return the value of the - * function at the given - * point. Unless there is only - * one component (i.e. the - * function is scalar), you - * should state the component you - * want to have evaluated; it - * defaults to zero, i.e. the - * first component. - */ - virtual double value (const Point &p, - const unsigned int component = 0) const; - - /** - * Return all components of a - * vector-valued function at the - * given point @p p. - * - * values shall have the - * right size beforehand, - * i.e. #n_components. - */ - virtual void vector_value (const Point &p, - Vector &values) const; - - /** @addtogroup Exceptions - * @{ */ - DeclException2 (ExcParseError, - int, char *, - << "Parsing Error at Column " << arg1 - << ". The parser said: " << arg2); - - DeclException2 (ExcInvalidExpressionSize, - int, int, - << "The number of components (" << arg1 - << ") is not equal to the number of expressions (" - << arg2 << ")."); - - //@} -private: + void initialize (const std::string &vars, + const std::string &expression, + const ConstMap &constants, + const bool time_dependent, + const bool use_degrees) DEAL_II_DEPRECATED; + /** + * Initialize the function. Same as above, but with units. + */ + + void initialize (const std::string &vars, + const std::string &expression, + const ConstMap &constants, + const ConstMap &units, + const bool time_dependent = false, + const bool use_degrees = false) DEAL_II_DEPRECATED; + + /** + * A function that returns default names for variables, to be used in the + * first argument of the initialize() functions: it returns "x" in 1d, + * "x,y" in 2d, and "x,y,z" in 3d. + */ + static + std::string + default_variable_names (); + + /** + * Return the value of the function at the given point. Unless there is + * only one component (i.e. the function is scalar), you should state the + * component you want to have evaluated; it defaults to zero, i.e. the + * first component. + */ + virtual double value (const Point &p, + const unsigned int component = 0) const; + + /** + * Return all components of a vector-valued function at the given point @p + * p. + * + * values shall have the right size beforehand, i.e. + * #n_components. + */ + virtual void vector_value (const Point &p, + Vector &values) const; + + /** + * @addtogroup Exceptions + * @{ + */ + DeclException2 (ExcParseError, + int, char *, + << "Parsing Error at Column " << arg1 + << ". The parser said: " << arg2); + + DeclException2 (ExcInvalidExpressionSize, + int, int, + << "The number of components (" << arg1 + << ") is not equal to the number of expressions (" + << arg2 << ")."); + + //@} + private: #ifdef DEAL_II_WITH_MUPARSER /** * place for the variables for each thread @@ -505,7 +450,8 @@ private: mutable Threads::ThreadLocalStorage > fp; /** - * keep track of all the constants, required to initialize fp in each thread + * keep track of all the constants, required to initialize fp in each + * thread */ std::map< std::string, double > constants; /** @@ -523,29 +469,19 @@ private: #endif /** - * State of usability. This - * variable is checked every time - * the function is called for - * evaluation. It's set to true - * in the initialize() methods. - */ - bool initialized; - - /** - * Number of variables. If this - * is also a function of time, - * then the number of variables - * is dim+1, otherwise it is - * dim. In the case that this is - * a time dependent function, the - * time is supposed to be the - * last variable. If #n_vars is - * not identical to the number of - * the variables parsed by the - * initialize() method, then an - * exception is thrown. - */ - unsigned int n_vars; + * State of usability. This variable is checked every time the function is + * called for evaluation. It's set to true in the initialize() methods. + */ + bool initialized; + + /** + * Number of variables. If this is also a function of time, then the + * number of variables is dim+1, otherwise it is dim. In the case that + * this is a time dependent function, the time is supposed to be the last + * variable. If #n_vars is not identical to the number of the variables + * parsed by the initialize() method, then an exception is thrown. + */ + unsigned int n_vars; }; @@ -554,16 +490,16 @@ std::string FunctionParser::default_variable_names () { switch (dim) - { - case 1: - return "x"; - case 2: - return "x,y"; - case 3: - return "x,y,z"; - default: - Assert (false, ExcNotImplemented()); - } + { + case 1: + return "x"; + case 2: + return "x,y"; + case 3: + return "x,y,z"; + default: + Assert (false, ExcNotImplemented()); + } return ""; } -- 2.39.5