Comparison with Python¶
This page documents the Python script compute_integral.py, which re-runs numerical integrations on data generated by the C++ program and compares those results against the C++ outputs.
Numerical integration in Python¶
The script imports:
The trapezoidal rule is implemented using scipy.integrate.trapezoid, and Simpson's rule is implemented using scipy.integrate.simpson. Instead, Romberg integration is not directly available in SciPy, so we implement it manually.
Romberg integration in Python¶
The Romberg integration method is implemented in Python as follows:
# ============================
# Romberg integration function
# ============================
def romberg(f, a, b, tol=ROMBERG_TOL, rtol=ROMBERG_RTOL, divmax=ROMBERG_DIVMAX):
"""
Compute the Romberg integration of function f on the interval [a, b]
using the trapezoidal rule and Richardson extrapolation.
"""
R = [] # Romberg table: a list of lists
R.append([(b - a) * (f(a) + f(b)) / 2.0])
for i in range(1, divmax):
n_intervals = 2**i
h = (b - a) / n_intervals
sum_ = 0.0
for k in range(1, n_intervals, 2):
sum_ += f(a + k * h)
R0 = 0.5 * R[i-1][0] + h * sum_
row = [R0]
for j in range(1, i+1):
factor = 4**j
extrap = row[j-1] + (row[j-1] - R[i-1][j-1]) / (factor - 1.0)
row.append(extrap)
R.append(row)
if i > 0 and abs(R[i][i] - R[i-1][i-1]) < tol:
return R[i][i]
return R[-1][-1]
Comparison with C++ results¶
The script reads the sampled data from the C++ output files and computes the integrals using the same methods as in C++. The results are then compared:
The script then computes the integrals:
N_AB = int(round((B - A) / dx)) + 1
integral_trapz = trapezoid(fx_subset, x_subset)
integral_simpson = simpson(fx_subset, x_subset)
f_interp = interp1d(x_subset, fx_subset, kind='cubic', fill_value="extrapolate")
integral_romberg = romberg(f_interp, A, B, tol=ROMBERG_TOL, rtol=ROMBERG_RTOL, divmax=ROMBERG_DIVMAX)
Finally, the script computes the absolute errors between C++ and Python results: