Romberg integration
This page explains the Romberg integration method implemented in Integrator::integrateRomberg()
, which uses Richardson extrapolation on trapezoidal estimates to achieve high accuracy.
All code is found in include/Integrator.hpp
.
Method outline
Romberg integration combines the trapezoidal rule with Richardson extrapolation to improve accuracy. It builds a table of estimates, refining them iteratively:
\[
R_{k,0}=T(h_k)
\]
with \(h_k=(b-a)/2^k\) and \(T(h_k)\) being the trapezoidal estimate with step size \(h_k\). Extrapolation then gives:
\[
R_{k,j} = R_{k,j-1} + \frac{R_{k,j-1} - R_{k-1,j-1}}{4^j - 1}
\]
for \(j=1,2,\ldots,k\).
Implementation details
The implementation in Integrator::integrateRomberg()
constructs the Romberg table and performs extrapolation:
Integrator.hpp |
---|
| // Romberg integration to desired depth 'm'.
double integrateRomberg(double a, double b, int maxIter = 5, double tol = 1e-12) const {
// Allocate a Romberg table R with dimensions maxIter x maxIter.
std::vector<std::vector<double>> R(maxIter, std::vector<double>(maxIter, 0.0));
// Initial trapezoidal rule: use 2^0 segments => n = 2 points.
int n = 2;
R[0][0] = integrateTrapz(a, b, n);
// Build the Romberg table.
for (int i = 1; i < maxIter; ++i) {
// Use 2^i segments, which means n = 2^i + 1 sampling points.
n = (1 << i) + 1; // 1<<i computes 2^i.
R[i][0] = integrateTrapz(a, b, n);
// Apply Richardson extrapolation.
for (int j = 1; j <= i; ++j) {
double factor = std::pow(4.0, j);
R[i][j] = R[i][j-1] + (R[i][j-1] - R[i-1][j-1]) / (factor - 1.0);
}
// Check for convergence between the last diagonal elements.
if (std::fabs(R[i][i] - R[i-1][i-1]) < tol) {
return R[i][i];
}
}
return R[maxIter-1][maxIter-1];
}
|