#ifndef SPACETIME_H #define SPACETIME_H #include #include typedef struct { double alpha; double beta[3]; double gamma[3][3]; double K[3][3]; double d_alpha[3]; double d_beta[3][3]; /* d_beta[spatial derivative][component] */ double d_gamma[3][3][3]; /* d_gamma[spatial derivative][j][k] */ } MetricData; /* Result of evaluating the metric at one event. `OK` is zero so that legacy * `if (eval(...))` call sites keep working. These codes describe data * availability only; they never express a physical capture. */ typedef enum { SPACETIME_POINT_OK = 0, SPACETIME_POINT_TIME_UNAVAILABLE, SPACETIME_POINT_OUT_OF_DOMAIN, SPACETIME_POINT_INVALID_METRIC, SPACETIME_POINT_INTERNAL_ERROR } SpacetimePointStatus; /* Optional legacy region query for backends that declare no asymptotic end. * It can only report ACTIVE or ESCAPED; it can never report a physical * capture, and it is not required by spacetime_source_finalize(). */ typedef enum { SPACETIME_RAY_ACTIVE, SPACETIME_RAY_ESCAPED } SpacetimeRayStatus; /* Stable identifier for one asymptotic end (infinity) of a backend. Backends * may describe more than one; the current analytic backends expose one. */ typedef uint32_t SpacetimeEndId; #define SPACETIME_END_NONE ((SpacetimeEndId)0xffffffffu) typedef enum { ASYMPTOTIC_EXTERIOR_MINKOWSKI, ASYMPTOTIC_EXTERIOR_SCHWARZSCHILD_MONOPOLE } AsymptoticExteriorKind; /* Declared asymptotic end. `frame_origin` and the columns of `frame_axes` * express the asymptotic reference frame in backend coordinates; spatial * `n_infinity` values use the same coordinate axes as the observer tetrad. */ typedef struct { SpacetimeEndId end_id; AsymptoticExteriorKind exterior_kind; double mass; double frame_origin[3]; double frame_axes[3][3]; } SpacetimeAsymptoticEnd; /* Escape worldtube sample at one coordinate time. A zero `radius_rate` and a * time-independent `velocity` describe the fixed/constant-velocity cases used * in this phase. `valid == 0` means the backend cannot describe the worldtube * at this time (history exhausted); callers must not treat that as a miss. */ typedef struct { double center[3]; double velocity[3]; double radius; double radius_rate; /* Nonzero when `velocity` and `radius_rate` are exact throughout the * current motion segment, so the first entry has a closed quadratic form. */ int velocity_constant; int valid; } SpacetimeEscapeWorldtubeSample; typedef struct SpacetimeSource SpacetimeSource; typedef struct MetricSlab MetricSlab; struct MetricSlab { const SpacetimeSource *source; double t_hi, t_lo; void *context; }; typedef struct { SpacetimePointStatus (*eval)(const SpacetimeSource *source, double t, const double x[3], MetricData *metric); SpacetimeRayStatus (*classify)(const SpacetimeSource *source, double t, const double x[3]); int (*load_slab)(const SpacetimeSource *source, double t_hi, double t_lo, MetricSlab **out); void (*free_slab)(MetricSlab *slab); SpacetimePointStatus (*eval_slab)(const MetricSlab *slab, double t, const double x[3], MetricData *metric); SpacetimeRayStatus (*classify_slab)(const MetricSlab *slab, double t, const double x[3]); /* Declared asymptotic ends and their moving escape worldtubes. Backends * without an escape sphere may leave these NULL. */ size_t (*asymptotic_end_count)(const SpacetimeSource *source); int (*asymptotic_end)(const SpacetimeSource *source, size_t index, SpacetimeAsymptoticEnd *out); int (*escape_worldtube_sample)(const SpacetimeSource *source, SpacetimeEndId end_id, double t, SpacetimeEscapeWorldtubeSample *out); /* Coordinate time of the next motion-segment boundary reached while * integrating backward in time, i.e. the largest boundary strictly less * than `t`. Return NAN when the worldtube description has a single open * segment. */ double (*escape_worldtube_next_segment)(const SpacetimeSource *source, SpacetimeEndId end_id, double t); /* Analytic backends have negligible per-ray metric state. A numerical * backend must opt in once its metric slabs and evaluator workspaces need * to reserve memory alongside the private HDR render buffers. */ int limit_render_workers_by_memory; void (*destroy)(SpacetimeSource *source); } SpacetimeOps; struct SpacetimeSource { const SpacetimeOps *ops; void *context; }; /* The selected build provides spacetime_create_default(). Named constructors * remain available to backend-specific tests and tools. */ int spacetime_create_default(SpacetimeSource *source); int spacetime_create_minkowski(SpacetimeSource *source, double escape_radius); int spacetime_create_schwarzschild_ks(SpacetimeSource *source, double mass, double escape_radius); /* Moving Alcubierre bubble with x_s(t) = vs*t and x_s(0) = 0. Requires * |vs| < 1, R > 0, and sigma > 0. */ int spacetime_create_alcubierre(SpacetimeSource *source, double vs, double radius, double sigma); /* Bubble-centered escape radius used by the Alcubierre backend; also lets * callers size their integration step budget. */ double spacetime_alcubierre_escape_radius(double radius, double sigma); void spacetime_destroy(SpacetimeSource *source); SpacetimePointStatus spacetime_eval(const SpacetimeSource *source, double t, const double x[3], MetricData *metric); SpacetimeRayStatus spacetime_classify(const SpacetimeSource *source, double t, const double x[3]); int spacetime_load_slab(const SpacetimeSource *source, double t_hi, double t_lo, MetricSlab **out); void spacetime_free_slab(MetricSlab *slab); SpacetimePointStatus spacetime_slab_eval(const MetricSlab *slab, double t, const double x[3], MetricData *metric); SpacetimeRayStatus spacetime_slab_classify(const MetricSlab *slab, double t, const double x[3]); size_t spacetime_asymptotic_end_count(const SpacetimeSource *source); int spacetime_asymptotic_end(const SpacetimeSource *source, size_t index, SpacetimeAsymptoticEnd *out); int spacetime_escape_worldtube_sample(const SpacetimeSource *source, SpacetimeEndId end_id, double t, SpacetimeEscapeWorldtubeSample *out); double spacetime_escape_worldtube_next_segment(const SpacetimeSource *source, SpacetimeEndId end_id, double t); /* Common structural validation that every successful constructor must pass * before returning. A source that passes is a promise that it can safely * enter ray tracing; backend-specific history/segment validation stays in the * backend constructor. On failure the constructor must destroy its context. */ int spacetime_source_finalize(SpacetimeSource *source); int spacetime_limits_render_workers_by_memory(const SpacetimeSource *source); #endif