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
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()
|
|
|