#include "geodesic.h" #include "frame.h" #include #include int main(void) { SpacetimeSource spacetime = {0}; MetricData metric; ObserverState observer; ObserverState oriented_observer; ObserverState inward_observer; const GeodesicTraceConfig trace = {.coordinate_time_step = 0.1, .max_steps = 4096, .capture_log_alpha_p0 = 8.0}; int result = 1; if (spacetime_create_schwarzschild_ks(&spacetime, 1.0, 256.0, 1.5) || spacetime_eval(&spacetime, 0.0, (double[]){2.0, 0.0, 0.0}, &metric) || !isfinite(metric.alpha) || !isfinite(metric.gamma[0][0]) || !isfinite(metric.K[0][0]) || observer_static_schwarzschild_ks(1.0, 30.0, &observer) || observer_static_schwarzschild_ks_look_at(1.0, 40.0, 270.0, 30.0, &oriented_observer) || fabs(oriented_observer.coordinate_position[0]) > 1e-12 || fabs(oriented_observer.coordinate_position[1] - 20.0 * sqrt(3.0)) > 1e-12 || fabs(oriented_observer.coordinate_position[2] + 20.0) > 1e-12 || fabs(oriented_observer.tetrad[1][1]) > 1e-12 || fabs(oriented_observer.tetrad[1][2] + sqrt(0.95) * sqrt(3.0) / 2.0) > 1e-12 || fabs(oriented_observer.tetrad[1][3] - 0.5 * sqrt(0.95)) > 1e-12 || observer_inward_schwarzschild_ks(1.0, 30.0, 0.5, &inward_observer) || fabs(inward_observer.tetrad[0][0] - (2.0 / sqrt(3.0)) * (observer.tetrad[0][0] + 0.5 * observer.tetrad[1][0])) > 1e-12 || fabs(inward_observer.tetrad[1][1] - (2.0 / sqrt(3.0)) * (0.5 * observer.tetrad[0][1] + observer.tetrad[1][1])) > 1e-12 || !observer_inward_schwarzschild_ks(1.0, 30.0, 1.0, &inward_observer)) goto done; const RayEndpoint central = geodesic_trace_past( &spacetime, &observer, (double[]){1.0, 0.0, 0.0}, &trace); const RayEndpoint inside_shadow = geodesic_trace_past( &spacetime, &observer, (double[]){cos(0.10), sin(0.10), 0.0}, &trace); const RayEndpoint outside_shadow = geodesic_trace_past( &spacetime, &observer, (double[]){cos(0.30), sin(0.30), 0.0}, &trace); if (central.status != RAY_ENDPOINT_CAPTURED || inside_shadow.status != RAY_ENDPOINT_CAPTURED || outside_shadow.status != RAY_ENDPOINT_ESCAPED) { fprintf(stderr, "Schwarzschild KS shadow regression failed (center=%d, inside=%d, " "outside=%d)\n", central.status, inside_shadow.status, outside_shadow.status); goto done; } /* A coarse field covering the shadow must genuinely refine: its initial * capture/escape-discontinuous triangles are a separate trigger from the * smooth direction-error criterion. */ FrameLensMesh mesh = {0}; const RefinementConfig refinement = {.max_level = 1, .angle_absolute_rad = 1e-5, .angle_relative = 1e-5, .jacobian_minimum = 1e-3, .min_edge_pixels = 1.0, .min_area_pixels2 = 1.0}; if (frame_lens_mesh_build_coarse(&mesh, 48, 48, 24, 40.0) || frame_lens_mesh_trace(&mesh, &spacetime, &observer, &trace) || frame_lens_mesh_refine(&mesh, &spacetime, &observer, &trace, &refinement) || mesh.vertex_count <= 9 || mesh.triangle_count <= 8) { fputs("Schwarzschild adaptive-refinement regression failed\n", stderr); frame_lens_mesh_destroy(&mesh); goto done; } frame_lens_mesh_destroy(&mesh); result = 0; done: spacetime_destroy(&spacetime); return result; }