Reference documentation for deal.II version 9.0.0
parsed_function.cc
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2007 - 2018 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE at
12 // the top level of the deal.II distribution.
13 //
14 // ---------------------------------------------------------------------
15 
16 #include <deal.II/base/parsed_function.h>
17 #include <deal.II/base/utilities.h>
18 
19 #include <cstdio>
20 
21 DEAL_II_NAMESPACE_OPEN
22 
23 namespace Functions
24 {
25  template <int dim>
26  ParsedFunction<dim>::ParsedFunction (const unsigned int n_components, const double h)
27  :
28  AutoDerivativeFunction<dim>(h, n_components),
29  function_object(n_components)
30  {}
31 
32 
33 
34  template <int dim>
35  void
37  const unsigned int n_components)
38  {
39  Assert(n_components > 0, ExcZero());
40 
41  std::string vnames;
42  switch (dim)
43  {
44  case 1:
45  vnames = "x,t";
46  break;
47  case 2:
48  vnames = "x,y,t";
49  break;
50  case 3:
51  vnames = "x,y,z,t";
52  break;
53  default:
55  break;
56  }
57  prm.declare_entry("Variable names", vnames, Patterns::Anything(),
58  "The names of the variables as they will be used in the "
59  "function, separated by commas. By default, the names of variables "
60  "at which the function will be evaluated are `x' (in 1d), `x,y' (in 2d) or "
61  "`x,y,z' (in 3d) for spatial coordinates and `t' for time. You can then "
62  "use these variable names in your function expression and they will be "
63  "replaced by the values of these variables at which the function is "
64  "currently evaluated. However, you can also choose a different set "
65  "of names for the independent variables at which to evaluate your function "
66  "expression. For example, if you work in spherical coordinates, you may "
67  "wish to set this input parameter to `r,phi,theta,t' and then use these "
68  "variable names in your function expression.");
69 
70  // The expression of the function
71  std::string expr = "0";
72  for (unsigned int i=1; i<n_components; ++i)
73  expr += "; 0";
74 
75  prm.declare_entry("Function expression", expr, Patterns::Anything(),
76  "The formula that denotes the function you want to evaluate for "
77  "particular values of the independent variables. This expression "
78  "may contain any of the usual operations such as addition or "
79  "multiplication, as well as all of the common functions such as "
80  "`sin' or `cos'. In addition, it may contain expressions like "
81  "`if(x>0, 1, -1)' where the expression evaluates to the second "
82  "argument if the first argument is true, and to the third argument "
83  "otherwise. For a full overview of possible expressions accepted "
84  "see the documentation of the muparser library at http://muparser.beltoforion.de/."
85  "\n\n"
86  "If the function you are describing represents a vector-valued "
87  "function with multiple components, then separate the expressions "
88  "for individual components by a semicolon.");
89  prm.declare_entry("Function constants", "", Patterns::Anything(),
90  "Sometimes it is convenient to use symbolic constants in the "
91  "expression that describes the function, rather than having to "
92  "use its numeric value everywhere the constant appears. These "
93  "values can be defined using this parameter, in the form "
94  "`var1=value1, var2=value2, ...'."
95  "\n\n"
96  "A typical example would be to set this runtime parameter to "
97  "`pi=3.1415926536' and then use `pi' in the expression of the "
98  "actual formula. (That said, for convenience this class actually "
99  "defines both `pi' and `Pi' by default, but you get the idea.)");
100  }
101 
102 
103 
104  template <int dim>
106  {
107  std::string vnames = prm.get("Variable names");
108  std::string expression = prm.get("Function expression");
109  std::string constants_list = prm.get("Function constants");
110 
111  std::vector<std::string> const_list =
112  Utilities::split_string_list(constants_list, ',');
113  std::map<std::string, double> constants;
114  for (unsigned int i = 0; i < const_list.size(); ++i)
115  {
116  std::vector<std::string> this_c =
117  Utilities::split_string_list(const_list[i], '=');
118  AssertThrow(this_c.size() == 2, ExcMessage("Invalid format"));
119  double tmp;
120  AssertThrow( std::sscanf(this_c[1].c_str(), "%lf", &tmp),
121  ExcMessage("Double number?"));
122  constants[this_c[0]] = tmp;
123  }
124 
125  // set pi and Pi as synonyms for the corresponding value. note that
126  // this overrides any value a user may have given
127  constants["pi"] = numbers::PI;
128  constants["Pi"] = numbers::PI;
129 
130  const unsigned int nn = (Utilities::split_string_list(vnames)).size();
131  switch (nn)
132  {
133  case dim:
134  // Time independent function
135  function_object.initialize(vnames, expression, constants);
136  break;
137  case dim+1:
138  // Time dependent function
139  function_object.initialize(vnames, expression, constants, true);
140  break;
141  default:
142  AssertThrow(false,
143  ExcMessage("The list of variables specified is <" + vnames
144  + "> which is a list of length "
146  + " but it has to be a list of length equal to"
147  + " either dim (for a time-independent function)"
148  + " or dim+1 (for a time-dependent function)."));
149  }
150  }
151 
152 
153 
154  template <int dim>
156  Vector<double> &values) const
157  {
158  function_object.vector_value(p, values);
159  }
160 
161 
162 
163  template <int dim>
165  unsigned int comp) const
166  {
167  return function_object.value(p, comp);
168  }
169 
170 
171 
172  template <int dim>
173  void ParsedFunction<dim>::set_time (const double newtime)
174  {
175  function_object.set_time(newtime);
177  }
178 
179 
180 // Explicit instantiations
181  template class ParsedFunction<1>;
182  template class ParsedFunction<2>;
183  template class ParsedFunction<3>;
184 }
185 DEAL_II_NAMESPACE_CLOSE
std::vector< std::string > split_string_list(const std::string &s, const std::string &delimiter=",")
Definition: utilities.cc:283
virtual double value(const Point< dim > &p, const unsigned int component=0) const
std::string get(const std::string &entry_string) const
#define AssertThrow(cond, exc)
Definition: exceptions.h:1221
static void declare_parameters(ParameterHandler &prm, const unsigned int n_components=1)
static const double PI
Definition: numbers.h:127
static ::ExceptionBase & ExcMessage(std::string arg1)
#define Assert(cond, exc)
Definition: exceptions.h:1142
virtual void vector_value(const Point< dim > &p, Vector< double > &values) const
void parse_parameters(ParameterHandler &prm)
std::string int_to_string(const unsigned int value, const unsigned int digits=numbers::invalid_unsigned_int)
Definition: utilities.cc:98
virtual void set_time(const Number new_time)
ParsedFunction(const unsigned int n_components=1, const double h=1e-8)
void declare_entry(const std::string &entry, const std::string &default_value, const Patterns::PatternBase &pattern=Patterns::Anything(), const std::string &documentation=std::string())
static ::ExceptionBase & ExcNotImplemented()
static ::ExceptionBase & ExcZero()
virtual void set_time(const double newtime)