deal.II version GIT relicensing-6834-g5b78e6bcdf 2026-10-01 11:20:01+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\}}\)
Loading...
Searching...
No Matches
auto_derivative_function.cc
Go to the documentation of this file.
1// -----------------------------------------------------------------------------
2//
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception OR LGPL-2.1-or-later
4// Copyright (C) 2001 - 2024 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Detailed license information governing the source code and contributions
9// can be found in LICENSE.md and CONTRIBUTING.md at the top level directory.
10//
11// -----------------------------------------------------------------------------
12
14#include <deal.II/base/point.h>
15
16#include <deal.II/lac/vector.h>
17
18#include <cmath>
19
21
22template <int dim>
24 const double hh,
25 const unsigned int n_components,
26 const double initial_time)
27 : Function<dim>(n_components, initial_time)
28 , h(1)
29 , ht(dim)
30 , formula(Euler)
31{
32 set_h(hh);
34}
35
36
37
38template <int dim>
39void
41{
42 // go through all known formulas, reject ones we don't know about
43 // and don't handle in the member functions of this class
44 switch (form)
45 {
46 case Euler:
47 case UpwindEuler:
48 case FourthOrder:
49 break;
50 default:
51 Assert(false,
52 ExcMessage("The argument passed to this function does not "
53 "match any known difference formula."));
54 }
55
56 formula = form;
57}
58
59
60template <int dim>
61void
63{
64 h = hh;
65 for (unsigned int i = 0; i < dim; ++i)
66 ht[i][i] = h;
67}
68
69
70template <int dim>
73 const unsigned int comp) const
74{
75 Tensor<1, dim> grad;
76 switch (formula)
77 {
78 case UpwindEuler:
79 {
80 Point<dim> q1;
81 for (unsigned int i = 0; i < dim; ++i)
82 {
83 q1 = p - ht[i];
84 grad[i] = (this->value(p, comp) - this->value(q1, comp)) / h;
85 }
86 break;
87 }
88 case Euler:
89 {
90 Point<dim> q1, q2;
91 for (unsigned int i = 0; i < dim; ++i)
92 {
93 q1 = p + ht[i];
94 q2 = p - ht[i];
95 grad[i] =
96 (this->value(q1, comp) - this->value(q2, comp)) / (2 * h);
97 }
98 break;
99 }
100 case FourthOrder:
101 {
102 Point<dim> q1, q2, q3, q4;
103 for (unsigned int i = 0; i < dim; ++i)
104 {
105 q2 = p + ht[i];
106 q1 = q2 + ht[i];
107 q3 = p - ht[i];
108 q4 = q3 - ht[i];
109 grad[i] = (-this->value(q1, comp) + 8 * this->value(q2, comp) -
110 8 * this->value(q3, comp) + this->value(q4, comp)) /
111 (12 * h);
112 }
113 break;
114 }
115 default:
117 }
118 return grad;
119}
120
121
122template <int dim>
123void
125 const Point<dim> &p,
126 std::vector<Tensor<1, dim>> &gradients) const
127{
128 Assert(gradients.size() == this->n_components,
129 ExcDimensionMismatch(gradients.size(), this->n_components));
130
131 switch (formula)
132 {
133 case UpwindEuler:
134 {
135 Point<dim> q1;
136 Vector<double> v(this->n_components), v1(this->n_components);
137 const double h_inv = 1. / h;
138 for (unsigned int i = 0; i < dim; ++i)
139 {
140 q1 = p - ht[i];
141 this->vector_value(p, v);
142 this->vector_value(q1, v1);
143
144 for (unsigned int comp = 0; comp < this->n_components; ++comp)
145 gradients[comp][i] = (v(comp) - v1(comp)) * h_inv;
146 }
147 break;
148 }
149
150 case Euler:
151 {
152 Point<dim> q1, q2;
153 Vector<double> v1(this->n_components), v2(this->n_components);
154 const double h_inv_2 = 1. / (2 * h);
155 for (unsigned int i = 0; i < dim; ++i)
156 {
157 q1 = p + ht[i];
158 q2 = p - ht[i];
159 this->vector_value(q1, v1);
160 this->vector_value(q2, v2);
161
162 for (unsigned int comp = 0; comp < this->n_components; ++comp)
163 gradients[comp][i] = (v1(comp) - v2(comp)) * h_inv_2;
164 }
165 break;
166 }
167
168 case FourthOrder:
169 {
170 Point<dim> q1, q2, q3, q4;
171 Vector<double> v1(this->n_components), v2(this->n_components),
172 v3(this->n_components), v4(this->n_components);
173 const double h_inv_12 = 1. / (12 * h);
174 for (unsigned int i = 0; i < dim; ++i)
175 {
176 q2 = p + ht[i];
177 q1 = q2 + ht[i];
178 q3 = p - ht[i];
179 q4 = q3 - ht[i];
180 this->vector_value(q1, v1);
181 this->vector_value(q2, v2);
182 this->vector_value(q3, v3);
183 this->vector_value(q4, v4);
184
185 for (unsigned int comp = 0; comp < this->n_components; ++comp)
186 gradients[comp][i] =
187 (-v1(comp) + 8 * v2(comp) - 8 * v3(comp) + v4(comp)) *
188 h_inv_12;
189 }
190 break;
191 }
192
193 default:
195 }
196}
197
198
199template <int dim>
200void
202 const std::vector<Point<dim>> &points,
203 std::vector<Tensor<1, dim>> &gradients,
204 const unsigned int comp) const
205{
206 Assert(gradients.size() == points.size(),
207 ExcDimensionMismatch(gradients.size(), points.size()));
208
209 switch (formula)
210 {
211 case UpwindEuler:
212 {
213 Point<dim> q1;
214 for (unsigned int p = 0; p < points.size(); ++p)
215 for (unsigned int i = 0; i < dim; ++i)
216 {
217 q1 = points[p] - ht[i];
218 gradients[p][i] =
219 (this->value(points[p], comp) - this->value(q1, comp)) / h;
220 }
221 break;
222 }
223
224 case Euler:
225 {
226 Point<dim> q1, q2;
227 for (unsigned int p = 0; p < points.size(); ++p)
228 for (unsigned int i = 0; i < dim; ++i)
229 {
230 q1 = points[p] + ht[i];
231 q2 = points[p] - ht[i];
232 gradients[p][i] =
233 (this->value(q1, comp) - this->value(q2, comp)) / (2 * h);
234 }
235 break;
236 }
237
238 case FourthOrder:
239 {
240 Point<dim> q1, q2, q3, q4;
241 for (unsigned int p = 0; p < points.size(); ++p)
242 for (unsigned int i = 0; i < dim; ++i)
243 {
244 q2 = points[p] + ht[i];
245 q1 = q2 + ht[i];
246 q3 = points[p] - ht[i];
247 q4 = q3 - ht[i];
248 gradients[p][i] =
249 (-this->value(q1, comp) + 8 * this->value(q2, comp) -
250 8 * this->value(q3, comp) + this->value(q4, comp)) /
251 (12 * h);
252 }
253 break;
254 }
255
256 default:
258 }
259}
260
261
262
263template <int dim>
264void
266 const std::vector<Point<dim>> &points,
267 std::vector<std::vector<Tensor<1, dim>>> &gradients) const
268{
269 Assert(gradients.size() == points.size(),
270 ExcDimensionMismatch(gradients.size(), points.size()));
271 for (unsigned int p = 0; p < points.size(); ++p)
272 Assert(gradients[p].size() == this->n_components,
273 ExcDimensionMismatch(gradients.size(), this->n_components));
274
275 switch (formula)
276 {
277 case UpwindEuler:
278 {
279 Point<dim> q1;
280 for (unsigned int p = 0; p < points.size(); ++p)
281 for (unsigned int i = 0; i < dim; ++i)
282 {
283 q1 = points[p] - ht[i];
284 for (unsigned int comp = 0; comp < this->n_components; ++comp)
285 gradients[p][comp][i] =
286 (this->value(points[p], comp) - this->value(q1, comp)) / h;
287 }
288 break;
289 }
290
291 case Euler:
292 {
293 Point<dim> q1, q2;
294 for (unsigned int p = 0; p < points.size(); ++p)
295 for (unsigned int i = 0; i < dim; ++i)
296 {
297 q1 = points[p] + ht[i];
298 q2 = points[p] - ht[i];
299 for (unsigned int comp = 0; comp < this->n_components; ++comp)
300 gradients[p][comp][i] =
301 (this->value(q1, comp) - this->value(q2, comp)) / (2 * h);
302 }
303 break;
304 }
305
306 case FourthOrder:
307 {
308 Point<dim> q1, q2, q3, q4;
309 for (unsigned int p = 0; p < points.size(); ++p)
310 for (unsigned int i = 0; i < dim; ++i)
311 {
312 q2 = points[p] + ht[i];
313 q1 = q2 + ht[i];
314 q3 = points[p] - ht[i];
315 q4 = q3 - ht[i];
316 for (unsigned int comp = 0; comp < this->n_components; ++comp)
317 gradients[p][comp][i] =
318 (-this->value(q1, comp) + 8 * this->value(q2, comp) -
319 8 * this->value(q3, comp) + this->value(q4, comp)) /
320 (12 * h);
321 }
322 break;
323 }
324
325 default:
327 }
328}
329
330
331template <int dim>
334{
335 switch (ord)
336 {
337 case 0:
338 case 1:
339 return UpwindEuler;
340 case 2:
341 return Euler;
342 case 3:
343 case 4:
344 return FourthOrder;
345 default:
347 }
348 return Euler;
349}
350
351
352template class AutoDerivativeFunction<1>;
353template class AutoDerivativeFunction<2>;
354template class AutoDerivativeFunction<3>;
355
AutoDerivativeFunction(const double h, const unsigned int n_components=1, const double initial_time=0.0)
virtual Tensor< 1, dim > gradient(const Point< dim > &p, const unsigned int component=0) const override
virtual void vector_gradient(const Point< dim > &p, std::vector< Tensor< 1, dim > > &gradients) const override
virtual void vector_gradient_list(const std::vector< Point< dim > > &points, std::vector< std::vector< Tensor< 1, dim > > > &gradients) const override
void set_formula(const DifferenceFormula formula=Euler)
virtual void gradient_list(const std::vector< Point< dim > > &points, std::vector< Tensor< 1, dim > > &gradients, const unsigned int component=0) const override
static DifferenceFormula get_formula_of_order(const unsigned int ord)
Definition point.h:111
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:38
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
#define DEAL_II_NOT_IMPLEMENTED()
const unsigned int v1
#define Assert(cond, exc)
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
static ::ExceptionBase & ExcMessage(std::string arg1)
std::size_t size
Definition mpi.cc:733