Reference documentation for deal.II version 9.4.0
\(\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
19#include <cstdio>
20
22
23namespace Functions
24{
25 template <int dim>
26 ParsedFunction<dim>::ParsedFunction(const unsigned int n_components,
27 const double h)
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(
58 "Variable names",
59 vnames,
61 "The names of the variables as they will be used in the "
62 "function, separated by commas. By default, the names of variables "
63 "at which the function will be evaluated are `x' (in 1d), `x,y' (in 2d) or "
64 "`x,y,z' (in 3d) for spatial coordinates and `t' for time. You can then "
65 "use these variable names in your function expression and they will be "
66 "replaced by the values of these variables at which the function is "
67 "currently evaluated. However, you can also choose a different set "
68 "of names for the independent variables at which to evaluate your function "
69 "expression. For example, if you work in spherical coordinates, you may "
70 "wish to set this input parameter to `r,phi,theta,t' and then use these "
71 "variable names in your function expression.");
72
73 // The expression of the function
74 std::string expr = "0";
75 for (unsigned int i = 1; i < n_components; ++i)
76 expr += "; 0";
77
78 prm.declare_entry(
79 "Function expression",
80 expr,
82 "The formula that denotes the function you want to evaluate for "
83 "particular values of the independent variables. This expression "
84 "may contain any of the usual operations such as addition or "
85 "multiplication, as well as all of the common functions such as "
86 "`sin' or `cos'. In addition, it may contain expressions like "
87 "`if(x>0, 1, -1)' where the expression evaluates to the second "
88 "argument if the first argument is true, and to the third argument "
89 "otherwise. For a full overview of possible expressions accepted "
90 "see the documentation of the muparser library at http://muparser.beltoforion.de/."
91 "\n\n"
92 "If the function you are describing represents a vector-valued "
93 "function with multiple components, then separate the expressions "
94 "for individual components by a semicolon.");
95 prm.declare_entry(
96 "Function constants",
97 "",
99 "Sometimes it is convenient to use symbolic constants in the "
100 "expression that describes the function, rather than having to "
101 "use its numeric value everywhere the constant appears. These "
102 "values can be defined using this parameter, in the form "
103 "`var1=value1, var2=value2, ...'."
104 "\n\n"
105 "A typical example would be to set this runtime parameter to "
106 "`pi=3.1415926536' and then use `pi' in the expression of the "
107 "actual formula. (That said, for convenience this class actually "
108 "defines both `pi' and `Pi' by default, but you get the idea.)");
109 }
110
111
112
113 template <int dim>
114 void
116 {
117 std::string vnames = prm.get("Variable names");
118 std::string expression = prm.get("Function expression");
119 std::string constants_list = prm.get("Function constants");
120
121 std::vector<std::string> const_list =
122 Utilities::split_string_list(constants_list, ',');
123 std::map<std::string, double> constants;
124 for (const auto &constant : const_list)
125 {
126 std::vector<std::string> this_c =
127 Utilities::split_string_list(constant, '=');
128 AssertThrow(this_c.size() == 2, ExcMessage("Invalid format"));
129 double tmp;
130 AssertThrow(std::sscanf(this_c[1].c_str(), "%lf", &tmp),
131 ExcMessage("Double number?"));
132 constants[this_c[0]] = tmp;
133 }
134
135 // set pi and Pi as synonyms for the corresponding value. note that
136 // this overrides any value a user may have given
137 constants["pi"] = numbers::PI;
138 constants["Pi"] = numbers::PI;
139
140 const unsigned int nn = (Utilities::split_string_list(vnames)).size();
141 switch (nn)
142 {
143 case dim:
144 // Time independent function
145 function_object.initialize(vnames, expression, constants);
146 break;
147 case dim + 1:
148 // Time dependent function
149 function_object.initialize(vnames, expression, constants, true);
150 break;
151 default:
152 AssertThrow(false,
154 "The list of variables specified is <" + vnames +
155 "> which is a list of length " +
157 " but it has to be a list of length equal to" +
158 " either dim (for a time-independent function)" +
159 " or dim+1 (for a time-dependent function)."));
160 }
161 }
162
163
164
165 template <int dim>
166 void
168 Vector<double> & values) const
169 {
170 function_object.vector_value(p, values);
171 }
172
173
174
175 template <int dim>
176 double
177 ParsedFunction<dim>::value(const Point<dim> &p, unsigned int comp) const
178 {
179 return function_object.value(p, comp);
180 }
181
182
183
184 template <int dim>
185 void
186 ParsedFunction<dim>::set_time(const double newtime)
187 {
188 function_object.set_time(newtime);
190 }
191
192
193 // Explicit instantiations
194 template class ParsedFunction<1>;
195 template class ParsedFunction<2>;
196 template class ParsedFunction<3>;
197} // 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:442
#define DEAL_II_NAMESPACE_CLOSE
Definition: config.h:443
static ::ExceptionBase & ExcZero()
static ::ExceptionBase & ExcNotImplemented()
#define Assert(cond, exc)
Definition: exceptions.h:1473
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
Definition: exceptions.h:1583
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:233