Aggregate movie rays through time slabs
This commit is contained in:
1 parent
2a00d7a2d1
commit
d3522886f0
8 files changed
+281
-37
No files matched your search
@@ -45,9 +45,12 @@ mkdir -p output/imgs
|
|||||||
This writes `minkowski_accel_000000.png` through
|
This writes `minkowski_accel_000000.png` through
|
||||||
`minkowski_accel_000060.png`. The renderer treats the CSV as its observer
|
`minkowski_accel_000060.png`. The renderer treats the CSV as its observer
|
||||||
input; the acceleration generator is only a reproducible flat-spacetime test
|
input; the acceleration generator is only a reproducible flat-spacetime test
|
||||||
fixture. The current movie path still renders frames independently while the
|
fixture. Movie mode collects all current frame-mesh vertices into a single
|
||||||
time-slab/RayPool scheduler is implemented next, so it must not yet be used
|
SoA ray pool, activates rays as a newest-to-oldest coordinate-time scan reaches
|
||||||
as a performance measurement for numerical-relativity data. The current
|
their observer event, and advances active rays to each slab boundary. The
|
||||||
|
analytic backends use logical slabs with no metric I/O; nmesh slab loading is
|
||||||
|
the next backend step. `--slab-duration` sets the coordinate-time width
|
||||||
|
(default `64`) for this current fixed-mesh pass. The current
|
||||||
synthetic test catalog uses global default exposure `1e-3`; the accelerated
|
synthetic test catalog uses global default exposure `1e-3`; the accelerated
|
||||||
benchmark explicitly uses `1e-5` because its physical Doppler blue shift
|
benchmark explicitly uses `1e-5` because its physical Doppler blue shift
|
||||||
otherwise clips the later frames.
|
otherwise clips the later frames.
|
||||||
|
|||||||
+53
-30
@@ -1,9 +1,7 @@
|
|||||||
#include "geodesic.h"
|
#include "geodesic.h"
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef GeodesicRayState State;
|
||||||
double x[3], Pi[3], log_alpha_p0;
|
|
||||||
} State;
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
double x[3], Pi[3], log_alpha_p0;
|
double x[3], Pi[3], log_alpha_p0;
|
||||||
} Derivative;
|
} Derivative;
|
||||||
@@ -106,8 +104,9 @@ static int rk4(const SpacetimeSource *source, double t, double h, State *s) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int initialize(const SpacetimeSource *source, const ObserverState *o,
|
int geodesic_initialize_past_ray(const SpacetimeSource *source,
|
||||||
const double n[3], State *s) {
|
const ObserverState *o, const double n[3],
|
||||||
|
State *s) {
|
||||||
MetricData m;
|
MetricData m;
|
||||||
double k[4] = {o->tetrad[0][0], o->tetrad[0][1], o->tetrad[0][2],
|
double k[4] = {o->tetrad[0][0], o->tetrad[0][1], o->tetrad[0][2],
|
||||||
o->tetrad[0][3]};
|
o->tetrad[0][3]};
|
||||||
@@ -127,6 +126,8 @@ static int initialize(const SpacetimeSource *source, const ObserverState *o,
|
|||||||
s->Pi[i] /= m.alpha * k[0];
|
s->Pi[i] /= m.alpha * k[0];
|
||||||
}
|
}
|
||||||
s->log_alpha_p0 = log(m.alpha * k[0]);
|
s->log_alpha_p0 = log(m.alpha * k[0]);
|
||||||
|
s->coordinate_time = o->coordinate_time;
|
||||||
|
s->steps = 0;
|
||||||
return isfinite(s->log_alpha_p0) ? 0 : -1;
|
return isfinite(s->log_alpha_p0) ? 0 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,6 +150,47 @@ static int escaped_direction(const SpacetimeSource *source, double t,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GeodesicAdvanceResult geodesic_advance_past_ray(
|
||||||
|
const SpacetimeSource *source, State *s, double slab_left_time,
|
||||||
|
const GeodesicTraceConfig *config, RayEndpoint *out) {
|
||||||
|
if (!source || !s || !config || !out || config->coordinate_time_step <= 0 ||
|
||||||
|
!config->max_steps || !isfinite(slab_left_time) ||
|
||||||
|
slab_left_time > s->coordinate_time)
|
||||||
|
return GEODESIC_ADVANCE_FAILED;
|
||||||
|
while (s->coordinate_time > slab_left_time) {
|
||||||
|
if (config->capture_log_alpha_p0 > 0.0 &&
|
||||||
|
s->log_alpha_p0 >= config->capture_log_alpha_p0) {
|
||||||
|
out->status = RAY_ENDPOINT_CAPTURED;
|
||||||
|
return GEODESIC_ADVANCE_TERMINATED;
|
||||||
|
}
|
||||||
|
SpacetimeRayStatus status =
|
||||||
|
spacetime_classify(source, s->coordinate_time, s->x);
|
||||||
|
if (status != SPACETIME_RAY_ACTIVE) {
|
||||||
|
out->status = status == SPACETIME_RAY_ESCAPED ? RAY_ENDPOINT_ESCAPED
|
||||||
|
: RAY_ENDPOINT_CAPTURED;
|
||||||
|
if (out->status == RAY_ENDPOINT_ESCAPED &&
|
||||||
|
escaped_direction(source, s->coordinate_time, s, out->n_infinity) == 0)
|
||||||
|
out->frequency_ratio = exp(-s->log_alpha_p0);
|
||||||
|
else if (out->status == RAY_ENDPOINT_ESCAPED)
|
||||||
|
out->status = RAY_ENDPOINT_INTEGRATION_FAILURE;
|
||||||
|
return out->status == RAY_ENDPOINT_INTEGRATION_FAILURE
|
||||||
|
? GEODESIC_ADVANCE_FAILED
|
||||||
|
: GEODESIC_ADVANCE_TERMINATED;
|
||||||
|
}
|
||||||
|
if (s->steps >= config->max_steps) {
|
||||||
|
out->status = RAY_ENDPOINT_MAX_STEPS;
|
||||||
|
return GEODESIC_ADVANCE_TERMINATED;
|
||||||
|
}
|
||||||
|
const double h = -fmin(config->coordinate_time_step,
|
||||||
|
s->coordinate_time - slab_left_time);
|
||||||
|
if (rk4(source, s->coordinate_time, h, s))
|
||||||
|
return GEODESIC_ADVANCE_FAILED;
|
||||||
|
s->coordinate_time += h;
|
||||||
|
++s->steps;
|
||||||
|
}
|
||||||
|
return GEODESIC_ADVANCE_ACTIVE;
|
||||||
|
}
|
||||||
|
|
||||||
RayEndpoint geodesic_trace_past(const SpacetimeSource *source,
|
RayEndpoint geodesic_trace_past(const SpacetimeSource *source,
|
||||||
const ObserverState *observer,
|
const ObserverState *observer,
|
||||||
const double n[3],
|
const double n[3],
|
||||||
@@ -156,34 +198,15 @@ RayEndpoint geodesic_trace_past(const SpacetimeSource *source,
|
|||||||
RayEndpoint out = {.frequency_ratio = 0,
|
RayEndpoint out = {.frequency_ratio = 0,
|
||||||
.magnification = 1,
|
.magnification = 1,
|
||||||
.status = RAY_ENDPOINT_INTEGRATION_FAILURE};
|
.status = RAY_ENDPOINT_INTEGRATION_FAILURE};
|
||||||
State s;
|
State state;
|
||||||
double t;
|
|
||||||
if (!source || !observer || !config || config->coordinate_time_step <= 0 ||
|
if (!source || !observer || !config || config->coordinate_time_step <= 0 ||
|
||||||
!config->max_steps || fabs(dot(n, n) - 1) > 1e-10 ||
|
!config->max_steps || fabs(dot(n, n) - 1) > 1e-10 ||
|
||||||
initialize(source, observer, n, &s))
|
geodesic_initialize_past_ray(source, observer, n, &state))
|
||||||
return out;
|
return out;
|
||||||
t = observer->coordinate_time;
|
const double last_time =
|
||||||
for (unsigned int i = 0; i < config->max_steps; i++) {
|
observer->coordinate_time - config->coordinate_time_step * config->max_steps;
|
||||||
if (config->capture_log_alpha_p0 > 0.0 &&
|
if (geodesic_advance_past_ray(source, &state, last_time, config, &out) ==
|
||||||
s.log_alpha_p0 >= config->capture_log_alpha_p0) {
|
GEODESIC_ADVANCE_ACTIVE)
|
||||||
out.status = RAY_ENDPOINT_CAPTURED;
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
SpacetimeRayStatus status = spacetime_classify(source, t, s.x);
|
|
||||||
if (status != SPACETIME_RAY_ACTIVE) {
|
|
||||||
out.status = status == SPACETIME_RAY_ESCAPED ? RAY_ENDPOINT_ESCAPED
|
|
||||||
: RAY_ENDPOINT_CAPTURED;
|
|
||||||
if (out.status == RAY_ENDPOINT_ESCAPED &&
|
|
||||||
escaped_direction(source, t, &s, out.n_infinity) == 0)
|
|
||||||
out.frequency_ratio = exp(-s.log_alpha_p0);
|
|
||||||
else if (out.status == RAY_ENDPOINT_ESCAPED)
|
|
||||||
out.status = RAY_ENDPOINT_INTEGRATION_FAILURE;
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
if (rk4(source, t, -config->coordinate_time_step, &s))
|
|
||||||
return out;
|
|
||||||
t -= config->coordinate_time_step;
|
|
||||||
}
|
|
||||||
out.status = RAY_ENDPOINT_MAX_STEPS;
|
out.status = RAY_ENDPOINT_MAX_STEPS;
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
@@ -28,10 +28,32 @@ typedef struct {
|
|||||||
double capture_log_alpha_p0;
|
double capture_log_alpha_p0;
|
||||||
} GeodesicTraceConfig;
|
} GeodesicTraceConfig;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
double coordinate_time;
|
||||||
|
double x[3];
|
||||||
|
double Pi[3];
|
||||||
|
double log_alpha_p0;
|
||||||
|
unsigned int steps;
|
||||||
|
} GeodesicRayState;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
GEODESIC_ADVANCE_ACTIVE = 0,
|
||||||
|
GEODESIC_ADVANCE_TERMINATED = 1,
|
||||||
|
GEODESIC_ADVANCE_FAILED = -1
|
||||||
|
} GeodesicAdvanceResult;
|
||||||
|
|
||||||
/* camera_direction is a unit vector in the observer's (forward, up, right)
|
/* camera_direction is a unit vector in the observer's (forward, up, right)
|
||||||
* tetrad. */
|
* tetrad. */
|
||||||
RayEndpoint geodesic_trace_past(const SpacetimeSource *source,
|
RayEndpoint geodesic_trace_past(const SpacetimeSource *source,
|
||||||
const ObserverState *observer,
|
const ObserverState *observer,
|
||||||
const double camera_direction[3],
|
const double camera_direction[3],
|
||||||
const GeodesicTraceConfig *config);
|
const GeodesicTraceConfig *config);
|
||||||
|
int geodesic_initialize_past_ray(const SpacetimeSource *source,
|
||||||
|
const ObserverState *observer,
|
||||||
|
const double camera_direction[3],
|
||||||
|
GeodesicRayState *state);
|
||||||
|
GeodesicAdvanceResult geodesic_advance_past_ray(
|
||||||
|
const SpacetimeSource *source, GeodesicRayState *state,
|
||||||
|
double slab_left_time, const GeodesicTraceConfig *config,
|
||||||
|
RayEndpoint *endpoint);
|
||||||
#endif
|
#endif
|
||||||
+52
-4
@@ -3,6 +3,7 @@
|
|||||||
#include "movie.h"
|
#include "movie.h"
|
||||||
#include "observer_track.h"
|
#include "observer_track.h"
|
||||||
#include "optics.h"
|
#include "optics.h"
|
||||||
|
#include "ray.h"
|
||||||
#include "spacetime.h"
|
#include "spacetime.h"
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
@@ -27,6 +28,7 @@ typedef struct {
|
|||||||
const char *frames_prefix;
|
const char *frames_prefix;
|
||||||
const char *write_minkowski_accel_track_path;
|
const char *write_minkowski_accel_track_path;
|
||||||
double movie_start_time, movie_duration, movie_fps;
|
double movie_start_time, movie_duration, movie_fps;
|
||||||
|
double slab_duration;
|
||||||
double minkowski_proper_acceleration;
|
double minkowski_proper_acceleration;
|
||||||
} Settings;
|
} Settings;
|
||||||
|
|
||||||
@@ -104,6 +106,7 @@ static int parse_args(int argc, char **argv, Settings *s,
|
|||||||
.frames_prefix = "frame",
|
.frames_prefix = "frame",
|
||||||
.movie_duration = 2.0,
|
.movie_duration = 2.0,
|
||||||
.movie_fps = 30.0,
|
.movie_fps = 30.0,
|
||||||
|
.slab_duration = 64.0,
|
||||||
.minkowski_proper_acceleration = 1.52};
|
.minkowski_proper_acceleration = 1.52};
|
||||||
*write_path = NULL;
|
*write_path = NULL;
|
||||||
for (int i = 1; i < argc; ++i) {
|
for (int i = 1; i < argc; ++i) {
|
||||||
@@ -147,6 +150,8 @@ static int parse_args(int argc, char **argv, Settings *s,
|
|||||||
!parse_nonnegative(argv[++i], &s->movie_duration)) {
|
!parse_nonnegative(argv[++i], &s->movie_duration)) {
|
||||||
} else if (!strcmp(argv[i], "--fps") && i + 1 < argc &&
|
} else if (!strcmp(argv[i], "--fps") && i + 1 < argc &&
|
||||||
!parse_positive(argv[++i], &s->movie_fps)) {
|
!parse_positive(argv[++i], &s->movie_fps)) {
|
||||||
|
} else if (!strcmp(argv[i], "--slab-duration") && i + 1 < argc &&
|
||||||
|
!parse_positive(argv[++i], &s->slab_duration)) {
|
||||||
} else if (!strcmp(argv[i], "--proper-acceleration") && i + 1 < argc &&
|
} else if (!strcmp(argv[i], "--proper-acceleration") && i + 1 < argc &&
|
||||||
!parse_nonnegative(argv[++i],
|
!parse_nonnegative(argv[++i],
|
||||||
&s->minkowski_proper_acceleration)) {
|
&s->minkowski_proper_acceleration)) {
|
||||||
@@ -233,21 +238,64 @@ static int render_movie(const Settings *s, const StarCatalog *catalog,
|
|||||||
const SpacetimeSource *spacetime) {
|
const SpacetimeSource *spacetime) {
|
||||||
ObserverTrack track = {0};
|
ObserverTrack track = {0};
|
||||||
Movie movie = {0};
|
Movie movie = {0};
|
||||||
|
RayPool rays = {0};
|
||||||
|
const GeodesicTraceConfig trace = trace_config();
|
||||||
int result = -1;
|
int result = -1;
|
||||||
if (s->observer_track_path == NULL ||
|
if (s->observer_track_path == NULL ||
|
||||||
observer_track_load_csv(&track, s->observer_track_path) ||
|
observer_track_load_csv(&track, s->observer_track_path) ||
|
||||||
movie_init(&movie, &track, s->movie_start_time, s->movie_duration,
|
movie_init(&movie, &track, s->movie_start_time, s->movie_duration,
|
||||||
s->movie_fps))
|
s->movie_fps) ||
|
||||||
|
movie_build_coarse_meshes(&movie, s->width, s->height,
|
||||||
|
s->coarse_cell_pixels, s->horizontal_fov_deg))
|
||||||
goto done;
|
goto done;
|
||||||
|
size_t ray_count = 0;
|
||||||
|
for (size_t i = 0; i < movie.frame_count; ++i)
|
||||||
|
ray_count += movie.frames[i].mesh.vertex_count;
|
||||||
|
if (ray_count == 0 || ray_pool_init(&rays, ray_count))
|
||||||
|
goto done;
|
||||||
|
for (size_t f = 0; f < movie.frame_count; ++f)
|
||||||
|
for (size_t v = 0; v < movie.frames[f].mesh.vertex_count; ++v)
|
||||||
|
if (ray_pool_append(&rays, spacetime, &movie.frames[f].observer,
|
||||||
|
movie.frames[f].mesh.vertices[v].camera_direction,
|
||||||
|
f, v))
|
||||||
|
goto done;
|
||||||
|
double slab_hi = movie.frames[movie.frame_count - 1].coordinate_time;
|
||||||
|
while (ray_pool_has_live(&rays)) {
|
||||||
|
const double slab_lo = slab_hi - s->slab_duration;
|
||||||
|
ray_pool_activate_in_time_range(&rays, slab_hi, slab_lo);
|
||||||
|
ray_pool_advance_active(&rays, spacetime, slab_lo, &trace);
|
||||||
|
slab_hi = slab_lo;
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < rays.count; ++i) {
|
||||||
|
LensVertex *vertex = &movie.frames[rays.frame_id[i]].mesh.vertices[rays.vertex_id[i]];
|
||||||
|
vertex->status = rays.endpoint[i].status;
|
||||||
|
if (vertex->status == RAY_ENDPOINT_ESCAPED) {
|
||||||
|
for (int axis = 0; axis < 3; ++axis)
|
||||||
|
vertex->n_infinity[axis] = rays.endpoint[i].n_infinity[axis];
|
||||||
|
vertex->log_frequency_ratio = log(rays.endpoint[i].frequency_ratio);
|
||||||
|
}
|
||||||
|
}
|
||||||
for (size_t i = 0; i < movie.frame_count; ++i) {
|
for (size_t i = 0; i < movie.frame_count; ++i) {
|
||||||
char output_path[PATH_MAX];
|
char output_path[PATH_MAX];
|
||||||
if (frame_output_path(output_path, s, movie.frames[i].frame_id) ||
|
double *hdr = calloc((size_t)s->width * s->height * 3, sizeof *hdr);
|
||||||
render_observer_frame(s, catalog, spacetime, &movie.frames[i].observer,
|
if (hdr == NULL || frame_output_path(output_path, s, movie.frames[i].frame_id)) {
|
||||||
output_path))
|
free(hdr);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
const size_t images = frame_splat_catalog(&movie.frames[i].mesh, catalog, hdr,
|
||||||
|
s->width, s->height, s->exposure, &s->psf);
|
||||||
|
if (s->draw_mesh)
|
||||||
|
frame_draw_mesh(&movie.frames[i].mesh, hdr, s->width, s->height, 0.5, 0.5);
|
||||||
|
const int write_result = write_tonemapped_image(output_path, hdr, s->width, s->height);
|
||||||
|
free(hdr);
|
||||||
|
fprintf(stderr, "Rendered %zu images from %zu catalog stars to %s (%s)\n",
|
||||||
|
images, catalog->count, output_path, write_result == 0 ? "ok" : "write failed");
|
||||||
|
if (write_result)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
result = 0;
|
result = 0;
|
||||||
done:
|
done:
|
||||||
|
ray_pool_destroy(&rays);
|
||||||
movie_destroy(&movie);
|
movie_destroy(&movie);
|
||||||
observer_track_destroy(&track);
|
observer_track_destroy(&track);
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
+16
@@ -33,9 +33,25 @@ int movie_init(Movie *movie, const ObserverTrack *track, double start_time,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int movie_build_coarse_meshes(Movie *movie, int width, int height,
|
||||||
|
int cell_pixels, double horizontal_fov_deg) {
|
||||||
|
if (movie == NULL)
|
||||||
|
return -1;
|
||||||
|
for (size_t i = 0; i < movie->frame_count; ++i)
|
||||||
|
if (frame_lens_mesh_build_coarse(&movie->frames[i].mesh, width, height,
|
||||||
|
cell_pixels, horizontal_fov_deg)) {
|
||||||
|
for (size_t j = 0; j <= i; ++j)
|
||||||
|
frame_lens_mesh_destroy(&movie->frames[j].mesh);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void movie_destroy(Movie *movie) {
|
void movie_destroy(Movie *movie) {
|
||||||
if (movie == NULL)
|
if (movie == NULL)
|
||||||
return;
|
return;
|
||||||
|
for (size_t i = 0; i < movie->frame_count; ++i)
|
||||||
|
frame_lens_mesh_destroy(&movie->frames[i].mesh);
|
||||||
free(movie->frames);
|
free(movie->frames);
|
||||||
*movie = (Movie){0};
|
*movie = (Movie){0};
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
#define MOVIE_H
|
#define MOVIE_H
|
||||||
|
|
||||||
#include "observer_track.h"
|
#include "observer_track.h"
|
||||||
|
#include "frame.h"
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
@@ -10,6 +11,7 @@ typedef struct {
|
|||||||
double coordinate_time;
|
double coordinate_time;
|
||||||
double proper_time;
|
double proper_time;
|
||||||
ObserverState observer;
|
ObserverState observer;
|
||||||
|
FrameLensMesh mesh;
|
||||||
} MovieFrame;
|
} MovieFrame;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -19,6 +21,8 @@ typedef struct {
|
|||||||
|
|
||||||
int movie_init(Movie *movie, const ObserverTrack *track, double start_time,
|
int movie_init(Movie *movie, const ObserverTrack *track, double start_time,
|
||||||
double duration, double frames_per_second);
|
double duration, double frames_per_second);
|
||||||
|
int movie_build_coarse_meshes(Movie *movie, int width, int height,
|
||||||
|
int cell_pixels, double horizontal_fov_deg);
|
||||||
void movie_destroy(Movie *movie);
|
void movie_destroy(Movie *movie);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
#include "ray.h"
|
||||||
|
|
||||||
|
#include <omp.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
int ray_pool_init(RayPool *p, size_t capacity) {
|
||||||
|
if (p == NULL || capacity == 0)
|
||||||
|
return -1;
|
||||||
|
*p = (RayPool){.capacity = capacity};
|
||||||
|
#define RAY_ALLOC(field) (p->field = calloc(capacity, sizeof *p->field))
|
||||||
|
if (!(RAY_ALLOC(t) && RAY_ALLOC(x0) && RAY_ALLOC(x1) && RAY_ALLOC(x2) &&
|
||||||
|
RAY_ALLOC(p0) && RAY_ALLOC(p1) && RAY_ALLOC(p2) &&
|
||||||
|
RAY_ALLOC(log_alpha_p0) && RAY_ALLOC(steps) && RAY_ALLOC(frame_id) &&
|
||||||
|
RAY_ALLOC(vertex_id) && RAY_ALLOC(status) && RAY_ALLOC(endpoint))) {
|
||||||
|
ray_pool_destroy(p);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#undef RAY_ALLOC
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ray_pool_append(RayPool *p, const SpacetimeSource *source,
|
||||||
|
const ObserverState *observer, const double direction[3],
|
||||||
|
size_t frame_id, size_t vertex_id) {
|
||||||
|
if (p == NULL || p->count == p->capacity)
|
||||||
|
return -1;
|
||||||
|
GeodesicRayState s;
|
||||||
|
const size_t i = p->count;
|
||||||
|
if (geodesic_initialize_past_ray(source, observer, direction, &s))
|
||||||
|
return -1;
|
||||||
|
p->t[i] = s.coordinate_time;
|
||||||
|
p->x0[i] = s.x[0]; p->x1[i] = s.x[1]; p->x2[i] = s.x[2];
|
||||||
|
p->p0[i] = s.Pi[0]; p->p1[i] = s.Pi[1]; p->p2[i] = s.Pi[2];
|
||||||
|
p->log_alpha_p0[i] = s.log_alpha_p0;
|
||||||
|
p->steps[i] = s.steps;
|
||||||
|
p->frame_id[i] = frame_id;
|
||||||
|
p->vertex_id[i] = vertex_id;
|
||||||
|
p->status[i] = RAY_POOL_PENDING;
|
||||||
|
p->endpoint[i] = (RayEndpoint){.magnification = 1.0,
|
||||||
|
.status = RAY_ENDPOINT_INTEGRATION_FAILURE};
|
||||||
|
++p->count;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ray_pool_activate_in_time_range(RayPool *p, double t_hi, double t_lo) {
|
||||||
|
for (size_t i = 0; i < p->count; ++i)
|
||||||
|
if (p->status[i] == RAY_POOL_PENDING && p->t[i] <= t_hi && p->t[i] > t_lo)
|
||||||
|
p->status[i] = RAY_POOL_ACTIVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ray_pool_advance_active(RayPool *p, const SpacetimeSource *source,
|
||||||
|
double t_lo, const GeodesicTraceConfig *config) {
|
||||||
|
#pragma omp parallel for schedule(static)
|
||||||
|
for (size_t i = 0; i < p->count; ++i) {
|
||||||
|
if (p->status[i] != RAY_POOL_ACTIVE)
|
||||||
|
continue;
|
||||||
|
GeodesicRayState s = {.coordinate_time = p->t[i],
|
||||||
|
.x = {p->x0[i], p->x1[i], p->x2[i]},
|
||||||
|
.Pi = {p->p0[i], p->p1[i], p->p2[i]},
|
||||||
|
.log_alpha_p0 = p->log_alpha_p0[i],
|
||||||
|
.steps = p->steps[i]};
|
||||||
|
const GeodesicAdvanceResult result =
|
||||||
|
geodesic_advance_past_ray(source, &s, t_lo, config, &p->endpoint[i]);
|
||||||
|
p->t[i] = s.coordinate_time;
|
||||||
|
p->x0[i] = s.x[0]; p->x1[i] = s.x[1]; p->x2[i] = s.x[2];
|
||||||
|
p->p0[i] = s.Pi[0]; p->p1[i] = s.Pi[1]; p->p2[i] = s.Pi[2];
|
||||||
|
p->log_alpha_p0[i] = s.log_alpha_p0;
|
||||||
|
p->steps[i] = s.steps;
|
||||||
|
if (result == GEODESIC_ADVANCE_TERMINATED)
|
||||||
|
p->status[i] = RAY_POOL_TERMINATED;
|
||||||
|
else if (result == GEODESIC_ADVANCE_FAILED)
|
||||||
|
p->status[i] = RAY_POOL_FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int ray_pool_has_live(const RayPool *p) {
|
||||||
|
if (p == NULL)
|
||||||
|
return 0;
|
||||||
|
for (size_t i = 0; i < p->count; ++i)
|
||||||
|
if (p->status[i] == RAY_POOL_PENDING || p->status[i] == RAY_POOL_ACTIVE)
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ray_pool_destroy(RayPool *p) {
|
||||||
|
if (p == NULL)
|
||||||
|
return;
|
||||||
|
free(p->t); free(p->x0); free(p->x1); free(p->x2);
|
||||||
|
free(p->p0); free(p->p1); free(p->p2); free(p->log_alpha_p0);
|
||||||
|
free(p->steps); free(p->frame_id); free(p->vertex_id); free(p->status);
|
||||||
|
free(p->endpoint);
|
||||||
|
*p = (RayPool){0};
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
#ifndef RAY_H
|
||||||
|
#define RAY_H
|
||||||
|
|
||||||
|
#include "geodesic.h"
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
RAY_POOL_PENDING,
|
||||||
|
RAY_POOL_ACTIVE,
|
||||||
|
RAY_POOL_TERMINATED,
|
||||||
|
RAY_POOL_FAILED
|
||||||
|
} RayPoolStatus;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
double *t, *x0, *x1, *x2, *p0, *p1, *p2, *log_alpha_p0;
|
||||||
|
unsigned int *steps;
|
||||||
|
size_t *frame_id, *vertex_id;
|
||||||
|
uint8_t *status;
|
||||||
|
RayEndpoint *endpoint;
|
||||||
|
size_t count, capacity;
|
||||||
|
} RayPool;
|
||||||
|
|
||||||
|
int ray_pool_init(RayPool *pool, size_t capacity);
|
||||||
|
int ray_pool_append(RayPool *pool, const SpacetimeSource *source,
|
||||||
|
const ObserverState *observer, const double direction[3],
|
||||||
|
size_t frame_id, size_t vertex_id);
|
||||||
|
void ray_pool_activate_in_time_range(RayPool *pool, double t_hi, double t_lo);
|
||||||
|
void ray_pool_advance_active(RayPool *pool, const SpacetimeSource *source,
|
||||||
|
double t_lo, const GeodesicTraceConfig *config);
|
||||||
|
int ray_pool_has_live(const RayPool *pool);
|
||||||
|
void ray_pool_destroy(RayPool *pool);
|
||||||
|
|
||||||
|
#endif
|
||||||
Reference in new issue
Block a user