56#ifndef DUMUX_COMMON_DOUBLEEXP_INTEGRATOR_HH
57#define DUMUX_COMMON_DOUBLEEXP_INTEGRATOR_HH
84 template<
class Function,
85 typename std::enable_if_t<std::is_invocable_r_v<Scalar, Function, Scalar>>...>
89 const Scalar targetAbsoluteError,
90 int& numFunctionEvaluations,
91 Scalar& errorEstimate)
97 const Scalar c = 0.5*(b - a);
98 const Scalar d = 0.5*(a + b);
99 return integrateCore_(f, c, d, targetAbsoluteError, numFunctionEvaluations, errorEstimate,
113 template<
class Function,
114 typename std::enable_if_t<std::is_invocable_r_v<Scalar, Function, Scalar>>...>
118 const Scalar targetAbsoluteError)
120 int numFunctionEvaluations;
121 Scalar errorEstimate;
122 return integrate(f, a, b, targetAbsoluteError, numFunctionEvaluations, errorEstimate);
127 template<
class Function>
128 static Scalar integrateCore_(
const Function& f,
131 Scalar targetAbsoluteError,
132 int& numFunctionEvaluations,
133 Scalar& errorEstimate,
134 const double* abcissas,
135 const double* weights)
137 targetAbsoluteError /= c;
141 static const int offsets[] = {1, 4, 7, 13, 25, 49, 97, 193};
142 static const int numLevels =
sizeof(offsets)/
sizeof(
int) - 1;
144 Scalar newContribution = 0.0;
145 Scalar integral = 0.0;
147 errorEstimate = std::numeric_limits<Scalar>::max();
148 Scalar previousDelta, currentDelta = std::numeric_limits<Scalar>::max();
150 integral = f(c*abcissas[0] + d) * weights[0];
152 for (i = offsets[0]; i != offsets[1]; ++i)
153 integral += weights[i]*(f(c*abcissas[i] + d) + f(-c*abcissas[i] + d));
155 for (
int level = 1; level != numLevels; ++level)
158 newContribution = 0.0;
159 for (i = offsets[level]; i != offsets[level+1]; ++i)
160 newContribution += weights[i]*(f(c*abcissas[i] + d) + f(-c*abcissas[i] + d));
161 newContribution *= h;
164 previousDelta = currentDelta;
166 currentDelta = abs(0.5*integral - newContribution);
167 integral = 0.5*integral + newContribution;
179 if (currentDelta == 0.0)
183 const Scalar rate = log( currentDelta )/log( previousDelta );
185 if (rate > 1.9 && rate < 2.1)
190 errorEstimate = currentDelta*currentDelta;
195 errorEstimate = currentDelta;
198 if (errorEstimate < 0.1*targetAbsoluteError)
202 numFunctionEvaluations = 2*i - 1;
Exponential integration abcissas.
Adaption of the non-isothermal two-phase two-component flow model to problems with CO2.
Definition: adapt.hh:29
constexpr double doubleExponentialIntegrationWeights[]
Definition: doubleexpintegrationconstants.hh:296
constexpr double doubleExponentialIntegrationAbcissas[]
Definition: doubleexpintegrationconstants.hh:92
Numerical integration in one dimension using the double exponential method of M. Mori.
Definition: doubleexpintegrator.hh:72
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:86
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:115