version 3.11-dev
numericdifferentiation.hh
Go to the documentation of this file.
1// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2// vi: set et ts=4 sw=4 sts=4:
3//
4// SPDX-FileCopyrightText: Copyright © DuMux Project contributors, see AUTHORS.md in root folder
5// SPDX-License-Identifier: GPL-3.0-or-later
6//
13#ifndef DUMUX_NUMERIC_DIFFERENTIATION_HH
14#define DUMUX_NUMERIC_DIFFERENTIATION_HH
15
16#include <cmath>
17#include <cassert>
18#include <limits>
19
20namespace Dumux {
21
27{
28public:
29
35 template<class Scalar>
36 static Scalar epsilon(const Scalar value, const Scalar baseEps = 1e-10)
37 {
38 assert(std::numeric_limits<Scalar>::epsilon()*1e4 < baseEps);
39 // the epsilon value used for the numeric differentiation is
40 // now scaled by the absolute value of the primary variable...
41 using std::abs;
42 return baseEps*(abs(value) + 1.0);
43 }
44
49 template<class Function, class Scalar, class FunctionEvalType>
50 static void partialDerivative(const Function& function, Scalar x0,
51 FunctionEvalType& derivative,
52 const FunctionEvalType& fx0,
53 const int numericDifferenceMethod = 1)
54 { partialDerivative(function, x0, derivative, fx0, epsilon(x0), numericDifferenceMethod); }
55
66 template<class Function, class Scalar, class EpsType, class FunctionEvalType>
67 static void partialDerivative(const Function& function, Scalar x0,
68 FunctionEvalType& derivative,
69 const FunctionEvalType& fx0,
70 const EpsType eps,
71 const int numericDifferenceMethod = 1)
72 requires(
73 std::is_same_v<Scalar, decltype(std::declval<Scalar>() + std::declval<EpsType>())>
74 && std::is_same_v<Scalar, decltype(std::declval<Scalar>() - std::declval<EpsType>())>
75 ){
76 // Five-point stencil numeric difference,
77 // Abramowitz & Stegun, Table 25.2.
78 // The error is proportional to eps^4.
79 if (numericDifferenceMethod == 5)
80 {
81 derivative = function(x0 + eps);
82 derivative -= function(x0 - eps);
83 derivative *= 8.0;
84 derivative += function(x0 - 2.0*eps);
85 derivative -= function(x0 + 2.0*eps);
86 derivative /= 12.0*eps;
87 return;
88 }
89
90 // Forward, central, or backward differences
91 Scalar delta = 0.0;
92
93 // we are using forward or central differences, i.e. we need to calculate f(x + \epsilon)
94 if (numericDifferenceMethod >= 0)
95 {
96 delta += eps;
97 // calculate the function evaluated with the deflected variable
98 derivative = function(x0 + eps);
99 }
100
101 // we are using backward differences,
102 // i.e. we don't need to calculate f(x + \epsilon)
103 // we can recycle the (possibly cached) f(x)
104 else derivative = fx0;
105
106 // we are using backward or central differences,
107 // i.e. we need to calculate f(x - \epsilon)
108 if (numericDifferenceMethod <= 0)
109 {
110 delta += eps;
111 // subtract the function evaluated with the deflected variable
112 derivative -= function(x0 - eps);
113 }
114
115 // we are using forward differences,
116 // i.e. we don't need to calculate f(x - \epsilon)
117 // we can recycle the (possibly cached) f(x)
118 else derivative -= fx0;
119
120 // divide difference in residuals by the magnitude of the
121 // deflections between the two function evaluation
122 derivative /= delta;
123 }
124};
125
126} // end namespace Dumux
127
128#endif
A class for numeric differentiation with respect to a scalar parameter.
Definition: numericdifferentiation.hh:27
static void partialDerivative(const Function &function, Scalar x0, FunctionEvalType &derivative, const FunctionEvalType &fx0, const EpsType eps, const int numericDifferenceMethod=1)
Computes the derivative of a function with respect to a function parameter.
Definition: numericdifferentiation.hh:67
static Scalar epsilon(const Scalar value, const Scalar baseEps=1e-10)
Computes the epsilon used for numeric differentiation.
Definition: numericdifferentiation.hh:36
static void partialDerivative(const Function &function, Scalar x0, FunctionEvalType &derivative, const FunctionEvalType &fx0, const int numericDifferenceMethod=1)
Computes the derivative of a function with respect to a function parameter.
Definition: numericdifferentiation.hh:50
Definition: adapt.hh:17