Feat: Rework ray termination into escaped/dark/unresolved/incomplete
Replace the position capture cutoff with a camera-relative dark threshold shared by every backend, and carry explicit outcome/reason provenance through the ray, RayPool, adaptive mesh, lens-map and replay paths. - eval/eval_slab return SpacetimePointStatus; remove SPACETIME_RAY_CAPTURED and the Schwarzschild capture radius; decouple observer construction from ray position. - RayEndpoint stores RayOutcome/RayReason plus the last trusted state; budget exhaustion is retryable UNRESOLVED, data/integration failures are INCOMPLETE. - Normal dark terminal is L - L0 >= --dark-threshold (default 8), with L0 taken at the camera event and kept distinct from the worldtube entry energy; photon energy and frequency ratio are never reset. - Implement E/D/U triangle decisions with merged budget retries, persistent probe witnesses promoted in place by vertex identity, conformity settling, and approximate-black boundary provenance with achieved-scale statistics. - Add RayPool continuation state and per-ray step budgets. - Bump lens-map to v2 with explicit end/outcome/reason, approx_black, threshold/retry/geometry provenance and per-frame retry counts; reject v1. - Gate production output on incomplete/error results, overridable with --allow-incomplete. - Update AGENTS.md, the design document and usage docs; add the termination oracle and regression coverage. make -B -j4 BUILD_TYPE=Debug test passes with bit-identical reference HDRs.
This commit is contained in:
1 parent
7fde49308b
commit
f7380cbf75
31 files changed
+2349
-402
No files matched your search
@@ -113,7 +113,7 @@ int main(int argc, char **argv) {
|
||||
/* Ingoing radial light seen from the horizon and its interior must still
|
||||
* trace backwards to the external sky, rather than be classified captured. */
|
||||
const GeodesicTraceConfig trace = {.coordinate_time_step = 0.05,
|
||||
.max_steps = 8192, .capture_log_alpha_p0 = 8};
|
||||
.max_steps = 8192, .threshold = {.kind = THRESHOLD_LOG_ENERGY_GROWTH, .value = 8.0, .policy_version = 3}};
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
camera = (ObserverCamera){.position = {2.25 - 0.25 * i, 0, 0},
|
||||
.velocity = {-0.5, 0, 0}};
|
||||
@@ -121,7 +121,7 @@ int main(int argc, char **argv) {
|
||||
CHECK(observer_from_coordinate_camera(&metric, &camera, &state, NULL) == OBSERVER_BUILD_OK);
|
||||
CHECK(check_state(&metric, &camera, &state) == 0);
|
||||
const RayEndpoint ray = geodesic_trace_past(&source, &state, (double[]){1, 0, 0}, &trace);
|
||||
CHECK(ray.status == RAY_ENDPOINT_ESCAPED);
|
||||
CHECK(ray.outcome == RAY_OUTCOME_ESCAPED);
|
||||
CHECK(fabs(ray.n_infinity[0] - 1) < 1e-12);
|
||||
/* Radial ingoing KS photon has k^r=-k^t and conserved E=k^t. The
|
||||
* asymptotic exterior transfers the photon to infinity, where
|
||||
@@ -140,14 +140,14 @@ int main(int argc, char **argv) {
|
||||
CHECK(observer_from_coordinate_camera(&metric, &camera, &state, NULL) == OBSERVER_BUILD_OK);
|
||||
const GeodesicTraceConfig trace = {.coordinate_time_step = 1, .max_steps = 2048};
|
||||
const RayEndpoint ray = geodesic_trace_past(&source, &state, (double[]){1, 0, 0}, &trace);
|
||||
CHECK(ray.status == RAY_ENDPOINT_ESCAPED);
|
||||
CHECK(ray.outcome == RAY_OUTCOME_ESCAPED);
|
||||
CHECK(fabs(ray.n_infinity[0] - 0.8) < 1e-12);
|
||||
CHECK(fabs(ray.n_infinity[1] + 0.6) < 1e-12);
|
||||
CHECK(fabs(ray.frequency_ratio - 0.8) < 1e-12);
|
||||
camera.position[0] = 25; camera.position[1] = -30; camera.position[2] = 10;
|
||||
CHECK(observer_from_coordinate_camera(&metric, &camera, &state, NULL) == OBSERVER_BUILD_OK);
|
||||
const RayEndpoint shifted = geodesic_trace_past(&source, &state, (double[]){1, 0, 0}, &trace);
|
||||
CHECK(shifted.status == ray.status && fabs(shifted.frequency_ratio - ray.frequency_ratio) < 1e-12);
|
||||
CHECK(shifted.outcome == ray.outcome && fabs(shifted.frequency_ratio - ray.frequency_ratio) < 1e-12);
|
||||
for (int i = 0; i < 3; ++i) CHECK(fabs(shifted.n_infinity[i] - ray.n_infinity[i]) < 1e-12);
|
||||
camera.velocity[1] = 1;
|
||||
CHECK(observer_from_coordinate_camera(&metric, &camera, &state, NULL) == OBSERVER_BUILD_NON_TIMELIKE);
|
||||
|
||||
Reference in new issue
Block a user