vibe coding an orbital mechanics simulation to try out claude code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

89 lines
2.8 KiB

#!/usr/bin/env python3
"""
Precalculate expected values for test_parabolic_orbit.
Simulates a parabolic comet orbiting the Sun for 300 days.
"""
import math
import sys
sys.path.insert(0, "scripts")
from sim_engine import Simulator, vmag, G
def main():
sim = Simulator("tests/test_parabolic_orbit.toml", dt=60.0)
comet = sim.get_body("ParabolicComet")
sun = sim.get_body("Sun")
# Initial state
r0 = vmag(comet.global_pos)
v0 = vmag(comet.global_vel)
mu = G * sun.mass
escape_v0 = math.sqrt(2.0 * mu / r0)
circular_v0 = math.sqrt(mu / r0)
print(f"// === Initial Conditions (SI units) ===")
print(f"// Distance: {r0:.6f} m ({r0 / 1.496e11:.6f} AU)")
print(f"// Velocity: {v0:.6f} m/s ({v0 / 1000.0:.6f} km/s)")
print(f"// Escape velocity: {escape_v0:.6f} m/s ({escape_v0 / 1000.0:.6f} km/s)")
print(f"// Circular velocity: {circular_v0:.6f} m/s ({circular_v0 / 1000.0:.6f} km/s)")
print(f"// Velocity error from escape: {(abs(v0 - escape_v0) / escape_v0) * 100.0:.6f}%")
print(f"// Eccentricity: {comet.orbit.e:.6f}")
print()
# Energy at start (local frame, comet relative to sun)
KE0 = 0.5 * comet.mass * v0**2
PE0 = -mu * comet.mass / r0
E0 = KE0 + PE0
print(f"// === Energy (Joules) ===")
print(f"// Initial KE: {KE0:.6e}")
print(f"// Initial PE: {PE0:.6e}")
print(f"// Initial total E: {E0:.6e}")
print()
# Run simulation for 300 days
total_seconds = 300.0 * 86400.0
steps = int(total_seconds / sim.dt)
print(f"// Total steps: {steps}")
print()
for i in range(steps):
sim._step()
# Final state
rf = vmag(comet.global_pos)
vf = vmag(comet.global_vel)
KEf = 0.5 * comet.mass * vf**2
PEf = -mu * comet.mass / rf
Ef = KEf + PEf
print()
print(f"// === Final State (t=300 days) ===")
print(f"// Distance: {rf:.6f} m ({rf / 1.496e11:.6f} AU)")
print(f"// Velocity: {vf:.6f} m/s ({vf / 1000.0:.6f} km/s)")
print(f"// Final KE: {KEf:.6e}")
print(f"// Final PE: {PEf:.6e}")
print(f"// Final total E: {Ef:.6e}")
print()
# Energy drift
avg_KE = (KE0 + KEf) / 2.0
energy_drift = abs(Ef - E0)
energy_drift_pct = (energy_drift / avg_KE) * 100.0 if avg_KE > 0 else 0.0
print(f"// === Energy Drift ===")
print(f"// Absolute drift: {energy_drift:.6e} J")
print(f"// Drift percent: {energy_drift_pct:.6f}%")
print()
# Assertions summary
print(f"// === Assertions ===")
print(f"// final_distance ({rf:.2f} m) > initial_distance ({r0:.2f} m): {rf > r0}")
print(f"// final_velocity ({vf:.2f} m/s) < initial_velocity ({v0:.2f} m/s): {vf < v0}")
print(f"// E0 >= -1e25: {E0 >= -1e25}")
print(f"// energy_drift_pct < 1.0: {energy_drift_pct < 1.0}")
print(f"// final_velocity matches {vf:.6f} m/s: True")
if __name__ == "__main__":
main()