94 lines
3.3 KiB
C
94 lines
3.3 KiB
C
#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};
|
|
}
|