]> https://gitweb.dealii.org/ - dealii-svn.git/commitdiff
Patch by Victor Prosolin: Add support for units in the FunctionParser class.
authorbangerth <bangerth@0785d39b-7218-0410-832d-ea1e28bc413d>
Mon, 2 Mar 2009 02:21:27 +0000 (02:21 +0000)
committerbangerth <bangerth@0785d39b-7218-0410-832d-ea1e28bc413d>
Mon, 2 Mar 2009 02:21:27 +0000 (02:21 +0000)
git-svn-id: https://svn.dealii.org/trunk@18440 0785d39b-7218-0410-832d-ea1e28bc413d

deal.II/base/include/base/function_parser.h
deal.II/base/source/function_parser.cc
deal.II/doc/news/changes.h

index a46319ed1504c4d4c6f130058de335b4efd53e88..588202ef815a0c958f3cf737988d785fc22c50e8 100644 (file)
@@ -77,6 +77,65 @@ template <typename> class Vector;
                            expressions,
                            constants); 
   @endverbatim
+
+ * FunctionParser also provides an option to use <b>units</b> in expressions.
+ * We can illustrate the use of this functionality with the following example:
+ * @verbatim
+ // Define some constants that will be used by the function parser
+  std::map<std::string> constants;
+  std::map<std::string> units;
+  constants["PI"] = numbers::PI;
+  units["cm"] = 10;
+  units["m"] = 1000;
+
+  // Define the variables that will be used inside the expressions
+  std::string variables = "x,y";
+
+  // Define the expressions of the individual components of a
+  // vector valued function with two components:
+  std::vector<std::string> expressions(1);
+  expressions[0] = "x cm + y m + PI cm;
+
+  // Generate an empty function for these two components.
+  FunctionParser<2> vector_function;
+
+  // And populate it with the newly created objects.
+  vector_function.initialize(variables,
+                expressions,
+                constants,
+                units); //An exptra argument here
+
+  // Point at which we want to evaluate the function
+  Point<2> point(2.0, 3.0);
+
+  // Output the evaluated function
+  std::cout << "Function " << "[" << expressions[0] << "]" <<
+    " @point " << "[" << point << "]" << " is " <<
+    "[" <<  vector_function.value(point) << "]" << std::endl;
+
+ * @endverbatim
+
+ * Units are similar to <b>constants</b> in the way they are passed to the
+ * parser, i.e. via std::map<std::string>.  But units are slightly different
+ * in that they have a higher precedence than any other operator
+ * (except parentheses). Thus for example "5/2in" is parsed as "5/(2*300)".
+ * (If 5/2 inches is what one wants, it has to be written "(5/2)in".)
+
+ * Overall, the main point of units is to make input expressions more readable
+ * since expressing, say, length as 10cm looks more natural than 10*cm.
+
+ * Beware that the user has full control over units as well as full
+ * responsibility for "sanity" of the parsed expressions, because the parser
+ * does NOT know anything about the physical nature of units and one would not
+ * be warned when adding kilometers to kilograms.
+
+ * <b>units</b> argument to the initialize function is <b>optional</b>, i.e. the
+ * user does NOT have to use this functionality.
+
+ * For more information on this feature, please see
+ * contrib/functionparser/fparser.txt
+
  * 
  * See http://warp.povusers.org/FunctionParser/ for an
  * explanation on how the underlying library works. 
@@ -369,6 +428,26 @@ class FunctionParser : public Function<dim>
                      const ConstMap                 &constants,
                      const bool time_dependent = false,
                      const bool use_degrees = false);
