Files
GR-raytracing/src/ray.c
T

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};
}