#include #include #include "../src/physics.h" #include "../src/simulation.h" #include "../src/config_loader.h" #include "../src/test_utilities.h" #include using Catch::Matchers::WithinAbs; SCENARIO("Energy conservation in circular orbit", "[energy][sanity]") { const double TIME_STEP = 60.0; const double DAYS_TO_SIMULATE = 10.0; const double SECONDS_PER_DAY = 86400.0; SimulationState* sim = create_simulation(2, 0, 0, TIME_STEP); REQUIRE(load_system_config(sim, "tests/test_energy.toml")); const double initial_energy = calculate_system_total_energy(sim); double total_time = DAYS_TO_SIMULATE * SECONDS_PER_DAY; while (sim->time < total_time) { update_simulation(sim); } const double final_energy = calculate_system_total_energy(sim); const double energy_drift = fabs(final_energy - initial_energy) / fabs(initial_energy); INFO("Initial energy: " << initial_energy << " J"); INFO("Final energy: " << final_energy << " J"); INFO("Relative drift: " << energy_drift << " (fraction)"); REQUIRE_THAT(energy_drift, WithinAbs(0.0, 1e-12)); destroy_simulation(sim); } SCENARIO("Orbit direction for zero inclination", "[direction][sanity]") { const double TIME_STEP = 60.0; const int STEPS = 1440; // 1 day at 60s steps SimulationState* sim = create_simulation(2, 0, 0, TIME_STEP); REQUIRE(load_system_config(sim, "tests/test_energy.toml")); CelestialBody* sun = &sim->bodies[0]; CelestialBody* earth = &sim->bodies[1]; Vec3 initial_rel = vec3_sub(earth->global_position, sun->global_position); const double theta_start = atan2(initial_rel.y, initial_rel.x); for (int i = 0; i < STEPS; i++) update_simulation(sim); Vec3 final_rel = vec3_sub(earth->global_position, sun->global_position); const double delta = atan2(final_rel.y, final_rel.x) - theta_start; INFO("Delta: " << delta << " rad"); REQUIRE_THAT(delta, WithinAbs(0.0172042841, 1e-6)); destroy_simulation(sim); }