+
+
+                                     /**
+                                      * Initialize the function. Same as
+                                      * above, but with an additional argument
+                                      * <b> units </b> - 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<std::string> &expressions,
+                      const ConstMap                 &constants,
+                      const ConstMap                 &units,
+                      const bool time_dependent = false,
+                      const bool use_degrees = false);
   
                                      /**
                                       * Initialize the function. Same as
@@ -386,6 +465,18 @@ class FunctionParser : public Function<dim>
                      const std::string &expression,
                      const ConstMap    &constants,
                      const bool time_dependent = false,
+                     const bool use_degrees = false);
+
+                                     /**
+                                      * Initialize the function. Same as
+                                      * above, but with <b>units</b>.
+                                      */
+
+    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);
 
                                     /**
index e8a0f14cf6259032a3b77b602866393c8f6c9382..8d7410cb85deb188bec334840c48ee5c743f319c 100644 (file)
@@ -52,11 +52,28 @@ FunctionParser<dim>::~FunctionParser()
 
 
 #ifndef DEAL_II_DISABLE_PARSER
-
 template <int dim>
 void FunctionParser<dim>::initialize (const std::string                   &variables,
+                      const std::vector<std::string>      &expressions,
+                      const std::map<std::string, double> &constants,
+                      const bool time_dependent,
+                      const bool use_degrees)
+{
+    initialize (variables,
+                expressions,
+                constants,
+                std::map< std::string, double >(),
+                time_dependent,
+                use_degrees);  
+}
+
+
+
+template <int dim>
+void FunctionParser<dim>::initialize (const std::string   &variables,
                                      const std::vector<std::string>      &expressions,
                                      const std::map<std::string, double> &constants,
+                      const std::map<std::string, double> &units,
                                      const bool time_dependent,
                                      const bool use_degrees)
 {
@@ -68,9 +85,26 @@ void FunctionParser<dim>::initialize (const std::string                   &varia
   AssertThrow(this->n_components == expressions.size(),
              ExcInvalidExpressionSize(this->n_components,
                                       expressions.size()) );
-  
+
+
+
   for (unsigned int i=0; i<this->n_components; ++i)
     {
+
+                       // Add the various units to
+                       // the parser.
+        std::map< std::string, double >::const_iterator
+            unit = units.begin(),
+            endu = units.end();
+        for (; unit != endu; ++unit)
+        {
+            const bool success = fp[i].AddUnit(unit->first, unit->second);
+            AssertThrow (success,
+                         ExcMessage("Invalid Unit Name [error adding a unit]"));
+        }
+
+
+                       
                                       // Add the various constants to
                                       // the parser.
       std::map< std::string, double >::const_iterator
@@ -137,12 +171,32 @@ void FunctionParser<dim>::initialize (const std::string &variables,
   initialize (variables,
               Utilities::split_string_list (expression, ';'),
               constants,
-             time_dependent,
+              time_dependent,
               use_degrees);  
 }
 
 
 
+template <int dim>
+void FunctionParser<dim>::initialize (const std::string &variables,
+                      const std::string &expression,
+                      const std::map<std::string, double> &constants,
+                      const std::map<std::string, double> &units,
+                      const bool time_dependent,
+                      const bool use_degrees)
+{
+                   // initialize with the things
+                   // we got.
+  initialize (variables,
+              Utilities::split_string_list (expression, ';'),
+              constants,
+              units,
+              time_dependent,
+              use_degrees);
+}
+
+
+
 template <int dim>
 double FunctionParser<dim>::value (const Point<dim>  &p,
                                   const unsigned int component) const 
index 861b01458ea9da2c85f84fef0cb5bf21f16c4b9f..fd6eeafa1e4addb47bcdbe92b117cede8fff2490 100644 (file)
@@ -371,6 +371,15 @@ inconvenience this causes.
 <h3>base</h3>
 
 <ol>
+  <li>
+  <p>
+  New: The FunctionParser class now supports the fparser library's interface to use
+  units (like cm, or km) in expressions. An example is given in the documentation of
+  that class.
+  <br> 
+  (Victor Prosolin 2009/03/01)
+  </p>
+
   <li>
   <p>
   Changed: The classes Threads::ThreadMutex and Threads::ThreadCondition have
@@ -379,7 +388,7 @@ inconvenience this causes.
   <br> 
   (WB 2009/01/14)
   </p>
-
+  
   <li>
   <p>
   New: There is now a class TimerOutput that allows to neatly measure computing

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.

Douglas Adams


Typeset in Trocchi and Trocchi Bold Sans Serif.