Exact patch tests¶
Question: does the code reproduce, to round-off, a solution it should get exactly?
For an explicit Runge-Kutta method, a solution linear in t is reproduced exactly for every step size, provided the right-hand side is right, the stage times match the table and the weights sum to one. The expected error is zero, not small, so bugs that are as small as the method's own error still show.
Example: a stage evaluated at the wrong time¶
"""A patch test: a straight-line solution that the midpoint method must reproduce to round-off."""
import numpy as np
from physverify.studies import patch_study
def make(buggy):
def integrate(source, y0, t_end, n):
h, y = t_end / n, np.array(y0, dtype=float)
def f(t, y):
return np.array([y[1], -y[0]]) + source(t)
for k in range(n):
t = k * h
tm = t + (0.4 if buggy else 0.5) * h # bug: the midpoint stage is evaluated at the wrong time
y = y + h * f(tm, y + 0.5 * h * f(t, y))
return y
return integrate
def rhs_ref(t, y):
return np.array([y[1], -y[0]])
for buggy in (False, True):
r = patch_study(make(buggy), rhs_ref, np.array([0.5, -0.3]), np.array([0.8, 1.1]), 1.0, [10, 20, 40])
print("buggy: " if buggy else "correct:", r.status, "-", r.message)
Output:
correct: EXACT - reproduced to round-off (largest error 6.7e-16), as designed
buggy: FAIL - expected an exact solution to round-off, but the error reaches 0.0115 and shrinks at about order 0.99
The bug shifts the midpoint stage from t + h/2 to t + 0.4 h. On a smooth problem this costs a little accuracy and might go unnoticed; on the patch solution it is a clear error.
Using it¶
patch_study(integrate, rhs_ref, y0, slope, t_end, ns) builds the source term for u(t) = y0 + slope * t and expects round-off error at every n. ode_checks(..., patch=(y0, slope)) adds it to the standard bundle.
The exact conditions, the proof and the heat-equation version are on Patch test theory.