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