init
This commit is contained in:
commit
d30f9ac56c
56 files changed
+40776
No files matched your search
@@ -0,0 +1,115 @@
|
||||
#include "frame.h"
|
||||
#include "optics.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <omp.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
int main(void) {
|
||||
const int width = 100, height = 100;
|
||||
const PointSpreadFunction psf = {.fwhm_pixels = 2.7, .moffat_beta = 4.5};
|
||||
const GeodesicTraceConfig trace = {.coordinate_time_step = 0.25,
|
||||
.max_steps = 100};
|
||||
const ObserverState observer = observer_fixed_at_origin();
|
||||
Star star = {
|
||||
.direction = {0.0, 0.0, -1.0}, .temperature_K = 7000.0, .amplitude = 1.0};
|
||||
StarCatalog catalog = {.stars = &star, .count = 1};
|
||||
SpacetimeSource spacetime = {0};
|
||||
FrameLensMesh mesh = {0};
|
||||
double *hdr = calloc((size_t)width * height * 3, sizeof *hdr);
|
||||
int result = 1;
|
||||
if (hdr == NULL || spacetime_create_minkowski(&spacetime, 10.0) ||
|
||||
frame_lens_mesh_build_coarse(&mesh, width, height, 20, 30.0) ||
|
||||
frame_lens_mesh_trace(&mesh, &spacetime, &observer, &trace))
|
||||
goto done;
|
||||
const size_t images =
|
||||
frame_splat_catalog(&mesh, &catalog, hdr, width, height, 100.0, &psf);
|
||||
if (images != 1 || hdr[3 * (50 * width + 50)] <= 0.0) {
|
||||
fputs("flat-space inverse lens-map regression failed\n", stderr);
|
||||
goto done;
|
||||
}
|
||||
/* Private HDR accumulation must preserve the serial splat result. */
|
||||
double *serial_hdr = calloc((size_t)width * height * 3, sizeof *serial_hdr);
|
||||
double *parallel_hdr = calloc((size_t)width * height * 3, sizeof *parallel_hdr);
|
||||
if (serial_hdr == NULL || parallel_hdr == NULL) {
|
||||
free(serial_hdr);
|
||||
free(parallel_hdr);
|
||||
goto done;
|
||||
}
|
||||
const int original_threads = omp_get_max_threads();
|
||||
omp_set_dynamic(0);
|
||||
omp_set_num_threads(1);
|
||||
const size_t serial_images = frame_splat_catalog(
|
||||
&mesh, &catalog, serial_hdr, width, height, 100.0, &psf);
|
||||
omp_set_num_threads(4);
|
||||
const size_t parallel_images = frame_splat_catalog(
|
||||
&mesh, &catalog, parallel_hdr, width, height, 100.0, &psf);
|
||||
omp_set_num_threads(original_threads);
|
||||
for (int value = 0; value < width * height * 3; ++value)
|
||||
if (fabs(serial_hdr[value] - parallel_hdr[value]) >
|
||||
1e-12 * fmax(1.0, fabs(serial_hdr[value]))) {
|
||||
fputs("parallel catalog splat regression failed\n", stderr);
|
||||
free(serial_hdr);
|
||||
free(parallel_hdr);
|
||||
goto done;
|
||||
}
|
||||
free(serial_hdr);
|
||||
free(parallel_hdr);
|
||||
if (serial_images != 1 || parallel_images != serial_images) {
|
||||
fputs("parallel catalog image-count regression failed\n", stderr);
|
||||
goto done;
|
||||
}
|
||||
const LinearRgb cool = blackbody_to_linear_rgb(3000.0);
|
||||
const LinearRgb hot = blackbody_to_linear_rgb(10000.0);
|
||||
if (!(cool.r > cool.b && hot.b > hot.r &&
|
||||
hot.r + hot.g + hot.b > cool.r + cool.g + cool.b)) {
|
||||
fputs("blackbody spectral-color regression failed\n", stderr);
|
||||
goto done;
|
||||
}
|
||||
/* The Moffat is flux-normalized and retains a measurable, continuous wing
|
||||
* beyond the former Gaussian's 3-sigma raster box. */
|
||||
memset(hdr, 0, (size_t)width * height * 3 * sizeof *hdr);
|
||||
splat_moffat(hdr, width, height, 50.5, 50.5,
|
||||
(LinearRgb){1.0, 1.0, 1.0}, 1.0, &psf);
|
||||
double moffat_flux = 0.0;
|
||||
for (int pixel = 0; pixel < width * height; ++pixel)
|
||||
moffat_flux += hdr[3 * pixel];
|
||||
if (fabs(moffat_flux - 1.0) > 0.01 ||
|
||||
hdr[3 * (50 * width + 62)] <= 0.0) {
|
||||
fputs("Moffat normalization or wing regression failed\n", stderr);
|
||||
goto done;
|
||||
}
|
||||
frame_draw_mesh(&mesh, hdr, width, height, 0.5, 0.5);
|
||||
if (hdr[3 * (10 * width + 20)] != 0.25) {
|
||||
fputs("mesh diagnostic overlay regression failed\n", stderr);
|
||||
goto done;
|
||||
}
|
||||
/* A fixed absolute edge tolerance used to make tiny source triangles claim
|
||||
* sources far outside their field. */
|
||||
FrameLensMesh fine_mesh = {0};
|
||||
Star fine_stars[2] = {{.direction = {0.0, 0.0, -1.0},
|
||||
.temperature_K = 7000.0,
|
||||
.amplitude = 1.0},
|
||||
{.direction = {0.01, 0.0, -0.9999499987499375},
|
||||
.temperature_K = 7000.0,
|
||||
.amplitude = 1.0}};
|
||||
StarCatalog fine_catalog = {.stars = fine_stars, .count = 2};
|
||||
memset(hdr, 0, (size_t)width * height * 3 * sizeof *hdr);
|
||||
if (frame_lens_mesh_build_coarse(&fine_mesh, width, height, 1, 0.1) ||
|
||||
frame_lens_mesh_trace(&fine_mesh, &spacetime, &observer, &trace) ||
|
||||
frame_splat_catalog(&fine_mesh, &fine_catalog, hdr, width, height,
|
||||
100.0, &psf) != 1) {
|
||||
fputs("fine source-triangle containment regression failed\n", stderr);
|
||||
frame_lens_mesh_destroy(&fine_mesh);
|
||||
goto done;
|
||||
}
|
||||
frame_lens_mesh_destroy(&fine_mesh);
|
||||
result = 0;
|
||||
done:
|
||||
frame_lens_mesh_destroy(&mesh);
|
||||
spacetime_destroy(&spacetime);
|
||||
free(hdr);
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
#include "geodesic.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static int nearly_equal(double a, double b) { return fabs(a - b) < 1e-12; }
|
||||
|
||||
static int check_ray(const SpacetimeSource *source,
|
||||
const ObserverState *observer,
|
||||
const double local_direction[3],
|
||||
const double expected[3]) {
|
||||
const GeodesicTraceConfig config = {.coordinate_time_step = 0.25,
|
||||
.max_steps = 100};
|
||||
RayEndpoint ray =
|
||||
geodesic_trace_past(source, observer, local_direction, &config);
|
||||
if (ray.status != RAY_ENDPOINT_ESCAPED ||
|
||||
!nearly_equal(ray.frequency_ratio, 1.0) ||
|
||||
!nearly_equal(ray.n_infinity[0], expected[0]) ||
|
||||
!nearly_equal(ray.n_infinity[1], expected[1]) ||
|
||||
!nearly_equal(ray.n_infinity[2], expected[2])) {
|
||||
fprintf(stderr, "flat-space geodesic regression failed\n");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
SpacetimeSource source = {0};
|
||||
const ObserverState observer = observer_fixed_at_origin();
|
||||
if (spacetime_create_minkowski(&source, 10.0))
|
||||
return 1;
|
||||
int result = check_ray(&source, &observer, (double[]){1.0, 0.0, 0.0},
|
||||
(double[]){0.0, 0.0, -1.0}) ||
|
||||
check_ray(&source, &observer, (double[]){0.0, 0.0, 1.0},
|
||||
(double[]){1.0, 0.0, 0.0});
|
||||
const ObserverState look_at_ra_zero =
|
||||
observer_fixed_at_origin_look_at(0.0, 0.0);
|
||||
result = result || check_ray(&source, &look_at_ra_zero,
|
||||
(double[]){1.0, 0.0, 0.0},
|
||||
(double[]){1.0, 0.0, 0.0});
|
||||
spacetime_destroy(&source);
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
#include "geodesic.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(void) {
|
||||
SpacetimeSource spacetime = {0};
|
||||
MetricData metric;
|
||||
ObserverState observer;
|
||||
ObserverState inward_observer;
|
||||
const GeodesicTraceConfig trace = {.coordinate_time_step = 0.1,
|
||||
.max_steps = 4096,
|
||||
.capture_log_alpha_p0 = 8.0};
|
||||
int result = 1;
|
||||
if (spacetime_create_schwarzschild_ks(&spacetime, 1.0, 256.0, 1.5) ||
|
||||
spacetime_eval(&spacetime, 0.0, (double[]){2.0, 0.0, 0.0}, &metric) ||
|
||||
!isfinite(metric.alpha) || !isfinite(metric.gamma[0][0]) ||
|
||||
!isfinite(metric.K[0][0]) ||
|
||||
observer_static_schwarzschild_ks(1.0, 30.0, &observer) ||
|
||||
observer_inward_schwarzschild_ks(1.0, 30.0, 0.5,
|
||||
&inward_observer) ||
|
||||
fabs(inward_observer.tetrad[0][0] -
|
||||
(2.0 / sqrt(3.0)) * (observer.tetrad[0][0] +
|
||||
0.5 * observer.tetrad[1][0])) >
|
||||
1e-12 ||
|
||||
fabs(inward_observer.tetrad[1][1] -
|
||||
(2.0 / sqrt(3.0)) * (0.5 * observer.tetrad[0][1] +
|
||||
observer.tetrad[1][1])) >
|
||||
1e-12 ||
|
||||
!observer_inward_schwarzschild_ks(1.0, 30.0, 1.0,
|
||||
&inward_observer))
|
||||
goto done;
|
||||
const RayEndpoint central = geodesic_trace_past(
|
||||
&spacetime, &observer, (double[]){1.0, 0.0, 0.0}, &trace);
|
||||
const RayEndpoint inside_shadow = geodesic_trace_past(
|
||||
&spacetime, &observer, (double[]){cos(0.10), sin(0.10), 0.0}, &trace);
|
||||
const RayEndpoint outside_shadow = geodesic_trace_past(
|
||||
&spacetime, &observer, (double[]){cos(0.30), sin(0.30), 0.0}, &trace);
|
||||
if (central.status != RAY_ENDPOINT_CAPTURED ||
|
||||
inside_shadow.status != RAY_ENDPOINT_CAPTURED ||
|
||||
outside_shadow.status != RAY_ENDPOINT_ESCAPED) {
|
||||
fprintf(stderr,
|
||||
"Schwarzschild KS shadow regression failed (center=%d, inside=%d, "
|
||||
"outside=%d)\n",
|
||||
central.status, inside_shadow.status, outside_shadow.status);
|
||||
goto done;
|
||||
}
|
||||
result = 0;
|
||||
done:
|
||||
spacetime_destroy(&spacetime);
|
||||
return result;
|
||||
}
|
||||
Reference in new issue
Block a user