50#ifndef DUMUX_COMMON_DOUBLEEXP_INTEGRATOR_HH
51#define DUMUX_COMMON_DOUBLEEXP_INTEGRATOR_HH
78 template<
class Function,
79 typename std::enable_if_t<std::is_invocable_r_v<Scalar, Function, Scalar>>...>
83 const Scalar targetAbsoluteError,
84 int& numFunctionEvaluations,
85 Scalar& errorEstimate)
91 const Scalar c = 0.5*(b - a);
92 const Scalar d = 0.5*(a + b);
93 return integrateCore_(f, c, d, targetAbsoluteError, numFunctionEvaluations, errorEstimate,
107 template<
class Function,
108 typename std::enable_if_t<std::is_invocable_r_v<Scalar, Function, Scalar>>...>
112 const Scalar targetAbsoluteError)
114 int numFunctionEvaluations;
115 Scalar errorEstimate;
116 return integrate(f, a, b, targetAbsoluteError, numFunctionEvaluations, errorEstimate);
121 template<
class Function>
122 static Scalar integrateCore_(
const Function& f,
125 Scalar targetAbsoluteError,
126 int& numFunctionEvaluations,
127 Scalar& errorEstimate,
128 const double* abcissas,
129 const double* weights)
131 targetAbsoluteError /= c;
135 static const int offsets[] = {1, 4, 7, 13, 25, 49, 97, 193};
136 static const int numLevels =
sizeof(offsets)/
sizeof(
int) - 1;
138 Scalar newContribution = 0.0;
139 Scalar integral = 0.0;
141 errorEstimate = std::numeric_limits<Scalar>::max();
142 Scalar previousDelta, currentDelta = std::numeric_limits<Scalar>::max();
144 integral = f(c*abcissas[0] + d) * weights[0];
146 for (i = offsets[0]; i != offsets[1]; ++i)
147 integral += weights[i]*(f(c*abcissas[i] + d) + f(-c*abcissas[i] + d));
149 for (
int level = 1; level != numLevels; ++level)
152 newContribution = 0.0;
153 for (i = offsets[level]; i != offsets[level+1]; ++i)
154 newContribution += weights[i]*(f(c*abcissas[i] + d) + f(-c*abcissas[i] + d));
155 newContribution *= h;
158 previousDelta = currentDelta;
160 currentDelta = abs(0.5*integral - newContribution);
161 integral = 0.5*integral + newContribution;
173 if (currentDelta == 0.0)
177 const Scalar rate = log( currentDelta )/log( previousDelta );
179 if (rate > 1.9 && rate < 2.1)
184 errorEstimate = currentDelta*currentDelta;
189 errorEstimate = currentDelta;
192 if (errorEstimate < 0.1*targetAbsoluteError)
196 numFunctionEvaluations = 2*i - 1;
Numerical integration in one dimension using the double exponential method of M. Mori.
Definition: doubleexpintegrator.hh:66
static Scalar integrate(const Function &f, const Scalar a, const Scalar b, const Scalar targetAbsoluteError, int &numFunctionEvaluations, Scalar &errorEstimate)
Integrate an analytic function over a finite interval.
Definition: doubleexpintegrator.hh:80
static Scalar integrate(const Function &f, const Scalar a, const Scalar b, const Scalar targetAbsoluteError)
Integrate an analytic function over a finite interval.
Definition: doubleexpintegrator.hh:109
Exponential integration abcissas.
constexpr double doubleExponentialIntegrationWeights[]
Definition: doubleexpintegrationconstants.hh:290
constexpr double doubleExponentialIntegrationAbcissas[]
Definition: doubleexpintegrationconstants.hh:86