FA-69521 / Orbital propagation / Open access
Fixed-step RK4 two-body propagation: Second RK4 stage samples a full step ahead · case 01
The integrator degrades to low order and orbits drift.
ROOT CAUSE
k2 is evaluated at s+h*k1 instead of the midpoint.
VERIFIED REPAIR
Evaluate k2 at s+h/2*k1.
Unsuccessful approach: A quarter-step probe is equally inconsistent with the RK4 weights.
Case contract
Input [r0, v0, mu, T, steps] for a planar two-body orbit. Integrate state [x,y,vx,vy] with acceleration -mu r/|r|^3 using classical RK4 with h=T/steps for exactly steps steps. Return the final state rounded to 6 decimals.
Why this case matters
Orbit determination and mission planning chain many small conversions; one wrong branch or unit silently moves a spacecraft by kilometres.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
r0,v0,mu,T,steps=x
h=T/steps
def f(s):
px,py,vx,vy=s
rr=(px*px+py*py)**1.5
return [vx,vy,-mu*px/rr,-mu*py/rr]
s=list(r0)+list(v0)
for _ in range(steps):
k1=f(s)
k2=f([s[i]+h*k1[i] for i in range(4)])
k3=f([s[i]+h/2*k2[i] for i in range(4)])
k4=f([s[i]+h*k3[i] for i in range(4)])
s=[s[i]+h/6*(k1[i]+2*k2[i]+2*k3[i]+k4[i]) for i in range(4)]
return [round(c,6) for c in s]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('fixed-step rk4 two-body propagation [[7000.0, 0.0], [0.0, 7.546], 398600.4418, 600.0, 12]', [[7000.0, 0.0], [0.0, 7.546], 398600.4418, 600.0, 12], [5586.092992, 4218.445527, -4.547562, 6.021804]), ('fixed-step rk4 two-body propagation [[7000.0, 0.0], [0.0, 8.5], 398600.4418, 900.0, 20]', [[7000.0, 0.0], [0.0, 8.5], 398600.4418, 900.0, 20], [4101.15166, 6610.394483, -5.692596, 5.332573]), ('fixed-step rk4 two-body propagation [[0.0, 9000.0], [-6.2, 0.8], 398600.4418, 1200.0, 15]', [[0.0, 9000.0], [-6.2, 0.8], 398600.4418, 1200.0, 15], [-6593.162659, 6759.502773, -4.170281, -4.18782]), ('fixed-step rk4 two-body propagation [[1.0, 0.0], [0.0, 1.0], 1.0, 3.0, 30]', [[1.0, 0.0], [0.0, 1.0], 1.0, 3.0, 30], [-0.98999, 0.141112, -0.141113, -0.989997]), ('fixed-step rk4 two-body propagation [[1.0, 0.0], [0.0, 1.2], 1.0, 5.0, 25]', [[1.0, 0.0], [0.0, 1.2], 1.0, 5.0, 25], [-2.095663, 1.089551, -0.384431, -0.37274]), ('fixed-step rk4 two-body propagation [[-1.5, 0.5], [0.1, -0.7], 1.0, 2.0, 10]', [[-1.5, 0.5], [0.1, -0.7], 1.0, 2.0, 10], [-0.154684, -0.721678, 1.394034, 0.039166]), ('fixed-step rk4 two-body propagation [[6800.0, 1200.0], [-1.1, 7.4], 398600.4418, 300.0, 6]', [[6800.0, 1200.0], [-1.1, 7.4], 398600.4418, 300.0, 6], [6111.623093, 3316.078893, -3.439749, 6.583115])], [('fixed-step rk4 two-body propagation [[7000.0, 0.0], [0.0, 8.5], 398600.4418, 900.0, 20]', [[7000.0, 0.0], [0.0, 8.5], 398600.4418, 900.0, 20], [4101.15166, 6610.394483, -5.692596, 5.332573]), ('fixed-step rk4 two-body propagation [[1.0, 0.0], [0.0, 1.0], 1.0, 3.0, 30]', [[1.0, 0.0], [0.0, 1.0], 1.0, 3.0, 30], [-0.98999, 0.141112, -0.141113, -0.989997]), ('fixed-step rk4 two-body propagation [[1.0, 0.0], [0.0, 1.2], 1.0, 5.0, 25]', [[1.0, 0.0], [0.0, 1.2], 1.0, 5.0, 25], [-2.095663, 1.089551, -0.384431, -0.37274]), ('fixed-step rk4 two-body propagation [[-1.5, 0.5], [0.1, -0.7], 1.0, 2.0, 10]', [[-1.5, 0.5], [0.1, -0.7], 1.0, 2.0, 10], [-0.154684, -0.721678, 1.394034, 0.039166]), ('fixed-step rk4 two-body propagation [[6800.0, 1200.0], [-1.1, 7.4], 398600.4418, 300.0, 6]', [[6800.0, 1200.0], [-1.1, 7.4], 398600.4418, 300.0, 6], [6111.623093, 3316.078893, -3.439749, 6.583115]), ('fixed-step rk4 two-body propagation [[2.0, 0.0], [0.0, 0.5], 1.0, 4.0, 8]', [[2.0, 0.0], [0.0, 0.5], 1.0, 4.0, 8], [-0.108631, 0.939625, -0.993051, -0.614991]), ('fixed-step rk4 two-body propagation [[7000.0, 0.0], [0.0, 7.546], 398600.4418, 600.0, 12]', [[7000.0, 0.0], [0.0, 7.546], 398600.4418, 600.0, 12], [5586.092992, 4218.445527, -4.547562, 6.021804])], [('fixed-step rk4 two-body propagation [[0.0, 9000.0], [-6.2, 0.8], 398600.4418, 1200.0, 15]', [[0.0, 9000.0], [-6.2, 0.8], 398600.4418, 1200.0, 15], [-6593.162659, 6759.502773, -4.170281, -4.18782]), ('fixed-step rk4 two-body propagation [[6800.0, 1200.0], [-1.1, 7.4], 398600.4418, 300.0, 6]', [[6800.0, 1200.0], [-1.1, 7.4], 398600.4418, 300.0, 6], [6111.623093, 3316.078893, -3.439749, 6.583115]), ('fixed-step rk4 two-body propagation [[2.0, 0.0], [0.0, 0.5], 1.0, 4.0, 8]', [[2.0, 0.0], [0.0, 0.5], 1.0, 4.0, 8], [-0.108631, 0.939625, -0.993051, -0.614991]), ('fixed-step rk4 two-body propagation [[7000.0, 0.0], [0.0, 7.546], 398600.4418, 600.0, 12]', [[7000.0, 0.0], [0.0, 7.546], 398600.4418, 600.0, 12], [5586.092992, 4218.445527, -4.547562, 6.021804]), ('fixed-step rk4 two-body propagation [[7000.0, 0.0], [0.0, 8.5], 398600.4418, 900.0, 20]', [[7000.0, 0.0], [0.0, 8.5], 398600.4418, 900.0, 20], [4101.15166, 6610.394483, -5.692596, 5.332573]), ('fixed-step rk4 two-body propagation [[1.0, 0.0], [0.0, 1.0], 1.0, 3.0, 30]', [[1.0, 0.0], [0.0, 1.0], 1.0, 3.0, 30], [-0.98999, 0.141112, -0.141113, -0.989997]), ('fixed-step rk4 two-body propagation [[1.0, 0.0], [0.0, 1.2], 1.0, 5.0, 25]', [[1.0, 0.0], [0.0, 1.2], 1.0, 5.0, 25], [-2.095663, 1.089551, -0.384431, -0.37274])], [('fixed-step rk4 two-body propagation [[1.0, 0.0], [0.0, 1.0], 1.0, 3.0, 30]', [[1.0, 0.0], [0.0, 1.0], 1.0, 3.0, 30], [-0.98999, 0.141112, -0.141113, -0.989997]), ('fixed-step rk4 two-body propagation [[7000.0, 0.0], [0.0, 8.5], 398600.4418, 900.0, 20]', [[7000.0, 0.0], [0.0, 8.5], 398600.4418, 900.0, 20], [4101.15166, 6610.394483, -5.692596, 5.332573]), ('fixed-step rk4 two-body propagation [[0.0, 9000.0], [-6.2, 0.8], 398600.4418, 1200.0, 15]', [[0.0, 9000.0], [-6.2, 0.8], 398600.4418, 1200.0, 15], [-6593.162659, 6759.502773, -4.170281, -4.18782]), ('fixed-step rk4 two-body propagation [[1.0, 0.0], [0.0, 1.2], 1.0, 5.0, 25]', [[1.0, 0.0], [0.0, 1.2], 1.0, 5.0, 25], [-2.095663, 1.089551, -0.384431, -0.37274]), ('fixed-step rk4 two-body propagation [[-1.5, 0.5], [0.1, -0.7], 1.0, 2.0, 10]', [[-1.5, 0.5], [0.1, -0.7], 1.0, 2.0, 10], [-0.154684, -0.721678, 1.394034, 0.039166]), ('fixed-step rk4 two-body propagation [[6800.0, 1200.0], [-1.1, 7.4], 398600.4418, 300.0, 6]', [[6800.0, 1200.0], [-1.1, 7.4], 398600.4418, 300.0, 6], [6111.623093, 3316.078893, -3.439749, 6.583115]), ('fixed-step rk4 two-body propagation [[2.0, 0.0], [0.0, 0.5], 1.0, 4.0, 8]', [[2.0, 0.0], [0.0, 0.5], 1.0, 4.0, 8], [-0.108631, 0.939625, -0.993051, -0.614991])], [('fixed-step rk4 two-body propagation [[1.0, 0.0], [0.0, 1.2], 1.0, 5.0, 25]', [[1.0, 0.0], [0.0, 1.2], 1.0, 5.0, 25], [-2.095663, 1.089551, -0.384431, -0.37274]), ('fixed-step rk4 two-body propagation [[-1.5, 0.5], [0.1, -0.7], 1.0, 2.0, 10]', [[-1.5, 0.5], [0.1, -0.7], 1.0, 2.0, 10], [-0.154684, -0.721678, 1.394034, 0.039166]), ('fixed-step rk4 two-body propagation [[6800.0, 1200.0], [-1.1, 7.4], 398600.4418, 300.0, 6]', [[6800.0, 1200.0], [-1.1, 7.4], 398600.4418, 300.0, 6], [6111.623093, 3316.078893, -3.439749, 6.583115]), ('fixed-step rk4 two-body propagation [[2.0, 0.0], [0.0, 0.5], 1.0, 4.0, 8]', [[2.0, 0.0], [0.0, 0.5], 1.0, 4.0, 8], [-0.108631, 0.939625, -0.993051, -0.614991]), ('fixed-step rk4 two-body propagation [[7000.0, 0.0], [0.0, 7.546], 398600.4418, 600.0, 12]', [[7000.0, 0.0], [0.0, 7.546], 398600.4418, 600.0, 12], [5586.092992, 4218.445527, -4.547562, 6.021804]), ('fixed-step rk4 two-body propagation [[7000.0, 0.0], [0.0, 8.5], 398600.4418, 900.0, 20]', [[7000.0, 0.0], [0.0, 8.5], 398600.4418, 900.0, 20], [4101.15166, 6610.394483, -5.692596, 5.332573]), ('fixed-step rk4 two-body propagation [[0.0, 9000.0], [-6.2, 0.8], 398600.4418, 1200.0, 15]', [[0.0, 9000.0], [-6.2, 0.8], 398600.4418, 1200.0, 15], [-6593.162659, 6759.502773, -4.170281, -4.18782])]]
for label, args, expected in fixtures[N-1]:
check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| fixed-step rk4 two-body propagation [[7000.0, 0.0], [0.0, 7.546], 398600.4418, 600.0, 12] | [5546.064346, 4192.246038, -4.557381, 5.968622] | [5586.092992, 4218.445527, -4.547562, 6.021804] | Failed |
| fixed-step rk4 two-body propagation [[7000.0, 0.0], [0.0, 8.5], 398600.4418, 900.0, 20] | [4057.743705, 6555.912848, -5.693804, 5.257275] | [4101.15166, 6610.394483, -5.692596, 5.332573] | Failed |
| fixed-step rk4 two-body propagation [[0.0, 9000.0], [-6.2, 0.8], 398600.4418, 1200.0, 15] | [-6534.003379, 6689.605238, -4.10591, -4.200932] | [-6593.162659, 6759.502773, -4.170281, -4.18782] | Failed |
| fixed-step rk4 two-body propagation [[1.0, 0.0], [0.0, 1.0], 1.0, 3.0, 30] | [-0.778012, -0.129876, 0.302598, -1.083354] | [-0.98999, 0.141112, -0.141113, -0.989997] | Failed |
| fixed-step rk4 two-body propagation [[1.0, 0.0], [0.0, 1.2], 1.0, 5.0, 25] | [-1.780693, 0.561706, -0.158913, -0.543872] | [-2.095663, 1.089551, -0.384431, -0.37274] | Failed |
| fixed-step rk4 two-body propagation [[-1.5, 0.5], [0.1, -0.7], 1.0, 2.0, 10] | [-0.058426, -0.622838, 1.440753, 0.287752] | [-0.154684, -0.721678, 1.394034, 0.039166] | Failed |
| fixed-step rk4 two-body propagation [[6800.0, 1200.0], [-1.1, 7.4], 398600.4418, 300.0, 6] | [6092.550954, 3306.445714, -3.436481, 6.560305] | [6111.623093, 3316.078893, -3.439749, 6.583115] | Failed |
SHA-256 / 21c2d4cfa1ec25dd348c7229f7c3f699d0e1989b99df9ce41a888e688dba409f
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
r0,v0,mu,T,steps=x
h=T/steps
def f(s):
px,py,vx,vy=s
rr=(px*px+py*py)**1.5
return [vx,vy,-mu*px/rr,-mu*py/rr]
s=list(r0)+list(v0)
for _ in range(steps):
k1=f(s)
k2=f([s[i]+h/4*k1[i] for i in range(4)])
k3=f([s[i]+h/2*k2[i] for i in range(4)])
k4=f([s[i]+h*k3[i] for i in range(4)])
s=[s[i]+h/6*(k1[i]+2*k2[i]+2*k3[i]+k4[i]) for i in range(4)]
return [round(c,6) for c in s]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('fixed-step rk4 two-body propagation [[7000.0, 0.0], [0.0, 7.546], 398600.4418, 600.0, 12]', [[7000.0, 0.0], [0.0, 7.546], 398600.4418, 600.0, 12], [5586.092992, 4218.445527, -4.547562, 6.021804]), ('fixed-step rk4 two-body propagation [[7000.0, 0.0], [0.0, 8.5], 398600.4418, 900.0, 20]', [[7000.0, 0.0], [0.0, 8.5], 398600.4418, 900.0, 20], [4101.15166, 6610.394483, -5.692596, 5.332573]), ('fixed-step rk4 two-body propagation [[0.0, 9000.0], [-6.2, 0.8], 398600.4418, 1200.0, 15]', [[0.0, 9000.0], [-6.2, 0.8], 398600.4418, 1200.0, 15], [-6593.162659, 6759.502773, -4.170281, -4.18782]), ('fixed-step rk4 two-body propagation [[1.0, 0.0], [0.0, 1.0], 1.0, 3.0, 30]', [[1.0, 0.0], [0.0, 1.0], 1.0, 3.0, 30], [-0.98999, 0.141112, -0.141113, -0.989997]), ('fixed-step rk4 two-body propagation [[1.0, 0.0], [0.0, 1.2], 1.0, 5.0, 25]', [[1.0, 0.0], [0.0, 1.2], 1.0, 5.0, 25], [-2.095663, 1.089551, -0.384431, -0.37274]), ('fixed-step rk4 two-body propagation [[-1.5, 0.5], [0.1, -0.7], 1.0, 2.0, 10]', [[-1.5, 0.5], [0.1, -0.7], 1.0, 2.0, 10], [-0.154684, -0.721678, 1.394034, 0.039166]), ('fixed-step rk4 two-body propagation [[6800.0, 1200.0], [-1.1, 7.4], 398600.4418, 300.0, 6]', [[6800.0, 1200.0], [-1.1, 7.4], 398600.4418, 300.0, 6], [6111.623093, 3316.078893, -3.439749, 6.583115])], [('fixed-step rk4 two-body propagation [[7000.0, 0.0], [0.0, 8.5], 398600.4418, 900.0, 20]', [[7000.0, 0.0], [0.0, 8.5], 398600.4418, 900.0, 20], [4101.15166, 6610.394483, -5.692596, 5.332573]), ('fixed-step rk4 two-body propagation [[1.0, 0.0], [0.0, 1.0], 1.0, 3.0, 30]', [[1.0, 0.0], [0.0, 1.0], 1.0, 3.0, 30], [-0.98999, 0.141112, -0.141113, -0.989997]), ('fixed-step rk4 two-body propagation [[1.0, 0.0], [0.0, 1.2], 1.0, 5.0, 25]', [[1.0, 0.0], [0.0, 1.2], 1.0, 5.0, 25], [-2.095663, 1.089551, -0.384431, -0.37274]), ('fixed-step rk4 two-body propagation [[-1.5, 0.5], [0.1, -0.7], 1.0, 2.0, 10]', [[-1.5, 0.5], [0.1, -0.7], 1.0, 2.0, 10], [-0.154684, -0.721678, 1.394034, 0.039166]), ('fixed-step rk4 two-body propagation [[6800.0, 1200.0], [-1.1, 7.4], 398600.4418, 300.0, 6]', [[6800.0, 1200.0], [-1.1, 7.4], 398600.4418, 300.0, 6], [6111.623093, 3316.078893, -3.439749, 6.583115]), ('fixed-step rk4 two-body propagation [[2.0, 0.0], [0.0, 0.5], 1.0, 4.0, 8]', [[2.0, 0.0], [0.0, 0.5], 1.0, 4.0, 8], [-0.108631, 0.939625, -0.993051, -0.614991]), ('fixed-step rk4 two-body propagation [[7000.0, 0.0], [0.0, 7.546], 398600.4418, 600.0, 12]', [[7000.0, 0.0], [0.0, 7.546], 398600.4418, 600.0, 12], [5586.092992, 4218.445527, -4.547562, 6.021804])], [('fixed-step rk4 two-body propagation [[0.0, 9000.0], [-6.2, 0.8], 398600.4418, 1200.0, 15]', [[0.0, 9000.0], [-6.2, 0.8], 398600.4418, 1200.0, 15], [-6593.162659, 6759.502773, -4.170281, -4.18782]), ('fixed-step rk4 two-body propagation [[6800.0, 1200.0], [-1.1, 7.4], 398600.4418, 300.0, 6]', [[6800.0, 1200.0], [-1.1, 7.4], 398600.4418, 300.0, 6], [6111.623093, 3316.078893, -3.439749, 6.583115]), ('fixed-step rk4 two-body propagation [[2.0, 0.0], [0.0, 0.5], 1.0, 4.0, 8]', [[2.0, 0.0], [0.0, 0.5], 1.0, 4.0, 8], [-0.108631, 0.939625, -0.993051, -0.614991]), ('fixed-step rk4 two-body propagation [[7000.0, 0.0], [0.0, 7.546], 398600.4418, 600.0, 12]', [[7000.0, 0.0], [0.0, 7.546], 398600.4418, 600.0, 12], [5586.092992, 4218.445527, -4.547562, 6.021804]), ('fixed-step rk4 two-body propagation [[7000.0, 0.0], [0.0, 8.5], 398600.4418, 900.0, 20]', [[7000.0, 0.0], [0.0, 8.5], 398600.4418, 900.0, 20], [4101.15166, 6610.394483, -5.692596, 5.332573]), ('fixed-step rk4 two-body propagation [[1.0, 0.0], [0.0, 1.0], 1.0, 3.0, 30]', [[1.0, 0.0], [0.0, 1.0], 1.0, 3.0, 30], [-0.98999, 0.141112, -0.141113, -0.989997]), ('fixed-step rk4 two-body propagation [[1.0, 0.0], [0.0, 1.2], 1.0, 5.0, 25]', [[1.0, 0.0], [0.0, 1.2], 1.0, 5.0, 25], [-2.095663, 1.089551, -0.384431, -0.37274])], [('fixed-step rk4 two-body propagation [[1.0, 0.0], [0.0, 1.0], 1.0, 3.0, 30]', [[1.0, 0.0], [0.0, 1.0], 1.0, 3.0, 30], [-0.98999, 0.141112, -0.141113, -0.989997]), ('fixed-step rk4 two-body propagation [[7000.0, 0.0], [0.0, 8.5], 398600.4418, 900.0, 20]', [[7000.0, 0.0], [0.0, 8.5], 398600.4418, 900.0, 20], [4101.15166, 6610.394483, -5.692596, 5.332573]), ('fixed-step rk4 two-body propagation [[0.0, 9000.0], [-6.2, 0.8], 398600.4418, 1200.0, 15]', [[0.0, 9000.0], [-6.2, 0.8], 398600.4418, 1200.0, 15], [-6593.162659, 6759.502773, -4.170281, -4.18782]), ('fixed-step rk4 two-body propagation [[1.0, 0.0], [0.0, 1.2], 1.0, 5.0, 25]', [[1.0, 0.0], [0.0, 1.2], 1.0, 5.0, 25], [-2.095663, 1.089551, -0.384431, -0.37274]), ('fixed-step rk4 two-body propagation [[-1.5, 0.5], [0.1, -0.7], 1.0, 2.0, 10]', [[-1.5, 0.5], [0.1, -0.7], 1.0, 2.0, 10], [-0.154684, -0.721678, 1.394034, 0.039166]), ('fixed-step rk4 two-body propagation [[6800.0, 1200.0], [-1.1, 7.4], 398600.4418, 300.0, 6]', [[6800.0, 1200.0], [-1.1, 7.4], 398600.4418, 300.0, 6], [6111.623093, 3316.078893, -3.439749, 6.583115]), ('fixed-step rk4 two-body propagation [[2.0, 0.0], [0.0, 0.5], 1.0, 4.0, 8]', [[2.0, 0.0], [0.0, 0.5], 1.0, 4.0, 8], [-0.108631, 0.939625, -0.993051, -0.614991])], [('fixed-step rk4 two-body propagation [[1.0, 0.0], [0.0, 1.2], 1.0, 5.0, 25]', [[1.0, 0.0], [0.0, 1.2], 1.0, 5.0, 25], [-2.095663, 1.089551, -0.384431, -0.37274]), ('fixed-step rk4 two-body propagation [[-1.5, 0.5], [0.1, -0.7], 1.0, 2.0, 10]', [[-1.5, 0.5], [0.1, -0.7], 1.0, 2.0, 10], [-0.154684, -0.721678, 1.394034, 0.039166]), ('fixed-step rk4 two-body propagation [[6800.0, 1200.0], [-1.1, 7.4], 398600.4418, 300.0, 6]', [[6800.0, 1200.0], [-1.1, 7.4], 398600.4418, 300.0, 6], [6111.623093, 3316.078893, -3.439749, 6.583115]), ('fixed-step rk4 two-body propagation [[2.0, 0.0], [0.0, 0.5], 1.0, 4.0, 8]', [[2.0, 0.0], [0.0, 0.5], 1.0, 4.0, 8], [-0.108631, 0.939625, -0.993051, -0.614991]), ('fixed-step rk4 two-body propagation [[7000.0, 0.0], [0.0, 7.546], 398600.4418, 600.0, 12]', [[7000.0, 0.0], [0.0, 7.546], 398600.4418, 600.0, 12], [5586.092992, 4218.445527, -4.547562, 6.021804]), ('fixed-step rk4 two-body propagation [[7000.0, 0.0], [0.0, 8.5], 398600.4418, 900.0, 20]', [[7000.0, 0.0], [0.0, 8.5], 398600.4418, 900.0, 20], [4101.15166, 6610.394483, -5.692596, 5.332573]), ('fixed-step rk4 two-body propagation [[0.0, 9000.0], [-6.2, 0.8], 398600.4418, 1200.0, 15]', [[0.0, 9000.0], [-6.2, 0.8], 398600.4418, 1200.0, 15], [-6593.162659, 6759.502773, -4.170281, -4.18782])]]
for label, args, expected in fixtures[N-1]:
check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| fixed-step rk4 two-body propagation [[7000.0, 0.0], [0.0, 7.546], 398600.4418, 600.0, 12] | [5606.326774, 4231.541789, -4.541473, 6.048658] | [5586.092992, 4218.445527, -4.547562, 6.021804] | Failed |
| fixed-step rk4 two-body propagation [[7000.0, 0.0], [0.0, 8.5], 398600.4418, 900.0, 20] | [4123.361019, 6637.7484, -5.690718, 5.370935] | [4101.15166, 6610.394483, -5.692596, 5.332573] | Failed |
| fixed-step rk4 two-body propagation [[0.0, 9000.0], [-6.2, 0.8], 398600.4418, 1200.0, 15] | [-6622.808203, 6794.837878, -4.202802, -4.180167] | [-6593.162659, 6759.502773, -4.170281, -4.18782] | Failed |
| fixed-step rk4 two-body propagation [[1.0, 0.0], [0.0, 1.0], 1.0, 3.0, 30] | [-1.055374, 0.269228, -0.281853, -0.920013] | [-0.98999, 0.141112, -0.141113, -0.989997] | Failed |
| fixed-step rk4 two-body propagation [[1.0, 0.0], [0.0, 1.2], 1.0, 5.0, 25] | [-2.207401, 1.347976, -0.461869, -0.291565] | [-2.095663, 1.089551, -0.384431, -0.37274] | Failed |
| fixed-step rk4 two-body propagation [[-1.5, 0.5], [0.1, -0.7], 1.0, 2.0, 10] | [-0.201323, -0.760716, 1.362333, -0.053628] | [-0.154684, -0.721678, 1.394034, 0.039166] | Failed |
| fixed-step rk4 two-body propagation [[6800.0, 1200.0], [-1.1, 7.4], 398600.4418, 300.0, 6] | [6121.217538, 3320.916466, -3.440766, 6.59477] | [6111.623093, 3316.078893, -3.439749, 6.583115] | Failed |
SHA-256 / 7baa722f5d9575443a5693de0f2428ed61eddcb101b6161c0772f9a5da1ac68d
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
r0,v0,mu,T,steps=x
h=T/steps
def f(s):
px,py,vx,vy=s
rr=(px*px+py*py)**1.5
return [vx,vy,-mu*px/rr,-mu*py/rr]
s=list(r0)+list(v0)
for _ in range(steps):
k1=f(s)
k2=f([s[i]+h/2*k1[i] for i in range(4)])
k3=f([s[i]+h/2*k2[i] for i in range(4)])
k4=f([s[i]+h*k3[i] for i in range(4)])
s=[s[i]+h/6*(k1[i]+2*k2[i]+2*k3[i]+k4[i]) for i in range(4)]
return [round(c,6) for c in s]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('fixed-step rk4 two-body propagation [[7000.0, 0.0], [0.0, 7.546], 398600.4418, 600.0, 12]', [[7000.0, 0.0], [0.0, 7.546], 398600.4418, 600.0, 12], [5586.092992, 4218.445527, -4.547562, 6.021804]), ('fixed-step rk4 two-body propagation [[7000.0, 0.0], [0.0, 8.5], 398600.4418, 900.0, 20]', [[7000.0, 0.0], [0.0, 8.5], 398600.4418, 900.0, 20], [4101.15166, 6610.394483, -5.692596, 5.332573]), ('fixed-step rk4 two-body propagation [[0.0, 9000.0], [-6.2, 0.8], 398600.4418, 1200.0, 15]', [[0.0, 9000.0], [-6.2, 0.8], 398600.4418, 1200.0, 15], [-6593.162659, 6759.502773, -4.170281, -4.18782]), ('fixed-step rk4 two-body propagation [[1.0, 0.0], [0.0, 1.0], 1.0, 3.0, 30]', [[1.0, 0.0], [0.0, 1.0], 1.0, 3.0, 30], [-0.98999, 0.141112, -0.141113, -0.989997]), ('fixed-step rk4 two-body propagation [[1.0, 0.0], [0.0, 1.2], 1.0, 5.0, 25]', [[1.0, 0.0], [0.0, 1.2], 1.0, 5.0, 25], [-2.095663, 1.089551, -0.384431, -0.37274]), ('fixed-step rk4 two-body propagation [[-1.5, 0.5], [0.1, -0.7], 1.0, 2.0, 10]', [[-1.5, 0.5], [0.1, -0.7], 1.0, 2.0, 10], [-0.154684, -0.721678, 1.394034, 0.039166]), ('fixed-step rk4 two-body propagation [[6800.0, 1200.0], [-1.1, 7.4], 398600.4418, 300.0, 6]', [[6800.0, 1200.0], [-1.1, 7.4], 398600.4418, 300.0, 6], [6111.623093, 3316.078893, -3.439749, 6.583115])], [('fixed-step rk4 two-body propagation [[7000.0, 0.0], [0.0, 8.5], 398600.4418, 900.0, 20]', [[7000.0, 0.0], [0.0, 8.5], 398600.4418, 900.0, 20], [4101.15166, 6610.394483, -5.692596, 5.332573]), ('fixed-step rk4 two-body propagation [[1.0, 0.0], [0.0, 1.0], 1.0, 3.0, 30]', [[1.0, 0.0], [0.0, 1.0], 1.0, 3.0, 30], [-0.98999, 0.141112, -0.141113, -0.989997]), ('fixed-step rk4 two-body propagation [[1.0, 0.0], [0.0, 1.2], 1.0, 5.0, 25]', [[1.0, 0.0], [0.0, 1.2], 1.0, 5.0, 25], [-2.095663, 1.089551, -0.384431, -0.37274]), ('fixed-step rk4 two-body propagation [[-1.5, 0.5], [0.1, -0.7], 1.0, 2.0, 10]', [[-1.5, 0.5], [0.1, -0.7], 1.0, 2.0, 10], [-0.154684, -0.721678, 1.394034, 0.039166]), ('fixed-step rk4 two-body propagation [[6800.0, 1200.0], [-1.1, 7.4], 398600.4418, 300.0, 6]', [[6800.0, 1200.0], [-1.1, 7.4], 398600.4418, 300.0, 6], [6111.623093, 3316.078893, -3.439749, 6.583115]), ('fixed-step rk4 two-body propagation [[2.0, 0.0], [0.0, 0.5], 1.0, 4.0, 8]', [[2.0, 0.0], [0.0, 0.5], 1.0, 4.0, 8], [-0.108631, 0.939625, -0.993051, -0.614991]), ('fixed-step rk4 two-body propagation [[7000.0, 0.0], [0.0, 7.546], 398600.4418, 600.0, 12]', [[7000.0, 0.0], [0.0, 7.546], 398600.4418, 600.0, 12], [5586.092992, 4218.445527, -4.547562, 6.021804])], [('fixed-step rk4 two-body propagation [[0.0, 9000.0], [-6.2, 0.8], 398600.4418, 1200.0, 15]', [[0.0, 9000.0], [-6.2, 0.8], 398600.4418, 1200.0, 15], [-6593.162659, 6759.502773, -4.170281, -4.18782]), ('fixed-step rk4 two-body propagation [[6800.0, 1200.0], [-1.1, 7.4], 398600.4418, 300.0, 6]', [[6800.0, 1200.0], [-1.1, 7.4], 398600.4418, 300.0, 6], [6111.623093, 3316.078893, -3.439749, 6.583115]), ('fixed-step rk4 two-body propagation [[2.0, 0.0], [0.0, 0.5], 1.0, 4.0, 8]', [[2.0, 0.0], [0.0, 0.5], 1.0, 4.0, 8], [-0.108631, 0.939625, -0.993051, -0.614991]), ('fixed-step rk4 two-body propagation [[7000.0, 0.0], [0.0, 7.546], 398600.4418, 600.0, 12]', [[7000.0, 0.0], [0.0, 7.546], 398600.4418, 600.0, 12], [5586.092992, 4218.445527, -4.547562, 6.021804]), ('fixed-step rk4 two-body propagation [[7000.0, 0.0], [0.0, 8.5], 398600.4418, 900.0, 20]', [[7000.0, 0.0], [0.0, 8.5], 398600.4418, 900.0, 20], [4101.15166, 6610.394483, -5.692596, 5.332573]), ('fixed-step rk4 two-body propagation [[1.0, 0.0], [0.0, 1.0], 1.0, 3.0, 30]', [[1.0, 0.0], [0.0, 1.0], 1.0, 3.0, 30], [-0.98999, 0.141112, -0.141113, -0.989997]), ('fixed-step rk4 two-body propagation [[1.0, 0.0], [0.0, 1.2], 1.0, 5.0, 25]', [[1.0, 0.0], [0.0, 1.2], 1.0, 5.0, 25], [-2.095663, 1.089551, -0.384431, -0.37274])], [('fixed-step rk4 two-body propagation [[1.0, 0.0], [0.0, 1.0], 1.0, 3.0, 30]', [[1.0, 0.0], [0.0, 1.0], 1.0, 3.0, 30], [-0.98999, 0.141112, -0.141113, -0.989997]), ('fixed-step rk4 two-body propagation [[7000.0, 0.0], [0.0, 8.5], 398600.4418, 900.0, 20]', [[7000.0, 0.0], [0.0, 8.5], 398600.4418, 900.0, 20], [4101.15166, 6610.394483, -5.692596, 5.332573]), ('fixed-step rk4 two-body propagation [[0.0, 9000.0], [-6.2, 0.8], 398600.4418, 1200.0, 15]', [[0.0, 9000.0], [-6.2, 0.8], 398600.4418, 1200.0, 15], [-6593.162659, 6759.502773, -4.170281, -4.18782]), ('fixed-step rk4 two-body propagation [[1.0, 0.0], [0.0, 1.2], 1.0, 5.0, 25]', [[1.0, 0.0], [0.0, 1.2], 1.0, 5.0, 25], [-2.095663, 1.089551, -0.384431, -0.37274]), ('fixed-step rk4 two-body propagation [[-1.5, 0.5], [0.1, -0.7], 1.0, 2.0, 10]', [[-1.5, 0.5], [0.1, -0.7], 1.0, 2.0, 10], [-0.154684, -0.721678, 1.394034, 0.039166]), ('fixed-step rk4 two-body propagation [[6800.0, 1200.0], [-1.1, 7.4], 398600.4418, 300.0, 6]', [[6800.0, 1200.0], [-1.1, 7.4], 398600.4418, 300.0, 6], [6111.623093, 3316.078893, -3.439749, 6.583115]), ('fixed-step rk4 two-body propagation [[2.0, 0.0], [0.0, 0.5], 1.0, 4.0, 8]', [[2.0, 0.0], [0.0, 0.5], 1.0, 4.0, 8], [-0.108631, 0.939625, -0.993051, -0.614991])], [('fixed-step rk4 two-body propagation [[1.0, 0.0], [0.0, 1.2], 1.0, 5.0, 25]', [[1.0, 0.0], [0.0, 1.2], 1.0, 5.0, 25], [-2.095663, 1.089551, -0.384431, -0.37274]), ('fixed-step rk4 two-body propagation [[-1.5, 0.5], [0.1, -0.7], 1.0, 2.0, 10]', [[-1.5, 0.5], [0.1, -0.7], 1.0, 2.0, 10], [-0.154684, -0.721678, 1.394034, 0.039166]), ('fixed-step rk4 two-body propagation [[6800.0, 1200.0], [-1.1, 7.4], 398600.4418, 300.0, 6]', [[6800.0, 1200.0], [-1.1, 7.4], 398600.4418, 300.0, 6], [6111.623093, 3316.078893, -3.439749, 6.583115]), ('fixed-step rk4 two-body propagation [[2.0, 0.0], [0.0, 0.5], 1.0, 4.0, 8]', [[2.0, 0.0], [0.0, 0.5], 1.0, 4.0, 8], [-0.108631, 0.939625, -0.993051, -0.614991]), ('fixed-step rk4 two-body propagation [[7000.0, 0.0], [0.0, 7.546], 398600.4418, 600.0, 12]', [[7000.0, 0.0], [0.0, 7.546], 398600.4418, 600.0, 12], [5586.092992, 4218.445527, -4.547562, 6.021804]), ('fixed-step rk4 two-body propagation [[7000.0, 0.0], [0.0, 8.5], 398600.4418, 900.0, 20]', [[7000.0, 0.0], [0.0, 8.5], 398600.4418, 900.0, 20], [4101.15166, 6610.394483, -5.692596, 5.332573]), ('fixed-step rk4 two-body propagation [[0.0, 9000.0], [-6.2, 0.8], 398600.4418, 1200.0, 15]', [[0.0, 9000.0], [-6.2, 0.8], 398600.4418, 1200.0, 15], [-6593.162659, 6759.502773, -4.170281, -4.18782])]]
for label, args, expected in fixtures[N-1]:
check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| fixed-step rk4 two-body propagation [[7000.0, 0.0], [0.0, 7.546], 398600.4418, 600.0, 12] | [5586.092992, 4218.445527, -4.547562, 6.021804] | [5586.092992, 4218.445527, -4.547562, 6.021804] | Passed |
| fixed-step rk4 two-body propagation [[7000.0, 0.0], [0.0, 8.5], 398600.4418, 900.0, 20] | [4101.15166, 6610.394483, -5.692596, 5.332573] | [4101.15166, 6610.394483, -5.692596, 5.332573] | Passed |
| fixed-step rk4 two-body propagation [[0.0, 9000.0], [-6.2, 0.8], 398600.4418, 1200.0, 15] | [-6593.162659, 6759.502773, -4.170281, -4.18782] | [-6593.162659, 6759.502773, -4.170281, -4.18782] | Passed |
| fixed-step rk4 two-body propagation [[1.0, 0.0], [0.0, 1.0], 1.0, 3.0, 30] | [-0.98999, 0.141112, -0.141113, -0.989997] | [-0.98999, 0.141112, -0.141113, -0.989997] | Passed |
| fixed-step rk4 two-body propagation [[1.0, 0.0], [0.0, 1.2], 1.0, 5.0, 25] | [-2.095663, 1.089551, -0.384431, -0.37274] | [-2.095663, 1.089551, -0.384431, -0.37274] | Passed |
| fixed-step rk4 two-body propagation [[-1.5, 0.5], [0.1, -0.7], 1.0, 2.0, 10] | [-0.154684, -0.721678, 1.394034, 0.039166] | [-0.154684, -0.721678, 1.394034, 0.039166] | Passed |
| fixed-step rk4 two-body propagation [[6800.0, 1200.0], [-1.1, 7.4], 398600.4418, 300.0, 6] | [6111.623093, 3316.078893, -3.439749, 6.583115] | [6111.623093, 3316.078893, -3.439749, 6.583115] | Passed |
SHA-256 / 4dde3624fcf421a2c56fe0547cd5ef2fdbdbe920a2f0a647b409c44c26ca17c0
Verification & scope
A deterministic toy two-body model with stipulated constants and conventions; not flight dynamics software or a validated SGP4 implementation. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.
Observations recorded using Python 3.12.14 at 2026-09-29T14:48:12.150708+00:00.
Case digest / fc7b3766d7eac509e1f3a8915243d3a0f5a5e96fd327be0be8110b332d24804c