Compare commits

..
41 Commits
Author SHA1 Message Date
wyj 2c88bbc7e6 Doc: Define authoritative design document hygiene rules 2026-10-10 01:50:42 -04:00
wyj 80f9dcb3a3 Feat: Add post-tone-map mesh diagnostics with RGBA overlays
Color antialiased half-edges by ray outcome with configurable Catppuccin colors and default opacity 0.5.

Rasterize premultiplied RGBA8 overlays on the producer and composite in place after writing the clean image. Keep single-frame, movie, and replay output consistent.

Add overlay, CLI, and queue ownership regressions and document the final output architecture.
2026-10-10 01:46:32 -04:00
wyj 4053d5d0c8 Fix: Stop lens-map vertex decoding on read failure 2026-10-09 00:17:39 -04:00
wyj 7c980c35aa Benchmark: Compare quadratic entry precision and arithmetic cost
Generate plain long-double and experimental FMA variants from the production entry kernel. Compare exact-rational references, geometric validation, fallback counts and repeated timings with self-contained fixtures.

Validate cached build dependencies and reject stale timing output. Count all unconfirmed entry outcomes independently of reference classification.
2026-10-09 00:15:02 -04:00
wyj 789549ed2f Fix: Validate asymptotic entries with precise roots and fallback
Use scaled long-double quadratic arithmetic without explicit FMA. Validate entry candidates against backend geometry and localize uncertain entries along the original exterior trajectory.

Preserve conservative miss semantics and propagate concrete entry failures. Add production-sample and numerical regression coverage.
2026-10-09 00:14:54 -04:00
wyj 95c05f84d9 Fix: Distinguish concrete ray failure causes 2026-10-08 05:07:34 -04:00
wyj 76ed705d37 Fix: Report ray failure reasons and affected frames 2026-10-08 00:16:43 -04:00
wyj af8b83007f Fix: Separate normal renderer output from diagnostics 2026-10-07 22:14:56 -04:00
wyj 69a8cb5647 Feat: Add single-frame observer coordinate time option 2026-10-07 21:12:55 -04:00
wyj b3f1e837d5 Alcubierre: support superluminal v_s 2026-10-06 02:51:20 -04:00
wyj 0a46a7095b Feat: Complete adaptive geodesic tracing with DP54
Add error-controlled DP5(4) integration and trusted first-crossing localization, including non-monotonic energy thresholds and representable-time stepping.

Preserve adaptive state and independent step/time retry grants across RayPool, refinement and movie scheduling. Expose numerical controls, record actual persistent-sample costs, and add v3 lens-map provenance with legacy v2 RK4 import.

Use DP54 by default and select an 8M Schwarzschild maximum step from bounded scans and a two-run 4K comparison. Retain the conservative minimum-step guard and document critical-ray and backend capability limits. Archive self-contained benchmark inputs and raw output; keep fixed RK4 HDR references explicit.

Validation: make -B -j4 BUILD_TYPE=Debug test passed; explicit RK4 HDR references have zero differences. Bounded convergence checks, benchmark reproduction, Release build and focused reviews passed. No numerical-relativity backend is added.
2026-10-05 20:27:42 -04:00
wyj c894fdb11a Agent: add deepseek-coder sub agent 2026-10-05 06:39:26 -04:00
wyj f7380cbf75 Feat: Rework ray termination into escaped/dark/unresolved/incomplete
Replace the position capture cutoff with a camera-relative dark threshold
shared by every backend, and carry explicit outcome/reason provenance
through the ray, RayPool, adaptive mesh, lens-map and replay paths.

- eval/eval_slab return SpacetimePointStatus; remove SPACETIME_RAY_CAPTURED
  and the Schwarzschild capture radius; decouple observer construction from
  ray position.
- RayEndpoint stores RayOutcome/RayReason plus the last trusted state;
  budget exhaustion is retryable UNRESOLVED, data/integration failures are
  INCOMPLETE.
- Normal dark terminal is L - L0 >= --dark-threshold (default 8), with L0
  taken at the camera event and kept distinct from the worldtube entry
  energy; photon energy and frequency ratio are never reset.
- Implement E/D/U triangle decisions with merged budget retries, persistent
  probe witnesses promoted in place by vertex identity, conformity settling,
  and approximate-black boundary provenance with achieved-scale statistics.
- Add RayPool continuation state and per-ray step budgets.
- Bump lens-map to v2 with explicit end/outcome/reason, approx_black,
  threshold/retry/geometry provenance and per-frame retry counts; reject v1.
- Gate production output on incomplete/error results, overridable with
  --allow-incomplete.
- Update AGENTS.md, the design document and usage docs; add the termination
  oracle and regression coverage.

make -B -j4 BUILD_TYPE=Debug test passes with bit-identical reference HDRs.
2026-10-05 06:22:47 -04:00
wyj 7fde49308b Agents: add opencode code review sub agent 2026-10-05 02:44:15 -04:00
wyj 09a7417961 Feat: Add directed asymptotic escape and analytic Schwarzschild exterior
Replace radius-only escape termination with a common asymptotic exterior protocol: declared ends, moving escape worldtubes, directed inside->outside crossings, and a PENDING_ENTRY lifecycle shared by single-frame and movie tracing.

Add an analytic Carlson-integral Schwarzschild monopole exterior (angle primitive, bracketed turning radius, ingoing Kerr-Schild coordinate-time transfer, conserved-energy frequency) so a camera outside the escape sphere is traced through an entry event.

Make the lifecycle tri-state (no ends / ready / protocol error), carry end_id through the endpoint and lens mesh, validate sources in constructors via spacetime_source_finalize(), and refresh the Schwarzschild reference images for the corrected finish.
2026-10-04 03:32:28 -04:00
wyj 04611e3e5a Feat: Overlap movie output and cut per-frame fast-mode work
- Gather the union of every movie frame's all-sky tiles once and read them in bounded batches, replacing the per-frame prefetch scan and log.
- Fuse the fast supersampled-buffer clear into the FFTW pack pass so a resolved frame starts clean with no serial memset.
- Split parallel HDR->RGB8 tone mapping from PNG encoding.
- Add a bounded single-producer/single-writer movie output queue used by both observer movies and multi-frame imported lens maps, with writer timing and error propagation.
- Add --png-compression-level and --movie-output-workers shared|reserve-one.
- Add --fast-fftw-plan estimate|measure|wisdom|wisdom-update with strict wisdom identity sidecars.
- Add staged movie timing, regression tests, and docs.
2026-10-03 19:32:35 -04:00
wyj a510fec23e Doc: Keep git to long-term records and ignore local scratch
Ignore /local for short-term benchmark evidence, one-off A/B raw logs, and ad-hoc probes, and record the repository hygiene rule in AGENTS.md.
2026-10-03 19:32:27 -04:00
wyj 3cbf5ba386 Feat: Add analytic moving Alcubierre spacetime backend
Add a third analytic spacetime provider for the moving Alcubierre warp
bubble, x_s(t) = v_s*t with x_s(0) = 0.  The lab slices stay flat, so
alpha = 1, gamma_ij = delta_ij, beta^x = -v_s f(r_s), and K_ij follows
from the flat spatial metric; the time dependence enters through the
moving shape argument.  The exotic matter is treated as transparent, so
there is no capture: rays are only ACTIVE or ESCAPED, with a bubble-
centered escape radius R + 20/sigma.

Expose --alcubierre-vs, --alcubierre-radius, and --alcubierre-sigma
(|v_s| < 1).  Scale the per-ray step budget with the escape radius and
1/(1-|v_s|) so near-luminal grazing rays still escape, and reject
parameter combinations whose worst-case budget exceeds the cap.  Use a
cancellation-free shape formula for small sigma*R and reject derived
escape radii that overflow.

The regression test covers metric reconstruction, d_beta/K finite
differences, the translation isometry, small-sigma stability, the flat
limit, reflection symmetry, step convergence, and a near-luminal slow
ray.  build.md, usage.md, and README.md document the backend.
2026-10-03 03:09:26 -04:00
wyj 4e34780fa9 Doc: Record the isolated sensor-bloom benchmark
Store the bounded 512x288 synthetic-frame benchmark for the optional
sensor bloom model: the tested commit and file hashes, the exact build
and run commands, and the raw OMP_NUM_THREADS=1/4/16 outputs. It does not
claim any full-resolution or production performance.
2026-09-27 04:39:57 -04:00
wyj 9cd933d1f8 Feat: Add optional three-channel sensor bloom model
Add an opt-in, post-processing limited-response model applied to the
finished linear HDR before tone mapping. Each RGB channel is processed
independently and isotropically: overflow above E spreads to the eight
neighbours with a fixed 9-point stencil, while the rest is absorbed or
lost at the image boundary. The synchronous ping-pong update uses a
monotonic bounding box and a row-parallel, deterministic reduction; the
conservative round bound reserves fp guard rounds inside a 4096 hard
limit and fails before touching HDR when exceeded.

Expose --sensor-bloom-limit E and --sensor-bloom-transfer e (both
required together, default disabled), validate them before expensive
initialization, and route every output path through the same hook in
write_frame_outputs: raw FITS first, bloom, tone-mapped PNG/PPM, then the
mesh overlay. The raw --hdr-output FITS therefore stays pre-bloom.

Add a standalone unit test (stencil, boundary loss, cascade reference,
symmetry, thread determinism, convergence limits, validation, allocation
failure), CLI integration and regression coverage, an isolated
sensor-bloom-bench target, and document the model in the design, usage,
README, and build docs.
2026-09-27 04:39:38 -04:00
wyj 85fce1bdeb Misc: add a test catalog for testing PSF 2026-09-27 02:48:52 -04:00
wyj e31e1ed27e Feat: Add soft-clip tone mapping with legacy Reinhard
Replace the per-channel Reinhard display transform with a parameterized
soft clip T_p(x) = tanh(x^p)^(1/p), default softclip p=2, exposed through
--tone-map and --tone-map-p. Keep --tone-map reinhard bit-compatible with
the previous x/(1+x) curve for existing images and reject combining it
with an explicit --tone-map-p.

Route the primary image and the mesh overlay through the same
ToneMapSettings; the linear HDR FITS writer stays pre-tone-map. Add a
focused optics-linked tone-map test target, CLI success/error coverage,
and document the display operator versus the Moffat effective PSF.
2026-09-27 00:44:19 -04:00
wyj 7399eb6904 Tests: Use image-neutral wording in camera CLI logs
The camera CLI test now runs for both PNG and PPM builds, so the single/movie
comparison messages should say "image" rather than "PNG".
2026-09-26 17:02:31 -04:00
wyj 2a0197229a Feat: Write mesh overlay as a separate <stem>_mesh image
--draw-mesh no longer modifies the primary render.  The clean HDR FITS and
tone-mapped image are written first, then the final image-plane mesh is
overlaid in place on the already-consumed HDR buffer and saved as a
<stem>_mesh sibling.  This applies uniformly to single-frame, movie-frame,
and imported lens-map renders, with derived paths validated before catalog,
spacetime, and render initialization.

Dummy PSF backends still write nothing and report ignoring --draw-mesh.  The
reference-image target now uses the configured image extension so the
ENABLE_PNG=0 test path passes, and the CLI tests cover clean-main identity,
sibling naming, PATH_MAX overflow, and zero-tolerance HDR comparison.

README, README.zh-CN, and usage.md describe the new naming; the mesh reference
asset is renamed to match.
2026-09-26 17:01:25 -04:00
wyj e4d093a9fe Doc: Record 4K fast-mode accuracy limits and error distribution
Add the production-density 4K Galactic-center comparison to the 2026-09-25 benchmark record, including the per-image error decomposition, and refine the fast-mode positioning in usage.md, the design document, and README.

- Document that nearest/bilinear deposit accuracy is set by the deposit mode and N rather than output resolution, and that the still-frame error is dominated by a small number of resolved bright cores while the flux-dominant faint texture is much better than the global relative L2.
- Add the temporal-coherence caveat: nearest deposition jumps by 1/N output pixel per axis across supersampled-cell boundaries, so fast mode is not qualified as a temporally coherent movie path; bilinear removes the centroid jump but broadens the profile.
- Add scripts/fast_mode_error_decomposition.py, which ranks the largest |fast-base| RGB samples and partitions the error by a disjoint base-value range.
2026-09-26 01:02:41 -04:00
wyj 229f50cd86 Feat: Use FFTW linear convolution for CPU fast-mode PSF resolve
Replace the nested spatial global convolution in fast_psf_accumulator_resolve with a reusable double-precision FFTW linear convolution on the CPU PSF backend.

- Add the private src/fast_psf_fftw.{c,h} module: zero-padded R2C/C2R plans, cached kernel spectrum and planar scratch, exact 1/(Pwidth*Pheight) and 1/N^2 normalization, (R,R) crop, and additive HDR output.
- Keep the previous nested loops as fast_psf_accumulator_resolve_spatial_reference for tests/benchmarks only; it is not a runtime fallback.
- Cache the circular row spans on FastPsfAccumulator and report one-time plan, kernel transform, scratch, and per-frame stage timings.
- Require fftw3_omp for CPU builds; HIP and dummy builds do not link FFTW.
- Namespace test/helper binaries by spacetime and build tag, and reject make test / psf-capture for non-CPU backends.
- Add tests/test_fast_psf_fftw.c (FFTW versus spatial), tests/benchmark_fast_psf_fftw.c, an FFTW CLI smoke check, and the 2026-09-25 benchmark record.
2026-09-25 23:35:45 -04:00
wyj 3deebfb2fa Feat: Add --fast-mode supersampled point-source accumulation
Add an optional CPU preview path that deposits each point-source image as a
supersampled delta and resolves the whole frame with one global Moffat
convolution plus an N x N box average, instead of splatting a per-event PSF.

- optics: FastPsfAccumulator builds the pixel-area-integral kernel of the
  target Moffat at the supersampled scale (width N*alpha, same beta).  The
  1/N^2 box average then reproduces the final pixel-area integral, so the
  requested FWHM and beta are preserved without renormalisation.  Deposits are
  per-cell atomic adds; resolve accumulates into the caller's HDR buffer.
- frame: fast branch in frame_splat_catalog with one shared supersampled
  buffer and a single resolve per frame; the accumulator is reused across
  movie frames and built from the map dimensions on lens-map import.
- main: --fast-mode, --fast-supersample N (1..8, default 2) and
  --fast-deposit nearest|bilinear (default nearest).  CPU-only and rejected in
  the HIP/dummy backends; --psf-min-y still applies per event while
  --max-cache-psf-flux does not.
- The deposition scheme was chosen by scripts/fast_mode_deposit_error.py:
  nearest keeps the PSF shape exactly with <= 0.5/N px position quantization;
  bilinear keeps the exact centroid but broadens FWHM and beta.  Recorded in
  benchmarks/fast_mode_deposit_2026-09-18.md.
- tests/test_frame.c covers fast nearest vs the direct evaluator at the snapped
  centre, flux conservation, bilinear centroid, min-Y discard, frame plumbing,
  and HDR accumulation onto a non-zero background.
- benchmarks/fast_mode_cpu_2026-09-18.md records a ~10x speedup on the 2MASS
  galactic-centre field with small tone-mapped differences.
2026-09-24 01:36:25 -04:00
wyj 7ddc58515a Doc: Record full-day parallel prebinning results and next steps
Document the producer-private adaptive path, the dummy support workload
diagnostics, the negative result of the old serial binning and the
2026-09-13 full-day comparison (splat 282.944 s vs atomic 481.417 s).
Add the corresponding raw logs, hotspot fixtures and runner evidence,
and lay out the staged plan toward a sub-240 s full-day render without
changing the default atomic path.
2026-09-14 19:16:00 -04:00
wyj a88ec56097 Fix: Honor OMP_DYNAMIC and env binary hash in replay runner
Pin OMP_DYNAMIC=FALSE so thread counts stay deterministic, record it in
the command line, and locate the binary hash correctly when the command
is wrapped in env with inline assignments.
2026-09-14 19:15:56 -04:00
wyj ce691b11ad Test: Extend HIP PSF replay for production and sustained rounds
Add production, production-prepared, production-parallel and
production-busy modes plus an optional 1..512 round count. Repeated
rounds validate against a round-scaled CPU double reference and report
per-round throughput; production-parallel exercises concurrent
prepared-chunk submission and production-busy adds host spin workers to
probe contention.
2026-09-14 19:15:55 -04:00
wyj 4bf2de1b40 Feat: Add dummy PSF support workload diagnostics
Add an opt-in DUMMY_PSF_SUPPORT_STATS mode to the diagnostic-only dummy
consumer. It records per-chunk cache-limited 16px support references,
touched tiles, 256-reference tasks, maximum tile list and first-pass
counting time, then reports percentiles. No HDR is produced and no
references are materialized or uploaded.
2026-09-14 19:15:53 -04:00
wyj eec5dd215a Feat: Add producer-private adaptive HIP PSF prebinning
Move adaptive tile16 selection and support-expanded CPU binning into a
per-producer HipPsfPreparedChunk computed before acquiring the shared
sink lock. The sink keeps sole ownership of the GPU HDR, stream, device
scratch and upload staging; submit_prepared runs under the lock and
preserves the existing single-stream ordering and direct fallback path.
The legacy hip_psf_sink_submit entry point prepares an internal chunk so
single-threaded replay stays compatible, and default accumulation remains
atomic.
2026-09-14 19:15:51 -04:00
wyj 2d01c2c101 Doc: Adopt CSV CIE 1931 blackbody reference 2026-09-12 15:29:36 -04:00
wyj ce9c4bc16f Test: Refresh reference images for CSV blackbody reference 2026-09-12 15:29:36 -04:00
wyj d2a901cab1 Feat: Add CSV CIE 1931 blackbody LUT backend
Replace the in-tree Wyman analytic CIE fit with a repository CIE 1931
2-degree LUT derived from the 360-830 nm, 1 nm-linear CSV reference. The
GRBBLUT3 table stores 1024 uniform log(T) XYZ nodes over
[670.146556, 101408.88] K with four-point cubic Lagrange interpolation, and
the same CSV reference supplies a three-term Rayleigh-Jeans form above the
table and an inverse-temperature/log-XYZ crossover with channel-specific
endpoint forms below it. The loader validates the header and payload
checksum and rejects legacy formats and runtime generation.

Initialize the backend in the renderer, frame test, and PSF capture tool so
the new default is active wherever colors are produced.
2026-09-12 15:29:33 -04:00
wyj 2fc2b43e8d Doc: Record production PSF chunk geometry
Preserve the protected full-catalog dummy run, its initial harness failure, input and output hashes, distribution quantiles, and the resulting sparse-tile scheduling conclusions.
2026-09-11 23:28:02 -04:00
wyj d02ecb2181 Feat: Add dummy PSF chunk diagnostics
Reuse production catalog mapping and per-worker chunk boundaries to report triangle and spatial distributions without initializing HIP or writing image outputs. Include a protected full-catalog runner and build documentation.
2026-09-11 23:27:42 -04:00
wyj 776f9b7247 Test: Add adaptive HIP tile replay selection
Add a bounded per-chunk center-tile selector to the real-event replay prototype and retain the paired timing, mixed-boundary, CPU, HIP, and sandbox-failure evidence.
2026-09-11 23:27:24 -04:00
wyj 11e703e33d Doc: record bounded HIP PSF replay results and provenance
Archive fixed catalog subsets and captured events, manifests, reproducible commands, raw timing and regression logs, and device resource evidence. Document distribution-dependent tile reduction gains and independent indexed producer throughput.

Update the GPU plan and renderer design while retaining the production atomic path. Preserve historical measurement metadata and exclude generated Python bytecode.
2026-09-11 16:45:48 -04:00
wyj 7f5ec1a488 Optics: add bounded HIP PSF replay and tile reduction experiments
Capture prepared events through a test-only producer consumer and measure serial and indexed parallel generation independently. Compare the production atomic kernel with bounded pixel-owned tile reductions while preserving double HDR, cache support, and direct fallback ordering.

Validate captured inputs, edge and multichunk fixtures, CPU/HIP renderer regressions, and 45 isolated final replays. Keep the production HIP algorithm unchanged because gains depend on event distribution.
2026-09-11 16:43:53 -04:00
wyj 5eccc31c99 Doc: refresh Galactic-center reference image and benchmark links
Replace the artifact-affected Schwarzschild image with the corrected 4K render. Link both READMEs to the paired CPU/HIP benchmark and clarify that this run had no PSF wing clipping or direct fallbacks.
2026-09-06 22:02:39 -04:00
506 changed files with 384469 additions and 901 deletions

No files matched your search

+1
View File
@@ -1,5 +1,6 @@
/build
/output
/local
/scripts/__pycache__
assets/2mass/processed/all_sky/*.csv
assets/2mass/processed/all_sky/.done/
+70
View File
@@ -0,0 +1,70 @@
---
description: 审查本项目代码变更,核实功能、修复与性能进展;复用已完成的完整测试,仅做受限专项验证,按实际影响报告可操作问题。
mode: subagent
model: openai/gpt-6.1-sol
variant: high
options:
reasoningEffort: high
permission:
edit: deny
task: deny
bash:
"*": allow
"make test*": deny
"make * test*": deny
"git add*": deny
"git commit*": deny
"git push*": deny
"git reset*": deny
"git checkout*": deny
"git restore*": deny
"git clean*": deny
---
# 角色与目标
你是本项目专属的 `code-reviewer`。进行独立、基于证据、与实际风险相称的 code review。你的职责是核实实现与宣称是否一致,发现值得修复的具体缺陷,并提出低复杂度、低开销的修正方向。
默认只审查,不修改源码、测试、文档或配置,不暂存、提交或重置 Git,不启动其他 subagent。Shell 同样受只读审查约束,不得借助脚本、重定向或其他命令绕过编辑权限。仅允许必要的专项编译/测试产生构建产物;临时探针与日志放在 `/tmp/opencode/`,遵守项目的路径与仓库卫生规则。
回复使用用户最新消息的语言;面向父 agent 的结论必须自包含,不能假定父 agent 已看到你的工具输出。
# 审查范围与进展核实
1. 先读项目 `AGENTS.md`,再读 `nr_spacetime_movie_renderer_design.md` 中与变更相关的章节。遵循当前权威设计,不把自己的偏好当作项目要求;文档与代码冲突时说明冲突及依据。
2. 确认要求审查的范围:工作区变更、指定 commit/range 或相对指定 base 的分支变更。父 agent 给出的总结只作为待核实的线索,不作为实现证据。
3. 用 `git status --short`、相关 `git diff`(包括 staged 与 unstaged)及必要的提交历史确认真实状态。新文件未必出现在普通 diff 中,必须检查审查范围内的 untracked 文件;已提交实现也不能因工作区 diff 为空而忽略。不得把无关的既有用户改动归因于本次实现。
4. 阅读变更的完整上下文,沿实际调用链检查入口、配置、数据流、错误处理和输出。新增函数、字段、CLI 选项或测试文件的存在不等于功能已接通;排查未调用实现、stub、TODO、错误的默认路径、遗漏的 build/test 注册以及仅覆盖理想路径的测试。
5. 对父 agent/用户明确描述的关键进展逐项核实,给出“代码支持”“部分支持”“与代码不符”或“证据不足”。区分已实现、已接入、已验证与性能已测量,避免把其中一项等同于全部完成。提供具体文件位置、调用链或日志证据;无法验证时如实说明,不推断其一定失败。
6. bug 修复要检查原触发条件是否真的被阻断、相关分支是否仍有相同问题;性能提升要检查热点路径确实使用优化、工作量和结果语义是否可比,以及是否存在 fallback 或开销转移。未经测量只能确认优化实现,不能确认速度提升;已有有效 benchmark 足以支撑其测量范围内的结论,不强求扩展到所有平台与输入。
7. 若审查期间代码继续变化,在结束前确认相关 diff 状态。结论限定于实际检查的版本;发现关键变化时仅复查受影响部分,不重启整轮审查或完整测试。
# 测试复用与受限验证(硬性约束)
- 父 agent 或用户明确声明已完成的 `make test` 类完整测试,必须复用该信息,绝不得重新完整运行。该约束覆盖带不同 flags 的同一 suite、其他完整测试入口、clean/rebuild 后重跑,以及拆成多个专项命令累计重跑整个 suite 等等价方式。不能为了“更放心”“独立确认”或补齐自己的测试记录而重跑。
- 明确区分“父 agent/用户报告完成”“已查看原始日志”和“本 reviewer 亲自执行”。“完成”不自动等于“通过”;没有明确结果就注明结果未提供。缺少日志不构成不信任声明或重新完整测试的理由,可以读取已有日志或指出有限的证据缺口。
- 即使没有完整测试声明,本 reviewer 也只运行受限规模的专项验证。需要完整 suite 时,将必要性与具体缺口交回父 agent/用户,不自行运行。配置中的命令拦截仅是辅助,不能利用命令包装、别名、脚本或其他工具绕过本节规则。
- 优先静态检查和既有测试/benchmark 结果。仅当某个具体疑点不能由这些证据解决时,才选择直接针对疑点的最小测试、现有测试的单例/过滤子集或小型复现。不要为样式、注释或与生产逻辑无关的低影响变更运行测试。
- 运行前先阅读 Makefile/测试入口,确认目标的依赖、默认数据规模和实际执行范围,防止“单个目标”隐式触发完整 suite、昂贵渲染或完整 benchmark。构建仅限必要目标,不做 `make clean` 或无关的全量重建。
- 每次先明确要验证的假设、命令和规模上限。默认整轮审查最多 3 次专项执行,每次超时不超过 60 秒,累计运行预算不超过 120 秒;使用小 fixture、低分辨率、少量 ray/样本、有限线程。父 agent/用户可以指定更合适的专项预算,但这不解除完整测试禁令。
- 超时、资源不足或无法在预算内复现时停止,报告验证限制,不将其直接判为产品失败。一次验证解决疑点后停止;只有新证据或失败需要解释时才继续使用剩余预算,不无限追加专项测试。
- 性能审查优先读取已有原始输出,核对命令、输入、build/cache、线程、工作量、fallback 和数值结果。确有必要时仅做小规模、同条件的对照,不将微基准结论泛化到完整 4K 视频工作负载。
# 风险校准与建议原则
- 正式 finding 必须有具体触发条件、可达路径和实际影响。先检查调用方保证、现有 guard、输入约束、数值容差、fallback 与测试,再下结论。不能仅凭“理论上可能”声称崩溃、数据损坏、物理失真或严重性能退化。
- 严重性根据实际影响、适用范围与触发可能性评估:P0 为已证实且广泛阻断的紧急问题;P1 为主要功能/物理正确性严重受损;P2 为明确可达、局部但值得修复的问题;P3 为低影响改进。P0/P1 必须有强证据,不因措辞耸动提高级别。
- 对实际上不会造成问题、已经由不变量保证安全或仅属个人风格偏好的点,不报缺陷。低严重性点不得夸大为 blocker;可选建议与正式缺陷分开,默认不堆积 nitpick,也不为了凑数制造问题。可以明确给出“未发现值得报告的缺陷”。
- 尚未证实的疑点作为待确认问题,写明缺少什么证据,不包装成已证实 bug。缺少某项测试本身不自动构成缺陷;说明它是否留下了与本次变更直接相关的、实质性的验证缺口。
- 优先最小局部修正和适用的专项 regression,不要求为低风险假设增加复杂状态机、全局防御性扫描、细粒度锁、重复热路径检查或大规模架构重写。建议成本必须与风险相称。
- 若确实存在严重正确性问题,而解决它必然涉及复杂度或性能代价,应如实说明证据与权衡;不隐藏问题,也不未经论证地指定最昂贵的方案。性能影响要有复杂度分析或测量支持,不使用无依据的倍数/百分比。
- 聚焦本次变更引入或影响的问题。既有问题仅在直接阻碍本次目标时提出,并明确注明它并非本次新增。
# 输出格式
1. **结论与范围**:简述检查的版本/变更范围,是否发现需要修复的问题,以及重要限制。测试通过不是“没有 bug”的证明;审查未发现问题也不等于全系统认证。
2. **Findings**:按严重性排序。每项包含 `[P1/P2/…] 简洁标题`、最小且相关的 `文件:行号`、触发条件、代码证据、实际影响与最小修正方向。合并同一根因,避免重复计数。不确定问题单列,不放入已证实 findings。
3. **进展核实**:对关键宣称列出“宣称 → 核实状态 → 证据/缺口”,特别区分实现、集成、测试和性能测量;用实际状态修正过于乐观的描述,也承认已经充分完成的部分。
4. **验证记录**:列出复用的完整测试声明/日志、自己实际执行的专项命令及规模/结果、未执行验证的具体限制。绝不声称自己运行了只由他人报告的测试。
保持报告精炼、可操作;没有某类内容时直接省略或用一句话说明,不输出冗长模板或泛化风险清单。
+32
View File
@@ -0,0 +1,32 @@
---
description: 搭配 GPT 父 agent 执行技术路线已初步敲定的明确任务。委派前,父 agent 必须提供明确、完整、详细、可执行的计划,包含目标、范围、已确定的技术方案、步骤、约束及验收方法;尚需探索、路线选择或关键决策的任务不得交给本 agent。有疑问时暂停并询问父 agent,否则按计划完整推进。
mode: subagent
model: deepseek/deepseek-flash
---
# 角色与分工
你是 `deepseek-coder`,作为 GPT 父 agent 的执行搭档,负责落实已经初步确定技术路线的明确任务。父 agent 负责探索、技术决策与计划制定,你负责按计划完成实现和验证,不自行承担未明确的路线选择或扩大任务范围。
# 开始前
1. 阅读当前适用的 `AGENTS.md`(包括相关目录的局部指引),以及它们和任务计划引用的设计文档、规范及必要的代码上下文,从这些文件获取实时要求。不要假定项目架构、模块边界或技术约定固定不变。
2. 检查父 agent 提供的计划是否明确、完整、详细且可执行:应包含目标与交付物、修改范围、已确定的技术方案、实施步骤、约束、依赖和验收方法。简单任务无需冗长模板,但不能缺少执行所需的信息。
3. 检查相关工作区状态,识别已有用户或其他 agent 的改动;不得覆盖、撤销或清理非你产生的修改。
# 疑问与阻塞
- 只要出现影响执行的疑问,就暂停并向父 agent 询问,包括需求含糊、计划缺漏、关键参数未定、存在需要取舍的多个方案、计划与实时指引或代码冲突,以及验证失败后需要改变技术路线。
- 说明疑问或阻塞、相关证据、需要父 agent 决定的具体事项,以及已经完成和尚未完成的部分。向父 agent 返回澄清请求,等待其明确答复后再继续;不要以猜测代替确认,也不要直接要求最终用户决策。
- 不擅自重新设计、替换已确定方案、降低验收标准或开展计划外重构。计划内不改变语义和路线的普通实现细节可依照现有代码惯例处理,无需逐项请示。
# 执行与验证
1. 没有疑问或阻塞时,按照计划持续推进全部步骤,完成实现、必要的接入、测试与要求的文档更新;不要只给出建议、留下占位实现,或在部分完成后无故停止。
2. 遵守实时项目指引及现有代码风格,保持修改聚焦,只实施计划授权的内容。不得擅自委派其他 agent、提交或推送代码,除非父 agent 明确授权。
3. 按计划执行验证并记录实际结果。失败时先做计划范围内的定位;若修复需要新决策,按上述规则暂停询问。不能通过跳过失败、修改预期或弱化测试来宣称完成。
4. 如遇工具、权限、环境或资源限制,明确报告限制及其对交付的影响,不把未执行或未通过的验证描述为成功。
# 向父 agent 交付
使用父 agent 要求的语言,默认跟随用户最新消息的语言。报告应自包含,简明列出完成内容、涉及文件、实际运行的验证命令与结果,以及剩余问题或阻塞。明确区分已完成、未完成和未经验证的事项;不能假定父 agent 已看过你的工具输出。
+28 -2
View File
@@ -59,9 +59,18 @@ catalog 内部数据保留 `(direction, temperature, amplitude)`,而非 RGB。
优先从 3+1 identities、已知 gauge RHS 或 temporal interpolant 的解析导数获得时间导数;不要为已有插值量另行做低阶 finite difference,也不要在 geodesic RHS 中计算不会使用的量。
## 黑洞终止
## 黑洞终止与暗终态
对 moving-puncture 数据,生产渲染使用经 AH calibration 得到、保守地位于 apparent horizon 内部的 puncture-centered cutoff 判定捕获。不要假定每次生产演化都会运行昂贵的 AH finder。可在未来加入 common-horizon 终止优化,但不得改变物理分类。
过去向光线不使用 horizon 内位置 cutoff、AH-calibrated puncture 小球或 armed/re-entry
状态机判定正常物理捕获。正常 dark 终态来自相机相对局域能量增长
`L - L0 = ln(alpha p^0) - ln(alpha p^0)|_start` 达到可配置阈值(默认 8,可用
`--dark-threshold` 覆盖),对所有 spacetime backend 统一生效;这是已确定需求,
不重置光子能量或频移。不同 dark reason 不制造 mesh seam。无法可靠推进的
积分必须报告具体数值失败,不得改写成 capture。轨迹仍可信但计算配额耗尽时返回可重试的
`UNRESOLVED/BUDGET_EXHAUSTED`;有限分辨率下的 triangle 决策中 `UUU` 必须追加计算,
`UUD/UDD` 达到几何停止尺度后可近似标黑并保留 triangle provenance 与面积统计。
不假定每次生产演化都会运行昂贵的 AH finder,也不依赖 capture sidecar。跨 chart、
跨 region 或穿越视界本身不是暗终态。
## 开发与验证顺序
@@ -76,6 +85,23 @@ catalog 内部数据保留 `(direction, temperature, amplitude)`,而非 RGB。
性能 benchmark 记录必须保留完整、可复制的命令及原始终端输出,不能只记录汇总耗时或吞吐量;输出中的 build/cache、输入加载、工作线程、处理数量与 fallback 等统计是后续正确归因性能变化的证据。
## 权威设计文档卫生
- 仓库级文档规则应具有跨任务适用性,不夹带单次任务的细节或案例。
- `nr_spacetime_movie_renderer_design.md` 应简明描述当前确定的架构、物理与数值约定、模块边界、数据流及 ownership;尚未确定的问题须明确标为待验证。
- 写最终设计,不写 agent 工作过程、对话经过、实现日记或备选方案淘汰史。已排除的临时设想不要改写成长期禁止条款;必要的物理与架构约束仍须保留。
- 决策依据只保留理解设计所必需的简要理由。实验过程、性能数据及详细对照放到符合仓库卫生要求的独立记录中,设计文档按需引用。
- 使用说明集中到 `usage.md`;README 保留面向使用者的简介与示例,避免在权威设计文档中重复罗列。
- 设计变更应改写并整合原有相关章节,删除过时或重复表述,检查跨章节一致性;不要通过不断追加补充段落堆积历史。
## 仓库卫生与短期产物
只有对本项目有长期记录价值、且值得进入 public repo 的测试与 benchmark 才纳入 git。
- 短期性能对照、一次性 A/B 原始日志、临时测量脚本、ad-hoc probe 与中间数据放到仓库根目录的 `local/`;该目录已被 `.gitignore` 排除,不进入版本库。
- 追踪文件必须可复现:命令把输出、原始日志写到 `/tmp` 或 `local/` 是正常的,这些仓库外/被忽略的数据无需跟踪;但复现所需的输入、脚本、fixture 必须一并纳入 git(放在 `scripts/` 或 `benchmarks/<name>/`),不得依赖未跟踪的脚本或数据。
- `benchmarks/` 只保留自包含、可复现的长期记录;`tests/` 只保留针对生产代码的回归测试,不保留为单次实验服务的一次性探针。
## 修改原则
- 改动应保持 backend、observer、geodesic、movie mesh 与 optics 的职责分离。
+213 -38
View File
@@ -29,22 +29,14 @@ else
IMAGE_EXT := ppm
endif
COMMON_SOURCES := $(filter-out src/main.c src/spacetime_minkowski.c src/spacetime_schwarzschild.c,$(wildcard src/*.c))
COMMON_SOURCES := $(filter-out src/main.c src/dummy_psf.c src/fast_psf_fftw.c src/spacetime_minkowski.c src/spacetime_schwarzschild.c src/spacetime_alcubierre.c,$(wildcard src/*.c))
PROVIDER_SOURCE := src/spacetime_$(SPACETIME).c
BUILD_DIR := build/$(BUILD_TYPE)
TARGET_BASENAME := $(SPACETIME)_sky
OBJECT_DIR := $(BUILD_DIR)/obj/$(SPACETIME)
CORE_MINKOWSKI_SOURCES := $(COMMON_SOURCES) src/spacetime_minkowski.c
TEST_TARGET := $(BUILD_DIR)/test_geodesic
FRAME_TEST_TARGET := $(BUILD_DIR)/test_frame
SCHWARZSCHILD_TEST_TARGET := $(BUILD_DIR)/test_schwarzschild
OBSERVER_TRACK_TEST_TARGET := $(BUILD_DIR)/test_observer_track
CATALOG_PREFETCH_TEST_TARGET := $(BUILD_DIR)/test_catalog_prefetch
HIP_PSF_TEST_TARGET := $(BUILD_DIR)/test_hip_psf
HIP_PSF_BENCH_TARGET := $(BUILD_DIR)/benchmark_hip_psf
CAMERA_TEST_TARGETS := $(BUILD_DIR)/test_observer_minkowski $(BUILD_DIR)/test_observer_schwarzschild
.PHONY: all backend clean run test hip-psf-test hip-psf-bench minkowski schwarzschild FORCE
.PHONY: all backend clean run test tone-map-test sensor-bloom-test sensor-bloom-bench mesh-overlay-test hip-psf-test hip-psf-bench fast-psf-fftw-bench minkowski schwarzschild alcubierre FORCE
ifneq ($(filter 0 1,$(PSF_EVENT_SINK)),$(PSF_EVENT_SINK))
$(error Unknown PSF_EVENT_SINK '$(PSF_EVENT_SINK)'; choose 0 or 1)
@@ -53,19 +45,50 @@ BUILD_CPPFLAGS += -DFRAME_PSF_EVENT_SINK=$(PSF_EVENT_SINK)
ifeq ($(PSF_BACKEND),cpu)
RENDER_LINKER := $(CC)
ifeq ($(shell pkg-config --exists fftw3_omp && echo yes),yes)
CPU_FFTW_CPPFLAGS := -DFAST_PSF_FFTW $(shell pkg-config --cflags fftw3_omp)
CPU_FFTW_LDLIBS := $(shell pkg-config --libs fftw3_omp)
CPU_FFTW_SOURCES := src/fast_psf_fftw.c
BUILD_CPPFLAGS += $(CPU_FFTW_CPPFLAGS)
LDLIBS += $(CPU_FFTW_LDLIBS)
else
$(error PSF_BACKEND=cpu requires the FFTW OpenMP package 'fftw3_omp' (pkg-config --exists fftw3_omp). On Gentoo enable sci-libs/fftw[openmp].)
endif
else ifeq ($(PSF_BACKEND),hip)
RENDER_LINKER := $(HIPCC)
BUILD_CPPFLAGS += -DPSF_BACKEND_HIP
else ifeq ($(PSF_BACKEND),dummy)
RENDER_LINKER := $(CC)
BUILD_CPPFLAGS += -DPSF_BACKEND_DUMMY
else
$(error Unknown PSF_BACKEND '$(PSF_BACKEND)'; choose cpu or hip)
$(error Unknown PSF_BACKEND '$(PSF_BACKEND)'; choose cpu, hip, or dummy)
endif
# `make test` builds and runs the CPU regression suite. The dummy and hip
# backends do not build those binaries, so reject the goal explicitly instead of
# silently reusing a stale test binary left by an earlier CPU build.
ifneq ($(filter test test-reference-images,$(MAKECMDGOALS)),)
ifneq ($(PSF_BACKEND),cpu)
$(error make test requires PSF_BACKEND=cpu)
endif
endif
# psf-capture is a CPU producer diagnostic; the dummy and hip backends do not
# provide the producer/frame symbols it links.
ifneq ($(filter psf-capture,$(MAKECMDGOALS)),)
ifneq ($(PSF_BACKEND),cpu)
$(error psf-capture requires PSF_BACKEND=cpu)
endif
endif
ifeq ($(SPACETIME),minkowski)
BACKEND_CPPFLAGS := -DSPACETIME_MINKOWSKI
else ifeq ($(SPACETIME),schwarzschild)
BACKEND_CPPFLAGS := -DSPACETIME_SCHWARZSCHILD
else ifeq ($(SPACETIME),alcubierre)
BACKEND_CPPFLAGS := -DSPACETIME_ALCUBIERRE
else
$(error Unknown SPACETIME '$(SPACETIME)'; choose minkowski or schwarzschild)
$(error Unknown SPACETIME '$(SPACETIME)'; choose minkowski, schwarzschild, or alcubierre)
endif
ifeq ($(ENABLE_HDR),1)
@@ -78,12 +101,45 @@ else
$(error Unknown ENABLE_HDR '$(ENABLE_HDR)'; choose 0 or 1)
endif
# Test binaries are namespaced by spacetime and build tag so that switching
# PSF_BACKEND/ENABLE_HDR/PSF_EVENT_SINK cannot silently reuse a stale binary
# built for a different backend.
TEST_OUT_DIR := $(OBJECT_DIR)/$(HDR_BUILD_TAG)
TEST_TARGET := $(TEST_OUT_DIR)/test_geodesic
ADAPTIVE_GEODESIC_TEST_TARGET := $(TEST_OUT_DIR)/test_geodesic_adaptive
ASYMPTOTIC_TEST_TARGET := $(TEST_OUT_DIR)/test_asymptotic
ASYMPTOTIC_ENTRY_TEST_TARGET := $(TEST_OUT_DIR)/test_asymptotic_entry
ASYMPTOTIC_QUADRATIC_TEST_TARGET := $(TEST_OUT_DIR)/test_asymptotic_quadratic
ASYMPTOTIC_SCHWARZSCHILD_TEST_TARGET := $(TEST_OUT_DIR)/test_asymptotic_schwarzschild
TERMINATION_ORACLE_TEST_TARGET := $(TEST_OUT_DIR)/test_termination_oracle
FRAME_TEST_TARGET := $(TEST_OUT_DIR)/test_frame
SCHWARZSCHILD_TEST_TARGET := $(TEST_OUT_DIR)/test_schwarzschild
ALCUBIERRE_TEST_TARGET := $(TEST_OUT_DIR)/test_alcubierre
OBSERVER_TRACK_TEST_TARGET := $(TEST_OUT_DIR)/test_observer_track
CATALOG_PREFETCH_TEST_TARGET := $(TEST_OUT_DIR)/test_catalog_prefetch
HIP_PSF_TEST_TARGET := $(TEST_OUT_DIR)/test_hip_psf
HIP_PSF_BENCH_TARGET := $(TEST_OUT_DIR)/benchmark_hip_psf
CAMERA_TEST_TARGETS := $(TEST_OUT_DIR)/test_observer_minkowski $(TEST_OUT_DIR)/test_observer_schwarzschild
FAST_PSF_FFTW_TEST_TARGET := $(TEST_OUT_DIR)/test_fast_psf_fftw
FAST_PSF_FFTW_BENCH_TARGET := $(TEST_OUT_DIR)/benchmark_fast_psf_fftw
TONE_MAP_TEST_TARGET := $(TEST_OUT_DIR)/test_tone_map
MOVIE_OUTPUT_TEST_TARGET := $(TEST_OUT_DIR)/test_movie_output
SENSOR_BLOOM_TEST_TARGET := $(TEST_OUT_DIR)/test_sensor_bloom
SENSOR_BLOOM_BENCH_TARGET := $(TEST_OUT_DIR)/benchmark_sensor_bloom
MESH_OVERLAY_TEST_TARGET := $(TEST_OUT_DIR)/test_mesh_overlay
ifeq ($(PSF_BACKEND),hip)
TARGET := $(BUILD_DIR)/$(TARGET_BASENAME)_hip
else ifeq ($(PSF_BACKEND),dummy)
TARGET := $(BUILD_DIR)/$(TARGET_BASENAME)_dummy
else
TARGET := $(BUILD_DIR)/$(TARGET_BASENAME)
endif
RENDER_SOURCES := $(COMMON_SOURCES) $(PROVIDER_SOURCE) src/main.c
RENDER_SOURCES += $(CPU_FFTW_SOURCES)
ifeq ($(PSF_BACKEND),dummy)
RENDER_SOURCES += src/dummy_psf.c
endif
RENDER_OBJECTS := $(patsubst %.c,$(OBJECT_DIR)/$(HDR_BUILD_TAG)/%.o,$(RENDER_SOURCES))
ifeq ($(PSF_BACKEND),hip)
HIP_PSF_OBJECT := $(OBJECT_DIR)/$(HDR_BUILD_TAG)/src/hip_psf.o
@@ -97,7 +153,7 @@ RENDER_DEPS := $(RENDER_OBJECTS:.o=.d)
ifneq ($(filter command\ line environment environment\ override,$(origin SPACETIME)),)
all: backend
else
all: minkowski schwarzschild
all: minkowski schwarzschild alcubierre
endif
minkowski:
@@ -106,6 +162,9 @@ minkowski:
schwarzschild:
$(MAKE) SPACETIME=schwarzschild ENABLE_HDR=$(ENABLE_HDR) backend
alcubierre:
$(MAKE) SPACETIME=alcubierre ENABLE_HDR=$(ENABLE_HDR) backend
# Build exactly the selected backend/configuration, e.g.
# make SPACETIME=schwarzschild ENABLE_HDR=1 backend
backend: $(TARGET)
@@ -132,10 +191,10 @@ ifeq ($(PSF_BACKEND),hip)
hip-psf-test: $(HIP_PSF_TEST_TARGET)
hip-psf-bench: $(HIP_PSF_BENCH_TARGET)
$(HIP_PSF_BENCH_TARGET): tests/benchmark_hip_psf.hip $(HIP_PSF_OBJECT) $(OBJECT_DIR)/$(HDR_BUILD_TAG)/src/optics.o | $(BUILD_DIR)
$(HIP_PSF_BENCH_TARGET): tests/benchmark_hip_psf.hip $(HIP_PSF_OBJECT) $(OBJECT_DIR)/$(HDR_BUILD_TAG)/src/optics.o | $(TEST_OUT_DIR)
$(HIPCC) $(HIP_CXXFLAGS) $(OPENMP_FLAGS) -Isrc -x hip $< -x none $(filter-out $<,$^) $(LDLIBS) $(HDR_LDLIBS) -o $@
$(HIP_PSF_TEST_TARGET): tests/test_hip_psf.hip $(HIP_PSF_OBJECT) $(OBJECT_DIR)/$(HDR_BUILD_TAG)/src/optics.o | $(BUILD_DIR)
$(HIP_PSF_TEST_TARGET): tests/test_hip_psf.hip $(HIP_PSF_OBJECT) $(OBJECT_DIR)/$(HDR_BUILD_TAG)/src/optics.o | $(TEST_OUT_DIR)
$(HIPCC) $(HIP_CXXFLAGS) $(OPENMP_FLAGS) -Isrc -x hip $< -x none $(filter-out $<,$^) $(LDLIBS) $(HDR_LDLIBS) -o $@
else
hip-psf-test hip-psf-bench:
@@ -146,39 +205,155 @@ run: $(TARGET)
mkdir -p output/imgs
./$(TARGET) --catalog assets/sky_grid_5deg.csv --output output/imgs/$(SPACETIME)_sky.$(IMAGE_EXT)
$(TEST_TARGET): tests/test_geodesic.c $(CORE_MINKOWSKI_SOURCES) | $(BUILD_DIR)
$(TEST_OUT_DIR): | $(BUILD_DIR)
mkdir -p $@
$(TEST_TARGET): tests/test_geodesic.c $(CORE_MINKOWSKI_SOURCES) $(CPU_FFTW_SOURCES) | $(TEST_OUT_DIR)
$(CC) $(CPPFLAGS) $(BUILD_CPPFLAGS) $(CFLAGS) $(BUILD_CFLAGS) $(OPENMP_FLAGS) -Isrc $^ $(LDLIBS) -o $@
$(FRAME_TEST_TARGET): tests/test_frame.c $(CORE_MINKOWSKI_SOURCES) | $(BUILD_DIR)
# Explicit adaptive DP5(4) core and RayPool regression. The test textually
# includes both analytic providers (renaming spacetime_create_default), so the
# link line deliberately omits src/spacetime_{minkowski,schwarzschild}.c.
$(ADAPTIVE_GEODESIC_TEST_TARGET): tests/test_geodesic_adaptive.c $(COMMON_SOURCES) $(CPU_FFTW_SOURCES) | $(TEST_OUT_DIR)
$(CC) $(CPPFLAGS) $(BUILD_CPPFLAGS) $(CFLAGS) $(BUILD_CFLAGS) $(OPENMP_FLAGS) -DGEODESIC_EVENT_TESTING -Isrc $^ $(LDLIBS) -o $@
$(ASYMPTOTIC_TEST_TARGET): tests/test_asymptotic.c $(CORE_MINKOWSKI_SOURCES) $(CPU_FFTW_SOURCES) | $(TEST_OUT_DIR)
$(CC) $(CPPFLAGS) $(BUILD_CPPFLAGS) $(CFLAGS) $(BUILD_CFLAGS) $(OPENMP_FLAGS) -Isrc $^ $(LDLIBS) -o $@
$(SCHWARZSCHILD_TEST_TARGET): tests/test_schwarzschild.c $(COMMON_SOURCES) src/spacetime_schwarzschild.c | $(BUILD_DIR)
$(CC) $(CPPFLAGS) $(BUILD_CPPFLAGS) $(CFLAGS) $(BUILD_CFLAGS) $(OPENMP_FLAGS) -Isrc $^ $(LDLIBS) -o $@
# The test includes asymptotic.c to cover its private floating-point kernel.
$(ASYMPTOTIC_QUADRATIC_TEST_TARGET): tests/test_asymptotic_quadratic.c $(CORE_MINKOWSKI_SOURCES) $(CPU_FFTW_SOURCES) | $(TEST_OUT_DIR)
$(CC) $(CPPFLAGS) $(BUILD_CPPFLAGS) $(CFLAGS) $(BUILD_CFLAGS) $(OPENMP_FLAGS) -Isrc $(filter-out src/asymptotic.c,$^) $(LDLIBS) -o $@
$(OBSERVER_TRACK_TEST_TARGET): tests/test_observer_track.c $(COMMON_SOURCES) | $(BUILD_DIR)
$(CC) $(CPPFLAGS) $(BUILD_CPPFLAGS) $(CFLAGS) $(BUILD_CFLAGS) $(OPENMP_FLAGS) -Isrc $^ $(LDLIBS) -o $@
$(CATALOG_PREFETCH_TEST_TARGET): tests/test_catalog_prefetch.c $(CORE_MINKOWSKI_SOURCES) | $(BUILD_DIR)
$(CC) $(CPPFLAGS) $(BUILD_CPPFLAGS) $(CFLAGS) $(BUILD_CFLAGS) $(OPENMP_FLAGS) -Isrc $^ $(LDLIBS) -o $@
$(BUILD_DIR)/test_observer_minkowski: tests/test_observer.c $(CORE_MINKOWSKI_SOURCES) | $(BUILD_DIR)
$(CC) $(CPPFLAGS) $(BUILD_CPPFLAGS) $(CFLAGS) $(BUILD_CFLAGS) $(OPENMP_FLAGS) -Isrc $^ $(LDLIBS) -o $@
$(BUILD_DIR)/test_observer_schwarzschild: tests/test_observer.c $(COMMON_SOURCES) src/spacetime_schwarzschild.c | $(BUILD_DIR)
$(ASYMPTOTIC_SCHWARZSCHILD_TEST_TARGET): tests/test_asymptotic_schwarzschild.c $(COMMON_SOURCES) src/spacetime_schwarzschild.c $(CPU_FFTW_SOURCES) | $(TEST_OUT_DIR)
$(CC) $(CPPFLAGS) $(BUILD_CPPFLAGS) $(CFLAGS) $(BUILD_CFLAGS) $(OPENMP_FLAGS) -DSPACETIME_SCHWARZSCHILD -Isrc $^ $(LDLIBS) -o $@
test: $(CAMERA_TEST_TARGETS) $(TEST_TARGET) $(FRAME_TEST_TARGET) $(SCHWARZSCHILD_TEST_TARGET) $(OBSERVER_TRACK_TEST_TARGET) $(CATALOG_PREFETCH_TEST_TARGET)
./$(BUILD_DIR)/test_observer_minkowski
./$(BUILD_DIR)/test_observer_schwarzschild
./$(TEST_TARGET)
./$(FRAME_TEST_TARGET)
./$(SCHWARZSCHILD_TEST_TARGET)
./$(OBSERVER_TRACK_TEST_TARGET)
./$(CATALOG_PREFETCH_TEST_TARGET)
python3 tests/test_camera_cli.py $(BUILD_DIR)
# Independent core regression for the backend-free numerical entry localizer.
# It links only the new module and the shared spacetime dispatch wrapper: no
# analytic backend, no geodesic integrator and no asymptotic.c are required,
# so it stays exercisable independently of the route integration.
$(ASYMPTOTIC_ENTRY_TEST_TARGET): tests/test_asymptotic_entry.c src/asymptotic_entry.c src/spacetime_common.c src/asymptotic_entry.h src/asymptotic.h src/geodesic.h src/spacetime.h src/observer.h | $(TEST_OUT_DIR)
$(CC) $(CPPFLAGS) $(BUILD_CPPFLAGS) $(CFLAGS) $(BUILD_CFLAGS) $(OPENMP_FLAGS) -Isrc tests/test_asymptotic_entry.c src/asymptotic_entry.c src/spacetime_common.c $(LDLIBS) -o $@
$(FRAME_TEST_TARGET): tests/test_frame.c $(CORE_MINKOWSKI_SOURCES) $(CPU_FFTW_SOURCES) | $(TEST_OUT_DIR)
$(CC) $(CPPFLAGS) $(BUILD_CPPFLAGS) $(CFLAGS) $(BUILD_CFLAGS) $(OPENMP_FLAGS) -Isrc $^ $(LDLIBS) -o $@
$(SCHWARZSCHILD_TEST_TARGET): tests/test_schwarzschild.c $(COMMON_SOURCES) src/spacetime_schwarzschild.c $(CPU_FFTW_SOURCES) | $(TEST_OUT_DIR)
$(CC) $(CPPFLAGS) $(BUILD_CPPFLAGS) $(CFLAGS) $(BUILD_CFLAGS) $(OPENMP_FLAGS) -Isrc $^ $(LDLIBS) -o $@
# Independent physics oracle for the termination policy (plan P0); links the
# analytic Schwarzschild backend and its exterior module.
$(TERMINATION_ORACLE_TEST_TARGET): tests/test_termination_oracle.c $(COMMON_SOURCES) src/spacetime_schwarzschild.c $(CPU_FFTW_SOURCES) | $(TEST_OUT_DIR)
$(CC) $(CPPFLAGS) $(BUILD_CPPFLAGS) $(CFLAGS) $(BUILD_CFLAGS) $(OPENMP_FLAGS) -DSPACETIME_SCHWARZSCHILD -Isrc $^ $(LDLIBS) -o $@
$(ALCUBIERRE_TEST_TARGET): tests/test_alcubierre.c $(COMMON_SOURCES) src/spacetime_alcubierre.c $(CPU_FFTW_SOURCES) | $(TEST_OUT_DIR)
$(CC) $(CPPFLAGS) $(BUILD_CPPFLAGS) $(CFLAGS) $(BUILD_CFLAGS) $(OPENMP_FLAGS) -Isrc $^ $(LDLIBS) -o $@
$(OBSERVER_TRACK_TEST_TARGET): tests/test_observer_track.c $(COMMON_SOURCES) $(CPU_FFTW_SOURCES) | $(TEST_OUT_DIR)
$(CC) $(CPPFLAGS) $(BUILD_CPPFLAGS) $(CFLAGS) $(BUILD_CFLAGS) $(OPENMP_FLAGS) -Isrc $^ $(LDLIBS) -o $@
$(CATALOG_PREFETCH_TEST_TARGET): tests/test_catalog_prefetch.c $(CORE_MINKOWSKI_SOURCES) $(CPU_FFTW_SOURCES) | $(TEST_OUT_DIR)
$(CC) $(CPPFLAGS) $(BUILD_CPPFLAGS) $(CFLAGS) $(BUILD_CFLAGS) $(OPENMP_FLAGS) -Isrc $^ $(LDLIBS) -o $@
$(TEST_OUT_DIR)/test_observer_minkowski: tests/test_observer.c $(CORE_MINKOWSKI_SOURCES) $(CPU_FFTW_SOURCES) | $(TEST_OUT_DIR)
$(CC) $(CPPFLAGS) $(BUILD_CPPFLAGS) $(CFLAGS) $(BUILD_CFLAGS) $(OPENMP_FLAGS) -Isrc $^ $(LDLIBS) -o $@
$(TEST_OUT_DIR)/test_observer_schwarzschild: tests/test_observer.c $(COMMON_SOURCES) src/spacetime_schwarzschild.c $(CPU_FFTW_SOURCES) | $(TEST_OUT_DIR)
$(CC) $(CPPFLAGS) $(BUILD_CPPFLAGS) $(CFLAGS) $(BUILD_CFLAGS) $(OPENMP_FLAGS) -DSPACETIME_SCHWARZSCHILD -Isrc $^ $(LDLIBS) -o $@
$(FAST_PSF_FFTW_TEST_TARGET): tests/test_fast_psf_fftw.c $(CORE_MINKOWSKI_SOURCES) $(CPU_FFTW_SOURCES) | $(TEST_OUT_DIR)
$(CC) $(CPPFLAGS) $(BUILD_CPPFLAGS) $(CFLAGS) $(BUILD_CFLAGS) $(OPENMP_FLAGS) -Isrc $^ $(LDLIBS) -o $@
# The tone-map regression links production optics.c only, so it neither needs a
# catalog nor touches ray tracing, the mesh, or any image writer at runtime.
$(TONE_MAP_TEST_TARGET): tests/test_tone_map.c src/optics.c src/optics.h $(CPU_FFTW_SOURCES) | $(TEST_OUT_DIR)
$(CC) $(CPPFLAGS) $(BUILD_CPPFLAGS) $(CFLAGS) $(BUILD_CFLAGS) $(OPENMP_FLAGS) -Isrc tests/test_tone_map.c src/optics.c $(CPU_FFTW_SOURCES) $(LDLIBS) -o $@
# The movie-output queue links production optics, mesh overlay and FFTW only, so it
# needs neither a catalog nor ray tracing.
$(MOVIE_OUTPUT_TEST_TARGET): tests/test_movie_output.c src/movie_output.c src/movie_output.h src/mesh_overlay.c src/mesh_overlay.h src/optics.c src/optics.h $(CPU_FFTW_SOURCES) | $(TEST_OUT_DIR)
$(CC) $(CPPFLAGS) $(BUILD_CPPFLAGS) $(CFLAGS) $(BUILD_CFLAGS) $(OPENMP_FLAGS) -Isrc tests/test_movie_output.c src/movie_output.c src/mesh_overlay.c src/optics.c $(CPU_FFTW_SOURCES) $(LDLIBS) -o $@
$(FAST_PSF_FFTW_BENCH_TARGET): tests/benchmark_fast_psf_fftw.c $(CORE_MINKOWSKI_SOURCES) $(CPU_FFTW_SOURCES) | $(TEST_OUT_DIR)
$(CC) $(CPPFLAGS) $(BUILD_CPPFLAGS) $(CFLAGS) $(BUILD_CFLAGS) $(OPENMP_FLAGS) -Isrc $^ $(LDLIBS) -o $@
# The sensor-bloom checks link only the standalone model, so they need neither
# a catalog nor ray tracing, and build in every ENABLE_HDR/PSF_BACKEND
# configuration.
$(SENSOR_BLOOM_TEST_TARGET): tests/test_sensor_bloom.c src/sensor_bloom.c src/sensor_bloom.h | $(TEST_OUT_DIR)
$(CC) $(CPPFLAGS) $(BUILD_CPPFLAGS) $(CFLAGS) $(BUILD_CFLAGS) $(OPENMP_FLAGS) -Isrc tests/test_sensor_bloom.c src/sensor_bloom.c $(LDLIBS) -o $@
$(SENSOR_BLOOM_BENCH_TARGET): tests/benchmark_sensor_bloom.c src/sensor_bloom.c src/sensor_bloom.h | $(TEST_OUT_DIR)
$(CC) $(CPPFLAGS) $(BUILD_CPPFLAGS) $(CFLAGS) $(BUILD_CFLAGS) $(OPENMP_FLAGS) -Isrc tests/benchmark_sensor_bloom.c src/sensor_bloom.c $(LDLIBS) -o $@
# The mesh-overlay regression links only the standalone overlay module: it
# needs neither a catalog, ray tracing, FFTW, nor an output writer.
$(MESH_OVERLAY_TEST_TARGET): tests/test_mesh_overlay.c src/mesh_overlay.c src/mesh_overlay.h | $(TEST_OUT_DIR)
$(CC) $(CPPFLAGS) $(BUILD_CPPFLAGS) $(CFLAGS) $(BUILD_CFLAGS) $(OPENMP_FLAGS) -Isrc tests/test_mesh_overlay.c src/mesh_overlay.c $(LDLIBS) -o $@
# The FFTW-vs-spatial test is meaningful only in the CPU PSF build.
ifneq ($(CPU_FFTW_SOURCES),)
FAST_PSF_FFTW_TEST_DEP := $(FAST_PSF_FFTW_TEST_TARGET)
FAST_PSF_FFTW_TEST_RUN := $(FAST_PSF_FFTW_TEST_TARGET)
else
FAST_PSF_FFTW_TEST_DEP :=
FAST_PSF_FFTW_TEST_RUN :=
endif
test: $(CAMERA_TEST_TARGETS) $(TEST_TARGET) $(ADAPTIVE_GEODESIC_TEST_TARGET) $(ASYMPTOTIC_TEST_TARGET) $(ASYMPTOTIC_ENTRY_TEST_TARGET) $(ASYMPTOTIC_QUADRATIC_TEST_TARGET) $(ASYMPTOTIC_SCHWARZSCHILD_TEST_TARGET) $(TERMINATION_ORACLE_TEST_TARGET) $(FRAME_TEST_TARGET) $(SCHWARZSCHILD_TEST_TARGET) $(ALCUBIERRE_TEST_TARGET) $(OBSERVER_TRACK_TEST_TARGET) $(CATALOG_PREFETCH_TEST_TARGET) $(FAST_PSF_FFTW_TEST_DEP) $(TONE_MAP_TEST_TARGET) $(MOVIE_OUTPUT_TEST_TARGET) $(SENSOR_BLOOM_TEST_TARGET) $(MESH_OVERLAY_TEST_TARGET)
$(TEST_OUT_DIR)/test_observer_minkowski
$(TEST_OUT_DIR)/test_observer_schwarzschild
$(TEST_TARGET)
$(ADAPTIVE_GEODESIC_TEST_TARGET)
$(ASYMPTOTIC_TEST_TARGET)
$(ASYMPTOTIC_ENTRY_TEST_TARGET)
$(ASYMPTOTIC_QUADRATIC_TEST_TARGET)
$(ASYMPTOTIC_SCHWARZSCHILD_TEST_TARGET)
$(TERMINATION_ORACLE_TEST_TARGET)
$(FRAME_TEST_TARGET)
$(SCHWARZSCHILD_TEST_TARGET)
$(ALCUBIERRE_TEST_TARGET)
$(OBSERVER_TRACK_TEST_TARGET)
$(CATALOG_PREFETCH_TEST_TARGET)
$(FAST_PSF_FFTW_TEST_RUN)
$(TONE_MAP_TEST_TARGET)
$(MOVIE_OUTPUT_TEST_TARGET)
$(SENSOR_BLOOM_TEST_TARGET)
$(MESH_OVERLAY_TEST_TARGET)
python3 tests/test_camera_cli.py $(BUILD_DIR) $(TEST_OUT_DIR)
python3 tests/test_adaptive_cli.py $(BUILD_DIR) $(TEST_OUT_DIR)
python3 tests/test_ray_diagnostics.py $(BUILD_DIR) $(TEST_OUT_DIR)
python3 tests/test_output_streams.py $(BUILD_DIR) $(TEST_OUT_DIR)
python3 tests/test_mesh_overlay_cli.py $(BUILD_DIR)
tone-map-test: $(TONE_MAP_TEST_TARGET)
$(TONE_MAP_TEST_TARGET)
sensor-bloom-test: $(SENSOR_BLOOM_TEST_TARGET)
$(SENSOR_BLOOM_TEST_TARGET)
mesh-overlay-test: $(MESH_OVERLAY_TEST_TARGET)
$(MESH_OVERLAY_TEST_TARGET)
sensor-bloom-bench: $(SENSOR_BLOOM_BENCH_TARGET)
fast-psf-fftw-bench: $(FAST_PSF_FFTW_BENCH_TARGET)
clean:
rm -rf build
-include $(RENDER_DEPS)
include mk/reference_images.mk
# Test-only producer consumer: never linked into a renderer.
.PHONY: psf-capture
psf-capture: $(TEST_OUT_DIR)/capture_psf
$(TEST_OUT_DIR)/capture_psf: tests/capture_psf.c $(CORE_MINKOWSKI_SOURCES) $(CPU_FFTW_SOURCES) | $(TEST_OUT_DIR)
$(CC) $(CPPFLAGS) $(BUILD_CPPFLAGS) $(CFLAGS) $(BUILD_CFLAGS) $(OPENMP_FLAGS) -Isrc $< $(filter-out src/frame.c,$(CORE_MINKOWSKI_SOURCES)) $(CPU_FFTW_SOURCES) $(LDLIBS) -o $@
.PHONY: hip-psf-replay
hip-psf-replay: $(TEST_OUT_DIR)/replay_psf
$(TEST_OUT_DIR)/replay_psf: tests/replay_psf.hip src/hip_psf.hip src/hip_psf.h src/optics.h $(OBJECT_DIR)/$(HDR_BUILD_TAG)/src/optics.o | $(TEST_OUT_DIR)
$(HIPCC) $(HIP_CXXFLAGS) $(OPENMP_FLAGS) -Isrc -x hip $< -x none $(filter %.o,$^) $(LDLIBS) $(HDR_LDLIBS) -o $@
$(TEST_OUT_DIR)/make_psf_fixture: tests/make_psf_fixture.c src/optics.c src/optics.h $(CPU_FFTW_SOURCES) | $(TEST_OUT_DIR)
$(CC) $(CPPFLAGS) $(BUILD_CPPFLAGS) $(CFLAGS) $(BUILD_CFLAGS) $(OPENMP_FLAGS) -Isrc $< src/optics.c $(CPU_FFTW_SOURCES) $(LDLIBS) -o $@
+53 -21
View File
@@ -10,7 +10,8 @@ four-dimensional spacetime.
[![Schwarzschild black-hole lensing of the 2MASS Galactic-center star field](assets/images/schwarzschild_galactic_center.png)](assets/images/schwarzschild_galactic_center.png)
*The 2MASS Galactic-center star field seen through Schwarzschild spacetime,
from a camera at radius 100 M. Click the image for the full 4K render;
from a camera at radius 100 M. This reference image uses the legacy Reinhard
tone map (`--tone-map reinhard`). Click the image for the full 4K render;
[rendering command below](#example-galactic-center-field-through-schwarzschild-spacetime).*
Stars are individual catalog point sources with direction, temperature, and
@@ -27,8 +28,9 @@ the horizon. See [single-frame camera parameters and complete commands](usage.md
## Current status
The current implementation supports analytic **Minkowski** and
**Schwarzschild** spacetimes, single images and observer-track image sequences,
The current implementation supports analytic **Minkowski**,
**Schwarzschild**, and moving **Alcubierre** warp-bubble spacetimes,
single images and observer-track image sequences,
adaptive lens meshes, and reusable lens-map files. It is written primarily in
C with OpenMP CPU parallelism; an optional HIP backend accelerates PSF
accumulation.
@@ -37,7 +39,7 @@ HIP retains parallel CPU catalog mapping and uses bounded, completion-protected
event uploads. See [HIP configuration and bounded performance checks](build.md#optional-hip-psf-acceleration).
The [Nmesh](https://github.com/nmeshsource/nmesh) numerical-spacetime backend and BBH rendering are still planned.
The current scope is black-hole capture and distant stellar backgrounds;
The current scope is black-hole shadows and distant stellar backgrounds;
local matter emission, accretion disks, and plasma are outside this stage.
See the [design document](nr_spacetime_movie_renderer_design.md) for the
architecture and development roadmap.
@@ -51,8 +53,8 @@ libpng development files. From the repository root:
make -j
```
This builds both `build/Release/minkowski_sky` and
`build/Release/schwarzschild_sky`. For individual backends, Debug builds,
This builds `build/Release/minkowski_sky`, `build/Release/schwarzschild_sky`,
and `build/Release/alcubierre_sky`. For individual backends, Debug builds,
optional HDR/FITS output, HIP support, and regression checks, see
[build.md](build.md).
@@ -92,12 +94,14 @@ mkdir -p output/imgs
--all-sky-catalog assets/2mass/processed/all_sky \
--look-ra-deg 296 --look-dec-deg 27 --fov-deg 72 \
--width 3840 --height 2160 --exposure 1e12 \
--tone-map reinhard \
--output output/imgs/summer_triangle.png
```
[![Summer Triangle in flat spacetime, exposure 1e12](assets/images/summer_triangle.png)](assets/images/summer_triangle.png)
*4K reference image with exposure `1e12`. Click to view at full resolution.*
*4K reference image with exposure `1e12`; it uses the legacy Reinhard tone
map (`--tone-map reinhard`). Click to view at full resolution.*
Angles are in degrees; `--fov-deg` is the horizontal field of view. Exposure
is an adjustable display multiplier. Use `--verbose` for progress during long
@@ -119,20 +123,33 @@ mkdir -p output/imgs
--psf-fwhm-pixels 2.7 --psf-moffat-beta 4.5 \
--psf-relative-tail 1e-8 --psf-min-y 0 --max-cache-psf-flux 1e8 \
--catalog-load-workers 4 \
--tone-map reinhard \
--output output/imgs/schwarzschild_galactic_center.png
```
This uses the reference image's rendering settings, including its
`--max-cache-psf-flux 1e8` preview approximation, which clips bright PSF wings
to the cache radius. The [original benchmark record](benchmarks/2mass_galactic_center_blackhole.md)
preserves the command and terminal output; the command above omits the optional
HDR export.
This uses the updated reference image's rendering settings. The
`--max-cache-psf-flux 1e8` setting permits bright PSF wings to be clipped to the
cache radius, but this run reported no wing clipping or direct fallbacks.
The [CPU/HIP benchmark record](benchmarks/2mass_galactic_center_cpu_hip_2026-09-07.md)
preserves the commands and terminal output, and records bit-identical CPU/HIP
PNGs. The command above omits the optional HDR and lens-map exports.
This example infers a position facing the hole from its look direction and radius. Adaptive refinement should
be configured for the desired image accuracy; it is disabled by default.
Tone-mapped PNG/PPM output uses a per-channel soft-clip display transform by
default (`--tone-map softclip --tone-map-p 2`); `--tone-map reinhard` restores
the historical curve used by the reference images above. The linear HDR FITS
output never applies it. An optional limited-response sensor bloom
(`--sensor-bloom-limit E --sensor-bloom-transfer e`, default disabled) can be
applied to the linear HDR before display; it never changes the FITS output. See
[tone mapping and display](usage.md#tone-mapping-and-display).
Camera controls, movie sequences, lens-map reuse, PSF settings, and HDR output
are described in [usage.md](usage.md). Both binaries provide a complete option
list with `--help`.
are described in [usage.md](usage.md). For fast single-frame previews,
`--fast-mode` replaces per-event PSF splats with a supersampled delta deposit
plus one global PSF convolution and downsample. Its nearest-deposit path is not
qualified for temporally coherent movie output; see [usage.md](usage.md) for
the spatial and temporal accuracy limits. Both binaries provide a complete
option list with `--help`.
### Example: Looking outward just above the Schwarzschild horizon
@@ -153,13 +170,15 @@ mkdir -p output/imgs
--width 3840 --height 2160 --fov-deg 90 \
--coarse-cell-pixels 16 --refine-max-level 3 \
--exposure 0.01 \
--tone-map reinhard \
--output output/imgs/schwarzschild_near_horizon_outward_R2.1_0.01_refine3.png
```
[![Synthetic stellar sky seen outward by a static observer at r=2.1M](assets/images/schwarzschild_near_horizon_outward_R2.1_0.01_refine3.png)](assets/images/schwarzschild_near_horizon_outward_R2.1_0.01_refine3.png)
*4K render with a 90° horizontal field of view, exposure `0.01`, and maximum
refinement level 3. Click to view at full resolution.*
refinement level 3; it uses the legacy Reinhard tone map (`--tone-map
reinhard`). Click to view at full resolution.*
The distant sky occupies a bounded angular region around the outward
direction, with repeated images crowded near its edge. Strong gravitational
@@ -168,8 +187,15 @@ blueshift pushes both the 3000 K and 12000 K test stars toward blue-white.
### Example: Synthetic test grid with mesh overlay
This example uses `assets/sky_grid_5deg.csv` to inspect lensing and adaptive
mesh refinement in Schwarzschild spacetime. `--draw-mesh` overlays the final
image-plane triangles.
mesh refinement in Schwarzschild spacetime. The main output is the clean
tone-mapped image; `--draw-mesh` additionally writes the final image-plane
triangles, so one command produces both
`output/imgs/schwarzschild_test_grid.png` (no mesh) and
`output/imgs/schwarzschild_test_grid_mesh.png` (mesh overlay).
The antialiased mesh is drawn after tone mapping: gray escape half-edges,
purple dark half-edges, yellow budget-unresolved half-edges, and red failure
half-edges, using Catppuccin Mocha defaults. Color and opacity settings are
documented in `usage.md`.
```sh
mkdir -p output/imgs
@@ -182,12 +208,15 @@ mkdir -p output/imgs
--coarse-cell-pixels 32 \
--observer-radius 100 --exposure 0.2 \
--psf-fwhm-pixels 2.7 --psf-moffat-beta 4.5 --draw-mesh \
--tone-map reinhard \
--output output/imgs/schwarzschild_test_grid.png
```
[![Synthetic stellar grid lensed by a Schwarzschild black hole, with adaptive mesh overlay](assets/images/schwarzschild_test_grid.png)](assets/images/schwarzschild_test_grid.png)
[![Synthetic stellar grid lensed by a Schwarzschild black hole, with adaptive mesh overlay](assets/images/schwarzschild_test_grid_mesh.png)](assets/images/schwarzschild_test_grid_mesh.png)
*4K test-grid reference image. Click to view at full resolution.*
*4K test-grid reference image showing the `_mesh.png` overlay; it uses the
legacy Reinhard tone map (`--tone-map reinhard`). Click to view at full
resolution.*
### Freely falling Schwarzschild movie camera
@@ -229,8 +258,11 @@ derivatives. Defaults: `--rtol 1e-10 --atol 1e-12 --stop-radius 0.001`.
Integration crosses the horizon and stops at this numerical guard before the
singularity, reporting its proper time and retaining only regular cadence samples.
The guard is not the exact singularity; reduce it and tolerances to check convergence.
The renderer's independent ray capture cutoff remains `r=1.5M`: rows inside it are
valid trajectory data but the current renderer captures those rays immediately.
The renderer no longer uses a position capture cutoff: cameras at and inside the
old `r=1.5M` guard are valid targets, and a normal dark pixel comes from the
redshift-threshold truncation `log(alpha p^0) >= 8`. Budget-exhausted and
data/integration failures are separate unresolved/incomplete outcomes and are not
silently rendered as dark.
The script reports maximum tetrad drift and rejects errors above `1e-6` rather
than silently repairing the transported frame. Run the orbit, transport and CSV
render regressions after building with `python3 tests/test_schwarzschild_camera_track.py`.
+13 -8
View File
@@ -6,7 +6,7 @@
[![Schwarzschild 黑洞对 2MASS 银心方向星场的引力透镜效果](assets/images/schwarzschild_galactic_center.png)](assets/images/schwarzschild_galactic_center.png)
*从半径 100 M 处的相机观察 Schwarzschild 时空中的 2MASS 银心方向星场。点击图片查看完整 4K 图像;[渲染命令见下文](#示例schwarzschild-时空中的银心方向星场)。*
*从半径 100 M 处的相机观察 Schwarzschild 时空中的 2MASS 银心方向星场。该参考图像使用 legacy Reinhard tone map(`--tone-map reinhard`)。点击图片查看完整 4K 图像;[渲染命令见下文](#示例schwarzschild-时空中的银心方向星场)。*
恒星以独立的星表点源表示,保留方向、温度和振幅。渲染器将它们映射到相机图像中,处理多像、引力透镜放大和频移,再将保留亚像素位置的点扩散函数(PSF)累积到 HDR 图像。电影中的运动相机由世界线与四标架(tetrad)轨迹描述。
@@ -55,12 +55,13 @@ mkdir -p output/imgs
--all-sky-catalog assets/2mass/processed/all_sky \
--look-ra-deg 296 --look-dec-deg 27 --fov-deg 72 \
--width 3840 --height 2160 --exposure 1e12 \
--tone-map reinhard \
--output output/imgs/summer_triangle.png
```
[![平直时空中的夏季大三角,曝光为 1e12](assets/images/summer_triangle.png)](assets/images/summer_triangle.png)
*曝光为 `1e12` 的 4K 参考图像。点击查看完整分辨率。*
*曝光为 `1e12` 的 4K 参考图像;使用 legacy Reinhard tone map(`--tone-map reinhard`)。点击查看完整分辨率。*
角度单位为度,`--fov-deg` 表示水平视场角。曝光是可调节的显示倍率。长时间渲染时可使用 `--verbose` 查看进度。
@@ -79,12 +80,13 @@ mkdir -p output/imgs
--psf-fwhm-pixels 2.7 --psf-moffat-beta 4.5 \
--psf-relative-tail 1e-8 --psf-min-y 0 --max-cache-psf-flux 1e8 \
--catalog-load-workers 4 \
--tone-map reinhard \
--output output/imgs/schwarzschild_galactic_center.png
```
这里使用参考图像的渲染设置,包括 `--max-cache-psf-flux 1e8` 这一预览近似:它将明亮 PSF 的翼部截断在缓存半径内。[原始 benchmark 记录](benchmarks/2mass_galactic_center_blackhole.md)保留了命令与终端输出;上述命令省略了可选的 HDR 导出。
这里使用更新后的参考图像的渲染设置。`--max-cache-psf-flux 1e8` 允许将明亮 PSF 的翼部截断在缓存半径内,但本次运行没有发生翼部裁剪或 direct fallback。[CPU/HIP benchmark 记录](benchmarks/2mass_galactic_center_cpu_hip_2026-09-07.md)保留了命令、终端输出,以及 CPU/HIP PNG 比特级一致的结果;上述命令省略了可选的 HDR 和 lens-map 导出。
上述 Schwarzschild 示例省略位置,因此按指向与半径推导出朝向黑洞的相机。自适应细分默认关闭,应根据所需图像精度配置。相机控制、图像序列、透镜映射复用、PSF 设置及 HDR 输出参见 [usage.md](usage.md)(英文)。两个可执行文件都可通过 `--help` 查看完整选项。
上述 Schwarzschild 示例省略位置,因此按指向与半径推导出朝向黑洞的相机。自适应细分默认关闭,应根据所需图像精度配置。tone-mapped PNG/PPM 默认使用逐通道 soft-clip 显示变换(`--tone-map softclip --tone-map-p 2`);`--tone-map reinhard` 恢复上方参考图像使用的历史曲线,线性 HDR FITS 输出不受其影响。可选的有限响应 sensor bloom(`--sensor-bloom-limit E --sensor-bloom-transfer e`,默认关闭)在显示前作用于线性 HDR,且不会改变 FITS 输出。相机控制、图像序列、透镜映射复用、PSF 设置及 HDR 输出参见 [usage.md](usage.md)(英文)。两个可执行文件都可通过 `--help` 查看完整选项。
### 示例:紧贴史瓦西视界向外看
@@ -103,19 +105,21 @@ mkdir -p output/imgs
--width 3840 --height 2160 --fov-deg 90 \
--coarse-cell-pixels 16 --refine-max-level 3 \
--exposure 0.01 \
--tone-map reinhard \
--output output/imgs/schwarzschild_near_horizon_outward_R2.1_0.01_refine3.png
```
[![r=2.1M 处的静态观者向外观察合成恒星天空](assets/images/schwarzschild_near_horizon_outward_R2.1_0.01_refine3.png)](assets/images/schwarzschild_near_horizon_outward_R2.1_0.01_refine3.png)
*水平视场角 90°、曝光 `0.01`、最大细分级别 3 的 4K 图像。点击查看完整分辨率。*
*水平视场角 90°、曝光 `0.01`、最大细分级别 3 的 4K 图像;使用 legacy Reinhard tone map(`--tone-map reinhard`)。点击查看完整分辨率。*
远方天空集中在朝外方向的有限角域中,多级成像在边缘附近密集堆叠。
强烈的引力蓝移使 3000 K 和 12000 K 的测试恒星都被推向蓝白色。
### 示例:叠加网格的合成测试星表
这个示例使用 `assets/sky_grid_5deg.csv` 检查 Schwarzschild 时空中的引力透镜效果与自适应网格细分。`--draw-mesh` 会叠加显示最终的像平面三角网格。
这个示例使用 `assets/sky_grid_5deg.csv` 检查 Schwarzschild 时空中的引力透镜效果与自适应网格细分。主输出是不带网格的成品图;`--draw-mesh` 会额外写出最终的像平面三角网格,因此同一次命令会同时生成 `output/imgs/schwarzschild_test_grid.png`(无网格)和 `output/imgs/schwarzschild_test_grid_mesh.png`(网格叠加)。
网格在 tone mapping 后以抗锯齿半边叠加。默认采用 Catppuccin Mocha:逃逸为灰色、暗终态为紫色、预算耗尽未决为黄色、真实失败为红色,未追踪为蓝色。颜色与透明度配置详见 `usage.md`。
```sh
mkdir -p output/imgs
@@ -128,12 +132,13 @@ mkdir -p output/imgs
--coarse-cell-pixels 32 \
--observer-radius 100 --exposure 0.2 \
--psf-fwhm-pixels 2.7 --psf-moffat-beta 4.5 --draw-mesh \
--tone-map reinhard \
--output output/imgs/schwarzschild_test_grid.png
```
[![Schwarzschild 黑洞对合成恒星网格的透镜效果,叠加自适应网格](assets/images/schwarzschild_test_grid.png)](assets/images/schwarzschild_test_grid.png)
[![Schwarzschild 黑洞对合成恒星网格的透镜效果,叠加自适应网格](assets/images/schwarzschild_test_grid_mesh.png)](assets/images/schwarzschild_test_grid_mesh.png)
*4K 测试网格参考图像。点击查看完整分辨率。*
*4K 测试网格参考图像,展示 `_mesh.png` 网格叠加结果;使用 legacy Reinhard tone map(`--tone-map reinhard`)。点击查看完整分辨率。*
### Schwarzschild 自由落体相机轨迹
+471
View File
@@ -0,0 +1,471 @@
360,0.000129900000,0.0000039170000,0.000606100000
361,0.000145847000,0.0000043935810,0.000680879200
362,0.000163802100,0.0000049296040,0.000765145600
363,0.000184003700,0.0000055321360,0.000860012400
364,0.000206690200,0.0000062082450,0.000966592800
365,0.000232100000,0.0000069650000,0.001086000000
366,0.000260728000,0.0000078132190,0.001220586000
367,0.000293075000,0.0000087673360,0.001372729000
368,0.000329388000,0.0000098398440,0.001543579000
369,0.000369914000,0.0000110432300,0.001734286000
370,0.000414900000,0.0000123900000,0.001946000000
371,0.000464158700,0.0000138864100,0.002177777000
372,0.000518986000,0.0000155572800,0.002435809000
373,0.000581854000,0.0000174429600,0.002731953000
374,0.000655234700,0.0000195837500,0.003078064000
375,0.000741600000,0.0000220200000,0.003486000000
376,0.000845029600,0.0000248396500,0.003975227000
377,0.000964526800,0.0000280412600,0.004540880000
378,0.001094949000,0.0000315310400,0.005158320000
379,0.001231154000,0.0000352152100,0.005802907000
380,0.001368000000,0.0000390000000,0.006450001000
381,0.001502050000,0.0000428264000,0.007083216000
382,0.001642328000,0.0000469146000,0.007745488000
383,0.001802382000,0.0000515896000,0.008501152000
384,0.001995757000,0.0000571764000,0.009414544000
385,0.002236000000,0.0000640000000,0.010549990000
386,0.002535385000,0.0000723442100,0.011965800000
387,0.002892603000,0.0000822122400,0.013655870000
388,0.003300829000,0.0000935081600,0.015588050000
389,0.003753236000,0.0001061361000,0.017730150000
390,0.004243000000,0.0001200000000,0.020050010000
391,0.004762389000,0.0001349840000,0.022511360000
392,0.005330048000,0.0001514920000,0.025202880000
393,0.005978712000,0.0001702080000,0.028279720000
394,0.006741117000,0.0001918160000,0.031897040000
395,0.007650000000,0.0002170000000,0.036210000000
396,0.008751373000,0.0002469067000,0.041437710000
397,0.010028880000,0.0002812400000,0.047503720000
398,0.011421700000,0.0003185200000,0.054119880000
399,0.012869010000,0.0003572667000,0.060998030000
400,0.014310000000,0.0003960000000,0.067850010000
401,0.015704430000,0.0004337147000,0.074486320000
402,0.017147440000,0.0004730240000,0.081361560000
403,0.018781220000,0.0005178760000,0.089153640000
404,0.020748010000,0.0005722187000,0.098540480000
405,0.023190000000,0.0006400000000,0.110200000000
406,0.026207360000,0.0007245600000,0.124613300000
407,0.029782480000,0.0008255000000,0.141701700000
408,0.033880920000,0.0009411600000,0.161303500000
409,0.038468240000,0.0010698800000,0.183256800000
410,0.043510000000,0.0012100000000,0.207400000000
411,0.048995600000,0.0013620910000,0.233692100000
412,0.055022600000,0.0015307520000,0.262611400000
413,0.061718800000,0.0017203680000,0.294774600000
414,0.069212000000,0.0019353230000,0.330798500000
415,0.077630000000,0.0021800000000,0.371300000000
416,0.086958110000,0.0024548000000,0.416209100000
417,0.097176720000,0.0027640000000,0.465464200000
418,0.108406300000,0.0031178000000,0.519694800000
419,0.120767200000,0.0035264000000,0.579530300000
420,0.134380000000,0.0040000000000,0.645600000000
421,0.149358200000,0.0045462400000,0.718483800000
422,0.165395700000,0.0051593200000,0.796713300000
423,0.181983100000,0.0058292800000,0.877845900000
424,0.198611000000,0.0065461600000,0.959439000000
425,0.214770000000,0.0073000000000,1.039050100000
426,0.230186800000,0.0080865070000,1.115367300000
427,0.244879700000,0.0089087200000,1.188497100000
428,0.258777300000,0.0097676800000,1.258123300000
429,0.271807900000,0.0106644300000,1.323929600000
430,0.283900000000,0.0116000000000,1.385600000000
431,0.294943800000,0.0125731700000,1.442635200000
432,0.304896500000,0.0135827200000,1.494803500000
433,0.313787300000,0.0146296800000,1.542190300000
434,0.321645400000,0.0157150900000,1.584880700000
435,0.328500000000,0.0168400000000,1.622960000000
436,0.334351300000,0.0180073600000,1.656404800000
437,0.339210100000,0.0192144800000,1.685295900000
438,0.343121300000,0.0204539200000,1.709874500000
439,0.346129600000,0.0217182400000,1.730382100000
440,0.348280000000,0.0230000000000,1.747060000000
441,0.349599900000,0.0242946100000,1.760044600000
442,0.350147400000,0.0256102400000,1.769623300000
443,0.350013000000,0.0269585700000,1.776263700000
444,0.349287000000,0.0283512500000,1.780433400000
445,0.348060000000,0.0298000000000,1.782600000000
446,0.346373300000,0.0313108300000,1.782968200000
447,0.344262400000,0.0328836800000,1.781699800000
448,0.341808800000,0.0345211200000,1.779198200000
449,0.339094100000,0.0362257100000,1.775867100000
450,0.336200000000,0.0380000000000,1.772110000000
451,0.333197700000,0.0398466700000,1.768258900000
452,0.330041100000,0.0417680000000,1.764039000000
453,0.326635700000,0.0437660000000,1.758943800000
454,0.322886800000,0.0458426700000,1.752466300000
455,0.318700000000,0.0480000000000,1.744100000000
456,0.314025100000,0.0502436800000,1.733559500000
457,0.308884000000,0.0525730400000,1.720858100000
458,0.303290400000,0.0549805600000,1.705936900000
459,0.297257900000,0.0574587200000,1.688737200000
460,0.290800000000,0.0600000000000,1.669200000000
461,0.283970100000,0.0626019700000,1.647528700000
462,0.276721400000,0.0652775200000,1.623412700000
463,0.268917800000,0.0680420800000,1.596022300000
464,0.260422700000,0.0709110900000,1.564528000000
465,0.251100000000,0.0739000000000,1.528100000000
466,0.240847500000,0.0770160000000,1.486111400000
467,0.229851200000,0.0802664000000,1.439521500000
468,0.218407200000,0.0836668000000,1.389879900000
469,0.206811500000,0.0872328000000,1.338736200000
470,0.195360000000,0.0909800000000,1.287640000000
471,0.184213600000,0.0949175500000,1.237422300000
472,0.173327300000,0.0990458400000,1.187824300000
473,0.162688100000,0.1033674000000,1.138761100000
474,0.152283300000,0.1078846000000,1.090148000000
475,0.142100000000,0.1126000000000,1.041900000000
476,0.132178600000,0.1175320000000,0.994197600000
477,0.122569600000,0.1226744000000,0.947347300000
478,0.113275200000,0.1279928000000,0.901453100000
479,0.104297900000,0.1334528000000,0.856619300000
480,0.095640000000,0.1390200000000,0.812950100000
481,0.087299550000,0.1446764000000,0.770517300000
482,0.079308040000,0.1504693000000,0.729444800000
483,0.071717760000,0.1564619000000,0.689913600000
484,0.064580990000,0.1627177000000,0.652104900000
485,0.057950010000,0.1693000000000,0.616200000000
486,0.051862110000,0.1762431000000,0.582328600000
487,0.046281520000,0.1835581000000,0.550416200000
488,0.041150880000,0.1912735000000,0.520337600000
489,0.036412830000,0.1994180000000,0.491967300000
490,0.032010000000,0.2080200000000,0.465180000000
491,0.027917200000,0.2171199000000,0.439924600000
492,0.024144400000,0.2267345000000,0.416183600000
493,0.020687000000,0.2368571000000,0.393882200000
494,0.017540400000,0.2474812000000,0.372945900000
495,0.014700000000,0.2586000000000,0.353300000000
496,0.012161790000,0.2701849000000,0.334857800000
497,0.009919960000,0.2822939000000,0.317552100000
498,0.007967240000,0.2950505000000,0.301337500000
499,0.006296346000,0.3085780000000,0.286168600000
500,0.004900000000,0.3230000000000,0.272000000000
501,0.003777173000,0.3384021000000,0.258817100000
502,0.002945320000,0.3546858000000,0.246483800000
503,0.002424880000,0.3716986000000,0.234771800000
504,0.002236293000,0.3892875000000,0.223453300000
505,0.002400000000,0.4073000000000,0.212300000000
506,0.002925520000,0.4256299000000,0.201169200000
507,0.003836560000,0.4443096000000,0.190119600000
508,0.005174840000,0.4633944000000,0.179225400000
509,0.006982080000,0.4829395000000,0.168560800000
510,0.009300000000,0.5030000000000,0.158200000000
511,0.012149490000,0.5235693000000,0.148138300000
512,0.015535880000,0.5445120000000,0.138375800000
513,0.019477520000,0.5656900000000,0.128994200000
514,0.023992770000,0.5869653000000,0.120075100000
515,0.029100000000,0.6082000000000,0.111700000000
516,0.034814850000,0.6293456000000,0.103904800000
517,0.041120160000,0.6503068000000,0.096667480000
518,0.047985040000,0.6708752000000,0.089982720000
519,0.055378610000,0.6908424000000,0.083845310000
520,0.063270000000,0.7100000000000,0.078249990000
521,0.071635010000,0.7281852000000,0.073208990000
522,0.080462240000,0.7454636000000,0.068678160000
523,0.089739960000,0.7619694000000,0.064567840000
524,0.099456450000,0.7778368000000,0.060788350000
525,0.109600000000,0.7932000000000,0.057250010000
526,0.120167400000,0.8081104000000,0.053904350000
527,0.131114500000,0.8224962000000,0.050746640000
528,0.142367900000,0.8363068000000,0.047752760000
529,0.153854200000,0.8494916000000,0.044898590000
530,0.165500000000,0.8620000000000,0.042160000000
531,0.177257100000,0.8738108000000,0.039507280000
532,0.189140000000,0.8849624000000,0.036935640000
533,0.201169400000,0.8954936000000,0.034458360000
534,0.213365800000,0.9054432000000,0.032088720000
535,0.225749900000,0.9148501000000,0.029840000000
536,0.238320900000,0.9237348000000,0.027711810000
537,0.251066800000,0.9320924000000,0.025694440000
538,0.263992200000,0.9399226000000,0.023787160000
539,0.277101700000,0.9472252000000,0.021989250000
540,0.290400000000,0.9540000000000,0.020300000000
541,0.303891200000,0.9602561000000,0.018718050000
542,0.317572600000,0.9660074000000,0.017240360000
543,0.331438400000,0.9712606000000,0.015863640000
544,0.345482800000,0.9760225000000,0.014584610000
545,0.359700000000,0.9803000000000,0.013400000000
546,0.374083900000,0.9840924000000,0.012307230000
547,0.388639600000,0.9874182000000,0.011301880000
548,0.403378400000,0.9903128000000,0.010377920000
549,0.418311500000,0.9928116000000,0.009529306000
550,0.433449900000,0.9949501000000,0.008749999000
551,0.448795300000,0.9967108000000,0.008035200000
552,0.464336000000,0.9980983000000,0.007381600000
553,0.480064000000,0.9991120000000,0.006785400000
554,0.495971300000,0.9997482000000,0.006242800000
555,0.512050100000,1.0000000000000,0.005749999000
556,0.528295900000,0.9998567000000,0.005303600000
557,0.544691600000,0.9993046000000,0.004899800000
558,0.561209400000,0.9983255000000,0.004534200000
559,0.577821500000,0.9968987000000,0.004202400000
560,0.594500000000,0.9950000000000,0.003900000000
561,0.611220900000,0.9926005000000,0.003623200000
562,0.627975800000,0.9897426000000,0.003370600000
563,0.644760200000,0.9864444000000,0.003141400000
564,0.661569700000,0.9827241000000,0.002934800000
565,0.678400000000,0.9786000000000,0.002749999000
566,0.695239200000,0.9740837000000,0.002585200000
567,0.712058600000,0.9691712000000,0.002438600000
568,0.728828400000,0.9638568000000,0.002309400000
569,0.745518800000,0.9581349000000,0.002196800000
570,0.762100000000,0.9520000000000,0.002100000000
571,0.778543200000,0.9454504000000,0.002017733000
572,0.794825600000,0.9384992000000,0.001948200000
573,0.810926400000,0.9311628000000,0.001889800000
574,0.826824800000,0.9234576000000,0.001840933000
575,0.842500000000,0.9154000000000,0.001800000000
576,0.857932500000,0.9070064000000,0.001766267000
577,0.873081600000,0.8982772000000,0.001737800000
578,0.887894400000,0.8892048000000,0.001711200000
579,0.902318100000,0.8797816000000,0.001683067000
580,0.916300000000,0.8700000000000,0.001650001000
581,0.929799500000,0.8598613000000,0.001610133000
582,0.942798400000,0.8493920000000,0.001564400000
583,0.955277600000,0.8386220000000,0.001513600000
584,0.967217900000,0.8275813000000,0.001458533000
585,0.978600000000,0.8163000000000,0.001400000000
586,0.989385600000,0.8047947000000,0.001336667000
587,0.999548800000,0.7930820000000,0.001270000000
588,1.009089200000,0.7811920000000,0.001205000000
589,1.018006400000,0.7691547000000,0.001146667000
590,1.026300000000,0.7570000000000,0.001100000000
591,1.033982700000,0.7447541000000,0.001068800000
592,1.040986000000,0.7324224000000,0.001049400000
593,1.047188000000,0.7200036000000,0.001035600000
594,1.052466700000,0.7074965000000,0.001021200000
595,1.056700000000,0.6949000000000,0.001000000000
596,1.059794400000,0.6822192000000,0.000968640000
597,1.061799200000,0.6694716000000,0.000929920000
598,1.062806800000,0.6566744000000,0.000886880000
599,1.062909600000,0.6438448000000,0.000842560000
600,1.062200000000,0.6310000000000,0.000800000000
601,1.060735200000,0.6181555000000,0.000760960000
602,1.058443600000,0.6053144000000,0.000723680000
603,1.055224400000,0.5924756000000,0.000685920000
604,1.050976800000,0.5796379000000,0.000645440000
605,1.045600000000,0.5668000000000,0.000600000000
606,1.039036900000,0.5539611000000,0.000547866700
607,1.031360800000,0.5411372000000,0.000491600000
608,1.022666200000,0.5283528000000,0.000435400000
609,1.013047700000,0.5156323000000,0.000383466700
610,1.002600000000,0.5030000000000,0.000340000000
611,0.991367500000,0.4904688000000,0.000307253300
612,0.979331400000,0.4780304000000,0.000283160000
613,0.966491600000,0.4656776000000,0.000265440000
614,0.952847900000,0.4534032000000,0.000251813300
615,0.938400000000,0.4412000000000,0.000240000000
616,0.923194000000,0.4290800000000,0.000229546700
617,0.907244000000,0.4170360000000,0.000220640000
618,0.890502000000,0.4050320000000,0.000211960000
619,0.872920000000,0.3930320000000,0.000202186700
620,0.854449900000,0.3810000000000,0.000190000000
621,0.835084000000,0.3689184000000,0.000174213300
622,0.814946000000,0.3568272000000,0.000155640000
623,0.794186000000,0.3447768000000,0.000135960000
624,0.772954000000,0.3328176000000,0.000116853300
625,0.751400000000,0.3210000000000,0.000100000000
626,0.729583600000,0.3093381000000,0.000086133330
627,0.707588800000,0.2978504000000,0.000074600000
628,0.685602200000,0.2865936000000,0.000065000000
629,0.663810400000,0.2756245000000,0.000056933330
630,0.642400000000,0.2650000000000,0.000049999990
631,0.621514900000,0.2547632000000,0.000044160000
632,0.601113800000,0.2448896000000,0.000039480000
633,0.581105200000,0.2353344000000,0.000035720000
634,0.561397700000,0.2260528000000,0.000032640000
635,0.541900000000,0.2170000000000,0.000030000000
636,0.522599500000,0.2081616000000,0.000027653330
637,0.503546400000,0.1995488000000,0.000025560000
638,0.484743600000,0.1911552000000,0.000023640000
639,0.466193900000,0.1829744000000,0.000021813330
640,0.447900000000,0.1750000000000,0.000020000000
641,0.429861300000,0.1672235000000,0.000018133330
642,0.412098000000,0.1596464000000,0.000016200000
643,0.394644000000,0.1522776000000,0.000014200000
644,0.377533300000,0.1451259000000,0.000012133330
645,0.360800000000,0.1382000000000,0.000010000000
646,0.344456300000,0.1315003000000,0.000007733333
647,0.328516800000,0.1250248000000,0.000005400000
648,0.313019200000,0.1187792000000,0.000003200000
649,0.298001100000,0.1127691000000,0.000001333333
650,0.283500000000,0.1070000000000,0.000000000000
651,0.269544800000,0.1014762000000,0.000000000000
652,0.256118400000,0.0961886400000,0.000000000000
653,0.243189600000,0.0911229600000,0.000000000000
654,0.230727200000,0.0862648500000,0.000000000000
655,0.218700000000,0.0816000000000,0.000000000000
656,0.207097100000,0.0771206400000,0.000000000000
657,0.195923200000,0.0728255200000,0.000000000000
658,0.185170800000,0.0687100800000,0.000000000000
659,0.174832300000,0.0647697600000,0.000000000000
660,0.164900000000,0.0610000000000,0.000000000000
661,0.155366700000,0.0573962100000,0.000000000000
662,0.146230000000,0.0539550400000,0.000000000000
663,0.137490000000,0.0506737600000,0.000000000000
664,0.129146700000,0.0475496500000,0.000000000000
665,0.121200000000,0.0445800000000,0.000000000000
666,0.113639700000,0.0417587200000,0.000000000000
667,0.106465000000,0.0390849600000,0.000000000000
668,0.099690440000,0.0365638400000,0.000000000000
669,0.093330610000,0.0342004800000,0.000000000000
670,0.087400000000,0.0320000000000,0.000000000000
671,0.081900960000,0.0299626100000,0.000000000000
672,0.076804280000,0.0280766400000,0.000000000000
673,0.072077120000,0.0263293600000,0.000000000000
674,0.067686640000,0.0247080500000,0.000000000000
675,0.063600000000,0.0232000000000,0.000000000000
676,0.059806850000,0.0218007700000,0.000000000000
677,0.056282160000,0.0205011200000,0.000000000000
678,0.052971040000,0.0192810800000,0.000000000000
679,0.049818610000,0.0181206900000,0.000000000000
680,0.046770000000,0.0170000000000,0.000000000000
681,0.043784050000,0.0159037900000,0.000000000000
682,0.040875360000,0.0148371800000,0.000000000000
683,0.038072640000,0.0138106800000,0.000000000000
684,0.035404610000,0.0128347800000,0.000000000000
685,0.032900000000,0.0119200000000,0.000000000000
686,0.030564190000,0.0110683100000,0.000000000000
687,0.028380560000,0.0102733900000,0.000000000000
688,0.026344840000,0.0095333110000,0.000000000000
689,0.024452750000,0.0088461570000,0.000000000000
690,0.022700000000,0.0082100000000,0.000000000000
691,0.021084290000,0.0076237810000,0.000000000000
692,0.019599880000,0.0070854240000,0.000000000000
693,0.018237320000,0.0065914760000,0.000000000000
694,0.016987170000,0.0061384850000,0.000000000000
695,0.015840000000,0.0057230000000,0.000000000000
696,0.014790640000,0.0053430590000,0.000000000000
697,0.013831320000,0.0049957960000,0.000000000000
698,0.012948680000,0.0046764040000,0.000000000000
699,0.012129200000,0.0043800750000,0.000000000000
700,0.011359160000,0.0041020000000,0.000000000000
701,0.010629350000,0.0038384530000,0.000000000000
702,0.009938846000,0.0035890990000,0.000000000000
703,0.009288422000,0.0033542190000,0.000000000000
704,0.008678854000,0.0031340930000,0.000000000000
705,0.008110916000,0.0029290000000,0.000000000000
706,0.007582388000,0.0027381390000,0.000000000000
707,0.007088746000,0.0025598760000,0.000000000000
708,0.006627313000,0.0023932440000,0.000000000000
709,0.006195408000,0.0022372750000,0.000000000000
710,0.005790346000,0.0020910000000,0.000000000000
711,0.005409826000,0.0019535870000,0.000000000000
712,0.005052583000,0.0018245800000,0.000000000000
713,0.004717512000,0.0017035800000,0.000000000000
714,0.004403507000,0.0015901870000,0.000000000000
715,0.004109457000,0.0014840000000,0.000000000000
716,0.003833913000,0.0013844960000,0.000000000000
717,0.003575748000,0.0012912680000,0.000000000000
718,0.003334342000,0.0012040920000,0.000000000000
719,0.003109075000,0.0011227440000,0.000000000000
720,0.002899327000,0.0010470000000,0.000000000000
721,0.002704348000,0.0009765896000,0.000000000000
722,0.002523020000,0.0009111088000,0.000000000000
723,0.002354168000,0.0008501332000,0.000000000000
724,0.002196616000,0.0007932384000,0.000000000000
725,0.002049190000,0.0007400000000,0.000000000000
726,0.001910960000,0.0006900827000,0.000000000000
727,0.001781438000,0.0006433100000,0.000000000000
728,0.001660110000,0.0005994960000,0.000000000000
729,0.001546459000,0.0005584547000,0.000000000000
730,0.001439971000,0.0005200000000,0.000000000000
731,0.001340042000,0.0004839136000,0.000000000000
732,0.001246275000,0.0004500528000,0.000000000000
733,0.001158471000,0.0004183452000,0.000000000000
734,0.001076430000,0.0003887184000,0.000000000000
735,0.000999949300,0.0003611000000,0.000000000000
736,0.000928735800,0.0003353835000,0.000000000000
737,0.000862433200,0.0003114404000,0.000000000000
738,0.000800750300,0.0002891656000,0.000000000000
739,0.000743396000,0.0002684539000,0.000000000000
740,0.000690078600,0.0002492000000,0.000000000000
741,0.000640515600,0.0002313019000,0.000000000000
742,0.000594502100,0.0002146856000,0.000000000000
743,0.000551864600,0.0001992884000,0.000000000000
744,0.000512429000,0.0001850475000,0.000000000000
745,0.000476021300,0.0001719000000,0.000000000000
746,0.000442453600,0.0001597781000,0.000000000000
747,0.000411511700,0.0001486044000,0.000000000000
748,0.000382981400,0.0001383016000,0.000000000000
749,0.000356649100,0.0001287925000,0.000000000000
750,0.000332301100,0.0001200000000,0.000000000000
751,0.000309758600,0.0001118595000,0.000000000000
752,0.000288887100,0.0001043224000,0.000000000000
753,0.000269539400,0.0000973356000,0.000000000000
754,0.000251568200,0.0000908458700,0.000000000000
755,0.000234826100,0.0000848000000,0.000000000000
756,0.000219171000,0.0000791466700,0.000000000000
757,0.000204525800,0.0000738580000,0.000000000000
758,0.000190840500,0.0000689160000,0.000000000000
759,0.000178065400,0.0000643026700,0.000000000000
760,0.000166150500,0.0000600000000,0.000000000000
761,0.000155023600,0.0000559818700,0.000000000000
762,0.000144621900,0.0000522256000,0.000000000000
763,0.000134909800,0.0000487184000,0.000000000000
764,0.000125852000,0.0000454474700,0.000000000000
765,0.000117413000,0.0000424000000,0.000000000000
766,0.000109551500,0.0000395610400,0.000000000000
767,0.000102224500,0.0000369151200,0.000000000000
768,0.000095394450,0.0000344486800,0.000000000000
769,0.000089023900,0.0000321481600,0.000000000000
770,0.000083075270,0.0000300000000,0.000000000000
771,0.000077512690,0.0000279912500,0.000000000000
772,0.000072313040,0.0000261135600,0.000000000000
773,0.000067457780,0.0000243602400,0.000000000000
774,0.000062928440,0.0000227246100,0.000000000000
775,0.000058706520,0.0000212000000,0.000000000000
776,0.000054770280,0.0000197785500,0.000000000000
777,0.000051099180,0.0000184528500,0.000000000000
778,0.000047676540,0.0000172168700,0.000000000000
779,0.000044485670,0.0000160645900,0.000000000000
780,0.000041509940,0.0000149900000,0.000000000000
781,0.000038733240,0.0000139872800,0.000000000000
782,0.000036142030,0.0000130515500,0.000000000000
783,0.000033723520,0.0000121781800,0.000000000000
784,0.000031464870,0.0000113625400,0.000000000000
785,0.000029353260,0.0000106000000,0.000000000000
786,0.000027375730,0.0000098858770,0.000000000000
787,0.000025524330,0.0000092173040,0.000000000000
788,0.000023793760,0.0000085923620,0.000000000000
789,0.000022178700,0.0000080091330,0.000000000000
790,0.000020673830,0.0000074657000,0.000000000000
791,0.000019272260,0.0000069595670,0.000000000000
792,0.000017966400,0.0000064879950,0.000000000000
793,0.000016749910,0.0000060486990,0.000000000000
794,0.000015616480,0.0000056393960,0.000000000000
795,0.000014559770,0.0000052578000,0.000000000000
796,0.000013573870,0.0000049017710,0.000000000000
797,0.000012654360,0.0000045697200,0.000000000000
798,0.000011797230,0.0000042601940,0.000000000000
799,0.000010998440,0.0000039717390,0.000000000000
800,0.000010253980,0.0000037029000,0.000000000000
801,0.000009559646,0.0000034521630,0.000000000000
802,0.000008912044,0.0000032183020,0.000000000000
803,0.000008308358,0.0000030003000,0.000000000000
804,0.000007745769,0.0000027971390,0.000000000000
805,0.000007221456,0.0000026078000,0.000000000000
806,0.000006732475,0.0000024312200,0.000000000000
807,0.000006276423,0.0000022665310,0.000000000000
808,0.000005851304,0.0000021130130,0.000000000000
809,0.000005455118,0.0000019699430,0.000000000000
810,0.000005085868,0.0000018366000,0.000000000000
811,0.000004741466,0.0000017122300,0.000000000000
812,0.000004420236,0.0000015962280,0.000000000000
813,0.000004120783,0.0000014880900,0.000000000000
814,0.000003841716,0.0000013873140,0.000000000000
815,0.000003581652,0.0000012934000,0.000000000000
816,0.000003339127,0.0000012058200,0.000000000000
817,0.000003112949,0.0000011241430,0.000000000000
818,0.000002902121,0.0000010480090,0.000000000000
819,0.000002705645,0.0000009770578,0.000000000000
820,0.000002522525,0.0000009109300,0.000000000000
821,0.000002351726,0.0000008492513,0.000000000000
822,0.000002192415,0.0000007917212,0.000000000000
823,0.000002043902,0.0000007380904,0.000000000000
824,0.000001905497,0.0000006881098,0.000000000000
825,0.000001776509,0.0000006415300,0.000000000000
826,0.000001656215,0.0000005980895,0.000000000000
827,0.000001544022,0.0000005575746,0.000000000000
828,0.000001439440,0.0000005198080,0.000000000000
829,0.000001341977,0.0000004846123,0.000000000000
830,0.000001251141,0.0000004518100,0.000000000000
1 360 0.000129900000 0.0000039170000 0.000606100000
2 361 0.000145847000 0.0000043935810 0.000680879200
3 362 0.000163802100 0.0000049296040 0.000765145600
4 363 0.000184003700 0.0000055321360 0.000860012400
5 364 0.000206690200 0.0000062082450 0.000966592800
6 365 0.000232100000 0.0000069650000 0.001086000000
7 366 0.000260728000 0.0000078132190 0.001220586000
8 367 0.000293075000 0.0000087673360 0.001372729000
9 368 0.000329388000 0.0000098398440 0.001543579000
10 369 0.000369914000 0.0000110432300 0.001734286000
11 370 0.000414900000 0.0000123900000 0.001946000000
12 371 0.000464158700 0.0000138864100 0.002177777000
13 372 0.000518986000 0.0000155572800 0.002435809000
14 373 0.000581854000 0.0000174429600 0.002731953000
15 374 0.000655234700 0.0000195837500 0.003078064000
16 375 0.000741600000 0.0000220200000 0.003486000000
17 376 0.000845029600 0.0000248396500 0.003975227000
18 377 0.000964526800 0.0000280412600 0.004540880000
19 378 0.001094949000 0.0000315310400 0.005158320000
20 379 0.001231154000 0.0000352152100 0.005802907000
21 380 0.001368000000 0.0000390000000 0.006450001000
22 381 0.001502050000 0.0000428264000 0.007083216000
23 382 0.001642328000 0.0000469146000 0.007745488000
24 383 0.001802382000 0.0000515896000 0.008501152000
25 384 0.001995757000 0.0000571764000 0.009414544000
26 385 0.002236000000 0.0000640000000 0.010549990000
27 386 0.002535385000 0.0000723442100 0.011965800000
28 387 0.002892603000 0.0000822122400 0.013655870000
29 388 0.003300829000 0.0000935081600 0.015588050000
30 389 0.003753236000 0.0001061361000 0.017730150000
31 390 0.004243000000 0.0001200000000 0.020050010000
32 391 0.004762389000 0.0001349840000 0.022511360000
33 392 0.005330048000 0.0001514920000 0.025202880000
34 393 0.005978712000 0.0001702080000 0.028279720000
35 394 0.006741117000 0.0001918160000 0.031897040000
36 395 0.007650000000 0.0002170000000 0.036210000000
37 396 0.008751373000 0.0002469067000 0.041437710000
38 397 0.010028880000 0.0002812400000 0.047503720000
39 398 0.011421700000 0.0003185200000 0.054119880000
40 399 0.012869010000 0.0003572667000 0.060998030000
41 400 0.014310000000 0.0003960000000 0.067850010000
42 401 0.015704430000 0.0004337147000 0.074486320000
43 402 0.017147440000 0.0004730240000 0.081361560000
44 403 0.018781220000 0.0005178760000 0.089153640000
45 404 0.020748010000 0.0005722187000 0.098540480000
46 405 0.023190000000 0.0006400000000 0.110200000000
47 406 0.026207360000 0.0007245600000 0.124613300000
48 407 0.029782480000 0.0008255000000 0.141701700000
49 408 0.033880920000 0.0009411600000 0.161303500000
50 409 0.038468240000 0.0010698800000 0.183256800000
51 410 0.043510000000 0.0012100000000 0.207400000000
52 411 0.048995600000 0.0013620910000 0.233692100000
53 412 0.055022600000 0.0015307520000 0.262611400000
54 413 0.061718800000 0.0017203680000 0.294774600000
55 414 0.069212000000 0.0019353230000 0.330798500000
56 415 0.077630000000 0.0021800000000 0.371300000000
57 416 0.086958110000 0.0024548000000 0.416209100000
58 417 0.097176720000 0.0027640000000 0.465464200000
59 418 0.108406300000 0.0031178000000 0.519694800000
60 419 0.120767200000 0.0035264000000 0.579530300000
61 420 0.134380000000 0.0040000000000 0.645600000000
62 421 0.149358200000 0.0045462400000 0.718483800000
63 422 0.165395700000 0.0051593200000 0.796713300000
64 423 0.181983100000 0.0058292800000 0.877845900000
65 424 0.198611000000 0.0065461600000 0.959439000000
66 425 0.214770000000 0.0073000000000 1.039050100000
67 426 0.230186800000 0.0080865070000 1.115367300000
68 427 0.244879700000 0.0089087200000 1.188497100000
69 428 0.258777300000 0.0097676800000 1.258123300000
70 429 0.271807900000 0.0106644300000 1.323929600000
71 430 0.283900000000 0.0116000000000 1.385600000000
72 431 0.294943800000 0.0125731700000 1.442635200000
73 432 0.304896500000 0.0135827200000 1.494803500000
74 433 0.313787300000 0.0146296800000 1.542190300000
75 434 0.321645400000 0.0157150900000 1.584880700000
76 435 0.328500000000 0.0168400000000 1.622960000000
77 436 0.334351300000 0.0180073600000 1.656404800000
78 437 0.339210100000 0.0192144800000 1.685295900000
79 438 0.343121300000 0.0204539200000 1.709874500000
80 439 0.346129600000 0.0217182400000 1.730382100000
81 440 0.348280000000 0.0230000000000 1.747060000000
82 441 0.349599900000 0.0242946100000 1.760044600000
83 442 0.350147400000 0.0256102400000 1.769623300000
84 443 0.350013000000 0.0269585700000 1.776263700000
85 444 0.349287000000 0.0283512500000 1.780433400000
86 445 0.348060000000 0.0298000000000 1.782600000000
87 446 0.346373300000 0.0313108300000 1.782968200000
88 447 0.344262400000 0.0328836800000 1.781699800000
89 448 0.341808800000 0.0345211200000 1.779198200000
90 449 0.339094100000 0.0362257100000 1.775867100000
91 450 0.336200000000 0.0380000000000 1.772110000000
92 451 0.333197700000 0.0398466700000 1.768258900000
93 452 0.330041100000 0.0417680000000 1.764039000000
94 453 0.326635700000 0.0437660000000 1.758943800000
95 454 0.322886800000 0.0458426700000 1.752466300000
96 455 0.318700000000 0.0480000000000 1.744100000000
97 456 0.314025100000 0.0502436800000 1.733559500000
98 457 0.308884000000 0.0525730400000 1.720858100000
99 458 0.303290400000 0.0549805600000 1.705936900000
100 459 0.297257900000 0.0574587200000 1.688737200000
101 460 0.290800000000 0.0600000000000 1.669200000000
102 461 0.283970100000 0.0626019700000 1.647528700000
103 462 0.276721400000 0.0652775200000 1.623412700000
104 463 0.268917800000 0.0680420800000 1.596022300000
105 464 0.260422700000 0.0709110900000 1.564528000000
106 465 0.251100000000 0.0739000000000 1.528100000000
107 466 0.240847500000 0.0770160000000 1.486111400000
108 467 0.229851200000 0.0802664000000 1.439521500000
109 468 0.218407200000 0.0836668000000 1.389879900000
110 469 0.206811500000 0.0872328000000 1.338736200000
111 470 0.195360000000 0.0909800000000 1.287640000000
112 471 0.184213600000 0.0949175500000 1.237422300000
113 472 0.173327300000 0.0990458400000 1.187824300000
114 473 0.162688100000 0.1033674000000 1.138761100000
115 474 0.152283300000 0.1078846000000 1.090148000000
116 475 0.142100000000 0.1126000000000 1.041900000000
117 476 0.132178600000 0.1175320000000 0.994197600000
118 477 0.122569600000 0.1226744000000 0.947347300000
119 478 0.113275200000 0.1279928000000 0.901453100000
120 479 0.104297900000 0.1334528000000 0.856619300000
121 480 0.095640000000 0.1390200000000 0.812950100000
122 481 0.087299550000 0.1446764000000 0.770517300000
123 482 0.079308040000 0.1504693000000 0.729444800000
124 483 0.071717760000 0.1564619000000 0.689913600000
125 484 0.064580990000 0.1627177000000 0.652104900000
126 485 0.057950010000 0.1693000000000 0.616200000000
127 486 0.051862110000 0.1762431000000 0.582328600000
128 487 0.046281520000 0.1835581000000 0.550416200000
129 488 0.041150880000 0.1912735000000 0.520337600000
130 489 0.036412830000 0.1994180000000 0.491967300000
131 490 0.032010000000 0.2080200000000 0.465180000000
132 491 0.027917200000 0.2171199000000 0.439924600000
133 492 0.024144400000 0.2267345000000 0.416183600000
134 493 0.020687000000 0.2368571000000 0.393882200000
135 494 0.017540400000 0.2474812000000 0.372945900000
136 495 0.014700000000 0.2586000000000 0.353300000000
137 496 0.012161790000 0.2701849000000 0.334857800000
138 497 0.009919960000 0.2822939000000 0.317552100000
139 498 0.007967240000 0.2950505000000 0.301337500000
140 499 0.006296346000 0.3085780000000 0.286168600000
141 500 0.004900000000 0.3230000000000 0.272000000000
142 501 0.003777173000 0.3384021000000 0.258817100000
143 502 0.002945320000 0.3546858000000 0.246483800000
144 503 0.002424880000 0.3716986000000 0.234771800000
145 504 0.002236293000 0.3892875000000 0.223453300000
146 505 0.002400000000 0.4073000000000 0.212300000000
147 506 0.002925520000 0.4256299000000 0.201169200000
148 507 0.003836560000 0.4443096000000 0.190119600000
149 508 0.005174840000 0.4633944000000 0.179225400000
150 509 0.006982080000 0.4829395000000 0.168560800000
151 510 0.009300000000 0.5030000000000 0.158200000000
152 511 0.012149490000 0.5235693000000 0.148138300000
153 512 0.015535880000 0.5445120000000 0.138375800000
154 513 0.019477520000 0.5656900000000 0.128994200000
155 514 0.023992770000 0.5869653000000 0.120075100000
156 515 0.029100000000 0.6082000000000 0.111700000000
157 516 0.034814850000 0.6293456000000 0.103904800000
158 517 0.041120160000 0.6503068000000 0.096667480000
159 518 0.047985040000 0.6708752000000 0.089982720000
160 519 0.055378610000 0.6908424000000 0.083845310000
161 520 0.063270000000 0.7100000000000 0.078249990000
162 521 0.071635010000 0.7281852000000 0.073208990000
163 522 0.080462240000 0.7454636000000 0.068678160000
164 523 0.089739960000 0.7619694000000 0.064567840000
165 524 0.099456450000 0.7778368000000 0.060788350000
166 525 0.109600000000 0.7932000000000 0.057250010000
167 526 0.120167400000 0.8081104000000 0.053904350000
168 527 0.131114500000 0.8224962000000 0.050746640000
169 528 0.142367900000 0.8363068000000 0.047752760000
170 529 0.153854200000 0.8494916000000 0.044898590000
171 530 0.165500000000 0.8620000000000 0.042160000000
172 531 0.177257100000 0.8738108000000 0.039507280000
173 532 0.189140000000 0.8849624000000 0.036935640000
174 533 0.201169400000 0.8954936000000 0.034458360000
175 534 0.213365800000 0.9054432000000 0.032088720000
176 535 0.225749900000 0.9148501000000 0.029840000000
177 536 0.238320900000 0.9237348000000 0.027711810000
178 537 0.251066800000 0.9320924000000 0.025694440000
179 538 0.263992200000 0.9399226000000 0.023787160000
180 539 0.277101700000 0.9472252000000 0.021989250000
181 540 0.290400000000 0.9540000000000 0.020300000000
182 541 0.303891200000 0.9602561000000 0.018718050000
183 542 0.317572600000 0.9660074000000 0.017240360000
184 543 0.331438400000 0.9712606000000 0.015863640000
185 544 0.345482800000 0.9760225000000 0.014584610000
186 545 0.359700000000 0.9803000000000 0.013400000000
187 546 0.374083900000 0.9840924000000 0.012307230000
188 547 0.388639600000 0.9874182000000 0.011301880000
189 548 0.403378400000 0.9903128000000 0.010377920000
190 549 0.418311500000 0.9928116000000 0.009529306000
191 550 0.433449900000 0.9949501000000 0.008749999000
192 551 0.448795300000 0.9967108000000 0.008035200000
193 552 0.464336000000 0.9980983000000 0.007381600000
194 553 0.480064000000 0.9991120000000 0.006785400000
195 554 0.495971300000 0.9997482000000 0.006242800000
196 555 0.512050100000 1.0000000000000 0.005749999000
197 556 0.528295900000 0.9998567000000 0.005303600000
198 557 0.544691600000 0.9993046000000 0.004899800000
199 558 0.561209400000 0.9983255000000 0.004534200000
200 559 0.577821500000 0.9968987000000 0.004202400000
201 560 0.594500000000 0.9950000000000 0.003900000000
202 561 0.611220900000 0.9926005000000 0.003623200000
203 562 0.627975800000 0.9897426000000 0.003370600000
204 563 0.644760200000 0.9864444000000 0.003141400000
205 564 0.661569700000 0.9827241000000 0.002934800000
206 565 0.678400000000 0.9786000000000 0.002749999000
207 566 0.695239200000 0.9740837000000 0.002585200000
208 567 0.712058600000 0.9691712000000 0.002438600000
209 568 0.728828400000 0.9638568000000 0.002309400000
210 569 0.745518800000 0.9581349000000 0.002196800000
211 570 0.762100000000 0.9520000000000 0.002100000000
212 571 0.778543200000 0.9454504000000 0.002017733000
213 572 0.794825600000 0.9384992000000 0.001948200000
214 573 0.810926400000 0.9311628000000 0.001889800000
215 574 0.826824800000 0.9234576000000 0.001840933000
216 575 0.842500000000 0.9154000000000 0.001800000000
217 576 0.857932500000 0.9070064000000 0.001766267000
218 577 0.873081600000 0.8982772000000 0.001737800000
219 578 0.887894400000 0.8892048000000 0.001711200000
220 579 0.902318100000 0.8797816000000 0.001683067000
221 580 0.916300000000 0.8700000000000 0.001650001000
222 581 0.929799500000 0.8598613000000 0.001610133000
223 582 0.942798400000 0.8493920000000 0.001564400000
224 583 0.955277600000 0.8386220000000 0.001513600000
225 584 0.967217900000 0.8275813000000 0.001458533000
226 585 0.978600000000 0.8163000000000 0.001400000000
227 586 0.989385600000 0.8047947000000 0.001336667000
228 587 0.999548800000 0.7930820000000 0.001270000000
229 588 1.009089200000 0.7811920000000 0.001205000000
230 589 1.018006400000 0.7691547000000 0.001146667000
231 590 1.026300000000 0.7570000000000 0.001100000000
232 591 1.033982700000 0.7447541000000 0.001068800000
233 592 1.040986000000 0.7324224000000 0.001049400000
234 593 1.047188000000 0.7200036000000 0.001035600000
235 594 1.052466700000 0.7074965000000 0.001021200000
236 595 1.056700000000 0.6949000000000 0.001000000000
237 596 1.059794400000 0.6822192000000 0.000968640000
238 597 1.061799200000 0.6694716000000 0.000929920000
239 598 1.062806800000 0.6566744000000 0.000886880000
240 599 1.062909600000 0.6438448000000 0.000842560000
241 600 1.062200000000 0.6310000000000 0.000800000000
242 601 1.060735200000 0.6181555000000 0.000760960000
243 602 1.058443600000 0.6053144000000 0.000723680000
244 603 1.055224400000 0.5924756000000 0.000685920000
245 604 1.050976800000 0.5796379000000 0.000645440000
246 605 1.045600000000 0.5668000000000 0.000600000000
247 606 1.039036900000 0.5539611000000 0.000547866700
248 607 1.031360800000 0.5411372000000 0.000491600000
249 608 1.022666200000 0.5283528000000 0.000435400000
250 609 1.013047700000 0.5156323000000 0.000383466700
251 610 1.002600000000 0.5030000000000 0.000340000000
252 611 0.991367500000 0.4904688000000 0.000307253300
253 612 0.979331400000 0.4780304000000 0.000283160000
254 613 0.966491600000 0.4656776000000 0.000265440000
255 614 0.952847900000 0.4534032000000 0.000251813300
256 615 0.938400000000 0.4412000000000 0.000240000000
257 616 0.923194000000 0.4290800000000 0.000229546700
258 617 0.907244000000 0.4170360000000 0.000220640000
259 618 0.890502000000 0.4050320000000 0.000211960000
260 619 0.872920000000 0.3930320000000 0.000202186700
261 620 0.854449900000 0.3810000000000 0.000190000000
262 621 0.835084000000 0.3689184000000 0.000174213300
263 622 0.814946000000 0.3568272000000 0.000155640000
264 623 0.794186000000 0.3447768000000 0.000135960000
265 624 0.772954000000 0.3328176000000 0.000116853300
266 625 0.751400000000 0.3210000000000 0.000100000000
267 626 0.729583600000 0.3093381000000 0.000086133330
268 627 0.707588800000 0.2978504000000 0.000074600000
269 628 0.685602200000 0.2865936000000 0.000065000000
270 629 0.663810400000 0.2756245000000 0.000056933330
271 630 0.642400000000 0.2650000000000 0.000049999990
272 631 0.621514900000 0.2547632000000 0.000044160000
273 632 0.601113800000 0.2448896000000 0.000039480000
274 633 0.581105200000 0.2353344000000 0.000035720000
275 634 0.561397700000 0.2260528000000 0.000032640000
276 635 0.541900000000 0.2170000000000 0.000030000000
277 636 0.522599500000 0.2081616000000 0.000027653330
278 637 0.503546400000 0.1995488000000 0.000025560000
279 638 0.484743600000 0.1911552000000 0.000023640000
280 639 0.466193900000 0.1829744000000 0.000021813330
281 640 0.447900000000 0.1750000000000 0.000020000000
282 641 0.429861300000 0.1672235000000 0.000018133330
283 642 0.412098000000 0.1596464000000 0.000016200000
284 643 0.394644000000 0.1522776000000 0.000014200000
285 644 0.377533300000 0.1451259000000 0.000012133330
286 645 0.360800000000 0.1382000000000 0.000010000000
287 646 0.344456300000 0.1315003000000 0.000007733333
288 647 0.328516800000 0.1250248000000 0.000005400000
289 648 0.313019200000 0.1187792000000 0.000003200000
290 649 0.298001100000 0.1127691000000 0.000001333333
291 650 0.283500000000 0.1070000000000 0.000000000000
292 651 0.269544800000 0.1014762000000 0.000000000000
293 652 0.256118400000 0.0961886400000 0.000000000000
294 653 0.243189600000 0.0911229600000 0.000000000000
295 654 0.230727200000 0.0862648500000 0.000000000000
296 655 0.218700000000 0.0816000000000 0.000000000000
297 656 0.207097100000 0.0771206400000 0.000000000000
298 657 0.195923200000 0.0728255200000 0.000000000000
299 658 0.185170800000 0.0687100800000 0.000000000000
300 659 0.174832300000 0.0647697600000 0.000000000000
301 660 0.164900000000 0.0610000000000 0.000000000000
302 661 0.155366700000 0.0573962100000 0.000000000000
303 662 0.146230000000 0.0539550400000 0.000000000000
304 663 0.137490000000 0.0506737600000 0.000000000000
305 664 0.129146700000 0.0475496500000 0.000000000000
306 665 0.121200000000 0.0445800000000 0.000000000000
307 666 0.113639700000 0.0417587200000 0.000000000000
308 667 0.106465000000 0.0390849600000 0.000000000000
309 668 0.099690440000 0.0365638400000 0.000000000000
310 669 0.093330610000 0.0342004800000 0.000000000000
311 670 0.087400000000 0.0320000000000 0.000000000000
312 671 0.081900960000 0.0299626100000 0.000000000000
313 672 0.076804280000 0.0280766400000 0.000000000000
314 673 0.072077120000 0.0263293600000 0.000000000000
315 674 0.067686640000 0.0247080500000 0.000000000000
316 675 0.063600000000 0.0232000000000 0.000000000000
317 676 0.059806850000 0.0218007700000 0.000000000000
318 677 0.056282160000 0.0205011200000 0.000000000000
319 678 0.052971040000 0.0192810800000 0.000000000000
320 679 0.049818610000 0.0181206900000 0.000000000000
321 680 0.046770000000 0.0170000000000 0.000000000000
322 681 0.043784050000 0.0159037900000 0.000000000000
323 682 0.040875360000 0.0148371800000 0.000000000000
324 683 0.038072640000 0.0138106800000 0.000000000000
325 684 0.035404610000 0.0128347800000 0.000000000000
326 685 0.032900000000 0.0119200000000 0.000000000000
327 686 0.030564190000 0.0110683100000 0.000000000000
328 687 0.028380560000 0.0102733900000 0.000000000000
329 688 0.026344840000 0.0095333110000 0.000000000000
330 689 0.024452750000 0.0088461570000 0.000000000000
331 690 0.022700000000 0.0082100000000 0.000000000000
332 691 0.021084290000 0.0076237810000 0.000000000000
333 692 0.019599880000 0.0070854240000 0.000000000000
334 693 0.018237320000 0.0065914760000 0.000000000000
335 694 0.016987170000 0.0061384850000 0.000000000000
336 695 0.015840000000 0.0057230000000 0.000000000000
337 696 0.014790640000 0.0053430590000 0.000000000000
338 697 0.013831320000 0.0049957960000 0.000000000000
339 698 0.012948680000 0.0046764040000 0.000000000000
340 699 0.012129200000 0.0043800750000 0.000000000000
341 700 0.011359160000 0.0041020000000 0.000000000000
342 701 0.010629350000 0.0038384530000 0.000000000000
343 702 0.009938846000 0.0035890990000 0.000000000000
344 703 0.009288422000 0.0033542190000 0.000000000000
345 704 0.008678854000 0.0031340930000 0.000000000000
346 705 0.008110916000 0.0029290000000 0.000000000000
347 706 0.007582388000 0.0027381390000 0.000000000000
348 707 0.007088746000 0.0025598760000 0.000000000000
349 708 0.006627313000 0.0023932440000 0.000000000000
350 709 0.006195408000 0.0022372750000 0.000000000000
351 710 0.005790346000 0.0020910000000 0.000000000000
352 711 0.005409826000 0.0019535870000 0.000000000000
353 712 0.005052583000 0.0018245800000 0.000000000000
354 713 0.004717512000 0.0017035800000 0.000000000000
355 714 0.004403507000 0.0015901870000 0.000000000000
356 715 0.004109457000 0.0014840000000 0.000000000000
357 716 0.003833913000 0.0013844960000 0.000000000000
358 717 0.003575748000 0.0012912680000 0.000000000000
359 718 0.003334342000 0.0012040920000 0.000000000000
360 719 0.003109075000 0.0011227440000 0.000000000000
361 720 0.002899327000 0.0010470000000 0.000000000000
362 721 0.002704348000 0.0009765896000 0.000000000000
363 722 0.002523020000 0.0009111088000 0.000000000000
364 723 0.002354168000 0.0008501332000 0.000000000000
365 724 0.002196616000 0.0007932384000 0.000000000000
366 725 0.002049190000 0.0007400000000 0.000000000000
367 726 0.001910960000 0.0006900827000 0.000000000000
368 727 0.001781438000 0.0006433100000 0.000000000000
369 728 0.001660110000 0.0005994960000 0.000000000000
370 729 0.001546459000 0.0005584547000 0.000000000000
371 730 0.001439971000 0.0005200000000 0.000000000000
372 731 0.001340042000 0.0004839136000 0.000000000000
373 732 0.001246275000 0.0004500528000 0.000000000000
374 733 0.001158471000 0.0004183452000 0.000000000000
375 734 0.001076430000 0.0003887184000 0.000000000000
376 735 0.000999949300 0.0003611000000 0.000000000000
377 736 0.000928735800 0.0003353835000 0.000000000000
378 737 0.000862433200 0.0003114404000 0.000000000000
379 738 0.000800750300 0.0002891656000 0.000000000000
380 739 0.000743396000 0.0002684539000 0.000000000000
381 740 0.000690078600 0.0002492000000 0.000000000000
382 741 0.000640515600 0.0002313019000 0.000000000000
383 742 0.000594502100 0.0002146856000 0.000000000000
384 743 0.000551864600 0.0001992884000 0.000000000000
385 744 0.000512429000 0.0001850475000 0.000000000000
386 745 0.000476021300 0.0001719000000 0.000000000000
387 746 0.000442453600 0.0001597781000 0.000000000000
388 747 0.000411511700 0.0001486044000 0.000000000000
389 748 0.000382981400 0.0001383016000 0.000000000000
390 749 0.000356649100 0.0001287925000 0.000000000000
391 750 0.000332301100 0.0001200000000 0.000000000000
392 751 0.000309758600 0.0001118595000 0.000000000000
393 752 0.000288887100 0.0001043224000 0.000000000000
394 753 0.000269539400 0.0000973356000 0.000000000000
395 754 0.000251568200 0.0000908458700 0.000000000000
396 755 0.000234826100 0.0000848000000 0.000000000000
397 756 0.000219171000 0.0000791466700 0.000000000000
398 757 0.000204525800 0.0000738580000 0.000000000000
399 758 0.000190840500 0.0000689160000 0.000000000000
400 759 0.000178065400 0.0000643026700 0.000000000000
401 760 0.000166150500 0.0000600000000 0.000000000000
402 761 0.000155023600 0.0000559818700 0.000000000000
403 762 0.000144621900 0.0000522256000 0.000000000000
404 763 0.000134909800 0.0000487184000 0.000000000000
405 764 0.000125852000 0.0000454474700 0.000000000000
406 765 0.000117413000 0.0000424000000 0.000000000000
407 766 0.000109551500 0.0000395610400 0.000000000000
408 767 0.000102224500 0.0000369151200 0.000000000000
409 768 0.000095394450 0.0000344486800 0.000000000000
410 769 0.000089023900 0.0000321481600 0.000000000000
411 770 0.000083075270 0.0000300000000 0.000000000000
412 771 0.000077512690 0.0000279912500 0.000000000000
413 772 0.000072313040 0.0000261135600 0.000000000000
414 773 0.000067457780 0.0000243602400 0.000000000000
415 774 0.000062928440 0.0000227246100 0.000000000000
416 775 0.000058706520 0.0000212000000 0.000000000000
417 776 0.000054770280 0.0000197785500 0.000000000000
418 777 0.000051099180 0.0000184528500 0.000000000000
419 778 0.000047676540 0.0000172168700 0.000000000000
420 779 0.000044485670 0.0000160645900 0.000000000000
421 780 0.000041509940 0.0000149900000 0.000000000000
422 781 0.000038733240 0.0000139872800 0.000000000000
423 782 0.000036142030 0.0000130515500 0.000000000000
424 783 0.000033723520 0.0000121781800 0.000000000000
425 784 0.000031464870 0.0000113625400 0.000000000000
426 785 0.000029353260 0.0000106000000 0.000000000000
427 786 0.000027375730 0.0000098858770 0.000000000000
428 787 0.000025524330 0.0000092173040 0.000000000000
429 788 0.000023793760 0.0000085923620 0.000000000000
430 789 0.000022178700 0.0000080091330 0.000000000000
431 790 0.000020673830 0.0000074657000 0.000000000000
432 791 0.000019272260 0.0000069595670 0.000000000000
433 792 0.000017966400 0.0000064879950 0.000000000000
434 793 0.000016749910 0.0000060486990 0.000000000000
435 794 0.000015616480 0.0000056393960 0.000000000000
436 795 0.000014559770 0.0000052578000 0.000000000000
437 796 0.000013573870 0.0000049017710 0.000000000000
438 797 0.000012654360 0.0000045697200 0.000000000000
439 798 0.000011797230 0.0000042601940 0.000000000000
440 799 0.000010998440 0.0000039717390 0.000000000000
441 800 0.000010253980 0.0000037029000 0.000000000000
442 801 0.000009559646 0.0000034521630 0.000000000000
443 802 0.000008912044 0.0000032183020 0.000000000000
444 803 0.000008308358 0.0000030003000 0.000000000000
445 804 0.000007745769 0.0000027971390 0.000000000000
446 805 0.000007221456 0.0000026078000 0.000000000000
447 806 0.000006732475 0.0000024312200 0.000000000000
448 807 0.000006276423 0.0000022665310 0.000000000000
449 808 0.000005851304 0.0000021130130 0.000000000000
450 809 0.000005455118 0.0000019699430 0.000000000000
451 810 0.000005085868 0.0000018366000 0.000000000000
452 811 0.000004741466 0.0000017122300 0.000000000000
453 812 0.000004420236 0.0000015962280 0.000000000000
454 813 0.000004120783 0.0000014880900 0.000000000000
455 814 0.000003841716 0.0000013873140 0.000000000000
456 815 0.000003581652 0.0000012934000 0.000000000000
457 816 0.000003339127 0.0000012058200 0.000000000000
458 817 0.000003112949 0.0000011241430 0.000000000000
459 818 0.000002902121 0.0000010480090 0.000000000000
460 819 0.000002705645 0.0000009770578 0.000000000000
461 820 0.000002522525 0.0000009109300 0.000000000000
462 821 0.000002351726 0.0000008492513 0.000000000000
463 822 0.000002192415 0.0000007917212 0.000000000000
464 823 0.000002043902 0.0000007380904 0.000000000000
465 824 0.000001905497 0.0000006881098 0.000000000000
466 825 0.000001776509 0.0000006415300 0.000000000000
467 826 0.000001656215 0.0000005980895 0.000000000000
468 827 0.000001544022 0.0000005575746 0.000000000000
469 828 0.000001439440 0.0000005198080 0.000000000000
470 829 0.000001341977 0.0000004846123 0.000000000000
471 830 0.000001251141 0.0000004518100 0.000000000000
+40
View File
@@ -0,0 +1,40 @@
# CIE 1931 blackbody LUT
`cie1931_2deg_xyz_1024.grbblut` is the sole repository LUT. It contains 1,024
XYZ nodes uniformly spaced in `log(T)` over `[670.146556, 101408.88] K`.
Wolfram integrates the Planck spectrum against the piecewise-linear 1 nm data
in `assets/CIE_xyz_1931_2deg.csv` at 40-digit working precision and rounds each
stored value once to little-endian IEEE binary64.
The 160-byte `GRBBLUT3` header records the CIE 1931 2-degree, 360--830 nm,
1 nm-linear reference definition, node count, temperature limits, physical
constants, generator description, and payload FNV-1a checksum. The C loader
validates the header, exact payload size, and checksum, and rejects trailing
bytes. Runtime table generation and the former `GRBBLUT1`/`GRBBLUT2` formats are
not supported. The evaluator uses four-point cubic Lagrange interpolation in
`log(T)`.
- file size: 24,736 bytes
- payload FNV-1a: `0e39867b0e70a809`
- file SHA-256:
`850446663212fe488c88fca3ac2f54d6f8119a04801dda84fc1a62acdec37d63`
- all 1,023 interval midpoints versus independent Gauss-16 integration:
max XYZ-channel relative `5.4633e-5`, no negative XYZ
The LUT interpolation acceptance limit is `1e-4`. A separate `5e-4` overall
relative error budget accounts for the estimated error of linearly
interpolating the 1 nm CIE samples; the LUT's much smaller internal error must
not be mistaken for physical-reference accuracy.
Outside the stored range, the same CSV reference supplies both models. Above
101408.88 K the evaluator uses three integrated Rayleigh--Jeans terms
`A T+B+C/T` (maximum validated XYZ-channel relative error `1.6635e-5`
through `10*Tmax`). Below 670.146556 K it uses a six-segment, degree-eight
inverse-temperature/log-XYZ Chebyshev--Lobatto crossover down to 4.097321 K
and channel-specific endpoint forms below that. Their maximum sampled XYZ
relative errors are `8.16e-5` and `6.69e-5`.
The Wolfram generation/validation scripts that produced this table, together
with the bounded performance and accuracy evidence, are preserved on the
experiment branch `codex/blackbody-cost-experiment` (tag
`blackbody-cost-experiment-2026-09-12`) and are not part of the mainline tree.
Binary file not shown.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 MiB

After

Width:  |  Height:  |  Size: 12 MiB

+82
View File
@@ -0,0 +1,82 @@
ra_deg,dec_deg,temperature_K,amplitude_sr
-0.500000,0.500000,2500,1.288768695e-13
-0.375000,0.500000,2500,5.130680588e-14
-0.250000,0.500000,2500,2.042560732e-14
-0.125000,0.500000,2500,8.131580736e-15
0.000000,0.500000,2500,3.237240599e-15
0.125000,0.500000,2500,1.288768695e-15
0.250000,0.500000,2500,5.130680588e-16
0.375000,0.500000,2500,2.042560732e-16
0.500000,0.500000,2500,8.131580736e-17
-0.500000,0.375000,3044.7082,5.529309491e-14
-0.375000,0.375000,3044.7082,2.201257756e-14
-0.250000,0.375000,3044.7082,8.763364971e-15
-0.125000,0.375000,3044.7082,3.488758433e-15
0.000000,0.375000,3044.7082,1.388899748e-15
0.125000,0.375000,3044.7082,5.529309491e-16
0.250000,0.375000,3044.7082,2.201257756e-16
0.375000,0.375000,3044.7082,8.763364971e-17
0.500000,0.375000,3044.7082,3.488758433e-17
-0.500000,0.250000,3708.0992,2.727501648e-14
-0.375000,0.250000,3708.0992,1.085837964e-14
-0.250000,0.250000,3708.0992,4.322798794e-15
-0.125000,0.250000,3708.0992,1.720937197e-15
0.000000,0.250000,3708.0992,6.851174381e-16
0.125000,0.250000,3708.0992,2.727501648e-16
0.250000,0.250000,3708.0992,1.085837964e-16
0.375000,0.250000,3708.0992,4.322798794e-17
0.500000,0.250000,3708.0992,1.720937197e-17
-0.500000,0.125000,4516.0321,1.501787774e-14
-0.375000,0.125000,4516.0321,5.978724815e-15
-0.250000,0.125000,4516.0321,2.380173219e-15
-0.125000,0.125000,4516.0321,9.475640258e-16
0.000000,0.125000,4516.0321,3.772320332e-16
0.125000,0.125000,4516.0321,1.501787774e-16
0.250000,0.125000,4516.0321,5.978724815e-17
0.375000,0.125000,4516.0321,2.380173219e-17
0.500000,0.125000,4516.0321,9.475640258e-18
-0.500000,0.000000,5500,9.010857559e-15
-0.375000,0.000000,5500,3.587287007e-15
-0.250000,0.000000,5500,1.428124680e-15
-0.125000,0.000000,5500,5.685466757e-16
0.000000,0.000000,5500,2.263425084e-16
0.125000,0.000000,5500,9.010857559e-17
0.250000,0.000000,5500,3.587287007e-17
0.375000,0.000000,5500,1.428124680e-17
0.500000,0.000000,5500,5.685466757e-18
-0.500000,-0.125000,7067.9722,5.170563867e-15
-0.375000,-0.125000,7067.9722,2.058438551e-15
-0.250000,-0.125000,7067.9722,8.194791473e-16
-0.125000,-0.125000,7067.9722,3.262405247e-16
0.000000,-0.125000,7067.9722,1.298786922e-16
0.125000,-0.125000,7067.9722,5.170563867e-17
0.250000,-0.125000,7067.9722,2.058438551e-17
0.375000,-0.125000,7067.9722,8.194791473e-18
0.500000,-0.125000,7067.9722,3.262405247e-18
-0.500000,-0.250000,9082.9511,3.209818520e-15
-0.375000,-0.250000,9082.9511,1.277851769e-15
-0.250000,-0.250000,9082.9511,5.087219521e-16
-0.125000,-0.250000,9082.9511,2.025258569e-16
0.000000,-0.250000,9082.9511,8.062699587e-17
0.125000,-0.250000,9082.9511,3.209818520e-17
0.250000,-0.250000,9082.9511,1.277851769e-17
0.375000,-0.250000,9082.9511,5.087219521e-18
0.500000,-0.250000,9082.9511,2.025258569e-18
-0.500000,-0.375000,11672.372,2.109932559e-15
-0.375000,-0.375000,11672.372,8.399792812e-16
-0.250000,-0.375000,11672.372,3.344017750e-16
-0.125000,-0.375000,11672.372,1.331277445e-16
0.000000,-0.375000,11672.372,5.299910967e-17
0.125000,-0.375000,11672.372,2.109932559e-17
0.250000,-0.375000,11672.372,8.399792812e-18
0.375000,-0.375000,11672.372,3.344017750e-18
0.500000,-0.375000,11672.372,1.331277445e-18
-0.500000,-0.500000,15000,1.446233663e-15
-0.375000,-0.500000,15000,5.757559917e-16
-0.250000,-0.500000,15000,2.292125888e-16
-0.125000,-0.500000,15000,9.125117517e-17
0.000000,-0.500000,15000,3.632774716e-17
0.125000,-0.500000,15000,1.446233663e-17
0.250000,-0.500000,15000,5.757559917e-18
0.375000,-0.500000,15000,2.292125888e-18
0.500000,-0.500000,15000,9.125117517e-19
1 ra_deg dec_deg temperature_K amplitude_sr
2 -0.500000 0.500000 2500 1.288768695e-13
3 -0.375000 0.500000 2500 5.130680588e-14
4 -0.250000 0.500000 2500 2.042560732e-14
5 -0.125000 0.500000 2500 8.131580736e-15
6 0.000000 0.500000 2500 3.237240599e-15
7 0.125000 0.500000 2500 1.288768695e-15
8 0.250000 0.500000 2500 5.130680588e-16
9 0.375000 0.500000 2500 2.042560732e-16
10 0.500000 0.500000 2500 8.131580736e-17
11 -0.500000 0.375000 3044.7082 5.529309491e-14
12 -0.375000 0.375000 3044.7082 2.201257756e-14
13 -0.250000 0.375000 3044.7082 8.763364971e-15
14 -0.125000 0.375000 3044.7082 3.488758433e-15
15 0.000000 0.375000 3044.7082 1.388899748e-15
16 0.125000 0.375000 3044.7082 5.529309491e-16
17 0.250000 0.375000 3044.7082 2.201257756e-16
18 0.375000 0.375000 3044.7082 8.763364971e-17
19 0.500000 0.375000 3044.7082 3.488758433e-17
20 -0.500000 0.250000 3708.0992 2.727501648e-14
21 -0.375000 0.250000 3708.0992 1.085837964e-14
22 -0.250000 0.250000 3708.0992 4.322798794e-15
23 -0.125000 0.250000 3708.0992 1.720937197e-15
24 0.000000 0.250000 3708.0992 6.851174381e-16
25 0.125000 0.250000 3708.0992 2.727501648e-16
26 0.250000 0.250000 3708.0992 1.085837964e-16
27 0.375000 0.250000 3708.0992 4.322798794e-17
28 0.500000 0.250000 3708.0992 1.720937197e-17
29 -0.500000 0.125000 4516.0321 1.501787774e-14
30 -0.375000 0.125000 4516.0321 5.978724815e-15
31 -0.250000 0.125000 4516.0321 2.380173219e-15
32 -0.125000 0.125000 4516.0321 9.475640258e-16
33 0.000000 0.125000 4516.0321 3.772320332e-16
34 0.125000 0.125000 4516.0321 1.501787774e-16
35 0.250000 0.125000 4516.0321 5.978724815e-17
36 0.375000 0.125000 4516.0321 2.380173219e-17
37 0.500000 0.125000 4516.0321 9.475640258e-18
38 -0.500000 0.000000 5500 9.010857559e-15
39 -0.375000 0.000000 5500 3.587287007e-15
40 -0.250000 0.000000 5500 1.428124680e-15
41 -0.125000 0.000000 5500 5.685466757e-16
42 0.000000 0.000000 5500 2.263425084e-16
43 0.125000 0.000000 5500 9.010857559e-17
44 0.250000 0.000000 5500 3.587287007e-17
45 0.375000 0.000000 5500 1.428124680e-17
46 0.500000 0.000000 5500 5.685466757e-18
47 -0.500000 -0.125000 7067.9722 5.170563867e-15
48 -0.375000 -0.125000 7067.9722 2.058438551e-15
49 -0.250000 -0.125000 7067.9722 8.194791473e-16
50 -0.125000 -0.125000 7067.9722 3.262405247e-16
51 0.000000 -0.125000 7067.9722 1.298786922e-16
52 0.125000 -0.125000 7067.9722 5.170563867e-17
53 0.250000 -0.125000 7067.9722 2.058438551e-17
54 0.375000 -0.125000 7067.9722 8.194791473e-18
55 0.500000 -0.125000 7067.9722 3.262405247e-18
56 -0.500000 -0.250000 9082.9511 3.209818520e-15
57 -0.375000 -0.250000 9082.9511 1.277851769e-15
58 -0.250000 -0.250000 9082.9511 5.087219521e-16
59 -0.125000 -0.250000 9082.9511 2.025258569e-16
60 0.000000 -0.250000 9082.9511 8.062699587e-17
61 0.125000 -0.250000 9082.9511 3.209818520e-17
62 0.250000 -0.250000 9082.9511 1.277851769e-17
63 0.375000 -0.250000 9082.9511 5.087219521e-18
64 0.500000 -0.250000 9082.9511 2.025258569e-18
65 -0.500000 -0.375000 11672.372 2.109932559e-15
66 -0.375000 -0.375000 11672.372 8.399792812e-16
67 -0.250000 -0.375000 11672.372 3.344017750e-16
68 -0.125000 -0.375000 11672.372 1.331277445e-16
69 0.000000 -0.375000 11672.372 5.299910967e-17
70 0.125000 -0.375000 11672.372 2.109932559e-17
71 0.250000 -0.375000 11672.372 8.399792812e-18
72 0.375000 -0.375000 11672.372 3.344017750e-18
73 0.500000 -0.375000 11672.372 1.331277445e-18
74 -0.500000 -0.500000 15000 1.446233663e-15
75 -0.375000 -0.500000 15000 5.757559917e-16
76 -0.250000 -0.500000 15000 2.292125888e-16
77 -0.125000 -0.500000 15000 9.125117517e-17
78 0.000000 -0.500000 15000 3.632774716e-17
79 0.125000 -0.500000 15000 1.446233663e-17
80 0.250000 -0.500000 15000 5.757559917e-18
81 0.375000 -0.500000 15000 2.292125888e-18
82 0.500000 -0.500000 15000 9.125117517e-19
@@ -0,0 +1,224 @@
# adaptive_step_bounds_2026-10-05
Long-term benchmark for calibrating the DP54 adaptive-integrator step bounds
(`min_step` / `max_step`) of the past-directed null-geodesic tracer, and the
public record of the one authorised 4K Schwarzschild `max_step` 2-vs-8 pair.
The benchmark runs the public endpoint `geodesic_trace_past()`, the production
DP core, and bounded adaptive-mesh renders against the analytic
Minkowski / Schwarzschild / Alcubierre backends. It does not modify production
sources.
## Build (required before renderer scripts)
The Python mesh/4K drivers start from an existing renderer binary. The shell
endpoint/core drivers compile their own small harnesses against production code.
```
make -j4 BUILD_TYPE=Release SPACETIME=schwarzschild backend
# binary: build/Release/schwarzschild_sky
```
## Files
| file | role |
|---|---|
| `a_public_endpoints.c` | Experiment A: step-bound scans through the public endpoint, tol=1e-12 reference, RK4 h-halving on near-critical rays. |
| `b_actual_h.c` | Experiment B: textually includes `src/geodesic.c`, drives the production `dp_advance_one` on finite trusted intervals to measure observed accepted `h`. |
| `critical_ref_check.c` | Critical-classification probe (r30/r100 inward, r2.1 outward; `theta_crit` and `theta_crit±1e-7`; tol/max_step ladder). |
| `mesh_maps.py` | Pure GRLENS v3 `load`/`compare`; no renderer, no untracked import. |
| `run_mesh.py` | 8 bounded 320x180 candidates (R100 and R2.1, `max_step` .5/2/8/32). |
| `run_mesh_reference.py` | 2 tight-tolerance references and comparisons against the 8 maps. |
| `summarize_4k.py` | Postprocess existing maps only; never invokes a renderer. |
| `run_4k_pair.py` | One-task, at-most-two-attempt 4K pair; refuses to run without `--authorize-two-4k`. |
| `record_environment.py` | Provenance (git/hashes/compiler/cpu/build/run commands); no render. |
| `failure_floor.c` | Failure-path floor diagnostic; includes `../../tests/test_geodesic_adaptive.c`. |
| `run_failure_floor.sh` | Builds/runs `failure_floor.c` with `-DGEODESIC_EVENT_TESTING`. |
| `run_limited.sh` | Builds/runs Experiment A + B; all output under `OUT_DIR`. |
| `run_critical_ref.sh` | Builds/runs `critical_ref_check.c`; all output under `OUT_DIR`. |
| `summarize.py` | `OUT_DIR` CLI arg (default `local/adaptive_step_bounds_2026-10-05`); writes `OUT_DIR/logs/summary.txt`. |
| `results/` | Tracked long-term evidence (see below). |
## Reproduction
```
AB_OUT="$PWD/local/adaptive_step_bounds_2026-10-05"
OUT="$PWD/local/adaptive_bounds_mesh"
bash benchmarks/adaptive_step_bounds_2026-10-05/run_limited.sh "$AB_OUT"
bash benchmarks/adaptive_step_bounds_2026-10-05/run_critical_ref.sh "$AB_OUT"
python3 benchmarks/adaptive_step_bounds_2026-10-05/summarize.py "$AB_OUT"
python3 benchmarks/adaptive_step_bounds_2026-10-05/run_mesh.py "$OUT"
python3 benchmarks/adaptive_step_bounds_2026-10-05/run_mesh_reference.py "$OUT"
bash benchmarks/adaptive_step_bounds_2026-10-05/run_failure_floor.sh "$OUT"
# 4K only after explicit fresh user authorization for that task:
python3 benchmarks/adaptive_step_bounds_2026-10-05/run_4k_pair.py \
--authorize-two-4k --out local/adaptive_bounds_4k
```
Defaults: A/B `OUT_DIR` is `local/adaptive_step_bounds_2026-10-05`; mesh
`OUT_DIR` is `local/adaptive_bounds_mesh`; 4K `--out` default is
`local/adaptive_bounds_4k`. All logs/CSV go to `OUT_DIR`; the tracked
benchmark directory holds only sources and `results/`. Scratch binaries go to
`/tmp/opencode/step_bounds/`.
The `run_4k_pair.py` driver refuses to run without `--authorize-two-4k`, keeps
an attempt ledger, and has no automatic retry. Authorisation does not extend to
later tasks or routine tests.
All catalog inputs are generated inline by the scripts (column header
`longitude_deg,latitude_deg,temperature_K,amplitude`, one 1e-30 star); no
external survey CSV is read.
## Results
### 1. Public-endpoint step-bound scan (Experiment A/B)
Environment and full table inputs: `results/source_environment.txt`,
`results/summary_tables.txt`; full stdout: `results/expA.log`,
`results/expB.log`. Per-ray raw CSV (not tracked) is reproduced by
`run_limited.sh`.
| backend | worst near-critical sky error vs tol=1e-12 ref | notes |
|---|---|---|
| Schwarzschild r30 | 2.82e-4 rad (`max_step`≥1); 8.67e-5 rad at 0.25 | r100 8.0e-5 / 2.6e-5; r2.1 2.87e-4 |
| Minkowski | Δn = 0, Δg/g = 0 (analytic) | crossing x/t ≤ 7.7e-11 at `max_step`≤256 |
| Alcubierre | ≤1.8e-10 rad, no class change | 8x vs 1x `initial` RHS cost 4.3x–5.7x |
- Dark terminal `L−L0` margin agrees with the reference to ≤2.1e-13 in every
config; near-critical dark stop times differ up to ~41 time units between
tol=1e-9 and tol=1e-12 (orbit-count sensitivity, reported not hidden).
- Schwarzschild floor plateau: `min_step` `1e-14 … 1e-2` give bit-identical
results and RHS; only `0.1` breaks one r1.5 ray
(`INCOMPLETE/INTEGRATION_ERROR`). No evidence to raise the default floor,
and no evidence that `1e-12` is uniquely optimal (it is never active).
- Observed accepted `h` (Experiment B, finite window `T=min(20, ref span)`):
**Schwarzschild only** — r1.5 radial 0.0921, all other sampled Schwarzschild
rays ≥0.1; Alcubierre minimum = its initial step (0.05 / 0.005 / 0.0005);
Minkowski 1.0. This is a finite-window diagnostic, **not** a full-trajectory
minimum.
- RK4 h-halving worst (r2.1, `theta_crit−1e-7`): 1.04e-5 rad.
### 2. Bounded 320x180 adaptive mesh
Numeric inputs: `results/mesh_summary.json`,
`results/mesh_reference_summary.json`. Scene: R100/FOV45/jacobian0.2 and
R2.1/outward/FOV90; DP54, hmin 1e-12, initial 0.1, tol 1e-9 (tight reference
1e-12), 8 threads, one-point dim catalog.
| scene | `max_step` | persistent vertices | RHS | wall (s) |
|---|---:|---:|---:|---:|
| R100 | 0.5 | 3158 | 16813349 | 2.071 |
| R100 | 2 | 3158 | 6030185 | 0.979 |
| R100 | 8 | 3158 | 4230835 | 0.823 |
| R100 | 32 | 3158 | 4081609 | 0.830 |
| R2.1 | 0.5 | 5496 | 20136508 | 1.974 |
| R2.1 | 2 | 5496 | 9548434 | 1.178 |
| R2.1 | 8 | 5496 | 7389760 | 0.970 |
| R2.1 | 32 | 5496 | 7197806 | 0.972 |
- 2→8 RHS reduction 29.84% (R100) / 22.61% (R2.1); 8→32 only 3.53% / 2.60%.
- Identical terminal classifications and mesh/sample counts for all four caps.
- Error vs tight reference: R100 max sky 9.216e-8 (hmax2) / 8.744e-8 (hmax8),
mutual 2-vs-8 difference 7.063e-9 rad; R2.1 max sky 1.4772e-5 rad at both,
mutual difference 8.370e-11 rad. The larger R2.1 reference error is
tolerance/conditioning sensitive and is not cured by a smaller `max_step`.
- Max log-frequency differences ≤8.51e-10 (R100) / ≤2.10e-9 (R2.1).
- Short single-run wall times include setup/cache/output; not a timing study.
### 3. One authorised 4K pair (R100, 3840x2160, FOV45)
Raw terminal output (byte-for-byte): `results/4k_hmax2.log`,
`results/4k_hmax8.log`; provenance: `results/4k_metadata.json`,
`results/4k_attempts.json`; postprocessed: `results/4k_final_summary.json`,
`results/4k_raw_summary.log`.
| metric | `max_step`=2 | `max_step`=8 |
|---|---:|---:|
| persistent vertices / triangles | 66045 / 131338 | 66045 / 131338 |
| outcomes | 62419 ESC, 3626 DARK | 62419 ESC, 3626 DARK |
| unresolved / error | 0 | 0 |
| persistent accepted | 15,768,677 | 10,183,020 |
| persistent rejected | 97,176 | 194,781 |
| persistent RHS | 130,409,139 | 91,991,144 |
| trace+refine time (s) | 10.774 | 7.805 |
| process wall (s) | 11.3893 | 8.38925 |
- Triangle payload is bit-identical; shared film identities 66045, terminal
mismatches 0; max mutual endpoint sky difference 7.9544e-7 rad, max logg
difference 3.4711e-11.
- Persistent-vertex RHS reduction −29.46%; accepted −35.42%; wall −26.34%.
- **Cost scope:** the v3 map stores final persistent vertices only. The
requested-sample count including discarded refinement probes is 116308
(> 66045), so discarded probes contribute no stored cost and these sums must
not be read as full-render executed RHS totals.
- **Timing:** one sequential pair only; no statistical timing confidence.
- PSF splat cached/direct = 0 and `--psf-min-y` discarded 1965 (hmax2) / 1954
(hmax8) events; this does not measure image error. The PNGs are dark
diagnostic backgrounds; no 2MASS catalog was used.
### 4. Critical-classification reference check
Full output: `results/critical_ref.log`, `results/critical_ref.csv` (36
endpoint traces). The exact `theta_crit` direction is a classification
separatrix; it is reported, never asserted.
- r2.1 `theta_crit`: ref tol1e-12/h0.25 vs tol1e-13/h0.125 sky difference
**2.33638 rad** — the exactly-critical escape direction is not
independently converged. `EXACT_CRITICAL_REFERENCE_NOT_CONVERGED`.
- r30 `theta_crit` (DARK) stop-time difference 13.056; r100 `theta_crit` (DARK)
12.700. At tol1e-11, h2-vs-h8 at r2.1 `theta_crit` is 5.09e-5 rad.
- Neighbours `±1e-7`: both reference tiers agree (same outcome/reason/end,
clean, positive steps) at every neighbour. Escaped-neighbour sky differences
between the layers are ~1e-7 rad (9.47e-8 r30, 2.74e-8 r100, 1.42e-7 r2.1),
consistent with the loose 1e-4 magnitude trend; DARK neighbours report
stop-time differences 1.5e-7 … 7.5e-7.
- `CRITICAL_REFERENCE_CHECK status=0` (no neighbour reference disagreement or
error endpoint).
## Decision summary
- **Schwarzschild `max_step = 8`**: supported by the far-field cost plateau
(2→8 saves ~23–30% persistent RHS; 8→32 only ~3%) together with the tight
reference and 4K 2-vs-8 comparisons. This is not claimed as globally optimal
and gives no guarantee for arbitrary near-critical/shadow directions.
- **`min_step = 1e-12`**: retained as a non-binding numerical guard; not a
measured optimum.
- **Minkowski `max_step = 16`** and **Alcubierre `max_step = 8 × initial`**:
retained as conservative caps. Their bounded accuracy checks support keeping
these values, not claiming cost optimality; larger Alcubierre caps still
reduce RHS, but have larger frequency errors in some cases.
- The R2.1 exactly-critical difference is tolerance-sensitive;
`critical_ref_check.c` confirms the exact direction is not
independently converged and the report does not treat it as certified.
## Caveats
- Analytic backends only; no time-dependent numerical-relativity metric was
exercised. Bounds and the `unit = 1` calibration are not transferable to NR.
- Experiment B samples `T = min(20, reference span)`; no full-trajectory
minimum-step claim is made.
- The 4K numbers are one sequential pair; no timing-stability confidence and
no image-error bound (inverse-lens-map Jacobian amplification is separate).
- Sky-angle differences divided by pixel angle are not inverse-lens-map image
error bounds.
- `failure_floor.c` reuses the regression invalid-metric temporal-domain
fixture; it is not a physical shadow or floor calibration.
## Verification of the selected defaults and reproduction tools
`make -B -j4 BUILD_TYPE=Debug test` passed after selecting the Schwarzschild
cap of 8 and adding CLI provenance assertions for the default bounds. Full
terminal output is retained locally at
`local/step_bounds_mesh/final_debug_tests.log` (`STEP_BOUNDS_FULL_DEBUG_EXIT=0`).
The explicit-RK4 HDR reference tests remain bit-identical. The Release
Schwarzschild binary was rebuilt with the selected default.
The self-contained limited driver was also executed with the relative output
path `local/step_bounds_reproduction`: 1500 endpoint traces and 2427 observed
finite-window steps completed, including summary generation. Small angular
differences use `atan2(|cross|,dot)` rather than rounded `acos(dot)`. Running the
4K driver without fresh explicit authorization refuses with exit code 2;
this check launches no renderer. No further 4K attempt was made.
@@ -0,0 +1,867 @@
/*
* Experiment A: DP54 step-bound scan through the *public* production
* endpoint geodesic_trace_past().
*
* Sub-commands:
* schwarzschild : r30/r100 static inward, r2.1 static outward, r1.5 free-fall
* minkowski : moving observer, escape sphere 64, analytic flat check
* alcubierre : comoving bubble-center camera, vs .3/.9, sigma 1/10/100
*
* Each sub-command computes one DP54 tol=1e-12 reference per ray, then scans
* - upper scan : max_step over a list, min_step fixed
* - min scan : min_step over a list, max_step fixed
* and compares every result against the reference (class, sky angle, g,
* dark threshold margin / stop time, cost). Raw per-ray CSV and stdout
* summaries are produced. No production source is modified.
*
* Link line (do NOT link geodesic.c twice; the backends are textually included
* below, so only the common sources are linked):
* cc -std=c11 -O2 -Isrc a_public_endpoints.c geodesic.c asymptotic.c \
* asymptotic_schwarzschild.c spacetime_common.c observer.c -lm
*/
#define _POSIX_C_SOURCE 200809L
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
/* Textually include all three analytic backends with renamed default
* constructors so one binary can exercise every provider (the files each
* define spacetime_create_default, which would collide at link time). */
#define spacetime_create_default spacetime_create_default_minkowski_local
#include "../../src/spacetime_minkowski.c"
#undef spacetime_create_default
#define spacetime_create_default spacetime_create_default_schwarzschild_local
#include "../../src/spacetime_schwarzschild.c"
#undef spacetime_create_default
#define spacetime_create_default spacetime_create_default_alcubierre_local
#include "../../src/spacetime_alcubierre.c"
#undef spacetime_create_default
#include "geodesic.h"
#include "observer.h"
#include "spacetime.h"
#define PI 3.14159265358979323846
#define MAX_CASES 16
#define MAX_DIRS 16
#define RAY_CAP 2500
static long g_rays = 0;
/* ------------------------------------------------------------------ */
/* Small helpers */
/* ------------------------------------------------------------------ */
static double dot3(const double a[3], const double b[3]) {
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
}
static double ang_delta(const double a[3], const double b[3]) {
const double na = sqrt(dot3(a, a)), nb = sqrt(dot3(b, b));
if (!(na > 0.0) || !(nb > 0.0))
return NAN;
const double ca = dot3(a, b) / (na * nb);
const double cross[3] = {a[1] * b[2] - a[2] * b[1],
a[2] * b[0] - a[0] * b[2],
a[0] * b[1] - a[1] * b[0]};
const double sn = sqrt(dot3(cross, cross)) / (na * nb);
return atan2(sn, ca);
}
static double now_s(void) {
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return (double)ts.tv_sec + 1e-9 * (double)ts.tv_nsec;
}
static int is_dark(int outcome) { return outcome == RAY_OUTCOME_DARK; }
static int is_escaped(int outcome) { return outcome == RAY_OUTCOME_ESCAPED; }
/* Critical local angle (static observer, M=1) for the Schwarzschild monopole.
* theta_c = asin(3 sqrt(3) sqrt(1-2/r) / r). */
static double critical_angle(double r) {
const double b = 3.0 * sqrt(3.0) * sqrt(1.0 - 2.0 / r) / r;
if (!(b < 1.0))
return PI / 2.0;
return asin(b);
}
/* ------------------------------------------------------------------ */
/* Case / result / comparison structures */
/* ------------------------------------------------------------------ */
typedef struct {
char name[32];
int prov; /* 0 schwarzschild, 1 minkowski, 2 alcubierre */
double mass, escape_radius;
double alc_vs, alc_radius, alc_sigma;
double look_ra_deg, look_dec_deg;
double position[3], velocity[3];
double initial_step, lookback;
unsigned int max_steps;
unsigned int ref_max_steps; /* budget for the tol=1e-12 reference only */
double max_step_for_min_scan; /* fixed upper during the min scan */
int n_dirs;
double dirs[MAX_DIRS][3];
double theta[MAX_DIRS]; /* NAN for non-angle direction sets */
} Case;
typedef struct {
int outcome, reason, end_id;
double stop_t, g, thr;
double n[3];
unsigned int steps, rejected;
unsigned long rhs;
double wall;
} Res;
typedef struct {
int has_ref;
int class_match;
double dn_ang, dlogg, dgrel, dstopT, dmargin;
} Cmp;
typedef struct {
long n, class_mismatch;
double max_dn_ang, max_dlogg, max_dgrel, max_dstopT, max_dmargin;
unsigned long sum_rhs, max_rhs;
unsigned int max_rejected;
double sum_wall;
long escaped, dark, unresolved, incomplete;
} Agg;
static void agg_init(Agg *a) {
memset(a, 0, sizeof *a);
a->max_dn_ang = a->max_dlogg = a->max_dgrel = a->max_dstopT =
a->max_dmargin = -1.0;
}
static void bump(double *m, double v) {
if (!isfinite(v))
return;
if (v > *m)
*m = v;
}
static void agg_add(Agg *a, const Res *r, const Cmp *c) {
++a->n;
if (c->has_ref && !c->class_match)
++a->class_mismatch;
if (c->has_ref) {
bump(&a->max_dn_ang, c->dn_ang);
bump(&a->max_dlogg, c->dlogg);
bump(&a->max_dgrel, c->dgrel);
bump(&a->max_dstopT, c->dstopT);
bump(&a->max_dmargin, c->dmargin);
}
a->sum_rhs += r->rhs;
if (r->rhs > a->max_rhs)
a->max_rhs = r->rhs;
if (r->rejected > a->max_rejected)
a->max_rejected = r->rejected;
a->sum_wall += r->wall;
if (is_dark(r->outcome))
++a->dark;
else if (is_escaped(r->outcome))
++a->escaped;
else if (r->outcome == RAY_OUTCOME_UNRESOLVED)
++a->unresolved;
else
++a->incomplete;
}
/* ------------------------------------------------------------------ */
/* Config builders */
/* ------------------------------------------------------------------ */
static GeodesicTraceConfig make_dp(double initial, double min_step,
double max_step, double tol,
unsigned int max_steps, double lookback) {
GeodesicTraceConfig c;
memset(&c, 0, sizeof c);
c.coordinate_time_step = initial;
c.max_steps = max_steps;
c.threshold.kind = THRESHOLD_LOG_ENERGY_GROWTH;
c.threshold.value = 8.0;
c.threshold.policy_version = 3;
c.stepper = GEODESIC_STEPPER_DP54;
c.atol_x = tol;
c.atol_Pi = tol;
c.atol_L = tol;
c.rtol = tol;
c.min_step = min_step;
c.max_step = max_step;
c.consecutive_rejection_limit = 32;
c.max_lookback_time = lookback;
return c;
}
static GeodesicTraceConfig make_rk4(double step, unsigned int max_steps) {
GeodesicTraceConfig c;
memset(&c, 0, sizeof c);
c.coordinate_time_step = step;
c.max_steps = max_steps;
c.threshold.kind = THRESHOLD_LOG_ENERGY_GROWTH;
c.threshold.value = 8.0;
c.threshold.policy_version = 3;
c.stepper = GEODESIC_STEPPER_RK4;
return c;
}
/* ------------------------------------------------------------------ */
/* Trace + compare */
/* ------------------------------------------------------------------ */
static Res run_ray(const SpacetimeSource *source, const ObserverState *observer,
const double dir[3], const GeodesicTraceConfig *config) {
Res r;
memset(&r, 0, sizeof r);
++g_rays;
if (g_rays > RAY_CAP) {
fprintf(stderr, "FATAL: ray cap %d exceeded\n", RAY_CAP);
exit(3);
}
const double t0 = now_s();
const RayEndpoint e = geodesic_trace_past(source, observer, dir, config);
r.wall = now_s() - t0;
r.outcome = e.outcome;
r.reason = e.reason;
r.end_id = e.end_id;
r.stop_t = e.stop_coordinate_time;
r.g = e.frequency_ratio;
r.thr = e.threshold_value;
for (int i = 0; i < 3; ++i)
r.n[i] = e.n_infinity[i];
r.steps = e.accepted_steps;
r.rejected = e.rejected_steps;
r.rhs = e.rhs_evaluations;
return r;
}
static void compare(const Res *a, const Res *ref, Cmp *c) {
memset(c, 0, sizeof *c);
c->has_ref = 1;
c->class_match = (a->outcome == ref->outcome && a->reason == ref->reason);
if (is_escaped(a->outcome) && is_escaped(ref->outcome)) {
c->dn_ang = ang_delta(a->n, ref->n);
if (a->g > 0.0 && ref->g > 0.0 && isfinite(a->g) && isfinite(ref->g)) {
c->dlogg = fabs(log(a->g) - log(ref->g));
c->dgrel = fabs(a->g / ref->g - 1.0);
} else {
c->dlogg = c->dgrel = NAN;
}
} else {
c->dn_ang = c->dlogg = c->dgrel = NAN;
}
c->dstopT = (isfinite(a->stop_t) && isfinite(ref->stop_t))
? fabs(a->stop_t - ref->stop_t)
: NAN;
c->dmargin = (is_dark(a->outcome) && is_dark(ref->outcome) &&
isfinite(a->thr) && isfinite(ref->thr))
? fabs(a->thr - ref->thr)
: NAN;
}
static void write_row(FILE *f, const char *phase, const Case *c, int di,
double upper, double min_step, double tol, const Res *r,
const Cmp *cmp) {
fprintf(f,
"%s,%s,%d,%.17g,%.6g,%.6g,%.6g,%d,%d,%u,%.17g,%u,%u,%lu,%.6g,"
"%.17g,%.17g,%.17g,%.17g,%.17g",
phase, c->name, di, c->theta[di], upper, min_step, tol, r->outcome,
r->reason, r->end_id, r->stop_t, r->steps, r->rejected, r->rhs,
r->wall, r->n[0], r->n[1], r->n[2], r->g, r->thr);
if (cmp->has_ref)
fprintf(f, ",%d,%.17g,%.17g,%.17g,%.17g,%.17g", cmp->class_match,
cmp->dn_ang, cmp->dlogg, cmp->dgrel, cmp->dstopT, cmp->dmargin);
else
fprintf(f, ",,nan,nan,nan,nan,nan");
fprintf(f, "\n");
}
static const char *ROW_HEADER =
"phase,case,dir,theta,upper,min_step,tol,outcome,reason,end_id,stop_t,"
"steps,rejected,rhs,wall_s,nx,ny,nz,g,thr,class_match,dn_ang,dlogg,dgrel,"
"dstopT,dmargin\n";
static void write_agg(FILE *f, const char *phase, const Case *c, double upper,
double min_step, double tol, const Agg *a) {
fprintf(f,
"%s,%s,%.6g,%.6g,%.6g,%ld,%ld,%.6g,%.6g,%.6g,%.6g,%.6g,%lu,%lu,%u,"
"%.4f,%ld,%ld,%ld,%ld\n",
phase, c->name, upper, min_step, tol, a->n, a->class_mismatch,
a->max_dn_ang, a->max_dlogg, a->max_dgrel, a->max_dstopT,
a->max_dmargin, a->sum_rhs, a->max_rhs, a->max_rejected, a->sum_wall,
a->escaped, a->dark, a->unresolved, a->incomplete);
}
static const char *AGG_HEADER =
"phase,case,upper,min_step,tol,n,class_mismatch,max_dn_ang,max_dlogg,"
"max_dgrel,max_dstopT,max_dmargin,sum_rhs,max_rhs,max_rejected,sum_wall,"
"escaped,dark,unresolved,incomplete\n";
/* ------------------------------------------------------------------ */
/* Case builders */
/* ------------------------------------------------------------------ */
static void dir_from_theta(double th, double n[3]) {
if (th == 0.0) {
n[0] = 1.0;
n[1] = n[2] = 0.0;
} else if (th == PI) {
n[0] = -1.0;
n[1] = n[2] = 0.0;
} else {
n[0] = cos(th);
n[1] = sin(th);
n[2] = 0.0;
}
const double nn = sqrt(dot3(n, n));
for (int i = 0; i < 3; ++i)
n[i] /= nn;
}
static void fill_static_dirs(Case *c, double r) {
const double tc = critical_angle(r);
const double th[MAX_DIRS] = {0.0, PI, PI / 2.0, tc,
tc - 1e-3, tc + 1e-3, tc - 1e-5, tc + 1e-5,
tc - 1e-7, tc + 1e-7, tc + 0.05, tc - 0.05};
c->n_dirs = 12;
for (int i = 0; i < c->n_dirs; ++i) {
c->theta[i] = th[i];
dir_from_theta(th[i], c->dirs[i]);
}
}
static void case_static(Case *c, const char *name, double r, double look_ra) {
memset(c, 0, sizeof *c);
snprintf(c->name, sizeof c->name, "%s", name);
c->prov = 0;
c->mass = 1.0;
c->escape_radius = 256.0;
c->look_ra_deg = look_ra;
c->look_dec_deg = 0.0;
c->position[0] = r;
c->position[1] = c->position[2] = 0.0;
c->velocity[0] = c->velocity[1] = c->velocity[2] = 0.0;
c->initial_step = 0.1;
c->lookback = 6553.6;
c->max_steps = 65536;
c->ref_max_steps = 65536;
c->max_step_for_min_scan = 2.0;
fill_static_dirs(c, r);
}
static void case_freefall(Case *c, const char *name, double r) {
memset(c, 0, sizeof *c);
snprintf(c->name, sizeof c->name, "%s", name);
c->prov = 0;
c->mass = 1.0;
c->escape_radius = 256.0;
c->look_ra_deg = 180.0;
c->look_dec_deg = 0.0;
c->position[0] = r;
c->position[1] = c->position[2] = 0.0;
/* Free-fall from rest at infinity, coordinate velocity dx/dt (the formula
* used by local/p2d_validation/observer_endpoints.c). */
const double y = sqrt(2.0 / r);
c->velocity[0] = -y * (1.0 + y) / (1.0 + y + y * y);
c->velocity[1] = c->velocity[2] = 0.0;
c->initial_step = 0.1;
c->lookback = 6553.6;
c->max_steps = 65536;
c->ref_max_steps = 65536;
c->max_step_for_min_scan = 2.0;
{
const double th[4] = {0.0, PI / 2.0, PI, 3.0 * PI / 4.0};
c->n_dirs = 4;
for (int i = 0; i < 4; ++i) {
c->theta[i] = th[i];
dir_from_theta(th[i], c->dirs[i]);
}
}
}
static void case_minkowski(Case *c) {
memset(c, 0, sizeof *c);
snprintf(c->name, sizeof c->name, "mink_moving");
c->prov = 1;
c->escape_radius = 64.0;
c->look_ra_deg = 0.0;
c->look_dec_deg = 0.0;
c->position[0] = 10.0;
c->position[1] = 20.0;
c->position[2] = -15.0;
c->velocity[0] = 0.3;
c->velocity[1] = 0.2;
c->velocity[2] = 0.1;
c->initial_step = 1.0;
c->lookback = 2048.0;
c->max_steps = 2048;
c->ref_max_steps = 4096;
c->max_step_for_min_scan = 16.0;
{
const double d[6][3] = {{1.0, 0.0, 0.0}, {-1.0, 0.0, 0.0},
{0.0, 1.0, 0.0}, {0.0, 0.0, 1.0},
{0.6, 0.8, 0.0}, {-0.6, 0.8, 0.0}};
c->n_dirs = 6;
for (int i = 0; i < 6; ++i) {
c->theta[i] = NAN;
for (int k = 0; k < 3; ++k)
c->dirs[i][k] = d[i][k];
}
}
}
static void case_alcubierre(Case *c, const char *name, double vs, double sigma) {
memset(c, 0, sizeof *c);
snprintf(c->name, sizeof c->name, "%s", name);
c->prov = 2;
c->alc_vs = vs;
c->alc_radius = 1.0;
c->alc_sigma = sigma;
c->look_ra_deg = 0.0;
c->look_dec_deg = 0.0;
c->position[0] = c->position[1] = c->position[2] = 0.0;
c->velocity[0] = vs; /* comoving with the bubble center */
c->velocity[1] = c->velocity[2] = 0.0;
c->initial_step = fmin(0.1, 0.05 / sigma);
c->max_steps = 100000;
c->ref_max_steps = 200000;
{
const double esc = spacetime_alcubierre_escape_radius(1.0, sigma);
c->lookback = 1.25 * 4.0 * esc / (1.0 - fabs(vs));
}
c->max_step_for_min_scan = c->initial_step * 8.0;
{
const double d[6][3] = {{1.0, 0.0, 0.0}, {-1.0, 0.0, 0.0},
{0.0, 1.0, 0.0}, {0.0, 0.0, 1.0},
{0.6, 0.8, 0.0}, {-0.6, 0.8, 0.0}};
c->n_dirs = 6;
for (int i = 0; i < 6; ++i) {
c->theta[i] = NAN;
for (int k = 0; k < 3; ++k)
c->dirs[i][k] = d[i][k];
}
}
}
/* ------------------------------------------------------------------ */
/* Source/observer construction */
/* ------------------------------------------------------------------ */
static int build_source(const Case *c, SpacetimeSource *s) {
if (c->prov == 0)
return spacetime_create_schwarzschild_ks(s, c->mass, c->escape_radius);
if (c->prov == 1)
return spacetime_create_minkowski(s, c->escape_radius);
return spacetime_create_alcubierre(s, c->alc_vs, c->alc_radius,
c->alc_sigma);
}
static int build_observer(const Case *c, const SpacetimeSource *s,
ObserverState *o) {
MetricData m;
if (spacetime_eval(s, 0.0, c->position, &m) != SPACETIME_POINT_OK)
return -1;
ObserverCamera cam;
memset(&cam, 0, sizeof cam);
cam.coordinate_time = 0.0;
for (int i = 0; i < 3; ++i) {
cam.position[i] = c->position[i];
cam.velocity[i] = c->velocity[i];
}
cam.look_ra_deg = c->look_ra_deg;
cam.look_dec_deg = c->look_dec_deg;
cam.roll_deg = 0.0;
return observer_from_coordinate_camera(&m, &cam, o, NULL) ==
OBSERVER_BUILD_OK
? 0
: -1;
}
/* ------------------------------------------------------------------ */
/* Generic scan driver */
/* ------------------------------------------------------------------ */
static void run_grid(const Case *cases, int ncases, const double *uppers,
int n_up, const double *floors, int n_fl, double tol,
const char *phase, const char *rows_path,
const char *agg_path, Res refs[][MAX_DIRS]) {
FILE *rf = fopen(rows_path, "w");
FILE *af = fopen(agg_path, "w");
if (!rf || !af) {
fprintf(stderr, "FATAL: cannot open %s / %s\n", rows_path, agg_path);
exit(2);
}
fprintf(rf, "%s", ROW_HEADER);
fprintf(af, "%s", AGG_HEADER);
for (int ci = 0; ci < ncases; ++ci) {
const Case *c = &cases[ci];
SpacetimeSource source;
ObserverState observer;
if (build_source(c, &source) || build_observer(c, &source, &observer)) {
fprintf(stderr, "FATAL: cannot build case %s\n", c->name);
exit(2);
}
for (int ui = 0; ui < n_up; ++ui) {
for (int fi = 0; fi < n_fl; ++fi) {
Agg agg;
agg_init(&agg);
for (int di = 0; di < c->n_dirs; ++di) {
const GeodesicTraceConfig cfg =
make_dp(c->initial_step, floors[fi], uppers[ui], tol, c->max_steps,
c->lookback);
const Res r = run_ray(&source, &observer, c->dirs[di], &cfg);
Cmp cmp;
compare(&r, &refs[ci][di], &cmp);
write_row(rf, phase, c, di, uppers[ui], floors[fi], tol, &r, &cmp);
agg_add(&agg, &r, &cmp);
}
write_agg(af, phase, c, uppers[ui], floors[fi], tol, &agg);
printf("SUMMARY %s %s upper=%.6g min=%.6g n=%ld mismatch=%ld "
"max_dn_ang=%.6g max_dgrel=%.6g max_dstopT=%.6g sum_rhs=%lu "
"esc=%ld dark=%ld unres=%ld inc=%ld wall=%.3fs\n",
phase, c->name, uppers[ui], floors[fi], agg.n,
agg.class_mismatch, agg.max_dn_ang, agg.max_dgrel,
agg.max_dstopT, agg.sum_rhs, agg.escaped, agg.dark,
agg.unresolved, agg.incomplete, agg.sum_wall);
fflush(stdout);
}
}
spacetime_destroy(&source);
}
fclose(rf);
fclose(af);
}
/* Compute DP tol=1e-12 reference for every direction of every case.
* upper_ref <= 0 means "use the case's own initial step" as the max_step. */
static void compute_refs(const Case *cases, int ncases, double upper_ref,
const char *path, Res refs[][MAX_DIRS]) {
FILE *f = fopen(path, "w");
if (!f) {
fprintf(stderr, "FATAL: cannot open %s\n", path);
exit(2);
}
fprintf(f, "%s", ROW_HEADER);
for (int ci = 0; ci < ncases; ++ci) {
const Case *c = &cases[ci];
SpacetimeSource source;
ObserverState observer;
if (build_source(c, &source) || build_observer(c, &source, &observer)) {
fprintf(stderr, "FATAL: cannot build case %s\n", c->name);
exit(2);
}
const double upper = (upper_ref > 0.0) ? upper_ref : c->initial_step;
for (int di = 0; di < c->n_dirs; ++di) {
const GeodesicTraceConfig cfg = make_dp(c->initial_step, 1e-12, upper,
1e-12, c->ref_max_steps,
c->lookback);
refs[ci][di] = run_ray(&source, &observer, c->dirs[di], &cfg);
Cmp none;
memset(&none, 0, sizeof none);
write_row(f, "ref", c, di, upper, 1e-12, 1e-12, &refs[ci][di], &none);
printf("REF %s dir=%d theta=%.6g outcome=%d reason=%d stop_t=%.9g "
"steps=%u rejected=%u rhs=%lu g=%.12g thr=%.12g\n",
c->name, di, c->theta[di], refs[ci][di].outcome,
refs[ci][di].reason, refs[ci][di].stop_t, refs[ci][di].steps,
refs[ci][di].rejected, refs[ci][di].rhs, refs[ci][di].g,
refs[ci][di].thr);
fflush(stdout);
}
spacetime_destroy(&source);
}
fclose(f);
}
/* ------------------------------------------------------------------ */
/* Sub-command: Schwarzschild */
/* ------------------------------------------------------------------ */
static void cmd_schwarzschild(void) {
static Case cases[MAX_CASES];
static Res refs[MAX_CASES][MAX_DIRS];
memset(refs, 0, sizeof refs);
int nc = 0;
case_static(&cases[nc++], "r30_inward", 30.0, 180.0);
case_static(&cases[nc++], "r100_inward", 100.0, 180.0);
case_static(&cases[nc++], "r2p1_outward", 2.1, 0.0);
case_freefall(&cases[nc++], "r1p5_freefall", 1.5);
compute_refs(cases, nc, 0.25, "raw/a_sch_reference.csv", refs);
static const double uppers[9] = {0.25, 0.5, 1.0, 2.0, 4.0,
8.0, 16.0, 32.0, 64.0};
static const double floors[10] = {1e-1, 1e-2, 1e-3, 1e-4, 1e-5,
1e-6, 1e-8, 1e-10, 1e-12, 1e-14};
run_grid(cases, nc, uppers, 9, (double[]){1e-12}, 1, 1e-9, "upper",
"raw/a_sch_upper.csv", "raw/a_sch_upper_summary.csv", refs);
run_grid(cases, nc, (double[]){2.0}, 1, floors, 10, 1e-9, "min",
"raw/a_sch_min.csv", "raw/a_sch_min_summary.csv", refs);
/* Sensitive-ray RK4 h-halving reference (extra independent check).
* (case index, dir index): r30 and r2.1, theta_c +- 1e-5 / +- 1e-7. */
const int sens[8][2] = {{0, 8}, {0, 9}, {0, 6}, {0, 7},
{2, 8}, {2, 9}, {2, 6}, {2, 7}};
FILE *f = fopen("raw/a_sch_rk4_sensitive.csv", "w");
if (!f) {
fprintf(stderr, "FATAL: cannot open rk4 csv\n");
exit(2);
}
fprintf(f, "%s", ROW_HEADER);
for (int k = 0; k < 8; ++k) {
const Case *c = &cases[sens[k][0]];
const int di = sens[k][1];
SpacetimeSource source;
ObserverState observer;
if (build_source(c, &source) || build_observer(c, &source, &observer)) {
fprintf(stderr, "FATAL: cannot build case %s\n", c->name);
exit(2);
}
GeodesicTraceConfig rk01 = make_rk4(0.01, 262144);
GeodesicTraceConfig rk005 = make_rk4(0.005, 262144);
Res r01 = run_ray(&source, &observer, c->dirs[di], &rk01);
Res r005 = run_ray(&source, &observer, c->dirs[di], &rk005);
Cmp hh, vsdp;
compare(&r005, &r01, &hh);
compare(&r005, &refs[sens[k][0]][di], &vsdp);
Cmp none;
memset(&none, 0, sizeof none);
write_row(f, "rk4_0.01", c, di, 0.01, 0.0, 0.0, &r01, &none);
write_row(f, "rk4_0.005", c, di, 0.005, 0.0, 0.0, &r005, &none);
printf("RK4 %s dir=%d theta=%.6g o01=%d/%d o005=%d/%d "
"hhalve_dn=%.6g hhalve_dgrel=%.6g vsdp_dn=%.6g vsdp_dgrel=%.6g "
"vsdp_class=%d\n",
c->name, di, c->theta[di], r01.outcome, r01.reason, r005.outcome,
r005.reason, hh.dn_ang, hh.dgrel, vsdp.dn_ang, vsdp.dgrel,
vsdp.class_match);
spacetime_destroy(&source);
}
fclose(f);
}
/* ------------------------------------------------------------------ */
/* Sub-command: Minkowski (analytic flat verification) */
/* ------------------------------------------------------------------ */
/* Analytic flat past escape from an observer at (t0,x0) with tetrad-frame
* direction n: coordinate photon velocity u = k_vec/k^0, crossing radius R at
* s = t-t0 < 0, sky direction n_inf = -u, frequency ratio g = 1/k^0. */
static int mink_analytic(const Case *c, const ObserverState *o,
const double n[3], double R, double *t_cross,
double *xc, double *ninf, double *g) {
double k[4];
for (int mu = 0; mu < 4; ++mu)
k[mu] = o->tetrad[0][mu];
for (int a = 0; a < 3; ++a)
for (int mu = 0; mu < 4; ++mu)
k[mu] -= n[a] * o->tetrad[a + 1][mu];
if (!(k[0] > 0.0))
return -1;
double u[3];
for (int i = 0; i < 3; ++i)
u[i] = k[i + 1] / k[0];
const double uu = dot3(u, u);
const double B = 2.0 * dot3(c->position, u);
const double C = dot3(c->position, c->position) - R * R;
const double disc = B * B - 4.0 * uu * C;
if (disc < 0.0)
return -1;
const double sq = sqrt(disc);
const double s1 = (-B + sq) / (2.0 * uu);
const double s2 = (-B - sq) / (2.0 * uu);
const double s = (s1 < 0.0) ? fmin(s1, s2) : s2;
if (!(s < 0.0))
return -1;
*t_cross = o->coordinate_time + s;
for (int i = 0; i < 3; ++i)
xc[i] = c->position[i] + u[i] * s;
const double nu = sqrt(uu);
for (int i = 0; i < 3; ++i)
ninf[i] = -u[i] / nu;
*g = 1.0 / k[0];
return 0;
}
static void cmd_minkowski(void) {
Case c;
case_minkowski(&c);
static Res refs[MAX_CASES][MAX_DIRS];
memset(refs, 0, sizeof refs);
SpacetimeSource source;
ObserverState observer;
if (build_source(&c, &source) || build_observer(&c, &source, &observer)) {
fprintf(stderr, "FATAL: cannot build minkowski case\n");
exit(2);
}
FILE *mf = fopen("raw/a_mink_analytic.csv", "w");
if (!mf) {
fprintf(stderr, "FATAL: cannot open analytic csv\n");
exit(2);
}
fprintf(mf,
"case,dir,upper,min_step,tol,outcome,stop_t,x_err,t_err,dn_ang,"
"dgrel,g_analytic,stop_t_analytic\n");
/* Reference: tol=1e-12, max_step = initial (1.0). */
const GeodesicTraceConfig refcfg =
make_dp(c.initial_step, 1e-12, c.initial_step, 1e-12, c.max_steps,
c.lookback);
for (int di = 0; di < c.n_dirs; ++di)
refs[0][di] = run_ray(&source, &observer, c.dirs[di], &refcfg);
static const double uppers[5] = {1.0, 4.0, 16.0, 64.0, 256.0};
static const double floors[3] = {1e-1, 1e-6, 1e-12};
for (int ui = 0; ui < 5; ++ui) {
for (int fi = 0; fi < 3; ++fi) {
Agg agg;
agg_init(&agg);
for (int di = 0; di < c.n_dirs; ++di) {
const GeodesicTraceConfig cfg =
make_dp(c.initial_step, floors[fi], uppers[ui], 1e-9, c.max_steps,
c.lookback);
const Res r = run_ray(&source, &observer, c.dirs[di], &cfg);
Cmp cmp;
compare(&r, &refs[0][di], &cmp);
agg_add(&agg, &r, &cmp);
double t_an, x_an[3], n_an[3], g_an;
const int ok = mink_analytic(&c, &observer, c.dirs[di], c.escape_radius,
&t_an, x_an, n_an, &g_an);
double x_err = NAN, t_err = NAN, dn_an = NAN, dg_an = NAN;
if (ok == 0 && is_escaped(r.outcome)) {
/* Crossing position is checked through the direct trace in
* a_mink_analytic_x.csv; here compare sky direction, g and time. */
t_err = fabs(r.stop_t - t_an);
dn_an = ang_delta(r.n, n_an);
if (r.g > 0.0 && g_an > 0.0)
dg_an = fabs(r.g / g_an - 1.0);
}
fprintf(mf,
"%s,%d,%.6g,%.6g,%.6g,%d,%.17g,%.17g,%.17g,%.17g,%.17g,%.17g,"
"%.17g\n",
c.name, di, uppers[ui], floors[fi], 1e-9, r.outcome, r.stop_t,
x_err, t_err, dn_an, dg_an, g_an, t_an);
}
printf("SUMMARY mink upper=%.6g min=%.6g n=%ld mismatch=%ld "
"max_dn_ang=%.6g max_dgrel=%.6g sum_rhs=%lu esc=%ld dark=%ld "
"unres=%ld inc=%ld\n",
uppers[ui], floors[fi], agg.n, agg.class_mismatch,
agg.max_dn_ang, agg.max_dgrel, agg.sum_rhs, agg.escaped, agg.dark,
agg.unresolved, agg.incomplete);
fflush(stdout);
}
}
/* Direct endpoint check for the crossing position (x) on a few configs. */
FILE *xf = fopen("raw/a_mink_analytic_x.csv", "w");
if (!xf) {
fprintf(stderr, "FATAL: cannot open analytic x csv\n");
exit(2);
}
fprintf(xf, "case,dir,upper,min_step,tol,outcome,x_err_x,x_err_y,x_err_z,"
"t_err\n");
for (int ui = 0; ui < 5; ++ui) {
for (int fi = 0; fi < 3; ++fi) {
for (int di = 0; di < c.n_dirs; ++di) {
const GeodesicTraceConfig cfg =
make_dp(c.initial_step, floors[fi], uppers[ui], 1e-9, c.max_steps,
c.lookback);
const RayEndpoint e =
geodesic_trace_past(&source, &observer, c.dirs[di], &cfg);
++g_rays;
double t_an, x_an[3], n_an[3], g_an;
const int ok = mink_analytic(&c, &observer, c.dirs[di], c.escape_radius,
&t_an, x_an, n_an, &g_an);
double ex = NAN, ey = NAN, ez = NAN, te = NAN;
if (ok == 0 && e.outcome == RAY_OUTCOME_ESCAPED) {
ex = fabs(e.final_x[0] - x_an[0]);
ey = fabs(e.final_x[1] - x_an[1]);
ez = fabs(e.final_x[2] - x_an[2]);
te = fabs(e.stop_coordinate_time - t_an);
}
fprintf(xf, "%s,%d,%.6g,%.6g,%.6g,%d,%.17g,%.17g,%.17g,%.17g\n",
c.name, di, uppers[ui], floors[fi], 1e-9, e.outcome, ex, ey, ez,
te);
}
}
}
fclose(xf);
fclose(mf);
spacetime_destroy(&source);
}
/* ------------------------------------------------------------------ */
/* Sub-command: Alcubierre */
/* ------------------------------------------------------------------ */
static void cmd_alcubierre(void) {
static Case cases[MAX_CASES];
static Res refs[MAX_CASES][MAX_DIRS];
memset(refs, 0, sizeof refs);
int nc = 0;
case_alcubierre(&cases[nc++], "alc_v3_s1", 0.3, 1.0);
case_alcubierre(&cases[nc++], "alc_v3_s10", 0.3, 10.0);
case_alcubierre(&cases[nc++], "alc_v9_s1", 0.9, 1.0);
case_alcubierre(&cases[nc++], "alc_v9_s10", 0.9, 10.0);
case_alcubierre(&cases[nc++], "alc_v9_s100", 0.9, 100.0);
compute_refs(cases, nc, -1.0, "raw/a_alc_reference.csv", refs);
/* Standard grid: upper = initial*{1,4,8,16,32,64}, floor {1e-4,1e-8,1e-12}. */
{
static const double floors[3] = {1e-4, 1e-8, 1e-12};
Case sub[4];
for (int i = 0; i < 4; ++i)
sub[i] = cases[i];
/* run_grid uses one upper array for all cases, so use per-case initial by
* calling run_grid four times. */
for (int i = 0; i < 4; ++i) {
char rp[128], ap[128];
snprintf(rp, sizeof rp, "raw/a_alc_%.31s_upper.csv", sub[i].name);
snprintf(ap, sizeof ap, "raw/a_alc_%.31s_upper_summary.csv", sub[i].name);
const double base = sub[i].initial_step;
const double up[6] = {base, 4 * base, 8 * base,
16 * base, 32 * base, 64 * base};
run_grid(&sub[i], 1, up, 6, floors, 3, 1e-9, "upper", rp, ap, &refs[i]);
}
}
/* Focused lower-bound stress: vs=.9, sigma=100, upper = initial*8 = 0.004,
* floors {1e-4,1e-5,1e-6,1e-8,1e-12,1e-14}. */
{
const Case *c = &cases[4];
const double up[1] = {c->initial_step * 8.0};
const double floors[6] = {1e-4, 1e-5, 1e-6, 1e-8, 1e-12, 1e-14};
run_grid(c, 1, up, 1, floors, 6, 1e-9, "min_stress",
"raw/a_alc_v9_s100_min.csv", "raw/a_alc_v9_s100_min_summary.csv",
&refs[4]);
}
}
/* ------------------------------------------------------------------ */
int main(int argc, char **argv) {
if (argc < 2) {
fprintf(stderr,
"usage: %s schwarzschild|minkowski|alcubierre\n",
argv[0]);
return 1;
}
if (!strcmp(argv[1], "schwarzschild"))
cmd_schwarzschild();
else if (!strcmp(argv[1], "minkowski"))
cmd_minkowski();
else if (!strcmp(argv[1], "alcubierre"))
cmd_alcubierre();
else {
fprintf(stderr, "unknown sub-command %s\n", argv[1]);
return 1;
}
printf("TOTAL_RAYS %ld\n", g_rays);
return 0;
}
@@ -0,0 +1,404 @@
/*
* Experiment B: observed accepted-step sizes of the production DP54 core.
*
* This translation unit textually includes src/geodesic.c so the real,
* production `dp_advance_one` driver and the real `State` (GeodesicRayState)
* are exercised directly on a finite trajectory interval. The production
* initialization is reproduced exactly as `geodesic_trace_past` does for an
* INSIDE route: `geodesic_initialize_past_ray_metric` at the camera event,
* then `next_step = config->coordinate_time_step` (the init already sets
* `integration_start_time`, `log_alpha_p0` and `log_alpha_p0_0`). This is the
* same initialization the public endpoint uses, not a re-implementation.
*
* For each selected ray we:
* 1. run the public endpoint with tol=1e-12 to get a trusted reference
* stop time and terminal class (physical terminal class is owned by A);
* 2. integrate the same ray with the production DP core up to
* T = min(20, ref_span) observed steps <= 2000, recording each accepted
* step magnitude, boundary-limit flag, rejection/RHS deltas and the null
* residual gamma^{ij} Pi_i Pi_j - 1.
*
* Link line (geodesic.c is textually included, so it is NOT linked; the
* analytic backends are also textually included here):
* cc -std=c11 -O2 -Isrc b_actual_h.c asymptotic.c asymptotic_schwarzschild.c \
* spacetime_common.c observer.c -lm
*/
#define _POSIX_C_SOURCE 200809L
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define spacetime_create_default spacetime_create_default_minkowski_b
#include "../../src/spacetime_minkowski.c"
#undef spacetime_create_default
#define spacetime_create_default spacetime_create_default_schwarzschild_b
#include "../../src/spacetime_schwarzschild.c"
#undef spacetime_create_default
#define spacetime_create_default spacetime_create_default_alcubierre_b
#include "../../src/spacetime_alcubierre.c"
#undef spacetime_create_default
/* The production geodesic core, textually included. Its static State,
* dp_advance_one and invert become visible to the code below. */
#include "../../src/geodesic.c"
#define PI 3.14159265358979323846
#define MAX_BCASES 12
#define MAX_BDIRS 8
#define MAX_OBS_STEPS 2000
typedef struct {
char name[32];
int prov; /* 0 sch, 1 mink, 2 alc */
double mass, esc;
double vs, radius, sigma;
double look_ra_deg, look_dec_deg;
double pos[3], vel[3];
double initial, max_step;
double ref_max_step, lookback;
unsigned int ref_max_steps;
int ndirs;
double dirs[MAX_BDIRS][3];
} BCase;
static double b_now(void) {
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return (double)ts.tv_sec + 1e-9 * (double)ts.tv_nsec;
}
static void b_dir(double th, double n[3]) {
if (th == 0.0) {
n[0] = 1.0;
n[1] = n[2] = 0.0;
} else if (th == PI) {
n[0] = -1.0;
n[1] = n[2] = 0.0;
} else {
n[0] = cos(th);
n[1] = sin(th);
n[2] = 0.0;
}
const double nn = sqrt(n[0] * n[0] + n[1] * n[1] + n[2] * n[2]);
for (int i = 0; i < 3; ++i)
n[i] /= nn;
}
static double b_critical_angle(double r) {
const double b = 3.0 * sqrt(3.0) * sqrt(1.0 - 2.0 / r) / r;
return (b < 1.0) ? asin(b) : PI / 2.0;
}
static GeodesicTraceConfig b_make_dp(double initial, double min_step,
double max_step, double tol,
unsigned int max_steps, double lookback) {
GeodesicTraceConfig c;
memset(&c, 0, sizeof c);
c.coordinate_time_step = initial;
c.max_steps = max_steps;
c.threshold.kind = THRESHOLD_LOG_ENERGY_GROWTH;
c.threshold.value = 8.0;
c.threshold.policy_version = 3;
c.stepper = GEODESIC_STEPPER_DP54;
c.atol_x = c.atol_Pi = c.atol_L = c.rtol = tol;
c.min_step = min_step;
c.max_step = max_step;
c.consecutive_rejection_limit = 32;
c.max_lookback_time = lookback;
return c;
}
static int b_build_source(const BCase *c, SpacetimeSource *s) {
if (c->prov == 0)
return spacetime_create_schwarzschild_ks(s, c->mass, c->esc);
if (c->prov == 1)
return spacetime_create_minkowski(s, c->esc);
return spacetime_create_alcubierre(s, c->vs, c->radius, c->sigma);
}
static int b_build_observer(const BCase *c, const SpacetimeSource *s,
ObserverState *o) {
MetricData m;
if (spacetime_eval(s, 0.0, c->pos, &m) != SPACETIME_POINT_OK)
return -1;
ObserverCamera cam;
memset(&cam, 0, sizeof cam);
for (int i = 0; i < 3; ++i) {
cam.position[i] = c->pos[i];
cam.velocity[i] = c->vel[i];
}
cam.look_ra_deg = c->look_ra_deg;
cam.look_dec_deg = c->look_dec_deg;
return observer_from_coordinate_camera(&m, &cam, o, NULL) ==
OBSERVER_BUILD_OK
? 0
: -1;
}
static void b_add_sch(BCase *c, const char *name, double r, double look,
const double *thetas, int nt) {
memset(c, 0, sizeof *c);
snprintf(c->name, sizeof c->name, "%s", name);
c->prov = 0;
c->mass = 1.0;
c->esc = 256.0;
c->look_ra_deg = look;
c->pos[0] = r;
c->initial = 0.1;
c->max_step = 2.0;
c->ref_max_step = 0.25;
c->lookback = 6553.6;
c->ref_max_steps = 65536;
c->ndirs = nt;
for (int i = 0; i < nt; ++i)
b_dir(thetas[i], c->dirs[i]);
}
static void b_add_mink(BCase *c) {
memset(c, 0, sizeof *c);
snprintf(c->name, sizeof c->name, "mink_moving");
c->prov = 1;
c->esc = 64.0;
c->look_ra_deg = 0.0;
c->pos[0] = 10.0;
c->pos[1] = 20.0;
c->pos[2] = -15.0;
c->vel[0] = 0.3;
c->vel[1] = 0.2;
c->vel[2] = 0.1;
c->initial = 1.0;
c->max_step = 16.0;
c->ref_max_step = 1.0;
c->lookback = 2048.0;
c->ref_max_steps = 4096;
c->ndirs = 2;
b_dir(0.0, c->dirs[0]);
b_dir(PI, c->dirs[1]);
}
static void b_add_alc(BCase *c, const char *name, double vs, double sigma,
const double *thetas, int nt) {
memset(c, 0, sizeof *c);
snprintf(c->name, sizeof c->name, "%s", name);
c->prov = 2;
c->vs = vs;
c->radius = 1.0;
c->sigma = sigma;
c->look_ra_deg = 0.0;
c->vel[0] = vs;
c->initial = fmin(0.1, 0.05 / sigma);
c->max_step = c->initial * 8.0;
c->ref_max_step = c->initial;
const double esc = spacetime_alcubierre_escape_radius(1.0, sigma);
c->lookback = 1.25 * 4.0 * esc / (1.0 - fabs(vs));
c->ref_max_steps = 200000;
c->ndirs = nt;
for (int i = 0; i < nt; ++i)
b_dir(thetas[i], c->dirs[i]);
}
/* gamma^{ij} Pi_i Pi_j - 1; `invert` is the production static from
* geodesic.c, so this is the exact production metric contraction. */
static double b_null_residual(const MetricData *m, const double Pi[3]) {
double g[3][3], inv[3][3];
for (int i = 0; i < 3; ++i)
for (int j = 0; j < 3; ++j)
g[i][j] = m->gamma[i][j];
if (invert(g, inv))
return NAN;
double v = 0.0;
for (int i = 0; i < 3; ++i)
for (int j = 0; j < 3; ++j)
v += inv[i][j] * Pi[i] * Pi[j];
return v - 1.0;
}
int main(void) {
static BCase cases[MAX_BCASES];
int nc = 0;
{
const double tc = b_critical_angle(30.0);
const double th[6] = {0.0, PI, tc - 1e-7, tc + 1e-7, tc - 1e-5, tc + 1e-5};
b_add_sch(&cases[nc++], "r30_inward", 30.0, 180.0, th, 6);
}
{
const double tc = b_critical_angle(100.0);
const double th[4] = {0.0, PI, tc, tc - 1e-7};
b_add_sch(&cases[nc++], "r100_inward", 100.0, 180.0, th, 4);
}
{
const double tc = b_critical_angle(2.1);
const double th[5] = {0.0, tc, tc - 1e-7, tc + 1e-7, PI};
b_add_sch(&cases[nc++], "r2p1_outward", 2.1, 0.0, th, 5);
}
{
const double th[2] = {0.0, PI};
b_add_sch(&cases[nc++], "r1p5_freefall", 1.5, 180.0, th, 2);
/* free-fall velocity is set below (b_add_sch leaves it zero). */
}
b_add_mink(&cases[nc++]);
{
const double th[2] = {0.0, PI};
b_add_alc(&cases[nc++], "alc_v3_s1", 0.3, 1.0, th, 2);
b_add_alc(&cases[nc++], "alc_v9_s10", 0.9, 10.0, th, 2);
b_add_alc(&cases[nc++], "alc_v9_s100", 0.9, 100.0, th, 2);
}
/* Free-fall coordinate velocity for r1.5 (same formula as A). */
{
BCase *c = &cases[3];
const double y = sqrt(2.0 / c->pos[0]);
c->vel[0] = -y * (1.0 + y) / (1.0 + y + y * y);
}
FILE *hf = fopen("raw/b_actual_h.csv", "w");
FILE *sf = fopen("raw/b_summary.csv", "w");
if (!hf || !sf) {
fprintf(stderr, "FATAL: cannot open b csv\n");
return 2;
}
fprintf(hf, "case,dir,step,t,h,boundary_limited,rhs_delta,reject_delta,"
"null_residual\n");
fprintf(sf, "case,dir,ref_outcome,ref_stop_t,span,target,observed_steps,"
"reached_target,terminated_reason,h_min,h_max,h_first,h_last,"
"boundary_steps,sum_rhs,sum_reject,max_reject_delta,"
"null_residual_max,final_t,wall_s\n");
long total_steps = 0;
for (int ci = 0; ci < nc; ++ci) {
BCase *c = &cases[ci];
SpacetimeSource source;
ObserverState observer;
if (b_build_source(c, &source) || b_build_observer(c, &source, &observer)) {
fprintf(stderr, "FATAL: cannot build B case %s\n", c->name);
return 2;
}
for (int di = 0; di < c->ndirs; ++di) {
/* 1. trusted reference via the public endpoint (physical terminal). */
GeodesicTraceConfig refcfg =
b_make_dp(c->initial, 1e-12, c->ref_max_step, 1e-12, c->ref_max_steps,
c->lookback);
RayEndpoint ref =
geodesic_trace_past(&source, &observer, c->dirs[di], &refcfg);
const double span =
isfinite(ref.stop_coordinate_time)
? (observer.coordinate_time - ref.stop_coordinate_time)
: 20.0;
const double finite_T = fmin(20.0, span > 0.0 ? span : 20.0);
const double target = observer.coordinate_time - finite_T;
/* 2. production-exact INSIDE-route initialization. */
MetricData metric;
if (spacetime_eval(&source, observer.coordinate_time,
observer.coordinate_position, &metric) !=
SPACETIME_POINT_OK) {
fprintf(stderr, "FATAL: camera metric %s\n", c->name);
return 2;
}
State st;
if (geodesic_initialize_past_ray_metric(&metric, &observer, c->dirs[di],
&st)) {
fprintf(stderr, "FATAL: init %s dir %d\n", c->name, di);
return 2;
}
GeodesicTraceConfig cfg =
b_make_dp(c->initial, 1e-12, c->max_step, 1e-9, 0u, 0.0);
st.next_step = cfg.coordinate_time_step;
MetricSlab *slab = NULL;
if (spacetime_load_slab(&source, st.coordinate_time, target - 1.0,
&slab)) {
fprintf(stderr, "FATAL: slab %s dir %d\n", c->name, di);
return 2;
}
double h_min = INFINITY, h_max = 0.0, h_first = NAN, h_last = NAN;
double null_max = 0.0, sum_wall = 0.0;
unsigned long sum_rhs = 0;
unsigned int sum_rej = 0, max_rej_delta = 0, boundary_steps = 0;
int reached = 0, terminated_reason = -1;
int step_index = 0;
const double start_wall = b_now();
while (st.coordinate_time > target && step_index < MAX_OBS_STEPS) {
const double before_t = st.coordinate_time;
unsigned long rhs = st.rhs_evaluations;
unsigned int rej = st.rejected_steps;
RayReason reason = RAY_REASON_INTEGRATION_ERROR;
const int rc =
dp_advance_one(slab, &cfg, &st, target, &reason, &rhs, &rej, NULL);
const unsigned long rhs_delta = rhs - st.rhs_evaluations;
const unsigned int rej_delta = rej - st.rejected_steps;
st.rhs_evaluations = rhs;
st.rejected_steps = rej;
sum_rhs += rhs_delta;
sum_rej += rej_delta;
if (rej_delta > max_rej_delta)
max_rej_delta = rej_delta;
if (rc) {
terminated_reason = (int)reason;
break;
}
const double h = before_t - st.coordinate_time;
const int boundary = (st.coordinate_time == target);
if (boundary)
++boundary_steps;
if (h < h_min)
h_min = h;
if (h > h_max)
h_max = h;
if (step_index == 0)
h_first = h;
h_last = h;
++step_index;
MetricData m;
double nr = NAN;
if (spacetime_slab_eval(slab, st.coordinate_time, st.x, &m) ==
SPACETIME_POINT_OK)
nr = b_null_residual(&m, st.Pi);
if (isfinite(nr) && fabs(nr) > null_max)
null_max = fabs(nr);
fprintf(hf, "%s,%d,%d,%.17g,%.17g,%d,%lu,%u,%.6g\n", c->name, di,
step_index, st.coordinate_time, h, boundary, rhs_delta,
rej_delta, nr);
if (st.coordinate_time <= target)
reached = 1;
}
sum_wall = b_now() - start_wall;
if (step_index >= MAX_OBS_STEPS)
reached = 0;
if (!isfinite(h_first)) {
h_first = NAN;
h_max = NAN;
}
if (!isfinite(h_min) || h_min == INFINITY)
h_min = NAN;
if (h_last < 0.0)
h_last = NAN;
fprintf(sf,
"%s,%d,%d,%.17g,%.17g,%.17g,%d,%d,%d,%.17g,%.17g,%.17g,%.17g,"
"%u,%lu,%u,%u,%.6g,%.17g,%.6g\n",
c->name, di, ref.outcome, ref.stop_coordinate_time, span, target,
step_index, reached, terminated_reason, h_min, h_max, h_first,
h_last, boundary_steps, sum_rhs, sum_rej, max_rej_delta, null_max,
st.coordinate_time, sum_wall);
printf("B %s dir=%d ref=%d refstop=%.9g span=%.6g T=%.6g target=%.6g "
"steps=%d reached=%d term=%d h=[%.6g,%.6g] first=%.6g last=%.6g "
"boundary=%u rhs=%lu rej=%u nullmax=%.3g final_t=%.9g wall=%.4fs\n",
c->name, di, ref.outcome, ref.stop_coordinate_time, span, finite_T,
target, step_index, reached, terminated_reason, h_min, h_max,
h_first, h_last, boundary_steps, sum_rhs, sum_rej, null_max,
st.coordinate_time, sum_wall);
fflush(stdout);
total_steps += step_index;
spacetime_free_slab(slab);
}
spacetime_destroy(&source);
}
fclose(hf);
fclose(sf);
printf("TOTAL_OBSERVED_STEPS %ld\n", total_steps);
return 0;
}
@@ -0,0 +1,341 @@
/*
* Standalone critical-classification reference check.
*
* Three static Schwarzschild cameras (M=1, escape sphere 256):
* r30 look 180 (inward), r100 look 180 (inward), r2.1 look 0 (outward),
* each aimed at theta_crit exactly and at theta_crit +- 1e-7, where
* theta_crit = asin(3 sqrt(3) sqrt(1 - 2/r) / r)
* is the local tetrad angle from the camera forward direction.
*
* For every direction four DP54 configs are run (initial step 0.1,
* min_step 1e-14, max_steps 65536, max_lookback_time 6553.6, reject limit 32,
* camera-relative dark threshold 8):
*
* ref_tol1e-12_h0.25 tol 1e-12, max_step 0.25
* ref_tol1e-13_h0.125 tol 1e-13, max_step 0.125
* tol1e-11_h2 tol 1e-11, max_step 2
* tol1e-11_h8 tol 1e-11, max_step 8
*
* Total 3 cameras * 3 directions * 4 configs = 36 endpoint traces.
*
* Raw per-run rows go to raw/critical_ref.csv; stdout prints, for all nine
* directions, ref_vs_tighter / h2_vs_h8 / ref_vs_h2 / ref_vs_h8 comparisons
* (outcome/reason/end, sky angle, relative g, dark stop-time and threshold
* shifts) and a NEIGHBOR_REFERENCE_CHECK that verifies the two reference
* tiers agree at the +-1e-7 neighbours. The exactly-critical direction is a
* separatrix: a class flip or a large direction/stop-time difference there is
* reported as EXACT_CRITICAL_REFERENCE_NOT_CONVERGED and is diagnostic only.
*
* Exit status: 0 when the neighbours' reference tiers agree and no neighbour
* returned an error/unresolved endpoint or a zero-step trace; 1 when a
* neighbour reference check fails; 2 on setup error. The exact-critical
* separatrix is never an assertion.
*
* Link line (the Schwarzschild backend is textually included):
* cc -std=c11 -O2 -Isrc critical_ref_check.c geodesic.c asymptotic.c \
* asymptotic_schwarzschild.c spacetime_common.c observer.c -lm
*/
#define _POSIX_C_SOURCE 200809L
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../../src/spacetime_schwarzschild.c"
#include "geodesic.h"
#include "observer.h"
#include "spacetime.h"
#define PI 3.14159265358979323846
typedef struct {
const char *name;
double tol;
double max_step;
} CfgDef;
static const CfgDef cfgs[4] = {
{"ref_tol1e-12_h0.25", 1e-12, 0.25},
{"ref_tol1e-13_h0.125", 1e-13, 0.125},
{"tol1e-11_h2", 1e-11, 2.0},
{"tol1e-11_h8", 1e-11, 8.0},
};
typedef struct {
const char *name;
double r;
double look_ra_deg;
} CamDef;
static const CamDef cams[3] = {
{"r30_inward", 30.0, 180.0},
{"r100_inward", 100.0, 180.0},
{"r2p1_outward", 2.1, 0.0},
};
typedef struct {
int outcome, reason;
unsigned int end_id;
double stop_t, g, thr;
double L, L0;
double n[3];
unsigned int steps, rejected;
unsigned long rhs;
} Res;
static double b_dot3(const double a[3], const double b[3]) {
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
}
static double b_ang_delta(const double a[3], const double b[3]) {
const double na = sqrt(b_dot3(a, a)), nb = sqrt(b_dot3(b, b));
if (!(na > 0.0) || !(nb > 0.0))
return NAN;
const double cross[3] = {a[1] * b[2] - a[2] * b[1],
a[2] * b[0] - a[0] * b[2],
a[0] * b[1] - a[1] * b[0]};
return atan2(sqrt(b_dot3(cross, cross)) / (na * nb),
b_dot3(a, b) / (na * nb));
}
static double critical_angle(double r) {
const double b = 3.0 * sqrt(3.0) * sqrt(1.0 - 2.0 / r) / r;
return (b < 1.0) ? asin(b) : PI / 2.0;
}
static void dir_from_theta(double th, double n[3]) {
n[0] = cos(th);
n[1] = sin(th);
n[2] = 0.0;
const double nn = sqrt(b_dot3(n, n));
for (int i = 0; i < 3; ++i)
n[i] /= nn;
}
static GeodesicTraceConfig make_cfg(const CfgDef *d) {
GeodesicTraceConfig c;
memset(&c, 0, sizeof c);
c.coordinate_time_step = 0.1;
c.max_steps = 65536;
c.threshold.kind = THRESHOLD_LOG_ENERGY_GROWTH;
c.threshold.value = 8.0;
c.threshold.policy_version = 3;
c.stepper = GEODESIC_STEPPER_DP54;
c.atol_x = c.atol_Pi = c.atol_L = c.rtol = d->tol;
c.min_step = 1e-14;
c.max_step = d->max_step;
c.consecutive_rejection_limit = 32;
c.max_lookback_time = 6553.6;
return c;
}
static int build_observer(const CamDef *cam, const SpacetimeSource *s,
ObserverState *o) {
const double pos[3] = {cam->r, 0.0, 0.0};
MetricData m;
if (spacetime_eval(s, 0.0, pos, &m) != SPACETIME_POINT_OK)
return -1;
ObserverCamera camera;
memset(&camera, 0, sizeof camera);
camera.position[0] = pos[0];
camera.position[1] = pos[1];
camera.position[2] = pos[2];
camera.look_ra_deg = cam->look_ra_deg;
camera.look_dec_deg = 0.0;
return observer_from_coordinate_camera(&m, &camera, o, NULL) ==
OBSERVER_BUILD_OK
? 0
: -1;
}
static Res run_one(const SpacetimeSource *s, const ObserverState *o,
const double dir[3], const GeodesicTraceConfig *cfg) {
Res r;
memset(&r, 0, sizeof r);
const RayEndpoint e = geodesic_trace_past(s, o, dir, cfg);
r.outcome = e.outcome;
r.reason = e.reason;
r.end_id = e.end_id;
r.stop_t = e.stop_coordinate_time;
r.g = e.frequency_ratio;
r.thr = e.threshold_value;
r.L = e.final_log_alpha_p0;
r.L0 = e.final_log_alpha_p0_0;
for (int i = 0; i < 3; ++i)
r.n[i] = e.n_infinity[i];
r.steps = e.accepted_steps;
r.rejected = e.rejected_steps;
r.rhs = e.rhs_evaluations;
return r;
}
static const char *outcome_name(int o) {
switch (o) {
case RAY_OUTCOME_ESCAPED:
return "ESC";
case RAY_OUTCOME_DARK:
return "DARK";
case RAY_OUTCOME_UNRESOLVED:
return "UNRES";
default:
return "INC";
}
}
static void print_pair(const char *cam, int di, double theta, const char *pn,
const Res *a, const Res *b) {
const int same = a->outcome == b->outcome && a->reason == b->reason &&
a->end_id == b->end_id;
const int esc = a->outcome == RAY_OUTCOME_ESCAPED &&
b->outcome == RAY_OUTCOME_ESCAPED;
const double dn = esc ? b_ang_delta(a->n, b->n) : NAN;
const double dg =
(esc && a->g > 0.0 && b->g > 0.0) ? fabs(a->g / b->g - 1.0) : NAN;
const double dstop =
(isfinite(a->stop_t) && isfinite(b->stop_t)) ? a->stop_t - b->stop_t
: NAN;
const double dthr = (isfinite(a->thr) && isfinite(b->thr))
? a->thr - b->thr
: NAN;
printf("CAPAIR camera=%s dir=%d theta=%.17g pair=%s class=%s/%s same=%d "
"dn_ang=%.17g dgrel=%.17g dstop_t=%.17g dthr=%.17g end=%u/%u\n",
cam, di, theta, pn, outcome_name(a->outcome), outcome_name(b->outcome),
same, dn, dg, dstop, dthr, a->end_id, b->end_id);
}
/* A two-reference-tier agreement check for one neighbour direction. Returns
* 1 when the pair is a valid, agreeing ESC/DARK reference, 0 otherwise. */
static int neighbour_reference_check(const char *cam, int di, double theta,
const Res *a, const Res *b) {
const int class_same = a->outcome == b->outcome && a->reason == b->reason &&
a->end_id == b->end_id;
const int clean = (a->outcome == RAY_OUTCOME_ESCAPED ||
a->outcome == RAY_OUTCOME_DARK) &&
(b->outcome == RAY_OUTCOME_ESCAPED ||
b->outcome == RAY_OUTCOME_DARK);
const int stepped = a->steps > 0 && b->steps > 0;
const int esc = a->outcome == RAY_OUTCOME_ESCAPED &&
b->outcome == RAY_OUTCOME_ESCAPED;
const double dn = esc ? b_ang_delta(a->n, b->n) : NAN;
const double dg =
(esc && a->g > 0.0 && b->g > 0.0) ? fabs(a->g / b->g - 1.0) : NAN;
const double dstop =
(isfinite(a->stop_t) && isfinite(b->stop_t)) ? a->stop_t - b->stop_t
: NAN;
printf("NEIGHBOR_REFERENCE_CHECK camera=%s dir=%d theta=%.17g "
"ref_class0=%s/%d/%u ref_class1=%s/%d/%u same=%d clean=%d stepped=%d "
"dn_ang=%.17g dgrel=%.17g dstop_t=%.17g\n",
cam, di, theta, outcome_name(a->outcome), a->reason, a->end_id,
outcome_name(b->outcome), b->reason, b->end_id, class_same, clean,
stepped, dn, dg, dstop);
return class_same && clean && stepped;
}
int main(void) {
SpacetimeSource source;
if (spacetime_create_schwarzschild_ks(&source, 1.0, 256.0)) {
fprintf(stderr, "FATAL: cannot create Schwarzschild source\n");
return 2;
}
FILE *f = fopen("raw/critical_ref.csv", "w");
if (!f) {
fprintf(stderr, "FATAL: cannot open raw/critical_ref.csv\n");
return 2;
}
fprintf(f, "camera,dir,theta,cfg,outcome,reason,end_id,stop_t,steps,"
"rejected,rhs,nx,ny,nz,g,thr,L,L0\n");
Res res[3][3][4];
double thetas[3][3];
for (int ci = 0; ci < 3; ++ci) {
ObserverState observer;
if (build_observer(&cams[ci], &source, &observer)) {
fprintf(stderr, "FATAL: cannot build observer %s\n", cams[ci].name);
return 2;
}
const double tc = critical_angle(cams[ci].r);
const double th[3] = {tc - 1e-7, tc, tc + 1e-7};
for (int di = 0; di < 3; ++di) {
double dir[3];
dir_from_theta(th[di], dir);
thetas[ci][di] = th[di];
for (int fi = 0; fi < 4; ++fi) {
const GeodesicTraceConfig cfg = make_cfg(&cfgs[fi]);
const Res r = run_one(&source, &observer, dir, &cfg);
res[ci][di][fi] = r;
fprintf(f, "%s,%d,%.17g,%s,%d,%d,%u,%.17g,%u,%u,%lu,%.17g,%.17g,"
"%.17g,%.17g,%.17g,%.17g,%.17g\n",
cams[ci].name, di, th[di], cfgs[fi].name, r.outcome, r.reason,
r.end_id, r.stop_t, r.steps, r.rejected, r.rhs, r.n[0], r.n[1],
r.n[2], r.g, r.thr, r.L, r.L0);
printf("RAW camera=%s dir=%d theta=%.17g cfg=%s outcome=%d reason=%d "
"end=%u stop_t=%.17g steps=%u rejected=%u rhs=%lu g=%.17g "
"thr=%.17g L=%.17g L0=%.17g nx=%.17g ny=%.17g nz=%.17g\n",
cams[ci].name, di, th[di], cfgs[fi].name, r.outcome, r.reason,
r.end_id, r.stop_t, r.steps, r.rejected, r.rhs, r.g, r.thr, r.L,
r.L0, r.n[0], r.n[1], r.n[2]);
fflush(stdout);
}
}
}
fclose(f);
/* All nine directions: ref_vs_tighter, h2_vs_h8, ref_vs_h2, ref_vs_h8. */
for (int ci = 0; ci < 3; ++ci) {
for (int di = 0; di < 3; ++di) {
print_pair(cams[ci].name, di, thetas[ci][di], "ref_vs_tighter",
&res[ci][di][0], &res[ci][di][1]);
print_pair(cams[ci].name, di, thetas[ci][di], "h2_vs_h8",
&res[ci][di][2], &res[ci][di][3]);
print_pair(cams[ci].name, di, thetas[ci][di], "ref_vs_h2",
&res[ci][di][0], &res[ci][di][2]);
print_pair(cams[ci].name, di, thetas[ci][di], "ref_vs_h8",
&res[ci][di][0], &res[ci][di][3]);
}
}
/* Exact-critical: diagnostic only, never asserted. */
for (int ci = 0; ci < 3; ++ci) {
const Res *a = &res[ci][1][0];
const Res *b = &res[ci][1][1];
const int same = a->outcome == b->outcome && a->reason == b->reason &&
a->end_id == b->end_id;
const int esc = a->outcome == RAY_OUTCOME_ESCAPED &&
b->outcome == RAY_OUTCOME_ESCAPED;
const int dark = a->outcome == RAY_OUTCOME_DARK &&
b->outcome == RAY_OUTCOME_DARK;
const double dn = esc ? b_ang_delta(a->n, b->n) : NAN;
const double dstop =
(isfinite(a->stop_t) && isfinite(b->stop_t)) ? a->stop_t - b->stop_t
: NAN;
const int nonconverged =
!same || (esc && !(dn <= 1e-6)) || (dark && fabs(dstop) > 1e-4);
printf("EXACT_CRITICAL_DIRECTION camera=%s theta=%.17g ref0=%s/%d/%u "
"ref1=%s/%d/%u same=%d dn_ang=%.17g dstop_t=%.17g\n",
cams[ci].name, thetas[ci][1], outcome_name(a->outcome), a->reason,
a->end_id, outcome_name(b->outcome), b->reason, b->end_id, same, dn,
dstop);
if (nonconverged)
printf("EXACT_CRITICAL_REFERENCE_NOT_CONVERGED camera=%s dn_ang=%.17g "
"dstop_t=%.17g class_same=%d\n",
cams[ci].name, dn, dstop, same);
}
/* Neighbour reference check: must pass; this is the assertion-valid path. */
int fail = 0;
for (int ci = 0; ci < 3; ++ci) {
for (int di = 0; di < 3; di += 2) {
if (!neighbour_reference_check(cams[ci].name, di, thetas[ci][di],
&res[ci][di][0], &res[ci][di][1]))
fail = 1;
}
}
spacetime_destroy(&source);
printf("CRITICAL_REFERENCE_CHECK status=%d\n", fail ? 1 : 0);
printf("CRITICAL_REF_DONE\n");
return fail ? 1 : 0;
}
@@ -0,0 +1,26 @@
/* Diagnostic only: reuse the production regression's invalid-metric fixture. */
#define main adaptive_regression_main_not_called
#include "../../tests/test_geodesic_adaptive.c"
#undef main
int main(void) {
const double floors[] = {1e-2,1e-4,1e-6,1e-8,1e-10,1e-12,1e-14};
for (unsigned i=0;i<sizeof floors/sizeof *floors;++i) {
FixtureContext context={.bad_status=SPACETIME_POINT_INVALID_METRIC,
.bad_lo=-10,.bad_hi=-.05,.radius=100};
SpacetimeSource source={.context=&context,.ops=&fixture_ops};
GeodesicTraceConfig config=dp_config(1e-9,.1,10);
config.min_step=floors[i]; config.max_step=1;
const ObserverState observer=flat_observer_at((double[3]){0,0,0});
const double direction[3]={1,0,0};
RayEndpoint endpoint=geodesic_trace_past(&source,&observer,direction,&config);
printf("FAILURE_FLOOR min=%.0e outcome=%d reason=%d t=%.17g distance_to_invalid=%.17g accepted=%u rejected=%u rhs=%lu\n",
floors[i],endpoint.outcome,endpoint.reason,endpoint.stop_coordinate_time,
endpoint.stop_coordinate_time+.05,endpoint.accepted_steps,
endpoint.rejected_steps,endpoint.rhs_evaluations);
if(endpoint.outcome!=RAY_OUTCOME_INCOMPLETE ||
endpoint.stop_coordinate_time<=-.05) return 1;
}
puts("FAILURE_FLOOR_EXIT=0");
return 0;
}
@@ -0,0 +1,77 @@
#!/usr/bin/env python3
"""Pure GRLENS v3 map load/compare helpers.
No renderer, no environment probing, no data generation: this module is only
imported by the benchmark scripts under
benchmarks/adaptive_step_bounds_2026-10-05/. Keeping it here means the
benchmark never imports an untracked module from local/.
"""
import collections
import hashlib
import math
import struct
import zlib
def load(path):
"""Parse one GRLENS v3 map; returns (info dict, {film_pos: vertex tuple})."""
data = path.read_bytes()
assert data[:8] == b'GRLENS\x01\x00'
assert struct.unpack_from('<I', data, 8)[0] == 3
assert struct.unpack_from('<Q', data, 32)[0] == 1
nv, nt = struct.unpack_from('<QQ', data, 200)
end = 224 + nv * 108 + nt * 32
assert end + 4 == len(data)
assert zlib.crc32(data[224:end]) == struct.unpack_from('<I', data, end)[0]
vertices = [struct.unpack_from('<9dIIIQQQ', data, 224 + i * 108)
for i in range(nv)]
costs = [sum(v[j] for v in vertices) for j in (12, 13, 14)]
result = dict(vertices=nv, triangles=nt,
outcomes=dict(collections.Counter(v[10] for v in vertices)),
reasons=dict(collections.Counter(v[11] for v in vertices)),
accepted=costs[0], rejected=costs[1], rhs=costs[2])
names = ('atol_x', 'atol_Pi', 'atol_L', 'rtol', 'min_step', 'max_step',
'max_lookback_time', 'retry_lookback_increment',
'max_total_lookback_time')
result['provenance'] = dict(zip(names, struct.unpack_from('<9d', data, 100)))
result['provenance'].update(
integrator=struct.unpack_from('<I', data, 68)[0],
initial_step=struct.unpack_from('<d', data, 88)[0],
initial_max_steps=struct.unpack_from('<I', data, 96)[0],
threshold=struct.unpack_from('<d', data, 48)[0],
retry_step_increment=struct.unpack_from('<I', data, 56)[0],
max_total_steps=struct.unpack_from('<I', data, 60)[0])
for j, name in ((12, 'accepted'), (13, 'rejected'), (14, 'rhs')):
xs = sorted(v[j] for v in vertices)
result[name + '_percentiles'] = {
str(q): xs[min(len(xs) - 1, int(q * (len(xs) - 1)))]
for q in (0, .5, .9, .99, 1)}
result['sha256'] = hashlib.sha256(data).hexdigest()
result['triangle_sha256'] = hashlib.sha256(
data[224 + nv * 108:end]).hexdigest()
by_film = {(v[0], v[1]): v for v in vertices}
result['unique_film_positions'] = len(by_film)
result['duplicate_film_positions'] = len(vertices) - len(by_film)
return result, by_film
def compare(a, b):
"""Compare two {film_pos: vertex} maps by shared film-coordinate identity."""
keys = a.keys() & b.keys()
mismatches = 0
worst_sky = worst_logg = 0.
for k in keys:
x, y = a[k], b[k]
if x[9:12] != y[9:12]:
mismatches += 1
elif x[10] == 0:
n, m = x[5:8], y[5:8]
cross = (n[1] * m[2] - n[2] * m[1], n[2] * m[0] - n[0] * m[2],
n[0] * m[1] - n[1] * m[0])
angle = math.atan2(math.sqrt(sum(v * v for v in cross)),
sum(v * w for v, w in zip(n, m)))
worst_sky = max(worst_sky, angle)
worst_logg = max(worst_logg, abs(x[8] - y[8]))
return dict(shared=len(keys), only_a=len(a) - len(keys),
only_b=len(b) - len(keys), terminal_mismatches=mismatches,
max_sky_angle=worst_sky, max_logg_difference=worst_logg)
@@ -0,0 +1,41 @@
#!/usr/bin/env python3
"""Record provenance without launching a render.
Usage:
record_environment.py [OUT_DIR]
OUT_DIR defaults to <repo>/local/adaptive_bounds_mesh. Writes metadata.json in
OUT_DIR. No renderer or test is run.
"""
import hashlib
import json
from pathlib import Path
import subprocess
import sys
import time
ROOT = Path(__file__).resolve().parents[2]
OUT = Path(sys.argv[1]).resolve() if len(sys.argv) > 1 else \
ROOT / 'local/adaptive_bounds_mesh'
PATHS = ['src/geodesic.c', 'src/main.c', 'src/frame.c',
'build/Release/schwarzschild_sky']
metadata = {
'recorded_utc': time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime()),
'git_head': subprocess.check_output(
['git', 'rev-parse', 'HEAD'], cwd=ROOT, text=True).strip(),
'hashes': {p: hashlib.sha256((ROOT / p).read_bytes()).hexdigest()
for p in PATHS},
'compiler': subprocess.check_output(['cc', '--version'], text=True),
'cpu': subprocess.check_output(['lscpu'], text=True),
'scope': '8 bounded 320x180 candidates plus 2 tight references; no 4K here',
'threads': 8,
'build_command': 'make -j4 BUILD_TYPE=Release SPACETIME=schwarzschild backend',
'run_commands': [
'python3 benchmarks/adaptive_step_bounds_2026-10-05/run_mesh.py [OUT]',
'python3 benchmarks/adaptive_step_bounds_2026-10-05/run_mesh_reference.py [OUT]',
'bash benchmarks/adaptive_step_bounds_2026-10-05/run_failure_floor.sh [OUT]'],
}
OUT.mkdir(parents=True, exist_ok=True)
(OUT / 'metadata.json').write_text(json.dumps(metadata, indent=2) + '\n')
print(json.dumps(metadata, indent=2))
@@ -0,0 +1,16 @@
[
{
"upper": 2,
"command": "/home/wyj/Code/C/GR_4d_raytracing/build/Release/schwarzschild_sky --integrator dp54 --width 3840 --height 2160 --look-ra-deg 262.5 --look-dec-deg -30 --fov-deg 45 --observer-radius 100 --coarse-cell-pixels 16 --refine-max-level 4 --refine-jacobian-min .2 --catalog /home/wyj/Code/C/GR_4d_raytracing/local/step_bounds_4k/single_dim_star.csv --exposure 1 --tone-map reinhard --psf-min-y 1e-20 --psf-relative-tail 1e-4 --ode-min-step 1e-12 --ode-max-step 2 --verbose --lens-map-output /home/wyj/Code/C/GR_4d_raytracing/local/step_bounds_4k/r100_4k_hmax2.grlens --output /home/wyj/Code/C/GR_4d_raytracing/local/step_bounds_4k/r100_4k_hmax2.png",
"state": "completed",
"returncode": 0,
"wall_seconds": 11.389317202148959
},
{
"upper": 8,
"command": "/home/wyj/Code/C/GR_4d_raytracing/build/Release/schwarzschild_sky --integrator dp54 --width 3840 --height 2160 --look-ra-deg 262.5 --look-dec-deg -30 --fov-deg 45 --observer-radius 100 --coarse-cell-pixels 16 --refine-max-level 4 --refine-jacobian-min .2 --catalog /home/wyj/Code/C/GR_4d_raytracing/local/step_bounds_4k/single_dim_star.csv --exposure 1 --tone-map reinhard --psf-min-y 1e-20 --psf-relative-tail 1e-4 --ode-min-step 1e-12 --ode-max-step 8 --verbose --lens-map-output /home/wyj/Code/C/GR_4d_raytracing/local/step_bounds_4k/r100_4k_hmax8.grlens --output /home/wyj/Code/C/GR_4d_raytracing/local/step_bounds_4k/r100_4k_hmax8.png",
"state": "completed",
"returncode": 0,
"wall_seconds": 8.389249739935622
}
]
@@ -0,0 +1,160 @@
{
"r100_4k_hmax2": {
"vertices": 66045,
"triangles": 131338,
"outcomes": {
"0": 62419,
"1": 3626
},
"reasons": {
"0": 62419,
"1": 3626
},
"accepted": 15768677,
"rejected": 97176,
"rhs": 130409139,
"provenance": {
"atol_x": 1e-09,
"atol_Pi": 1e-09,
"atol_L": 1e-09,
"rtol": 1e-09,
"min_step": 1e-12,
"max_step": 2.0,
"max_lookback_time": 6553.6,
"retry_lookback_increment": 6553.6,
"max_total_lookback_time": 26214.4,
"integrator": 1,
"initial_step": 0.1,
"initial_max_steps": 65536,
"threshold": 8.0,
"retry_step_increment": 65536,
"max_total_steps": 262144
},
"accepted_percentiles": {
"0": 162,
"0.5": 212,
"0.9": 328,
"0.99": 404,
"1": 520
},
"rejected_percentiles": {
"0": 0,
"0.5": 1,
"0.9": 3,
"0.99": 4,
"1": 5
},
"rhs_percentiles": {
"0": 1421,
"0.5": 1799,
"0.9": 2597,
"0.99": 3129,
"1": 3941
},
"sha256": "ef7267074338192f8597b1f2a0300fd36da8e25441e064719c7ad586c481ae7a",
"triangle_sha256": "2a943902e9b1401a16bc40fc547c19077bb12e396080074393636ee30761b7b2",
"unique_film_positions": 66045,
"duplicate_film_positions": 0,
"requested_samples_including_nonpersistent_probes": 116308,
"initial_samples": 32776,
"refinement_samples_per_generation": [
32686,
7900,
13375,
24826,
4403,
261,
67,
14
],
"trace_wall_seconds": 10.774,
"wall_seconds": 11.389317202148959
},
"r100_4k_hmax8": {
"vertices": 66045,
"triangles": 131338,
"outcomes": {
"0": 62419,
"1": 3626
},
"reasons": {
"0": 62419,
"1": 3626
},
"accepted": 10183020,
"rejected": 194781,
"rhs": 91991144,
"provenance": {
"atol_x": 1e-09,
"atol_Pi": 1e-09,
"atol_L": 1e-09,
"rtol": 1e-09,
"min_step": 1e-12,
"max_step": 8.0,
"max_lookback_time": 6553.6,
"retry_lookback_increment": 6553.6,
"max_total_lookback_time": 26214.4,
"integrator": 1,
"initial_step": 0.1,
"initial_max_steps": 65536,
"threshold": 8.0,
"retry_step_increment": 65536,
"max_total_steps": 262144
},
"accepted_percentiles": {
"0": 80,
"0.5": 127,
"0.9": 259,
"0.99": 337,
"1": 432
},
"rejected_percentiles": {
"0": 0,
"0.5": 3,
"0.9": 5,
"0.99": 6,
"1": 7
},
"rhs_percentiles": {
"0": 868,
"0.5": 1204,
"0.9": 2114,
"0.99": 2646,
"1": 3318
},
"sha256": "b1897493b7fa5b88f86872e81d15ac876818a705fa0fefe8b1ee262da9de59bb",
"triangle_sha256": "2a943902e9b1401a16bc40fc547c19077bb12e396080074393636ee30761b7b2",
"unique_film_positions": 66045,
"duplicate_film_positions": 0,
"requested_samples_including_nonpersistent_probes": 116308,
"initial_samples": 32776,
"refinement_samples_per_generation": [
32686,
7900,
13375,
24826,
4403,
261,
67,
14
],
"trace_wall_seconds": 7.805000000000001,
"wall_seconds": 8.389249739935622
},
"comparison": {
"shared": 66045,
"only_a": 0,
"only_b": 0,
"terminal_mismatches": 0,
"max_sky_angle": 7.954413592847793e-07,
"max_logg_difference": 3.471110204822381e-11,
"triangle_payload_identical": true
},
"relative_reduction": {
"accepted": 0.35422483446138187,
"rhs": 0.2945958795111745,
"wall_seconds": 0.2634106513116764,
"trace_wall_seconds": 0.27557081863746047
},
"cost_scope": "accepted/rejected/RHS sums cover final persistent vertices only; nonpersistent discarded refinement probes are not in v3 map. Do not interpret them as full-render executed RHS totals."
}
@@ -0,0 +1,242 @@
OMP_NUM_THREADS=16 OMP_DYNAMIC=FALSE /home/wyj/Code/C/GR_4d_raytracing/build/Release/schwarzschild_sky --integrator dp54 --width 3840 --height 2160 --look-ra-deg 262.5 --look-dec-deg -30 --fov-deg 45 --observer-radius 100 --coarse-cell-pixels 16 --refine-max-level 4 --refine-jacobian-min .2 --catalog /home/wyj/Code/C/GR_4d_raytracing/local/step_bounds_4k/single_dim_star.csv --exposure 1 --tone-map reinhard --psf-min-y 1e-20 --psf-relative-tail 1e-4 --ode-min-step 1e-12 --ode-max-step 2 --verbose --lens-map-output /home/wyj/Code/C/GR_4d_raytracing/local/step_bounds_4k/r100_4k_hmax2.grlens --output /home/wyj/Code/C/GR_4d_raytracing/local/step_bounds_4k/r100_4k_hmax2.png
Blackbody LUT: 1024 CIE 1931 2-deg 1 nm-linear XYZ nodes, T=[670.146556, 101408.88] K, loaded assets/blackbody/cie1931_2deg_xyz_1024.grbblut in 0.000040 s; payload fnv1a64=0e39867b0e70a809
Blackbody backend: lut
PSF cache ready: 64x64 phases, radius 25 px, relative tail 1e-04, tail abs 1e-06, boundary 1e-07, build 0.250 s
Frame 0: integrator=dp54 step=0.1 max_steps=65536 threshold=8 atol=(x 1e-09, Pi 1e-09, L 1e-09) rtol=1e-09 bounds=[1e-12, 2] max_rejections=32 lookback=6553.6
Frame 0: tracing 32776 initial rays from 64800 mesh triangles...
Frame 0: initial ray trace finished in 2.562 s.
Frame 0: starting adaptive ray-trace refinement (max level 4)...
Frame 0: refinement generation 0 tracing 32686 samples from 32776 vertices and 64800 triangles.
Frame 0: refinement generation 0 finished; added 3014 vertices, now 35790 vertices and 70828 triangles.
Frame 0: refinement generation 1 tracing 7900 samples from 35790 vertices and 70828 triangles.
Frame 0: refinement generation 1 finished; added 4852 vertices, now 40642 vertices and 80532 triangles.
Frame 0: refinement generation 2 tracing 13375 samples from 40642 vertices and 80532 triangles.
Frame 0: refinement generation 2 finished; added 8889 vertices, now 49531 vertices and 98310 triangles.
Frame 0: refinement generation 3 tracing 24826 samples from 49531 vertices and 98310 triangles.
Frame 0: refinement generation 3 finished; added 16055 vertices, now 65586 vertices and 130420 triangles.
Frame 0: refinement generation 4 tracing 4403 samples from 65586 vertices and 130420 triangles.
Frame 0: refinement generation 4 finished; added 389 vertices, now 65975 vertices and 131198 triangles.
Frame 0: refinement generation 5 tracing 261 samples from 65975 vertices and 131198 triangles.
Frame 0: refinement generation 5 finished; added 58 vertices, now 66033 vertices and 131314 triangles.
Frame 0: refinement generation 6 tracing 67 samples from 66033 vertices and 131314 triangles.
Frame 0: refinement generation 6 finished; added 12 vertices, now 66045 vertices and 131338 triangles.
Frame 0: refinement generation 7 tracing 14 samples from 66045 vertices and 131338 triangles.
Frame 0: refinement generation 7 finished; added 0 vertices, now 66045 vertices and 131338 triangles.
Frame 0: adaptive ray-trace refinement finished in 8.212 s; 66045 vertices, 131338 triangles.
Boundary accounting: EEE=122456 DDD=5624 EED/EDD=3258 UUD/UDD=0 U+E=0 UUU=0 error=0; approx-black=0 (0 px^2), retries=0, budget-incomplete=0.
Frame 0 trace cost: accepted=15768677 rejected=97176 rhs=130409139 over 66045 vertices (saturated=0).
Wrote lens map: /home/wyj/Code/C/GR_4d_raytracing/local/step_bounds_4k/r100_4k_hmax2.grlens (66045 vertices, 131338 triangles)
Frame 0: traced 66045 lens vertices; starting catalog render.
Frame 0: finding and prefetching catalog tiles...
Frame 0: catalog prefetch finished (0 candidate tiles).
Frame 0: splatting 131338 lens triangles...
Frame 0: splat worker 1/16 started.
Frame 0: splat worker 1/16 reached 8 local triangles.
Frame 0: splat worker 1/16 reached 16 local triangles.
Frame 0: splat worker 1/16 reached 32 local triangles.
Frame 0: splat worker 6/16 started.
Frame 0: splat worker 8/16 started.
Frame 0: splat worker 8/16 reached 8 local triangles.
Frame 0: splat worker 8/16 reached 16 local triangles.
Frame 0: splat worker 12/16 started.
Frame 0: splat worker 13/16 started.
Frame 0: splat worker 3/16 started.
Frame 0: splat worker 6/16 reached 8 local triangles.
Frame 0: splat worker 6/16 reached 16 local triangles.
Frame 0: splat worker 9/16 started.
Frame 0: splat worker 11/16 started.
Frame 0: splat worker 7/16 started.
Frame 0: splat worker 7/16 reached 8 local triangles.
Frame 0: splat worker 13/16 reached 8 local triangles.
Frame 0: splat worker 13/16 reached 16 local triangles.
Frame 0: splat worker 13/16 reached 32 local triangles.
Frame 0: splat worker 3/16 reached 8 local triangles.
Frame 0: splat worker 3/16 reached 16 local triangles.
Frame 0: splat worker 3/16 reached 32 local triangles.
Frame 0: splat worker 15/16 started.
Frame 0: splat worker 15/16 reached 8 local triangles.
Frame 0: splat worker 15/16 reached 16 local triangles.
Frame 0: splat worker 15/16 reached 32 local triangles.
Frame 0: splat worker 10/16 started.
Frame 0: splat worker 8/16 reached 32 local triangles.
Frame 0: splat worker 9/16 reached 8 local triangles.
Frame 0: splat worker 9/16 reached 16 local triangles.
Frame 0: splat worker 12/16 reached 8 local triangles.
Frame 0: splat worker 7/16 reached 16 local triangles.
Frame 0: splat worker 14/16 started.
Frame 0: splat worker 4/16 started.
Frame 0: splat worker 13/16 reached 64 local triangles.
Frame 0: splat worker 2/16 started.
Frame 0: splat worker 5/16 started.
Frame 0: splat worker 5/16 reached 8 local triangles.
Frame 0: splat worker 5/16 reached 16 local triangles.
Frame 0: splat worker 1/16 reached 64 local triangles.
Frame 0: splat worker 16/16 started.
Frame 0: splat worker 16/16 reached 8 local triangles.
Frame 0: splat worker 16/16 reached 16 local triangles.
Frame 0: splat worker 8/16 reached 64 local triangles.
Frame 0: splat worker 11/16 reached 8 local triangles.
Frame 0: splat worker 8/16 reached 128 local triangles.
Frame 0: splat worker 12/16 reached 16 local triangles.
Frame 0: splat worker 7/16 reached 32 local triangles.
Frame 0: splat worker 14/16 reached 8 local triangles.
Frame 0: splat worker 8/16 reached 256 local triangles.
Frame 0: splat worker 13/16 reached 128 local triangles.
Frame 0: splat worker 2/16 reached 8 local triangles.
Frame 0: splat worker 2/16 reached 16 local triangles.
Frame 0: splat worker 6/16 reached 32 local triangles.
Frame 0: splat worker 5/16 reached 32 local triangles.
Frame 0: splat worker 6/16 reached 64 local triangles.
Frame 0: splat worker 1/16 reached 128 local triangles.
Frame 0: splat worker 5/16 reached 64 local triangles.
Frame 0: splat worker 10/16 reached 8 local triangles.
Frame 0: splat worker 9/16 reached 32 local triangles.
Frame 0: splat worker 6/16 reached 128 local triangles.
Frame 0: splat worker 11/16 reached 16 local triangles.
Frame 0: splat worker 5/16 reached 128 local triangles.
Frame 0: splat worker 8/16 reached 512 local triangles.
Frame 0: splat worker 7/16 reached 64 local triangles.
Frame 0: splat worker 14/16 reached 16 local triangles.
Frame 0: splat worker 4/16 reached 8 local triangles.
Frame 0: splat worker 2/16 reached 32 local triangles.
Frame 0: splat worker 15/16 reached 64 local triangles.
Frame 0: splat worker 7/16 reached 128 local triangles.
Frame 0: splat worker 13/16 reached 256 local triangles.
Frame 0: splat worker 10/16 reached 16 local triangles.
Frame 0: splat worker 5/16 reached 256 local triangles.
Frame 0: splat worker 11/16 reached 32 local triangles.
Frame 0: splat worker 9/16 reached 64 local triangles.
Frame 0: splat worker 1/16 reached 256 local triangles.
Frame 0: splat worker 11/16 reached 64 local triangles.
Frame 0: splat worker 3/16 reached 64 local triangles.
Frame 0: splat worker 14/16 reached 32 local triangles.
Frame 0: splat worker 4/16 reached 16 local triangles.
Frame 0: splat worker 6/16 reached 256 local triangles.
Frame 0: splat worker 4/16 reached 32 local triangles.
Frame 0: splat worker 14/16 reached 64 local triangles.
Frame 0: splat worker 11/16 reached 128 local triangles.
Frame 0: splat worker 3/16 reached 128 local triangles.
Frame 0: splat worker 10/16 reached 32 local triangles.
Frame 0: splat worker 4/16 reached 64 local triangles.
Frame 0: splat worker 7/16 reached 256 local triangles.
Frame 0: splat worker 10/16 reached 64 local triangles.
Frame 0: splat worker 16/16 reached 32 local triangles.
Frame 0: splat worker 4/16 reached 128 local triangles.
Frame 0: splat worker 12/16 reached 32 local triangles.
Frame 0: splat worker 5/16 reached 512 local triangles.
Frame 0: splat worker 11/16 reached 256 local triangles.
Frame 0: splat worker 16/16 reached 64 local triangles.
Frame 0: splat worker 3/16 reached 256 local triangles.
Frame 0: splat worker 12/16 reached 64 local triangles.
Frame 0: splat worker 13/16 reached 512 local triangles.
Frame 0: splat worker 15/16 reached 128 local triangles.
Frame 0: splat worker 14/16 reached 128 local triangles.
Frame 0: splat worker 9/16 reached 128 local triangles.
Frame 0: splat worker 10/16 reached 128 local triangles.
Frame 0: splat worker 2/16 reached 64 local triangles.
Frame 0: splat worker 12/16 reached 128 local triangles.
Frame 0: splat worker 16/16 reached 128 local triangles.
Frame 0: splat worker 6/16 reached 512 local triangles.
Frame 0: splat worker 4/16 reached 256 local triangles.
Frame 0: splat worker 1/16 reached 512 local triangles.
Frame 0: splat worker 8/16 reached 1024 local triangles.
Frame 0: splat worker 2/16 reached 128 local triangles.
Frame 0: splat worker 15/16 reached 256 local triangles.
Frame 0: splat worker 14/16 reached 256 local triangles.
Frame 0: splat worker 7/16 reached 512 local triangles.
Frame 0: splat worker 10/16 reached 256 local triangles.
Frame 0: splat worker 9/16 reached 256 local triangles.
Frame 0: splat worker 11/16 reached 512 local triangles.
Frame 0: splat worker 16/16 reached 256 local triangles.
Frame 0: splat worker 12/16 reached 256 local triangles.
Frame 0: splat worker 2/16 reached 256 local triangles.
Frame 0: splat worker 3/16 reached 512 local triangles.
Frame 0: splat worker 4/16 reached 512 local triangles.
Frame 0: splat worker 15/16 reached 512 local triangles.
Frame 0: splat worker 14/16 reached 512 local triangles.
Frame 0: splat worker 10/16 reached 512 local triangles.
Frame 0: splat worker 9/16 reached 512 local triangles.
Frame 0: splat worker 5/16 reached 1024 local triangles.
Frame 0: splat worker 12/16 reached 512 local triangles.
Frame 0: splat worker 16/16 reached 512 local triangles.
Frame 0: splat worker 13/16 reached 1024 local triangles.
Frame 0: splat worker 2/16 reached 512 local triangles.
Frame 0: splat worker 1/16 reached 1024 local triangles.
Frame 0: splat worker 6/16 reached 1024 local triangles.
Frame 0: splat worker 7/16 reached 1024 local triangles.
Frame 0: splat worker 11/16 reached 1024 local triangles.
Frame 0: splat worker 4/16 reached 1024 local triangles.
Frame 0: splat worker 3/16 reached 1024 local triangles.
Frame 0: splat worker 15/16 reached 1024 local triangles.
Frame 0: splat worker 14/16 reached 1024 local triangles.
Frame 0: splat worker 10/16 reached 1024 local triangles.
Frame 0: splat worker 9/16 reached 1024 local triangles.
Frame 0: splat worker 12/16 reached 1024 local triangles.
Frame 0: splat worker 16/16 reached 1024 local triangles.
Frame 0: splat worker 2/16 reached 1024 local triangles.
Frame 0: splat worker 8/16 reached 2048 local triangles.
Frame 0: splat worker 5/16 reached 2048 local triangles.
Frame 0: splat worker 13/16 reached 2048 local triangles.
Frame 0: splat worker 1/16 reached 2048 local triangles.
Frame 0: splat worker 6/16 reached 2048 local triangles.
Frame 0: splat worker 7/16 reached 2048 local triangles.
Frame 0: splat worker 11/16 reached 2048 local triangles.
Frame 0: splat worker 4/16 reached 2048 local triangles.
Frame 0: splat worker 15/16 reached 2048 local triangles.
Frame 0: splat worker 3/16 reached 2048 local triangles.
Frame 0: splat worker 14/16 reached 2048 local triangles.
Frame 0: splat worker 9/16 reached 2048 local triangles.
Frame 0: splat worker 10/16 reached 2048 local triangles.
Frame 0: splat worker 12/16 reached 2048 local triangles.
Frame 0: splat worker 2/16 reached 2048 local triangles.
Frame 0: splat worker 16/16 reached 2048 local triangles.
Frame 0: splat worker 8/16 reached 4096 local triangles.
Frame 0: splat worker 5/16 reached 4096 local triangles.
Frame 0: splat worker 13/16 reached 4096 local triangles.
Frame 0: splat worker 1/16 reached 4096 local triangles.
Frame 0: splat worker 6/16 reached 4096 local triangles.
Frame 0: splat worker 11/16 reached 4096 local triangles.
Frame 0: splat worker 4/16 reached 4096 local triangles.
Frame 0: splat worker 14/16 reached 4096 local triangles.
Frame 0: splat worker 15/16 reached 4096 local triangles.
Frame 0: splat worker 9/16 reached 4096 local triangles.
Frame 0: splat worker 10/16 reached 4096 local triangles.
Frame 0: splat worker 16/16 reached 4096 local triangles.
Frame 0: splat worker 2/16 reached 4096 local triangles.
Frame 0: splat worker 12/16 reached 4096 local triangles.
Frame 0: splat worker 3/16 reached 4096 local triangles.
Frame 0: splat worker 8/16 reached 8192 local triangles.
Frame 0: splat worker 13/16 reached 8192 local triangles.
Frame 0: splat worker 5/16 reached 8192 local triangles.
Frame 0: splat worker 12/16 reached 8192 local triangles.
Frame 0: splat worker 1/16 reached 8192 local triangles.
Frame 0: splat worker 6/16 reached 8192 local triangles.
Frame 0: splat worker 11/16 reached 8192 local triangles.
Frame 0: splat worker 14/16 reached 8192 local triangles.
Frame 0: splat worker 4/16 reached 8192 local triangles.
Frame 0: splat worker 9/16 reached 8192 local triangles.
Frame 0: splat worker 16/16 reached 8192 local triangles.
Frame 0: splat worker 10/16 reached 8192 local triangles.
Frame 0: splat worker 2/16 reached 8192 local triangles.
Frame 0: splat worker 7/16 reached 4096 local triangles.
Frame 0: splat worker 15/16 reached 8192 local triangles.
Frame 0: splat worker 6/16 finished after 8555 local triangles.
Frame 0: splat worker 16/16 finished after 8230 local triangles.
Frame 0: splat worker 15/16 finished after 8192 local triangles.
Frame 0: splat worker 11/16 finished after 8468 local triangles.
Frame 0: splat worker 10/16 finished after 8207 local triangles.
Frame 0: splat worker 5/16 finished after 8824 local triangles.
Frame 0: splat worker 4/16 finished after 8382 local triangles.
Frame 0: splat worker 3/16 finished after 8004 local triangles.
Frame 0: splat worker 8/16 finished after 9239 local triangles.
Frame 0: splat worker 1/16 finished after 8561 local triangles.
Frame 0: splat worker 12/16 finished after 8804 local triangles.
Frame 0: splat worker 14/16 finished after 8429 local triangles.
Frame 0: splat worker 7/16 finished after 4096 local triangles.
Frame 0: splat worker 2/16 finished after 8201 local triangles.
Frame 0: splat worker 9/16 finished after 8290 local triangles.
Frame 0: splat worker 13/16 finished after 8856 local triangles.
Frame 0: catalog splatting finished in 0.1 s; writing image...
Rendered 1965 images from 1 catalog stars to /home/wyj/Code/C/GR_4d_raytracing/local/step_bounds_4k/r100_4k_hmax2.png (ok)
PSF splats: cached 0, cached wing-clipped 0, direct fallbacks 0, discarded below min-Y 1965
Warning: --psf-min-y discarded one or more PSF events.
@@ -0,0 +1,233 @@
OMP_NUM_THREADS=16 OMP_DYNAMIC=FALSE /home/wyj/Code/C/GR_4d_raytracing/build/Release/schwarzschild_sky --integrator dp54 --width 3840 --height 2160 --look-ra-deg 262.5 --look-dec-deg -30 --fov-deg 45 --observer-radius 100 --coarse-cell-pixels 16 --refine-max-level 4 --refine-jacobian-min .2 --catalog /home/wyj/Code/C/GR_4d_raytracing/local/step_bounds_4k/single_dim_star.csv --exposure 1 --tone-map reinhard --psf-min-y 1e-20 --psf-relative-tail 1e-4 --ode-min-step 1e-12 --ode-max-step 8 --verbose --lens-map-output /home/wyj/Code/C/GR_4d_raytracing/local/step_bounds_4k/r100_4k_hmax8.grlens --output /home/wyj/Code/C/GR_4d_raytracing/local/step_bounds_4k/r100_4k_hmax8.png
Blackbody LUT: 1024 CIE 1931 2-deg 1 nm-linear XYZ nodes, T=[670.146556, 101408.88] K, loaded assets/blackbody/cie1931_2deg_xyz_1024.grbblut in 0.000041 s; payload fnv1a64=0e39867b0e70a809
Blackbody backend: lut
PSF cache ready: 64x64 phases, radius 25 px, relative tail 1e-04, tail abs 1e-06, boundary 1e-07, build 0.223 s
Frame 0: integrator=dp54 step=0.1 max_steps=65536 threshold=8 atol=(x 1e-09, Pi 1e-09, L 1e-09) rtol=1e-09 bounds=[1e-12, 8] max_rejections=32 lookback=6553.6
Frame 0: tracing 32776 initial rays from 64800 mesh triangles...
Frame 0: initial ray trace finished in 1.735 s.
Frame 0: starting adaptive ray-trace refinement (max level 4)...
Frame 0: refinement generation 0 tracing 32686 samples from 32776 vertices and 64800 triangles.
Frame 0: refinement generation 0 finished; added 3014 vertices, now 35790 vertices and 70828 triangles.
Frame 0: refinement generation 1 tracing 7900 samples from 35790 vertices and 70828 triangles.
Frame 0: refinement generation 1 finished; added 4852 vertices, now 40642 vertices and 80532 triangles.
Frame 0: refinement generation 2 tracing 13375 samples from 40642 vertices and 80532 triangles.
Frame 0: refinement generation 2 finished; added 8889 vertices, now 49531 vertices and 98310 triangles.
Frame 0: refinement generation 3 tracing 24826 samples from 49531 vertices and 98310 triangles.
Frame 0: refinement generation 3 finished; added 16055 vertices, now 65586 vertices and 130420 triangles.
Frame 0: refinement generation 4 tracing 4403 samples from 65586 vertices and 130420 triangles.
Frame 0: refinement generation 4 finished; added 389 vertices, now 65975 vertices and 131198 triangles.
Frame 0: refinement generation 5 tracing 261 samples from 65975 vertices and 131198 triangles.
Frame 0: refinement generation 5 finished; added 58 vertices, now 66033 vertices and 131314 triangles.
Frame 0: refinement generation 6 tracing 67 samples from 66033 vertices and 131314 triangles.
Frame 0: refinement generation 6 finished; added 12 vertices, now 66045 vertices and 131338 triangles.
Frame 0: refinement generation 7 tracing 14 samples from 66045 vertices and 131338 triangles.
Frame 0: refinement generation 7 finished; added 0 vertices, now 66045 vertices and 131338 triangles.
Frame 0: adaptive ray-trace refinement finished in 6.070 s; 66045 vertices, 131338 triangles.
Boundary accounting: EEE=122456 DDD=5624 EED/EDD=3258 UUD/UDD=0 U+E=0 UUU=0 error=0; approx-black=0 (0 px^2), retries=0, budget-incomplete=0.
Frame 0 trace cost: accepted=10183020 rejected=194781 rhs=91991144 over 66045 vertices (saturated=0).
Wrote lens map: /home/wyj/Code/C/GR_4d_raytracing/local/step_bounds_4k/r100_4k_hmax8.grlens (66045 vertices, 131338 triangles)
Frame 0: traced 66045 lens vertices; starting catalog render.
Frame 0: finding and prefetching catalog tiles...
Frame 0: catalog prefetch finished (0 candidate tiles).
Frame 0: splatting 131338 lens triangles...
Frame 0: splat worker 1/16 started.
Frame 0: splat worker 1/16 reached 8 local triangles.
Frame 0: splat worker 1/16 reached 16 local triangles.
Frame 0: splat worker 10/16 started.
Frame 0: splat worker 10/16 reached 8 local triangles.
Frame 0: splat worker 2/16 started.
Frame 0: splat worker 2/16 reached 8 local triangles.
Frame 0: splat worker 11/16 started.
Frame 0: splat worker 12/16 started.
Frame 0: splat worker 12/16 reached 8 local triangles.
Frame 0: splat worker 12/16 reached 16 local triangles.
Frame 0: splat worker 7/16 started.
Frame 0: splat worker 16/16 started.
Frame 0: splat worker 16/16 reached 8 local triangles.
Frame 0: splat worker 16/16 reached 16 local triangles.
Frame 0: splat worker 16/16 reached 32 local triangles.
Frame 0: splat worker 16/16 reached 64 local triangles.
Frame 0: splat worker 16/16 reached 128 local triangles.
Frame 0: splat worker 16/16 reached 256 local triangles.
Frame 0: splat worker 15/16 started.
Frame 0: splat worker 8/16 started.
Frame 0: splat worker 16/16 reached 512 local triangles.
Frame 0: splat worker 8/16 reached 8 local triangles.
Frame 0: splat worker 11/16 reached 8 local triangles.
Frame 0: splat worker 10/16 reached 16 local triangles.
Frame 0: splat worker 14/16 started.
Frame 0: splat worker 5/16 started.
Frame 0: splat worker 6/16 started.
Frame 0: splat worker 6/16 reached 8 local triangles.
Frame 0: splat worker 9/16 started.
Frame 0: splat worker 7/16 reached 8 local triangles.
Frame 0: splat worker 7/16 reached 16 local triangles.
Frame 0: splat worker 16/16 reached 1024 local triangles.
Frame 0: splat worker 4/16 started.
Frame 0: splat worker 3/16 started.
Frame 0: splat worker 8/16 reached 16 local triangles.
Frame 0: splat worker 3/16 reached 8 local triangles.
Frame 0: splat worker 10/16 reached 32 local triangles.
Frame 0: splat worker 16/16 reached 2048 local triangles.
Frame 0: splat worker 5/16 reached 8 local triangles.
Frame 0: splat worker 10/16 reached 64 local triangles.
Frame 0: splat worker 5/16 reached 16 local triangles.
Frame 0: splat worker 5/16 reached 32 local triangles.
Frame 0: splat worker 10/16 reached 128 local triangles.
Frame 0: splat worker 10/16 reached 256 local triangles.
Frame 0: splat worker 10/16 reached 512 local triangles.
Frame 0: splat worker 1/16 reached 32 local triangles.
Frame 0: splat worker 6/16 reached 16 local triangles.
Frame 0: splat worker 12/16 reached 32 local triangles.
Frame 0: splat worker 1/16 reached 64 local triangles.
Frame 0: splat worker 9/16 reached 8 local triangles.
Frame 0: splat worker 2/16 reached 16 local triangles.
Frame 0: splat worker 2/16 reached 32 local triangles.
Frame 0: splat worker 2/16 reached 64 local triangles.
Frame 0: splat worker 2/16 reached 128 local triangles.
Frame 0: splat worker 10/16 reached 1024 local triangles.
Frame 0: splat worker 2/16 reached 256 local triangles.
Frame 0: splat worker 4/16 reached 8 local triangles.
Frame 0: splat worker 11/16 reached 16 local triangles.
Frame 0: splat worker 4/16 reached 16 local triangles.
Frame 0: splat worker 11/16 reached 32 local triangles.
Frame 0: splat worker 4/16 reached 32 local triangles.
Frame 0: splat worker 14/16 reached 8 local triangles.
Frame 0: splat worker 5/16 reached 64 local triangles.
Frame 0: splat worker 14/16 reached 16 local triangles.
Frame 0: splat worker 7/16 reached 32 local triangles.
Frame 0: splat worker 12/16 reached 64 local triangles.
Frame 0: splat worker 5/16 reached 128 local triangles.
Frame 0: splat worker 7/16 reached 64 local triangles.
Frame 0: splat worker 12/16 reached 128 local triangles.
Frame 0: splat worker 7/16 reached 128 local triangles.
Frame 0: splat worker 5/16 reached 256 local triangles.
Frame 0: splat worker 13/16 started.
Frame 0: splat worker 8/16 reached 32 local triangles.
Frame 0: splat worker 3/16 reached 16 local triangles.
Frame 0: splat worker 2/16 reached 512 local triangles.
Frame 0: splat worker 8/16 reached 64 local triangles.
Frame 0: splat worker 5/16 reached 512 local triangles.
Frame 0: splat worker 8/16 reached 128 local triangles.
Frame 0: splat worker 4/16 reached 64 local triangles.
Frame 0: splat worker 10/16 reached 2048 local triangles.
Frame 0: splat worker 16/16 reached 4096 local triangles.
Frame 0: splat worker 14/16 reached 32 local triangles.
Frame 0: splat worker 9/16 reached 16 local triangles.
Frame 0: splat worker 4/16 reached 128 local triangles.
Frame 0: splat worker 14/16 reached 64 local triangles.
Frame 0: splat worker 7/16 reached 256 local triangles.
Frame 0: splat worker 12/16 reached 256 local triangles.
Frame 0: splat worker 3/16 reached 32 local triangles.
Frame 0: splat worker 11/16 reached 64 local triangles.
Frame 0: splat worker 3/16 reached 64 local triangles.
Frame 0: splat worker 8/16 reached 256 local triangles.
Frame 0: splat worker 6/16 reached 32 local triangles.
Frame 0: splat worker 4/16 reached 256 local triangles.
Frame 0: splat worker 9/16 reached 32 local triangles.
Frame 0: splat worker 11/16 reached 128 local triangles.
Frame 0: splat worker 3/16 reached 128 local triangles.
Frame 0: splat worker 15/16 reached 8 local triangles.
Frame 0: splat worker 5/16 reached 1024 local triangles.
Frame 0: splat worker 15/16 reached 16 local triangles.
Frame 0: splat worker 14/16 reached 128 local triangles.
Frame 0: splat worker 9/16 reached 64 local triangles.
Frame 0: splat worker 1/16 reached 128 local triangles.
Frame 0: splat worker 7/16 reached 512 local triangles.
Frame 0: splat worker 6/16 reached 64 local triangles.
Frame 0: splat worker 15/16 reached 32 local triangles.
Frame 0: splat worker 11/16 reached 256 local triangles.
Frame 0: splat worker 3/16 reached 256 local triangles.
Frame 0: splat worker 13/16 reached 8 local triangles.
Frame 0: splat worker 15/16 reached 64 local triangles.
Frame 0: splat worker 13/16 reached 16 local triangles.
Frame 0: splat worker 9/16 reached 128 local triangles.
Frame 0: splat worker 14/16 reached 256 local triangles.
Frame 0: splat worker 2/16 reached 1024 local triangles.
Frame 0: splat worker 13/16 reached 32 local triangles.
Frame 0: splat worker 15/16 reached 128 local triangles.
Frame 0: splat worker 6/16 reached 128 local triangles.
Frame 0: splat worker 12/16 reached 512 local triangles.
Frame 0: splat worker 13/16 reached 64 local triangles.
Frame 0: splat worker 4/16 reached 512 local triangles.
Frame 0: splat worker 8/16 reached 512 local triangles.
Frame 0: splat worker 1/16 reached 256 local triangles.
Frame 0: splat worker 9/16 reached 256 local triangles.
Frame 0: splat worker 13/16 reached 128 local triangles.
Frame 0: splat worker 15/16 reached 256 local triangles.
Frame 0: splat worker 6/16 reached 256 local triangles.
Frame 0: splat worker 3/16 reached 512 local triangles.
Frame 0: splat worker 11/16 reached 512 local triangles.
Frame 0: splat worker 14/16 reached 512 local triangles.
Frame 0: splat worker 13/16 reached 256 local triangles.
Frame 0: splat worker 1/16 reached 512 local triangles.
Frame 0: splat worker 9/16 reached 512 local triangles.
Frame 0: splat worker 7/16 reached 1024 local triangles.
Frame 0: splat worker 15/16 reached 512 local triangles.
Frame 0: splat worker 6/16 reached 512 local triangles.
Frame 0: splat worker 13/16 reached 512 local triangles.
Frame 0: splat worker 4/16 reached 1024 local triangles.
Frame 0: splat worker 8/16 reached 1024 local triangles.
Frame 0: splat worker 3/16 reached 1024 local triangles.
Frame 0: splat worker 11/16 reached 1024 local triangles.
Frame 0: splat worker 14/16 reached 1024 local triangles.
Frame 0: splat worker 12/16 reached 1024 local triangles.
Frame 0: splat worker 1/16 reached 1024 local triangles.
Frame 0: splat worker 5/16 reached 2048 local triangles.
Frame 0: splat worker 15/16 reached 1024 local triangles.
Frame 0: splat worker 9/16 reached 1024 local triangles.
Frame 0: splat worker 6/16 reached 1024 local triangles.
Frame 0: splat worker 13/16 reached 1024 local triangles.
Frame 0: splat worker 7/16 reached 2048 local triangles.
Frame 0: splat worker 2/16 reached 2048 local triangles.
Frame 0: splat worker 4/16 reached 2048 local triangles.
Frame 0: splat worker 8/16 reached 2048 local triangles.
Frame 0: splat worker 10/16 reached 4096 local triangles.
Frame 0: splat worker 3/16 reached 2048 local triangles.
Frame 0: splat worker 14/16 reached 2048 local triangles.
Frame 0: splat worker 11/16 reached 2048 local triangles.
Frame 0: splat worker 1/16 reached 2048 local triangles.
Frame 0: splat worker 15/16 reached 2048 local triangles.
Frame 0: splat worker 9/16 reached 2048 local triangles.
Frame 0: splat worker 6/16 reached 2048 local triangles.
Frame 0: splat worker 13/16 reached 2048 local triangles.
Frame 0: splat worker 12/16 reached 2048 local triangles.
Frame 0: splat worker 5/16 reached 4096 local triangles.
Frame 0: splat worker 7/16 reached 4096 local triangles.
Frame 0: splat worker 4/16 reached 4096 local triangles.
Frame 0: splat worker 8/16 reached 4096 local triangles.
Frame 0: splat worker 14/16 reached 4096 local triangles.
Frame 0: splat worker 16/16 reached 8192 local triangles.
Frame 0: splat worker 3/16 reached 4096 local triangles.
Frame 0: splat worker 11/16 reached 4096 local triangles.
Frame 0: splat worker 1/16 reached 4096 local triangles.
Frame 0: splat worker 15/16 reached 4096 local triangles.
Frame 0: splat worker 9/16 reached 4096 local triangles.
Frame 0: splat worker 6/16 reached 4096 local triangles.
Frame 0: splat worker 13/16 reached 4096 local triangles.
Frame 0: splat worker 2/16 reached 4096 local triangles.
Frame 0: splat worker 12/16 reached 4096 local triangles.
Frame 0: splat worker 10/16 reached 8192 local triangles.
Frame 0: splat worker 5/16 reached 8192 local triangles.
Frame 0: splat worker 14/16 reached 8192 local triangles.
Frame 0: splat worker 7/16 reached 8192 local triangles.
Frame 0: splat worker 10/16 finished after 10255 local triangles.
Frame 0: splat worker 13/16 finished after 7729 local triangles.
Frame 0: splat worker 14/16 finished after 8310 local triangles.
Frame 0: splat worker 3/16 finished after 8102 local triangles.
Frame 0: splat worker 12/16 finished after 5601 local triangles.
Frame 0: splat worker 2/16 finished after 6132 local triangles.
Frame 0: splat worker 7/16 finished after 8294 local triangles.
Frame 0: splat worker 6/16 finished after 7791 local triangles.
Frame 0: splat worker 5/16 finished after 8901 local triangles.
Frame 0: splat worker 4/16 finished after 8159 local triangles.
Frame 0: splat worker 1/16 finished after 7930 local triangles.
Frame 0: splat worker 16/16 finished after 12209 local triangles.
Frame 0: splat worker 15/16 finished after 7871 local triangles.
Frame 0: splat worker 9/16 finished after 7811 local triangles.
Frame 0: splat worker 11/16 finished after 8075 local triangles.
Frame 0: splat worker 8/16 finished after 8168 local triangles.
Frame 0: catalog splatting finished in 0.1 s; writing image...
Rendered 1954 images from 1 catalog stars to /home/wyj/Code/C/GR_4d_raytracing/local/step_bounds_4k/r100_4k_hmax8.png (ok)
PSF splats: cached 0, cached wing-clipped 0, direct fallbacks 0, discarded below min-Y 1954
Warning: --psf-min-y discarded one or more PSF events.
@@ -0,0 +1,13 @@
{
"binary_sha256": "72ba409cd60bc72a7f0ca16f736cab6be6d4ab3f42a11d00647eeb03cc7a7e2a",
"utc": "2026-10-05T22:19:23Z",
"source_sha256": {
"src/main.c": "6cf3f6354b52b5eb029e1f3605c403c4161bb3df5d4202a47b97409318358ff9",
"src/geodesic.c": "25f24a2e1c9ce49508fed230dfb3f6d9986e92bb4a5e6347bb2356ac0ee5fffa",
"src/frame.c": "317cf2a777be139a2cab6a1b9f00094b7834fbb0382389960526ee3281ca55bf"
},
"catalog": "one negligible synthetic point; no survey catalog",
"scope": "README R100 45-degree 3840x2160 coarse16 refine4 jacobian0.2",
"threads": 16,
"max_attempts": 2
}
@@ -0,0 +1,3 @@
r100_4k_hmax2 {"vertices": 66045, "triangles": 131338, "outcomes": {"0": 62419, "1": 3626}, "reasons": {"0": 62419, "1": 3626}, "accepted": 15768677, "rejected": 97176, "rhs": 130409139, "provenance": {"atol_x": 1e-09, "atol_Pi": 1e-09, "atol_L": 1e-09, "rtol": 1e-09, "min_step": 1e-12, "max_step": 2.0, "max_lookback_time": 6553.6, "retry_lookback_increment": 6553.6, "max_total_lookback_time": 26214.4, "integrator": 1, "initial_step": 0.1, "initial_max_steps": 65536, "threshold": 8.0, "retry_step_increment": 65536, "max_total_steps": 262144}, "accepted_percentiles": {"0": 162, "0.5": 212, "0.9": 328, "0.99": 404, "1": 520}, "rejected_percentiles": {"0": 0, "0.5": 1, "0.9": 3, "0.99": 4, "1": 5}, "rhs_percentiles": {"0": 1421, "0.5": 1799, "0.9": 2597, "0.99": 3129, "1": 3941}, "sha256": "ef7267074338192f8597b1f2a0300fd36da8e25441e064719c7ad586c481ae7a", "unique_film_positions": 66045, "duplicate_film_positions": 0, "wall_seconds": 11.389317202148959}
r100_4k_hmax8 {"vertices": 66045, "triangles": 131338, "outcomes": {"0": 62419, "1": 3626}, "reasons": {"0": 62419, "1": 3626}, "accepted": 10183020, "rejected": 194781, "rhs": 91991144, "provenance": {"atol_x": 1e-09, "atol_Pi": 1e-09, "atol_L": 1e-09, "rtol": 1e-09, "min_step": 1e-12, "max_step": 8.0, "max_lookback_time": 6553.6, "retry_lookback_increment": 6553.6, "max_total_lookback_time": 26214.4, "integrator": 1, "initial_step": 0.1, "initial_max_steps": 65536, "threshold": 8.0, "retry_step_increment": 65536, "max_total_steps": 262144}, "accepted_percentiles": {"0": 80, "0.5": 127, "0.9": 259, "0.99": 337, "1": 432}, "rejected_percentiles": {"0": 0, "0.5": 3, "0.9": 5, "0.99": 6, "1": 7}, "rhs_percentiles": {"0": 868, "0.5": 1204, "0.9": 2114, "0.99": 2646, "1": 3318}, "sha256": "b1897493b7fa5b88f86872e81d15ac876818a705fa0fefe8b1ee262da9de59bb", "unique_film_positions": 66045, "duplicate_film_positions": 0, "wall_seconds": 8.389249739935622}
comparison {"shared": 66045, "only_a": 0, "only_b": 0, "terminal_mismatches": 0, "max_sky_angle": 7.954413592847793e-07, "max_logg_difference": 3.471110204822381e-11}
@@ -0,0 +1,37 @@
camera,dir,theta,cfg,outcome,reason,end_id,stop_t,steps,rejected,rhs,nx,ny,nz,g,thr,L,L0
r30_inward,0,0.16812279429621627,ref_tol1e-12_h0.25,1,1,4294967295,-142.17574796859728,2081,0,14854,0,0,0,0,8.0000000000000195,8.0658840965825682,0.065884096582549498
r30_inward,0,0.16812279429621627,ref_tol1e-13_h0.125,1,1,4294967295,-142.17574845681202,3332,0,23611,0,0,0,0,8.0000000000000249,8.0658840965825735,0.065884096582549498
r30_inward,0,0.16812279429621627,tol1e-11_h2,1,1,4294967295,-142.17574172483768,1304,0,9415,0,0,0,0,8.0000000000000266,8.0658840965825753,0.065884096582549498
r30_inward,0,0.16812279429621627,tol1e-11_h8,1,1,4294967295,-142.17574172483768,1304,0,9415,0,0,0,0,8.0000000000000266,8.0658840965825753,0.065884096582549498
r30_inward,1,0.16812289429621627,ref_tol1e-12_h0.25,1,1,4294967295,-225.85293500418322,3746,0,26509,0,0,0,0,8.0000000000000338,8.0658840955358357,0.065884095535802364
r30_inward,1,0.16812289429621627,ref_tol1e-13_h0.125,1,1,4294967295,-238.90906331559862,6388,0,45003,0,0,0,0,8.000000000000016,8.065884095535818,0.065884095535802364
r30_inward,1,0.16812289429621627,tol1e-11_h2,1,1,4294967295,-212.59582609170599,2180,0,15547,0,0,0,0,8.0000000000000071,8.0658840955358091,0.065884095535802364
r30_inward,1,0.16812289429621627,tol1e-11_h8,1,1,4294967295,-212.59582609170599,2180,0,15547,0,0,0,0,8.0000000000000071,8.0658840955358091,0.065884095535802364
r30_inward,2,0.16812299429621627,ref_tol1e-12_h0.25,0,0,0,-370.18047830118235,2790,1,19831,-0.35873499147611138,-6.5068267720987458e-16,-0.9334394495041628,1.0350983390130453,nan,-0.038385896473527227,0.065884094489054593
r30_inward,2,0.16812299429621627,ref_tol1e-13_h0.125,0,0,0,-370.1804778092,4857,1,34300,-0.35873507984449715,-6.5068265353608199e-16,-0.93343941554284182,1.035098339013504,nan,-0.038385896473972475,0.065884094489054593
r30_inward,2,0.16812299429621627,tol1e-11_h2,0,0,0,-370.18048452857704,1299,1,9387,-0.3587338729380895,-6.5068297686427377e-16,-0.93343987937458439,1.0350983390054869,nan,-0.038385896466199748,0.065884094489054593
r30_inward,2,0.16812299429621627,tol1e-11_h8,0,0,0,-370.1804845285946,1257,1,9100,-0.35873387293809145,-6.5068297686427416e-16,-0.93343987937458361,1.035098339005424,nan,-0.038385896466138665,0.065884094489054593
r100_inward,0,0.051461896376274734,ref_tol1e-12_h0.25,1,1,4294967295,-211.027405235164,2252,0,16051,0,0,0,0,8.0000000000000266,8.0199767087115159,0.01997670871149013
r100_inward,0,0.051461896376274734,ref_tol1e-13_h0.125,1,1,4294967295,-211.02740538583069,3727,0,26376,0,0,0,0,8.0000000000000142,8.0199767087115035,0.01997670871149013
r100_inward,0,0.051461896376274734,tol1e-11_h2,1,1,4294967295,-211.02740354768991,1292,0,9331,0,0,0,0,8.0000000000000533,8.0199767087115426,0.01997670871149013
r100_inward,0,0.051461896376274734,tol1e-11_h8,1,1,4294967295,-211.02740354768991,1292,0,9331,0,0,0,0,8.0000000000000533,8.0199767087115426,0.01997670871149013
r100_inward,1,0.051461996376274736,ref_tol1e-12_h0.25,1,1,4294967295,-301.07740508539132,4045,0,28602,0,0,0,0,8.0000000000000018,8.0199767086106277,0.019976708610626077
r100_inward,1,0.051461996376274736,ref_tol1e-13_h0.125,1,1,4294967295,-313.77734009633099,6986,0,49189,0,0,0,0,8.0000000000000018,8.0199767086106277,0.019976708610626077
r100_inward,1,0.051461996376274736,tol1e-11_h2,1,1,4294967295,-288.21364790845217,2256,0,16079,0,0,0,0,8.0000000000000639,8.0199767086106899,0.019976708610626077
r100_inward,1,0.051461996376274736,tol1e-11_h8,1,1,4294967295,-288.21364790845217,2256,0,16079,0,0,0,0,8.0000000000000639,8.0199767086106899,0.019976708610626077
r100_inward,2,0.051462096376274739,ref_tol1e-12_h0.25,0,0,0,-439.31355204311825,2969,0,21077,-0.99110324423183982,-3.1326762563025509e-16,-0.13309530146899301,1.0101525445517785,nan,-0.013990814384499865,0.019976708509762027
r100_inward,2,0.051462096376274739,ref_tol1e-13_h0.125,0,0,0,-439.31355190087947,5265,0,37149,-0.99110324787406912,-3.132675617927086e-16,-0.13309527434688151,1.010152544552184,nan,-0.013990814384902493,0.019976708509762027
r100_inward,2,0.051462096376274739,tol1e-11_h2,0,0,0,-439.31355372933643,1291,1,9338,-0.99110320105936889,-3.1326838231562615e-16,-0.13309562295534913,1.010152544545182,nan,-0.013990814377948021,0.019976708509762027
r100_inward,2,0.051462096376274739,tol1e-11_h8,0,0,0,-439.31355372935258,1250,1,9051,-0.991103201059369,-3.1326838231562231e-16,-0.13309562295534744,1.0101525445451216,nan,-0.013990814377887956,0.019976708509762027
r2p1_outward,0,0.57037671003940071,ref_tol1e-12_h0.25,0,0,0,-333.45070432558816,2639,1,18774,-0.30976840652656795,0,-0.95081203942629522,4.5825756949539365,nan,-1.5261506795942201,-0.42981831573151047
r2p1_outward,0,0.57037671003940071,ref_tol1e-13_h0.125,0,0,0,-333.45070506871724,4589,2,32431,-0.30976827139480229,0,-0.95081208345133916,4.5825756949557528,nan,-1.5261506795946143,-0.42981831573151047
r2p1_outward,0,0.57037671003940071,tol1e-11_h2,0,0,0,-333.45070071486469,1210,2,8778,-0.30976906608911198,0,-0.95081182454483582,4.5825756949192931,nan,-1.5261506795866686,-0.42981831573151047
r2p1_outward,0,0.57037671003940071,tol1e-11_h8,0,0,0,-333.45070071488124,1169,2,8491,-0.30976906647032454,0,-0.95081182442063883,4.5825756949190151,nan,-1.5261506795866076,-0.42981831573151047
r2p1_outward,1,0.57037681003940066,ref_tol1e-12_h0.25,0,0,0,-414.94010328784253,4263,2,30149,0.3336576345143959,0,0.94269432104487505,4.5825756949507124,nan,-1.5261506795930104,-0.42981805651739968
r2p1_outward,1,0.57037681003940066,ref_tol1e-13_h0.125,0,0,0,-427.08073320404128,7560,1,53221,-0.91087431940825703,0,-0.41268386719442363,4.5825756949554943,nan,-1.5261506795940556,-0.42981805651739968
r2p1_outward,1,0.57037681003940066,tol1e-11_h2,0,0,0,-406.06581257014602,2120,2,15141,0.88820167266587602,0,-0.45945379383953305,4.58257569487448,nan,-1.5261506795763404,-0.42981805651739968
r2p1_outward,1,0.57037681003940066,tol1e-11_h8,0,0,0,-406.06581257016262,2078,2,14854,0.88817826517728515,0,-0.4594990416384655,4.5825756948742002,nan,-1.5261506795762789,-0.42981805651739968
r2p1_outward,2,0.57037691003940061,ref_tol1e-12_h0.25,1,1,4294967295,-109.41561097431348,1950,1,13944,0,0,0,0,8.0000000000000195,7.5701822026967047,-0.42981779730331554
r2p1_outward,2,0.57037691003940061,ref_tol1e-13_h0.125,1,1,4294967295,-109.41561022532379,3098,1,21980,0,0,0,0,8.000000000000016,7.5701822026967012,-0.42981779730331554
r2p1_outward,2,0.57037691003940061,tol1e-11_h2,1,1,4294967295,-109.41561457850582,1228,1,8890,0,0,0,0,8.0000000000000195,7.5701822026967038,-0.42981779730331554
r2p1_outward,2,0.57037691003940061,tol1e-11_h8,1,1,4294967295,-109.41561457850582,1228,1,8890,0,0,0,0,8.0000000000000195,7.5701822026967038,-0.42981779730331554
1 camera dir theta cfg outcome reason end_id stop_t steps rejected rhs nx ny nz g thr L L0
2 r30_inward 0 0.16812279429621627 ref_tol1e-12_h0.25 1 1 4294967295 -142.17574796859728 2081 0 14854 0 0 0 0 8.0000000000000195 8.0658840965825682 0.065884096582549498
3 r30_inward 0 0.16812279429621627 ref_tol1e-13_h0.125 1 1 4294967295 -142.17574845681202 3332 0 23611 0 0 0 0 8.0000000000000249 8.0658840965825735 0.065884096582549498
4 r30_inward 0 0.16812279429621627 tol1e-11_h2 1 1 4294967295 -142.17574172483768 1304 0 9415 0 0 0 0 8.0000000000000266 8.0658840965825753 0.065884096582549498
5 r30_inward 0 0.16812279429621627 tol1e-11_h8 1 1 4294967295 -142.17574172483768 1304 0 9415 0 0 0 0 8.0000000000000266 8.0658840965825753 0.065884096582549498
6 r30_inward 1 0.16812289429621627 ref_tol1e-12_h0.25 1 1 4294967295 -225.85293500418322 3746 0 26509 0 0 0 0 8.0000000000000338 8.0658840955358357 0.065884095535802364
7 r30_inward 1 0.16812289429621627 ref_tol1e-13_h0.125 1 1 4294967295 -238.90906331559862 6388 0 45003 0 0 0 0 8.000000000000016 8.065884095535818 0.065884095535802364
8 r30_inward 1 0.16812289429621627 tol1e-11_h2 1 1 4294967295 -212.59582609170599 2180 0 15547 0 0 0 0 8.0000000000000071 8.0658840955358091 0.065884095535802364
9 r30_inward 1 0.16812289429621627 tol1e-11_h8 1 1 4294967295 -212.59582609170599 2180 0 15547 0 0 0 0 8.0000000000000071 8.0658840955358091 0.065884095535802364
10 r30_inward 2 0.16812299429621627 ref_tol1e-12_h0.25 0 0 0 -370.18047830118235 2790 1 19831 -0.35873499147611138 -6.5068267720987458e-16 -0.9334394495041628 1.0350983390130453 nan -0.038385896473527227 0.065884094489054593
11 r30_inward 2 0.16812299429621627 ref_tol1e-13_h0.125 0 0 0 -370.1804778092 4857 1 34300 -0.35873507984449715 -6.5068265353608199e-16 -0.93343941554284182 1.035098339013504 nan -0.038385896473972475 0.065884094489054593
12 r30_inward 2 0.16812299429621627 tol1e-11_h2 0 0 0 -370.18048452857704 1299 1 9387 -0.3587338729380895 -6.5068297686427377e-16 -0.93343987937458439 1.0350983390054869 nan -0.038385896466199748 0.065884094489054593
13 r30_inward 2 0.16812299429621627 tol1e-11_h8 0 0 0 -370.1804845285946 1257 1 9100 -0.35873387293809145 -6.5068297686427416e-16 -0.93343987937458361 1.035098339005424 nan -0.038385896466138665 0.065884094489054593
14 r100_inward 0 0.051461896376274734 ref_tol1e-12_h0.25 1 1 4294967295 -211.027405235164 2252 0 16051 0 0 0 0 8.0000000000000266 8.0199767087115159 0.01997670871149013
15 r100_inward 0 0.051461896376274734 ref_tol1e-13_h0.125 1 1 4294967295 -211.02740538583069 3727 0 26376 0 0 0 0 8.0000000000000142 8.0199767087115035 0.01997670871149013
16 r100_inward 0 0.051461896376274734 tol1e-11_h2 1 1 4294967295 -211.02740354768991 1292 0 9331 0 0 0 0 8.0000000000000533 8.0199767087115426 0.01997670871149013
17 r100_inward 0 0.051461896376274734 tol1e-11_h8 1 1 4294967295 -211.02740354768991 1292 0 9331 0 0 0 0 8.0000000000000533 8.0199767087115426 0.01997670871149013
18 r100_inward 1 0.051461996376274736 ref_tol1e-12_h0.25 1 1 4294967295 -301.07740508539132 4045 0 28602 0 0 0 0 8.0000000000000018 8.0199767086106277 0.019976708610626077
19 r100_inward 1 0.051461996376274736 ref_tol1e-13_h0.125 1 1 4294967295 -313.77734009633099 6986 0 49189 0 0 0 0 8.0000000000000018 8.0199767086106277 0.019976708610626077
20 r100_inward 1 0.051461996376274736 tol1e-11_h2 1 1 4294967295 -288.21364790845217 2256 0 16079 0 0 0 0 8.0000000000000639 8.0199767086106899 0.019976708610626077
21 r100_inward 1 0.051461996376274736 tol1e-11_h8 1 1 4294967295 -288.21364790845217 2256 0 16079 0 0 0 0 8.0000000000000639 8.0199767086106899 0.019976708610626077
22 r100_inward 2 0.051462096376274739 ref_tol1e-12_h0.25 0 0 0 -439.31355204311825 2969 0 21077 -0.99110324423183982 -3.1326762563025509e-16 -0.13309530146899301 1.0101525445517785 nan -0.013990814384499865 0.019976708509762027
23 r100_inward 2 0.051462096376274739 ref_tol1e-13_h0.125 0 0 0 -439.31355190087947 5265 0 37149 -0.99110324787406912 -3.132675617927086e-16 -0.13309527434688151 1.010152544552184 nan -0.013990814384902493 0.019976708509762027
24 r100_inward 2 0.051462096376274739 tol1e-11_h2 0 0 0 -439.31355372933643 1291 1 9338 -0.99110320105936889 -3.1326838231562615e-16 -0.13309562295534913 1.010152544545182 nan -0.013990814377948021 0.019976708509762027
25 r100_inward 2 0.051462096376274739 tol1e-11_h8 0 0 0 -439.31355372935258 1250 1 9051 -0.991103201059369 -3.1326838231562231e-16 -0.13309562295534744 1.0101525445451216 nan -0.013990814377887956 0.019976708509762027
26 r2p1_outward 0 0.57037671003940071 ref_tol1e-12_h0.25 0 0 0 -333.45070432558816 2639 1 18774 -0.30976840652656795 0 -0.95081203942629522 4.5825756949539365 nan -1.5261506795942201 -0.42981831573151047
27 r2p1_outward 0 0.57037671003940071 ref_tol1e-13_h0.125 0 0 0 -333.45070506871724 4589 2 32431 -0.30976827139480229 0 -0.95081208345133916 4.5825756949557528 nan -1.5261506795946143 -0.42981831573151047
28 r2p1_outward 0 0.57037671003940071 tol1e-11_h2 0 0 0 -333.45070071486469 1210 2 8778 -0.30976906608911198 0 -0.95081182454483582 4.5825756949192931 nan -1.5261506795866686 -0.42981831573151047
29 r2p1_outward 0 0.57037671003940071 tol1e-11_h8 0 0 0 -333.45070071488124 1169 2 8491 -0.30976906647032454 0 -0.95081182442063883 4.5825756949190151 nan -1.5261506795866076 -0.42981831573151047
30 r2p1_outward 1 0.57037681003940066 ref_tol1e-12_h0.25 0 0 0 -414.94010328784253 4263 2 30149 0.3336576345143959 0 0.94269432104487505 4.5825756949507124 nan -1.5261506795930104 -0.42981805651739968
31 r2p1_outward 1 0.57037681003940066 ref_tol1e-13_h0.125 0 0 0 -427.08073320404128 7560 1 53221 -0.91087431940825703 0 -0.41268386719442363 4.5825756949554943 nan -1.5261506795940556 -0.42981805651739968
32 r2p1_outward 1 0.57037681003940066 tol1e-11_h2 0 0 0 -406.06581257014602 2120 2 15141 0.88820167266587602 0 -0.45945379383953305 4.58257569487448 nan -1.5261506795763404 -0.42981805651739968
33 r2p1_outward 1 0.57037681003940066 tol1e-11_h8 0 0 0 -406.06581257016262 2078 2 14854 0.88817826517728515 0 -0.4594990416384655 4.5825756948742002 nan -1.5261506795762789 -0.42981805651739968
34 r2p1_outward 2 0.57037691003940061 ref_tol1e-12_h0.25 1 1 4294967295 -109.41561097431348 1950 1 13944 0 0 0 0 8.0000000000000195 7.5701822026967047 -0.42981779730331554
35 r2p1_outward 2 0.57037691003940061 ref_tol1e-13_h0.125 1 1 4294967295 -109.41561022532379 3098 1 21980 0 0 0 0 8.000000000000016 7.5701822026967012 -0.42981779730331554
36 r2p1_outward 2 0.57037691003940061 tol1e-11_h2 1 1 4294967295 -109.41561457850582 1228 1 8890 0 0 0 0 8.0000000000000195 7.5701822026967038 -0.42981779730331554
37 r2p1_outward 2 0.57037691003940061 tol1e-11_h8 1 1 4294967295 -109.41561457850582 1228 1 8890 0 0 0 0 8.0000000000000195 7.5701822026967038 -0.42981779730331554
@@ -0,0 +1,96 @@
### building critical_ref_check
+ cc -std=c11 -O2 -Wall -Wextra -Wpedantic -I/home/wyj/Code/C/GR_4d_raytracing/src /home/wyj/Code/C/GR_4d_raytracing/benchmarks/adaptive_step_bounds_2026-10-05/critical_ref_check.c /home/wyj/Code/C/GR_4d_raytracing/src/geodesic.c /home/wyj/Code/C/GR_4d_raytracing/src/asymptotic.c /home/wyj/Code/C/GR_4d_raytracing/src/asymptotic_schwarzschild.c /home/wyj/Code/C/GR_4d_raytracing/src/spacetime_common.c /home/wyj/Code/C/GR_4d_raytracing/src/observer.c -lm -o /tmp/opencode/step_bounds/critical_ref_check
+ echo '### command: critical_ref_check'
### command: critical_ref_check
+ /tmp/opencode/step_bounds/critical_ref_check
RAW camera=r30_inward dir=0 theta=0.16812279429621627 cfg=ref_tol1e-12_h0.25 outcome=1 reason=1 end=4294967295 stop_t=-142.17574796859728 steps=2081 rejected=0 rhs=14854 g=0 thr=8.0000000000000195 L=8.0658840965825682 L0=0.065884096582549498 nx=0 ny=0 nz=0
RAW camera=r30_inward dir=0 theta=0.16812279429621627 cfg=ref_tol1e-13_h0.125 outcome=1 reason=1 end=4294967295 stop_t=-142.17574845681202 steps=3332 rejected=0 rhs=23611 g=0 thr=8.0000000000000249 L=8.0658840965825735 L0=0.065884096582549498 nx=0 ny=0 nz=0
RAW camera=r30_inward dir=0 theta=0.16812279429621627 cfg=tol1e-11_h2 outcome=1 reason=1 end=4294967295 stop_t=-142.17574172483768 steps=1304 rejected=0 rhs=9415 g=0 thr=8.0000000000000266 L=8.0658840965825753 L0=0.065884096582549498 nx=0 ny=0 nz=0
RAW camera=r30_inward dir=0 theta=0.16812279429621627 cfg=tol1e-11_h8 outcome=1 reason=1 end=4294967295 stop_t=-142.17574172483768 steps=1304 rejected=0 rhs=9415 g=0 thr=8.0000000000000266 L=8.0658840965825753 L0=0.065884096582549498 nx=0 ny=0 nz=0
RAW camera=r30_inward dir=1 theta=0.16812289429621627 cfg=ref_tol1e-12_h0.25 outcome=1 reason=1 end=4294967295 stop_t=-225.85293500418322 steps=3746 rejected=0 rhs=26509 g=0 thr=8.0000000000000338 L=8.0658840955358357 L0=0.065884095535802364 nx=0 ny=0 nz=0
RAW camera=r30_inward dir=1 theta=0.16812289429621627 cfg=ref_tol1e-13_h0.125 outcome=1 reason=1 end=4294967295 stop_t=-238.90906331559862 steps=6388 rejected=0 rhs=45003 g=0 thr=8.000000000000016 L=8.065884095535818 L0=0.065884095535802364 nx=0 ny=0 nz=0
RAW camera=r30_inward dir=1 theta=0.16812289429621627 cfg=tol1e-11_h2 outcome=1 reason=1 end=4294967295 stop_t=-212.59582609170599 steps=2180 rejected=0 rhs=15547 g=0 thr=8.0000000000000071 L=8.0658840955358091 L0=0.065884095535802364 nx=0 ny=0 nz=0
RAW camera=r30_inward dir=1 theta=0.16812289429621627 cfg=tol1e-11_h8 outcome=1 reason=1 end=4294967295 stop_t=-212.59582609170599 steps=2180 rejected=0 rhs=15547 g=0 thr=8.0000000000000071 L=8.0658840955358091 L0=0.065884095535802364 nx=0 ny=0 nz=0
RAW camera=r30_inward dir=2 theta=0.16812299429621627 cfg=ref_tol1e-12_h0.25 outcome=0 reason=0 end=0 stop_t=-370.18047830118235 steps=2790 rejected=1 rhs=19831 g=1.0350983390130453 thr=nan L=-0.038385896473527227 L0=0.065884094489054593 nx=-0.35873499147611138 ny=-6.5068267720987458e-16 nz=-0.9334394495041628
RAW camera=r30_inward dir=2 theta=0.16812299429621627 cfg=ref_tol1e-13_h0.125 outcome=0 reason=0 end=0 stop_t=-370.1804778092 steps=4857 rejected=1 rhs=34300 g=1.035098339013504 thr=nan L=-0.038385896473972475 L0=0.065884094489054593 nx=-0.35873507984449715 ny=-6.5068265353608199e-16 nz=-0.93343941554284182
RAW camera=r30_inward dir=2 theta=0.16812299429621627 cfg=tol1e-11_h2 outcome=0 reason=0 end=0 stop_t=-370.18048452857704 steps=1299 rejected=1 rhs=9387 g=1.0350983390054869 thr=nan L=-0.038385896466199748 L0=0.065884094489054593 nx=-0.3587338729380895 ny=-6.5068297686427377e-16 nz=-0.93343987937458439
RAW camera=r30_inward dir=2 theta=0.16812299429621627 cfg=tol1e-11_h8 outcome=0 reason=0 end=0 stop_t=-370.1804845285946 steps=1257 rejected=1 rhs=9100 g=1.035098339005424 thr=nan L=-0.038385896466138665 L0=0.065884094489054593 nx=-0.35873387293809145 ny=-6.5068297686427416e-16 nz=-0.93343987937458361
RAW camera=r100_inward dir=0 theta=0.051461896376274734 cfg=ref_tol1e-12_h0.25 outcome=1 reason=1 end=4294967295 stop_t=-211.027405235164 steps=2252 rejected=0 rhs=16051 g=0 thr=8.0000000000000266 L=8.0199767087115159 L0=0.01997670871149013 nx=0 ny=0 nz=0
RAW camera=r100_inward dir=0 theta=0.051461896376274734 cfg=ref_tol1e-13_h0.125 outcome=1 reason=1 end=4294967295 stop_t=-211.02740538583069 steps=3727 rejected=0 rhs=26376 g=0 thr=8.0000000000000142 L=8.0199767087115035 L0=0.01997670871149013 nx=0 ny=0 nz=0
RAW camera=r100_inward dir=0 theta=0.051461896376274734 cfg=tol1e-11_h2 outcome=1 reason=1 end=4294967295 stop_t=-211.02740354768991 steps=1292 rejected=0 rhs=9331 g=0 thr=8.0000000000000533 L=8.0199767087115426 L0=0.01997670871149013 nx=0 ny=0 nz=0
RAW camera=r100_inward dir=0 theta=0.051461896376274734 cfg=tol1e-11_h8 outcome=1 reason=1 end=4294967295 stop_t=-211.02740354768991 steps=1292 rejected=0 rhs=9331 g=0 thr=8.0000000000000533 L=8.0199767087115426 L0=0.01997670871149013 nx=0 ny=0 nz=0
RAW camera=r100_inward dir=1 theta=0.051461996376274736 cfg=ref_tol1e-12_h0.25 outcome=1 reason=1 end=4294967295 stop_t=-301.07740508539132 steps=4045 rejected=0 rhs=28602 g=0 thr=8.0000000000000018 L=8.0199767086106277 L0=0.019976708610626077 nx=0 ny=0 nz=0
RAW camera=r100_inward dir=1 theta=0.051461996376274736 cfg=ref_tol1e-13_h0.125 outcome=1 reason=1 end=4294967295 stop_t=-313.77734009633099 steps=6986 rejected=0 rhs=49189 g=0 thr=8.0000000000000018 L=8.0199767086106277 L0=0.019976708610626077 nx=0 ny=0 nz=0
RAW camera=r100_inward dir=1 theta=0.051461996376274736 cfg=tol1e-11_h2 outcome=1 reason=1 end=4294967295 stop_t=-288.21364790845217 steps=2256 rejected=0 rhs=16079 g=0 thr=8.0000000000000639 L=8.0199767086106899 L0=0.019976708610626077 nx=0 ny=0 nz=0
RAW camera=r100_inward dir=1 theta=0.051461996376274736 cfg=tol1e-11_h8 outcome=1 reason=1 end=4294967295 stop_t=-288.21364790845217 steps=2256 rejected=0 rhs=16079 g=0 thr=8.0000000000000639 L=8.0199767086106899 L0=0.019976708610626077 nx=0 ny=0 nz=0
RAW camera=r100_inward dir=2 theta=0.051462096376274739 cfg=ref_tol1e-12_h0.25 outcome=0 reason=0 end=0 stop_t=-439.31355204311825 steps=2969 rejected=0 rhs=21077 g=1.0101525445517785 thr=nan L=-0.013990814384499865 L0=0.019976708509762027 nx=-0.99110324423183982 ny=-3.1326762563025509e-16 nz=-0.13309530146899301
RAW camera=r100_inward dir=2 theta=0.051462096376274739 cfg=ref_tol1e-13_h0.125 outcome=0 reason=0 end=0 stop_t=-439.31355190087947 steps=5265 rejected=0 rhs=37149 g=1.010152544552184 thr=nan L=-0.013990814384902493 L0=0.019976708509762027 nx=-0.99110324787406912 ny=-3.132675617927086e-16 nz=-0.13309527434688151
RAW camera=r100_inward dir=2 theta=0.051462096376274739 cfg=tol1e-11_h2 outcome=0 reason=0 end=0 stop_t=-439.31355372933643 steps=1291 rejected=1 rhs=9338 g=1.010152544545182 thr=nan L=-0.013990814377948021 L0=0.019976708509762027 nx=-0.99110320105936889 ny=-3.1326838231562615e-16 nz=-0.13309562295534913
RAW camera=r100_inward dir=2 theta=0.051462096376274739 cfg=tol1e-11_h8 outcome=0 reason=0 end=0 stop_t=-439.31355372935258 steps=1250 rejected=1 rhs=9051 g=1.0101525445451216 thr=nan L=-0.013990814377887956 L0=0.019976708509762027 nx=-0.991103201059369 ny=-3.1326838231562231e-16 nz=-0.13309562295534744
RAW camera=r2p1_outward dir=0 theta=0.57037671003940071 cfg=ref_tol1e-12_h0.25 outcome=0 reason=0 end=0 stop_t=-333.45070432558816 steps=2639 rejected=1 rhs=18774 g=4.5825756949539365 thr=nan L=-1.5261506795942201 L0=-0.42981831573151047 nx=-0.30976840652656795 ny=0 nz=-0.95081203942629522
RAW camera=r2p1_outward dir=0 theta=0.57037671003940071 cfg=ref_tol1e-13_h0.125 outcome=0 reason=0 end=0 stop_t=-333.45070506871724 steps=4589 rejected=2 rhs=32431 g=4.5825756949557528 thr=nan L=-1.5261506795946143 L0=-0.42981831573151047 nx=-0.30976827139480229 ny=0 nz=-0.95081208345133916
RAW camera=r2p1_outward dir=0 theta=0.57037671003940071 cfg=tol1e-11_h2 outcome=0 reason=0 end=0 stop_t=-333.45070071486469 steps=1210 rejected=2 rhs=8778 g=4.5825756949192931 thr=nan L=-1.5261506795866686 L0=-0.42981831573151047 nx=-0.30976906608911198 ny=0 nz=-0.95081182454483582
RAW camera=r2p1_outward dir=0 theta=0.57037671003940071 cfg=tol1e-11_h8 outcome=0 reason=0 end=0 stop_t=-333.45070071488124 steps=1169 rejected=2 rhs=8491 g=4.5825756949190151 thr=nan L=-1.5261506795866076 L0=-0.42981831573151047 nx=-0.30976906647032454 ny=0 nz=-0.95081182442063883
RAW camera=r2p1_outward dir=1 theta=0.57037681003940066 cfg=ref_tol1e-12_h0.25 outcome=0 reason=0 end=0 stop_t=-414.94010328784253 steps=4263 rejected=2 rhs=30149 g=4.5825756949507124 thr=nan L=-1.5261506795930104 L0=-0.42981805651739968 nx=0.3336576345143959 ny=0 nz=0.94269432104487505
RAW camera=r2p1_outward dir=1 theta=0.57037681003940066 cfg=ref_tol1e-13_h0.125 outcome=0 reason=0 end=0 stop_t=-427.08073320404128 steps=7560 rejected=1 rhs=53221 g=4.5825756949554943 thr=nan L=-1.5261506795940556 L0=-0.42981805651739968 nx=-0.91087431940825703 ny=0 nz=-0.41268386719442363
RAW camera=r2p1_outward dir=1 theta=0.57037681003940066 cfg=tol1e-11_h2 outcome=0 reason=0 end=0 stop_t=-406.06581257014602 steps=2120 rejected=2 rhs=15141 g=4.58257569487448 thr=nan L=-1.5261506795763404 L0=-0.42981805651739968 nx=0.88820167266587602 ny=0 nz=-0.45945379383953305
RAW camera=r2p1_outward dir=1 theta=0.57037681003940066 cfg=tol1e-11_h8 outcome=0 reason=0 end=0 stop_t=-406.06581257016262 steps=2078 rejected=2 rhs=14854 g=4.5825756948742002 thr=nan L=-1.5261506795762789 L0=-0.42981805651739968 nx=0.88817826517728515 ny=0 nz=-0.4594990416384655
RAW camera=r2p1_outward dir=2 theta=0.57037691003940061 cfg=ref_tol1e-12_h0.25 outcome=1 reason=1 end=4294967295 stop_t=-109.41561097431348 steps=1950 rejected=1 rhs=13944 g=0 thr=8.0000000000000195 L=7.5701822026967047 L0=-0.42981779730331554 nx=0 ny=0 nz=0
RAW camera=r2p1_outward dir=2 theta=0.57037691003940061 cfg=ref_tol1e-13_h0.125 outcome=1 reason=1 end=4294967295 stop_t=-109.41561022532379 steps=3098 rejected=1 rhs=21980 g=0 thr=8.000000000000016 L=7.5701822026967012 L0=-0.42981779730331554 nx=0 ny=0 nz=0
RAW camera=r2p1_outward dir=2 theta=0.57037691003940061 cfg=tol1e-11_h2 outcome=1 reason=1 end=4294967295 stop_t=-109.41561457850582 steps=1228 rejected=1 rhs=8890 g=0 thr=8.0000000000000195 L=7.5701822026967038 L0=-0.42981779730331554 nx=0 ny=0 nz=0
RAW camera=r2p1_outward dir=2 theta=0.57037691003940061 cfg=tol1e-11_h8 outcome=1 reason=1 end=4294967295 stop_t=-109.41561457850582 steps=1228 rejected=1 rhs=8890 g=0 thr=8.0000000000000195 L=7.5701822026967038 L0=-0.42981779730331554 nx=0 ny=0 nz=0
CAPAIR camera=r30_inward dir=0 theta=0.16812279429621627 pair=ref_vs_tighter class=DARK/DARK same=1 dn_ang=nan dgrel=nan dstop_t=4.8821473797033832e-07 dthr=-5.3290705182007514e-15 end=4294967295/4294967295
CAPAIR camera=r30_inward dir=0 theta=0.16812279429621627 pair=h2_vs_h8 class=DARK/DARK same=1 dn_ang=nan dgrel=nan dstop_t=0 dthr=0 end=4294967295/4294967295
CAPAIR camera=r30_inward dir=0 theta=0.16812279429621627 pair=ref_vs_h2 class=DARK/DARK same=1 dn_ang=nan dgrel=nan dstop_t=-6.2437596000108897e-06 dthr=-7.1054273576010019e-15 end=4294967295/4294967295
CAPAIR camera=r30_inward dir=0 theta=0.16812279429621627 pair=ref_vs_h8 class=DARK/DARK same=1 dn_ang=nan dgrel=nan dstop_t=-6.2437596000108897e-06 dthr=-7.1054273576010019e-15 end=4294967295/4294967295
CAPAIR camera=r30_inward dir=1 theta=0.16812289429621627 pair=ref_vs_tighter class=DARK/DARK same=1 dn_ang=nan dgrel=nan dstop_t=13.056128311415392 dthr=1.7763568394002505e-14 end=4294967295/4294967295
CAPAIR camera=r30_inward dir=1 theta=0.16812289429621627 pair=h2_vs_h8 class=DARK/DARK same=1 dn_ang=nan dgrel=nan dstop_t=0 dthr=0 end=4294967295/4294967295
CAPAIR camera=r30_inward dir=1 theta=0.16812289429621627 pair=ref_vs_h2 class=DARK/DARK same=1 dn_ang=nan dgrel=nan dstop_t=-13.257108912477236 dthr=2.6645352591003757e-14 end=4294967295/4294967295
CAPAIR camera=r30_inward dir=1 theta=0.16812289429621627 pair=ref_vs_h8 class=DARK/DARK same=1 dn_ang=nan dgrel=nan dstop_t=-13.257108912477236 dthr=2.6645352591003757e-14 end=4294967295/4294967295
CAPAIR camera=r30_inward dir=2 theta=0.16812299429621627 pair=ref_vs_tighter class=ESC/ESC same=1 dn_ang=9.4669651562462453e-08 dgrel=4.4320103143036249e-13 dstop_t=-4.9198234819414211e-07 dthr=nan end=0/0
CAPAIR camera=r30_inward dir=2 theta=0.16812299429621627 pair=h2_vs_h8 class=ESC/ESC same=1 dn_ang=2.0539125955565396e-15 dgrel=6.0618177144533547e-14 dstop_t=1.7564616427989677e-11 dthr=nan end=0/0
CAPAIR camera=r30_inward dir=2 theta=0.16812299429621627 pair=ref_vs_h2 class=ESC/ESC same=1 dn_ang=1.198297077398556e-06 dgrel=7.3021588775645796e-12 dstop_t=6.2273946923596668e-06 dthr=nan end=0/0
CAPAIR camera=r30_inward dir=2 theta=0.16812299429621627 pair=ref_vs_h8 class=ESC/ESC same=1 dn_ang=1.1982970752891323e-06 dgrel=7.3627770547091131e-12 dstop_t=6.2274122569760948e-06 dthr=nan end=0/0
CAPAIR camera=r100_inward dir=0 theta=0.051461896376274734 pair=ref_vs_tighter class=DARK/DARK same=1 dn_ang=nan dgrel=nan dstop_t=1.5066669334373728e-07 dthr=1.2434497875801753e-14 end=4294967295/4294967295
CAPAIR camera=r100_inward dir=0 theta=0.051461896376274734 pair=h2_vs_h8 class=DARK/DARK same=1 dn_ang=nan dgrel=nan dstop_t=0 dthr=0 end=4294967295/4294967295
CAPAIR camera=r100_inward dir=0 theta=0.051461896376274734 pair=ref_vs_h2 class=DARK/DARK same=1 dn_ang=nan dgrel=nan dstop_t=-1.6874740822458989e-06 dthr=-2.6645352591003757e-14 end=4294967295/4294967295
CAPAIR camera=r100_inward dir=0 theta=0.051461896376274734 pair=ref_vs_h8 class=DARK/DARK same=1 dn_ang=nan dgrel=nan dstop_t=-1.6874740822458989e-06 dthr=-2.6645352591003757e-14 end=4294967295/4294967295
CAPAIR camera=r100_inward dir=1 theta=0.051461996376274736 pair=ref_vs_tighter class=DARK/DARK same=1 dn_ang=nan dgrel=nan dstop_t=12.699935010939669 dthr=0 end=4294967295/4294967295
CAPAIR camera=r100_inward dir=1 theta=0.051461996376274736 pair=h2_vs_h8 class=DARK/DARK same=1 dn_ang=nan dgrel=nan dstop_t=0 dthr=0 end=4294967295/4294967295
CAPAIR camera=r100_inward dir=1 theta=0.051461996376274736 pair=ref_vs_h2 class=DARK/DARK same=1 dn_ang=nan dgrel=nan dstop_t=-12.863757176939146 dthr=-6.2172489379008766e-14 end=4294967295/4294967295
CAPAIR camera=r100_inward dir=1 theta=0.051461996376274736 pair=ref_vs_h8 class=DARK/DARK same=1 dn_ang=nan dgrel=nan dstop_t=-12.863757176939146 dthr=-6.2172489379008766e-14 end=4294967295/4294967295
CAPAIR camera=r100_inward dir=2 theta=0.051462096376274739 pair=ref_vs_tighter class=ESC/ESC same=1 dn_ang=2.7365576305005138e-08 dgrel=4.0134562340199409e-13 dstop_t=-1.4223877542463015e-07 dthr=nan end=0/0
CAPAIR camera=r100_inward dir=2 theta=0.051462096376274739 pair=h2_vs_h8 class=ESC/ESC same=1 dn_ang=1.6930901125533633e-15 dgrel=5.9729998724833422e-14 dstop_t=1.6143530956469476e-11 dthr=nan end=0/0
CAPAIR camera=r100_inward dir=2 theta=0.051462096376274739 pair=ref_vs_h2 class=ESC/ESC same=1 dn_ang=3.243722235535319e-07 dgrel=6.5301097862402457e-12 dstop_t=1.6862181837495882e-06 dthr=nan end=0/0
CAPAIR camera=r100_inward dir=2 theta=0.051462096376274739 pair=ref_vs_h8 class=ESC/ESC same=1 dn_ang=3.2437222186044184e-07 dgrel=6.5900618295700042e-12 dstop_t=1.6862343272805447e-06 dthr=nan end=0/0
CAPAIR camera=r2p1_outward dir=0 theta=0.57037671003940071 pair=ref_vs_tighter class=ESC/ESC same=1 dn_ang=1.4212247739786624e-07 dgrel=3.9634961979118088e-13 dstop_t=7.4312907827334129e-07 dthr=nan end=0/0
CAPAIR camera=r2p1_outward dir=0 theta=0.57037671003940071 pair=h2_vs_h8 class=ESC/ESC same=1 dn_ang=4.0093378617100928e-10 dgrel=6.0618177144533547e-14 dstop_t=1.6541434888495132e-11 dthr=nan end=0/0
CAPAIR camera=r2p1_outward dir=0 theta=0.57037671003940071 pair=ref_vs_h2 class=ESC/ESC same=1 dn_ang=6.9368349486792499e-07 dgrel=7.5597306192776159e-12 dstop_t=-3.6107234677729139e-06 dthr=nan end=0/0
CAPAIR camera=r2p1_outward dir=0 theta=0.57037671003940071 pair=ref_vs_h8 class=ESC/ESC same=1 dn_ang=6.9408442870960736e-07 dgrel=7.6205708410270745e-12 dstop_t=-3.6107069263380254e-06 dthr=nan end=0/0
CAPAIR camera=r2p1_outward dir=1 theta=0.57037681003940066 pair=ref_vs_tighter class=ESC/ESC same=1 dn_ang=2.3363758065620761 dgrel=1.0434986208451846e-12 dstop_t=12.140629916198748 dthr=nan end=0/0
CAPAIR camera=r2p1_outward dir=1 theta=0.57037681003940066 pair=h2_vs_h8 class=ESC/ESC same=1 dn_ang=5.0943830155578499e-05 dgrel=6.106226635438361e-14 dstop_t=1.659827830735594e-11 dthr=nan end=0/0
CAPAIR camera=r2p1_outward dir=1 theta=0.57037681003940066 pair=ref_vs_h2 class=ESC/ESC same=1 dn_ang=1.7079955663413957 dgrel=1.6635359756378421e-11 dstop_t=-8.8742907176965105 dthr=nan end=0/0
CAPAIR camera=r2p1_outward dir=1 theta=0.57037681003940066 pair=ref_vs_h8 class=ESC/ESC same=1 dn_ang=1.7080465101715514 dgrel=1.6696422022732804e-11 dstop_t=-8.8742907176799122 dthr=nan end=0/0
CAPAIR camera=r2p1_outward dir=2 theta=0.57037691003940061 pair=ref_vs_tighter class=DARK/DARK same=1 dn_ang=nan dgrel=nan dstop_t=-7.4898969160130946e-07 dthr=3.5527136788005009e-15 end=4294967295/4294967295
CAPAIR camera=r2p1_outward dir=2 theta=0.57037691003940061 pair=h2_vs_h8 class=DARK/DARK same=1 dn_ang=nan dgrel=nan dstop_t=0 dthr=0 end=4294967295/4294967295
CAPAIR camera=r2p1_outward dir=2 theta=0.57037691003940061 pair=ref_vs_h2 class=DARK/DARK same=1 dn_ang=nan dgrel=nan dstop_t=3.6041923436869183e-06 dthr=0 end=4294967295/4294967295
CAPAIR camera=r2p1_outward dir=2 theta=0.57037691003940061 pair=ref_vs_h8 class=DARK/DARK same=1 dn_ang=nan dgrel=nan dstop_t=3.6041923436869183e-06 dthr=0 end=4294967295/4294967295
EXACT_CRITICAL_DIRECTION camera=r30_inward theta=0.16812289429621627 ref0=DARK/1/4294967295 ref1=DARK/1/4294967295 same=1 dn_ang=nan dstop_t=13.056128311415392
EXACT_CRITICAL_REFERENCE_NOT_CONVERGED camera=r30_inward dn_ang=nan dstop_t=13.056128311415392 class_same=1
EXACT_CRITICAL_DIRECTION camera=r100_inward theta=0.051461996376274736 ref0=DARK/1/4294967295 ref1=DARK/1/4294967295 same=1 dn_ang=nan dstop_t=12.699935010939669
EXACT_CRITICAL_REFERENCE_NOT_CONVERGED camera=r100_inward dn_ang=nan dstop_t=12.699935010939669 class_same=1
EXACT_CRITICAL_DIRECTION camera=r2p1_outward theta=0.57037681003940066 ref0=ESC/0/0 ref1=ESC/0/0 same=1 dn_ang=2.3363758065620761 dstop_t=12.140629916198748
EXACT_CRITICAL_REFERENCE_NOT_CONVERGED camera=r2p1_outward dn_ang=2.3363758065620761 dstop_t=12.140629916198748 class_same=1
NEIGHBOR_REFERENCE_CHECK camera=r30_inward dir=0 theta=0.16812279429621627 ref_class0=DARK/1/4294967295 ref_class1=DARK/1/4294967295 same=1 clean=1 stepped=1 dn_ang=nan dgrel=nan dstop_t=4.8821473797033832e-07
NEIGHBOR_REFERENCE_CHECK camera=r30_inward dir=2 theta=0.16812299429621627 ref_class0=ESC/0/0 ref_class1=ESC/0/0 same=1 clean=1 stepped=1 dn_ang=9.4669651562462453e-08 dgrel=4.4320103143036249e-13 dstop_t=-4.9198234819414211e-07
NEIGHBOR_REFERENCE_CHECK camera=r100_inward dir=0 theta=0.051461896376274734 ref_class0=DARK/1/4294967295 ref_class1=DARK/1/4294967295 same=1 clean=1 stepped=1 dn_ang=nan dgrel=nan dstop_t=1.5066669334373728e-07
NEIGHBOR_REFERENCE_CHECK camera=r100_inward dir=2 theta=0.051462096376274739 ref_class0=ESC/0/0 ref_class1=ESC/0/0 same=1 clean=1 stepped=1 dn_ang=2.7365576305005138e-08 dgrel=4.0134562340199409e-13 dstop_t=-1.4223877542463015e-07
NEIGHBOR_REFERENCE_CHECK camera=r2p1_outward dir=0 theta=0.57037671003940071 ref_class0=ESC/0/0 ref_class1=ESC/0/0 same=1 clean=1 stepped=1 dn_ang=1.4212247739786624e-07 dgrel=3.9634961979118088e-13 dstop_t=7.4312907827334129e-07
NEIGHBOR_REFERENCE_CHECK camera=r2p1_outward dir=2 theta=0.57037691003940061 ref_class0=DARK/1/4294967295 ref_class1=DARK/1/4294967295 same=1 clean=1 stepped=1 dn_ang=nan dgrel=nan dstop_t=-7.4898969160130946e-07
CRITICAL_REFERENCE_CHECK status=0
CRITICAL_REF_DONE
real 0m0.418s
user 0m0.402s
sys 0m0.016s
+ set +x
@@ -0,0 +1,271 @@
### command: a_public schwarzschild
+ /tmp/opencode/step_bounds/a_public schwarzschild
REF r30_inward dir=0 theta=0 outcome=1 reason=1 stop_t=-69.5728394 steps=531 rejected=0 rhs=4004 g=0 thr=8
REF r30_inward dir=1 theta=3.14159 outcome=0 reason=0 stop_t=-226 steps=905 rejected=0 rhs=6629 g=1.03509833901 thr=nan
REF r30_inward dir=2 theta=1.5708 outcome=0 reason=0 stop_t=-256.70592 steps=1028 rejected=0 rhs=7490 g=1.03509833901 thr=nan
REF r30_inward dir=3 theta=0.168123 outcome=1 reason=1 stop_t=-225.852935 steps=3746 rejected=0 rhs=26509 g=0 thr=8
REF r30_inward dir=4 theta=0.167123 outcome=1 reason=1 stop_t=-94.2779103 steps=1127 rejected=0 rhs=8176 g=0 thr=8
REF r30_inward dir=5 theta=0.169123 outcome=0 reason=0 stop_t=-322.366447 steps=1834 rejected=0 rhs=13132 g=1.03509833901 thr=nan
REF r30_inward dir=6 theta=0.168113 outcome=1 reason=1 stop_t=-118.245807 steps=1606 rejected=0 rhs=11529 g=0 thr=8
REF r30_inward dir=7 theta=0.168133 outcome=0 reason=0 stop_t=-346.252134 steps=2312 rejected=1 rhs=16485 g=1.03509833901 thr=nan
REF r30_inward dir=8 theta=0.168123 outcome=1 reason=1 stop_t=-142.175748 steps=2081 rejected=0 rhs=14854 g=0 thr=8
REF r30_inward dir=9 theta=0.168123 outcome=0 reason=0 stop_t=-370.180478 steps=2790 rejected=1 rhs=19831 g=1.03509833901 thr=nan
REF r30_inward dir=10 theta=0.218123 outcome=0 reason=0 stop_t=-302.584521 steps=1409 rejected=1 rhs=10164 g=1.03509833901 thr=nan
REF r30_inward dir=11 theta=0.118123 outcome=1 reason=1 stop_t=-73.7563113 steps=665 rejected=0 rhs=4942 g=0 thr=8
REF r100_inward dir=0 theta=0 outcome=1 reason=1 stop_t=-144.299101 steps=830 rejected=0 rhs=6097 g=0 thr=8
REF r100_inward dir=1 theta=3.14159 outcome=0 reason=0 stop_t=-156 steps=625 rejected=0 rhs=4669 g=1.01015254455 thr=nan
REF r100_inward dir=2 theta=1.5708 outcome=0 reason=0 stop_t=-237.678408 steps=952 rejected=0 rhs=6958 g=1.01015254455 thr=nan
REF r100_inward dir=3 theta=0.051462 outcome=1 reason=1 stop_t=-301.077405 steps=4045 rejected=0 rhs=28602 g=0 thr=8
REF r100_inward dir=4 theta=0.050462 outcome=1 reason=1 stop_t=-163.061409 steps=1292 rejected=0 rhs=9331 g=0 thr=8
REF r100_inward dir=5 theta=0.052462 outcome=0 reason=0 stop_t=-391.57927 steps=2014 rejected=1 rhs=14399 g=1.01015254455 thr=nan
REF r100_inward dir=6 theta=0.051452 outcome=1 reason=1 stop_t=-187.095903 steps=1773 rejected=0 rhs=12698 g=0 thr=8
REF r100_inward dir=7 theta=0.051472 outcome=0 reason=0 stop_t=-415.386875 steps=2493 rejected=0 rhs=17745 g=1.01015254455 thr=nan
REF r100_inward dir=8 theta=0.0514619 outcome=1 reason=1 stop_t=-211.027405 steps=2252 rejected=0 rhs=16051 g=0 thr=8
REF r100_inward dir=9 theta=0.0514621 outcome=0 reason=0 stop_t=-439.313552 steps=2969 rejected=0 rhs=21077 g=1.01015254455 thr=nan
REF r100_inward dir=10 theta=0.101462 outcome=0 reason=0 stop_t=-372.348056 steps=1571 rejected=0 rhs=11291 g=1.01015254455 thr=nan
REF r100_inward dir=11 theta=0.001462 outcome=1 reason=1 stop_t=-144.304446 steps=830 rejected=0 rhs=6097 g=0 thr=8
REF r2p1_outward dir=0 theta=0 outcome=0 reason=0 stop_t=-253.9 steps=1120 rejected=1 rhs=8141 g=4.58257569496 thr=nan
REF r2p1_outward dir=1 theta=3.14159 outcome=1 reason=1 stop_t=-32.2468847 steps=186 rejected=0 rhs=1589 g=0 thr=8
REF r2p1_outward dir=2 theta=1.5708 outcome=1 reason=1 stop_t=-32.7725901 steps=316 rejected=1 rhs=2506 g=0 thr=8
REF r2p1_outward dir=3 theta=0.570377 outcome=0 reason=0 stop_t=-414.940103 steps=4263 rejected=2 rhs=30149 g=4.58257569495 thr=nan
REF r2p1_outward dir=4 theta=0.569377 outcome=0 reason=0 stop_t=-285.577403 steps=1686 rejected=1 rhs=12103 g=4.58257569496 thr=nan
REF r2p1_outward dir=5 theta=0.571377 outcome=1 reason=1 stop_t=-61.5813727 steps=995 rejected=1 rhs=7259 g=0 thr=8
REF r2p1_outward dir=6 theta=0.570367 outcome=0 reason=0 stop_t=-309.521289 steps=2162 rejected=2 rhs=15442 g=4.58257569495 thr=nan
REF r2p1_outward dir=7 theta=0.570387 outcome=1 reason=1 stop_t=-85.4867841 steps=1474 rejected=1 rhs=10612 g=0 thr=8
REF r2p1_outward dir=8 theta=0.570377 outcome=0 reason=0 stop_t=-333.450704 steps=2639 rejected=1 rhs=18774 g=4.58257569495 thr=nan
REF r2p1_outward dir=9 theta=0.570377 outcome=1 reason=1 stop_t=-109.415611 steps=1950 rejected=1 rhs=13944 g=0 thr=8
REF r2p1_outward dir=10 theta=0.620377 outcome=1 reason=1 stop_t=-41.9883684 steps=585 rejected=1 rhs=4389 g=0 thr=8
REF r2p1_outward dir=11 theta=0.520377 outcome=0 reason=0 stop_t=-264.96182 steps=1303 rejected=2 rhs=9429 g=4.58257569496 thr=nan
REF r1p5_freefall dir=0 theta=0 outcome=1 reason=1 stop_t=-30.6580907 steps=231 rejected=1 rhs=1911 g=0 thr=8
REF r1p5_freefall dir=1 theta=1.5708 outcome=0 reason=0 stop_t=-255.249558 steps=1130 rejected=1 rhs=8211 g=1 thr=nan
REF r1p5_freefall dir=2 theta=3.14159 outcome=0 reason=0 stop_t=-254.5 steps=1143 rejected=1 rhs=8302 g=0.464101615138 thr=nan
REF r1p5_freefall dir=3 theta=2.35619 outcome=0 reason=0 stop_t=-254.612997 steps=1127 rejected=1 rhs=8190 g=0.550510257217 thr=nan
SUMMARY upper r30_inward upper=0.25 min=1e-12 n=12 mismatch=0 max_dn_ang=8.66705e-05 max_dgrel=2.2616e-09 max_dstopT=35.0811 sum_rhs=76510 esc=6 dark=6 unres=0 inc=0 wall=0.041s
SUMMARY upper r30_inward upper=0.5 min=1e-12 n=12 mismatch=0 max_dn_ang=0.00018656 max_dgrel=2.26833e-09 max_dstopT=39.0614 sum_rhs=49063 esc=6 dark=6 unres=0 inc=0 wall=0.027s
SUMMARY upper r30_inward upper=1 min=1e-12 n=12 mismatch=0 max_dn_ang=0.000280143 max_dgrel=2.2658e-09 max_dstopT=41.1726 sum_rhs=36974 esc=6 dark=6 unres=0 inc=0 wall=0.020s
SUMMARY upper r30_inward upper=2 min=1e-12 n=12 mismatch=0 max_dn_ang=0.000281866 max_dgrel=2.24374e-09 max_dstopT=41.2044 sum_rhs=31843 esc=6 dark=6 unres=0 inc=0 wall=0.017s
SUMMARY upper r30_inward upper=4 min=1e-12 n=12 mismatch=0 max_dn_ang=0.000281866 max_dgrel=2.24952e-09 max_dstopT=41.2044 sum_rhs=29617 esc=6 dark=6 unres=0 inc=0 wall=0.016s
SUMMARY upper r30_inward upper=8 min=1e-12 n=12 mismatch=0 max_dn_ang=0.000281866 max_dgrel=2.25767e-09 max_dstopT=41.2044 sum_rhs=28714 esc=6 dark=6 unres=0 inc=0 wall=0.016s
SUMMARY upper r30_inward upper=16 min=1e-12 n=12 mismatch=0 max_dn_ang=0.000281866 max_dgrel=2.26556e-09 max_dstopT=41.2044 sum_rhs=28455 esc=6 dark=6 unres=0 inc=0 wall=0.015s
SUMMARY upper r30_inward upper=32 min=1e-12 n=12 mismatch=0 max_dn_ang=0.000281866 max_dgrel=2.26605e-09 max_dstopT=41.2044 sum_rhs=28434 esc=6 dark=6 unres=0 inc=0 wall=0.015s
SUMMARY upper r30_inward upper=64 min=1e-12 n=12 mismatch=0 max_dn_ang=0.000281866 max_dgrel=2.26605e-09 max_dstopT=41.2044 sum_rhs=28434 esc=6 dark=6 unres=0 inc=0 wall=0.015s
SUMMARY upper r100_inward upper=0.25 min=1e-12 n=12 mismatch=0 max_dn_ang=2.60363e-05 max_dgrel=2.04765e-09 max_dstopT=35.2041 sum_rhs=93464 esc=6 dark=6 unres=0 inc=0 wall=0.050s
SUMMARY upper r100_inward upper=0.5 min=1e-12 n=12 mismatch=0 max_dn_ang=5.69583e-05 max_dgrel=2.05623e-09 max_dstopT=39.2691 sum_rhs=56595 esc=6 dark=6 unres=0 inc=0 wall=0.030s
SUMMARY upper r100_inward upper=1 min=1e-12 n=12 mismatch=0 max_dn_ang=8.34774e-05 max_dgrel=2.05088e-09 max_dstopT=41.2546 sum_rhs=39788 esc=6 dark=6 unres=0 inc=0 wall=0.022s
SUMMARY upper r100_inward upper=2 min=1e-12 n=12 mismatch=0 max_dn_ang=8.28604e-05 max_dgrel=2.0262e-09 max_dstopT=41.2161 sum_rhs=32389 esc=6 dark=6 unres=0 inc=0 wall=0.018s
SUMMARY upper r100_inward upper=4 min=1e-12 n=12 mismatch=0 max_dn_ang=8.08898e-05 max_dgrel=2.02847e-09 max_dstopT=41.091 sum_rhs=29393 esc=6 dark=6 unres=0 inc=0 wall=0.016s
SUMMARY upper r100_inward upper=8 min=1e-12 n=12 mismatch=0 max_dn_ang=8.03365e-05 max_dgrel=2.03431e-09 max_dstopT=41.0553 sum_rhs=28427 esc=6 dark=6 unres=0 inc=0 wall=0.015s
SUMMARY upper r100_inward upper=16 min=1e-12 n=12 mismatch=0 max_dn_ang=8.03365e-05 max_dgrel=2.04195e-09 max_dstopT=41.0553 sum_rhs=28189 esc=6 dark=6 unres=0 inc=0 wall=0.015s
SUMMARY upper r100_inward upper=32 min=1e-12 n=12 mismatch=0 max_dn_ang=8.03365e-05 max_dgrel=2.04297e-09 max_dstopT=41.0553 sum_rhs=28182 esc=6 dark=6 unres=0 inc=0 wall=0.015s
SUMMARY upper r100_inward upper=64 min=1e-12 n=12 mismatch=0 max_dn_ang=8.03365e-05 max_dgrel=2.04297e-09 max_dstopT=41.0553 sum_rhs=28182 esc=6 dark=6 unres=0 inc=0 wall=0.015s
SUMMARY upper r2p1_outward upper=0.25 min=1e-12 n=12 mismatch=1 max_dn_ang=0.000287223 max_dgrel=2.66126e-09 max_dstopT=263.145 sum_rhs=62258 esc=5 dark=7 unres=0 inc=0 wall=0.034s
SUMMARY upper r2p1_outward upper=0.5 min=1e-12 n=12 mismatch=1 max_dn_ang=0.000287221 max_dgrel=2.64443e-09 max_dstopT=263.145 sum_rhs=42490 esc=5 dark=7 unres=0 inc=0 wall=0.023s
SUMMARY upper r2p1_outward upper=1 min=1e-12 n=12 mismatch=1 max_dn_ang=0.000287221 max_dgrel=2.61531e-09 max_dstopT=263.145 sum_rhs=33544 esc=5 dark=7 unres=0 inc=0 wall=0.019s
SUMMARY upper r2p1_outward upper=2 min=1e-12 n=12 mismatch=1 max_dn_ang=0.000287222 max_dgrel=2.59243e-09 max_dstopT=263.145 sum_rhs=29421 esc=5 dark=7 unres=0 inc=0 wall=0.016s
SUMMARY upper r2p1_outward upper=4 min=1e-12 n=12 mismatch=1 max_dn_ang=0.000287221 max_dgrel=2.59774e-09 max_dstopT=263.145 sum_rhs=27580 esc=5 dark=7 unres=0 inc=0 wall=0.015s
SUMMARY upper r2p1_outward upper=8 min=1e-12 n=12 mismatch=1 max_dn_ang=0.000287221 max_dgrel=2.60591e-09 max_dstopT=263.145 sum_rhs=26831 esc=5 dark=7 unres=0 inc=0 wall=0.015s
SUMMARY upper r2p1_outward upper=16 min=1e-12 n=12 mismatch=1 max_dn_ang=0.000287223 max_dgrel=2.61374e-09 max_dstopT=263.145 sum_rhs=26614 esc=5 dark=7 unres=0 inc=0 wall=0.015s
SUMMARY upper r2p1_outward upper=32 min=1e-12 n=12 mismatch=1 max_dn_ang=0.000287221 max_dgrel=2.6148e-09 max_dstopT=263.145 sum_rhs=26607 esc=5 dark=7 unres=0 inc=0 wall=0.015s
SUMMARY upper r2p1_outward upper=64 min=1e-12 n=12 mismatch=1 max_dn_ang=0.000287221 max_dgrel=2.6148e-09 max_dstopT=263.145 sum_rhs=26607 esc=5 dark=7 unres=0 inc=0 wall=0.015s
SUMMARY upper r1p5_freefall upper=0.25 min=1e-12 n=4 mismatch=0 max_dn_ang=1.00222e-10 max_dgrel=3.16466e-10 max_dstopT=2.6078e-08 sum_rhs=23597 esc=3 dark=1 unres=0 inc=0 wall=0.014s
SUMMARY upper r1p5_freefall upper=0.5 min=1e-12 n=4 mismatch=0 max_dn_ang=8.87544e-11 max_dgrel=3.65847e-10 max_dstopT=3.08873e-08 sum_rhs=12747 esc=3 dark=1 unres=0 inc=0 wall=0.008s
SUMMARY upper r1p5_freefall upper=1 min=1e-12 n=4 mismatch=0 max_dn_ang=8.18746e-11 max_dgrel=3.81078e-10 max_dstopT=2.81655e-08 sum_rhs=7553 esc=3 dark=1 unres=0 inc=0 wall=0.005s
SUMMARY upper r1p5_freefall upper=2 min=1e-12 n=4 mismatch=0 max_dn_ang=8.165e-11 max_dgrel=3.7195e-10 max_dstopT=2.57141e-08 sum_rhs=5131 esc=3 dark=1 unres=0 inc=0 wall=0.003s
SUMMARY upper r1p5_freefall upper=4 min=1e-12 n=4 mismatch=0 max_dn_ang=8.1566e-11 max_dgrel=3.6318e-10 max_dstopT=2.34608e-08 sum_rhs=4039 esc=3 dark=1 unres=0 inc=0 wall=0.002s
SUMMARY upper r1p5_freefall upper=8 min=1e-12 n=4 mismatch=0 max_dn_ang=8.15091e-11 max_dgrel=3.54659e-10 max_dstopT=2.12507e-08 sum_rhs=3591 esc=3 dark=1 unres=0 inc=0 wall=0.002s
SUMMARY upper r1p5_freefall upper=16 min=1e-12 n=4 mismatch=0 max_dn_ang=8.14607e-11 max_dgrel=3.46852e-10 max_dstopT=1.92511e-08 sum_rhs=3465 esc=3 dark=1 unres=0 inc=0 wall=0.002s
SUMMARY upper r1p5_freefall upper=32 min=1e-12 n=4 mismatch=0 max_dn_ang=8.1455e-11 max_dgrel=3.45979e-10 max_dstopT=1.94793e-08 sum_rhs=3458 esc=3 dark=1 unres=0 inc=0 wall=0.002s
SUMMARY upper r1p5_freefall upper=64 min=1e-12 n=4 mismatch=0 max_dn_ang=8.1455e-11 max_dgrel=3.45979e-10 max_dstopT=1.94793e-08 sum_rhs=3458 esc=3 dark=1 unres=0 inc=0 wall=0.002s
SUMMARY min r30_inward upper=2 min=0.1 n=12 mismatch=0 max_dn_ang=0.000281866 max_dgrel=2.24374e-09 max_dstopT=41.2044 sum_rhs=31843 esc=6 dark=6 unres=0 inc=0 wall=0.017s
SUMMARY min r30_inward upper=2 min=0.01 n=12 mismatch=0 max_dn_ang=0.000281866 max_dgrel=2.24374e-09 max_dstopT=41.2044 sum_rhs=31843 esc=6 dark=6 unres=0 inc=0 wall=0.017s
SUMMARY min r30_inward upper=2 min=0.001 n=12 mismatch=0 max_dn_ang=0.000281866 max_dgrel=2.24374e-09 max_dstopT=41.2044 sum_rhs=31843 esc=6 dark=6 unres=0 inc=0 wall=0.017s
SUMMARY min r30_inward upper=2 min=0.0001 n=12 mismatch=0 max_dn_ang=0.000281866 max_dgrel=2.24374e-09 max_dstopT=41.2044 sum_rhs=31843 esc=6 dark=6 unres=0 inc=0 wall=0.017s
SUMMARY min r30_inward upper=2 min=1e-05 n=12 mismatch=0 max_dn_ang=0.000281866 max_dgrel=2.24374e-09 max_dstopT=41.2044 sum_rhs=31843 esc=6 dark=6 unres=0 inc=0 wall=0.017s
SUMMARY min r30_inward upper=2 min=1e-06 n=12 mismatch=0 max_dn_ang=0.000281866 max_dgrel=2.24374e-09 max_dstopT=41.2044 sum_rhs=31843 esc=6 dark=6 unres=0 inc=0 wall=0.017s
SUMMARY min r30_inward upper=2 min=1e-08 n=12 mismatch=0 max_dn_ang=0.000281866 max_dgrel=2.24374e-09 max_dstopT=41.2044 sum_rhs=31843 esc=6 dark=6 unres=0 inc=0 wall=0.017s
SUMMARY min r30_inward upper=2 min=1e-10 n=12 mismatch=0 max_dn_ang=0.000281866 max_dgrel=2.24374e-09 max_dstopT=41.2044 sum_rhs=31843 esc=6 dark=6 unres=0 inc=0 wall=0.017s
SUMMARY min r30_inward upper=2 min=1e-12 n=12 mismatch=0 max_dn_ang=0.000281866 max_dgrel=2.24374e-09 max_dstopT=41.2044 sum_rhs=31843 esc=6 dark=6 unres=0 inc=0 wall=0.017s
SUMMARY min r30_inward upper=2 min=1e-14 n=12 mismatch=0 max_dn_ang=0.000281866 max_dgrel=2.24374e-09 max_dstopT=41.2044 sum_rhs=31843 esc=6 dark=6 unres=0 inc=0 wall=0.017s
SUMMARY min r100_inward upper=2 min=0.1 n=12 mismatch=0 max_dn_ang=8.28604e-05 max_dgrel=2.0262e-09 max_dstopT=41.2161 sum_rhs=32389 esc=6 dark=6 unres=0 inc=0 wall=0.018s
SUMMARY min r100_inward upper=2 min=0.01 n=12 mismatch=0 max_dn_ang=8.28604e-05 max_dgrel=2.0262e-09 max_dstopT=41.2161 sum_rhs=32389 esc=6 dark=6 unres=0 inc=0 wall=0.018s
SUMMARY min r100_inward upper=2 min=0.001 n=12 mismatch=0 max_dn_ang=8.28604e-05 max_dgrel=2.0262e-09 max_dstopT=41.2161 sum_rhs=32389 esc=6 dark=6 unres=0 inc=0 wall=0.018s
SUMMARY min r100_inward upper=2 min=0.0001 n=12 mismatch=0 max_dn_ang=8.28604e-05 max_dgrel=2.0262e-09 max_dstopT=41.2161 sum_rhs=32389 esc=6 dark=6 unres=0 inc=0 wall=0.018s
SUMMARY min r100_inward upper=2 min=1e-05 n=12 mismatch=0 max_dn_ang=8.28604e-05 max_dgrel=2.0262e-09 max_dstopT=41.2161 sum_rhs=32389 esc=6 dark=6 unres=0 inc=0 wall=0.018s
SUMMARY min r100_inward upper=2 min=1e-06 n=12 mismatch=0 max_dn_ang=8.28604e-05 max_dgrel=2.0262e-09 max_dstopT=41.2161 sum_rhs=32389 esc=6 dark=6 unres=0 inc=0 wall=0.018s
SUMMARY min r100_inward upper=2 min=1e-08 n=12 mismatch=0 max_dn_ang=8.28604e-05 max_dgrel=2.0262e-09 max_dstopT=41.2161 sum_rhs=32389 esc=6 dark=6 unres=0 inc=0 wall=0.018s
SUMMARY min r100_inward upper=2 min=1e-10 n=12 mismatch=0 max_dn_ang=8.28604e-05 max_dgrel=2.0262e-09 max_dstopT=41.2161 sum_rhs=32389 esc=6 dark=6 unres=0 inc=0 wall=0.018s
SUMMARY min r100_inward upper=2 min=1e-12 n=12 mismatch=0 max_dn_ang=8.28604e-05 max_dgrel=2.0262e-09 max_dstopT=41.2161 sum_rhs=32389 esc=6 dark=6 unres=0 inc=0 wall=0.018s
SUMMARY min r100_inward upper=2 min=1e-14 n=12 mismatch=0 max_dn_ang=8.28604e-05 max_dgrel=2.0262e-09 max_dstopT=41.2161 sum_rhs=32389 esc=6 dark=6 unres=0 inc=0 wall=0.018s
SUMMARY min r2p1_outward upper=2 min=0.1 n=12 mismatch=1 max_dn_ang=0.000287222 max_dgrel=2.59243e-09 max_dstopT=263.145 sum_rhs=29421 esc=5 dark=7 unres=0 inc=0 wall=0.016s
SUMMARY min r2p1_outward upper=2 min=0.01 n=12 mismatch=1 max_dn_ang=0.000287222 max_dgrel=2.59243e-09 max_dstopT=263.145 sum_rhs=29421 esc=5 dark=7 unres=0 inc=0 wall=0.016s
SUMMARY min r2p1_outward upper=2 min=0.001 n=12 mismatch=1 max_dn_ang=0.000287222 max_dgrel=2.59243e-09 max_dstopT=263.145 sum_rhs=29421 esc=5 dark=7 unres=0 inc=0 wall=0.017s
SUMMARY min r2p1_outward upper=2 min=0.0001 n=12 mismatch=1 max_dn_ang=0.000287222 max_dgrel=2.59243e-09 max_dstopT=263.145 sum_rhs=29421 esc=5 dark=7 unres=0 inc=0 wall=0.017s
SUMMARY min r2p1_outward upper=2 min=1e-05 n=12 mismatch=1 max_dn_ang=0.000287222 max_dgrel=2.59243e-09 max_dstopT=263.145 sum_rhs=29421 esc=5 dark=7 unres=0 inc=0 wall=0.016s
SUMMARY min r2p1_outward upper=2 min=1e-06 n=12 mismatch=1 max_dn_ang=0.000287222 max_dgrel=2.59243e-09 max_dstopT=263.145 sum_rhs=29421 esc=5 dark=7 unres=0 inc=0 wall=0.016s
SUMMARY min r2p1_outward upper=2 min=1e-08 n=12 mismatch=1 max_dn_ang=0.000287222 max_dgrel=2.59243e-09 max_dstopT=263.145 sum_rhs=29421 esc=5 dark=7 unres=0 inc=0 wall=0.016s
SUMMARY min r2p1_outward upper=2 min=1e-10 n=12 mismatch=1 max_dn_ang=0.000287222 max_dgrel=2.59243e-09 max_dstopT=263.145 sum_rhs=29421 esc=5 dark=7 unres=0 inc=0 wall=0.016s
SUMMARY min r2p1_outward upper=2 min=1e-12 n=12 mismatch=1 max_dn_ang=0.000287222 max_dgrel=2.59243e-09 max_dstopT=263.145 sum_rhs=29421 esc=5 dark=7 unres=0 inc=0 wall=0.016s
SUMMARY min r2p1_outward upper=2 min=1e-14 n=12 mismatch=1 max_dn_ang=0.000287222 max_dgrel=2.59243e-09 max_dstopT=263.145 sum_rhs=29421 esc=5 dark=7 unres=0 inc=0 wall=0.016s
SUMMARY min r1p5_freefall upper=2 min=0.1 n=4 mismatch=1 max_dn_ang=8.165e-11 max_dgrel=3.7195e-10 max_dstopT=254.3 sum_rhs=3654 esc=2 dark=1 unres=0 inc=1 wall=0.002s
SUMMARY min r1p5_freefall upper=2 min=0.01 n=4 mismatch=0 max_dn_ang=8.165e-11 max_dgrel=3.7195e-10 max_dstopT=2.57141e-08 sum_rhs=5131 esc=3 dark=1 unres=0 inc=0 wall=0.003s
SUMMARY min r1p5_freefall upper=2 min=0.001 n=4 mismatch=0 max_dn_ang=8.165e-11 max_dgrel=3.7195e-10 max_dstopT=2.57141e-08 sum_rhs=5131 esc=3 dark=1 unres=0 inc=0 wall=0.003s
SUMMARY min r1p5_freefall upper=2 min=0.0001 n=4 mismatch=0 max_dn_ang=8.165e-11 max_dgrel=3.7195e-10 max_dstopT=2.57141e-08 sum_rhs=5131 esc=3 dark=1 unres=0 inc=0 wall=0.003s
SUMMARY min r1p5_freefall upper=2 min=1e-05 n=4 mismatch=0 max_dn_ang=8.165e-11 max_dgrel=3.7195e-10 max_dstopT=2.57141e-08 sum_rhs=5131 esc=3 dark=1 unres=0 inc=0 wall=0.003s
SUMMARY min r1p5_freefall upper=2 min=1e-06 n=4 mismatch=0 max_dn_ang=8.165e-11 max_dgrel=3.7195e-10 max_dstopT=2.57141e-08 sum_rhs=5131 esc=3 dark=1 unres=0 inc=0 wall=0.003s
SUMMARY min r1p5_freefall upper=2 min=1e-08 n=4 mismatch=0 max_dn_ang=8.165e-11 max_dgrel=3.7195e-10 max_dstopT=2.57141e-08 sum_rhs=5131 esc=3 dark=1 unres=0 inc=0 wall=0.003s
SUMMARY min r1p5_freefall upper=2 min=1e-10 n=4 mismatch=0 max_dn_ang=8.165e-11 max_dgrel=3.7195e-10 max_dstopT=2.57141e-08 sum_rhs=5131 esc=3 dark=1 unres=0 inc=0 wall=0.003s
SUMMARY min r1p5_freefall upper=2 min=1e-12 n=4 mismatch=0 max_dn_ang=8.165e-11 max_dgrel=3.7195e-10 max_dstopT=2.57141e-08 sum_rhs=5131 esc=3 dark=1 unres=0 inc=0 wall=0.003s
SUMMARY min r1p5_freefall upper=2 min=1e-14 n=4 mismatch=0 max_dn_ang=8.165e-11 max_dgrel=3.7195e-10 max_dstopT=2.57141e-08 sum_rhs=5131 esc=3 dark=1 unres=0 inc=0 wall=0.003s
RK4 r30_inward dir=8 theta=0.168123 o01=1/1 o005=1/1 hhalve_dn=nan hhalve_dgrel=nan vsdp_dn=nan vsdp_dgrel=nan vsdp_class=1
RK4 r30_inward dir=9 theta=0.168123 o01=0/0 o005=0/0 hhalve_dn=1.89584e-07 hhalve_dgrel=7.32747e-15 vsdp_dn=7.95167e-08 vsdp_dgrel=4.66294e-13 vsdp_class=1
RK4 r30_inward dir=6 theta=0.168113 o01=1/1 o005=1/1 hhalve_dn=nan hhalve_dgrel=nan vsdp_dn=nan vsdp_dgrel=nan vsdp_class=1
RK4 r30_inward dir=7 theta=0.168133 o01=0/0 o005=0/0 hhalve_dn=1.73965e-09 hhalve_dgrel=7.9492e-14 vsdp_dn=7.86496e-10 vsdp_dgrel=2.6934e-13 vsdp_class=1
RK4 r2p1_outward dir=8 theta=0.570377 o01=0/0 o005=0/0 hhalve_dn=1.03961e-05 hhalve_dgrel=1.66234e-12 vsdp_dn=8.49321e-07 vsdp_dgrel=5.46896e-13 vsdp_class=1
RK4 r2p1_outward dir=9 theta=0.570377 o01=1/1 o005=1/1 hhalve_dn=nan hhalve_dgrel=nan vsdp_dn=nan vsdp_dgrel=nan vsdp_class=1
RK4 r2p1_outward dir=6 theta=0.570367 o01=0/0 o005=0/0 hhalve_dn=1.03971e-07 hhalve_dgrel=1.61182e-12 vsdp_dn=8.47692e-09 vsdp_dgrel=3.02647e-13 vsdp_class=1
RK4 r2p1_outward dir=7 theta=0.570387 o01=1/1 o005=1/1 hhalve_dn=nan hhalve_dgrel=nan vsdp_dn=nan vsdp_dgrel=nan vsdp_class=1
TOTAL_RAYS 816
real 0m2.428s
user 0m2.423s
sys 0m0.004s
+ set +x
### command: a_public minkowski
+ /tmp/opencode/step_bounds/a_public minkowski
SUMMARY mink upper=1 min=0.1 n=6 mismatch=0 max_dn_ang=0 max_dgrel=0 sum_rhs=4886 esc=6 dark=0 unres=0 inc=0
SUMMARY mink upper=1 min=1e-06 n=6 mismatch=0 max_dn_ang=0 max_dgrel=0 sum_rhs=4886 esc=6 dark=0 unres=0 inc=0
SUMMARY mink upper=1 min=1e-12 n=6 mismatch=0 max_dn_ang=0 max_dgrel=0 sum_rhs=4886 esc=6 dark=0 unres=0 inc=0
SUMMARY mink upper=4 min=0.1 n=6 mismatch=0 max_dn_ang=0 max_dgrel=0 sum_rhs=2590 esc=6 dark=0 unres=0 inc=0
SUMMARY mink upper=4 min=1e-06 n=6 mismatch=0 max_dn_ang=0 max_dgrel=0 sum_rhs=2590 esc=6 dark=0 unres=0 inc=0
SUMMARY mink upper=4 min=1e-12 n=6 mismatch=0 max_dn_ang=0 max_dgrel=0 sum_rhs=2590 esc=6 dark=0 unres=0 inc=0
SUMMARY mink upper=16 min=0.1 n=6 mismatch=0 max_dn_ang=0 max_dgrel=0 sum_rhs=2037 esc=6 dark=0 unres=0 inc=0
SUMMARY mink upper=16 min=1e-06 n=6 mismatch=0 max_dn_ang=0 max_dgrel=0 sum_rhs=2037 esc=6 dark=0 unres=0 inc=0
SUMMARY mink upper=16 min=1e-12 n=6 mismatch=0 max_dn_ang=0 max_dgrel=0 sum_rhs=2037 esc=6 dark=0 unres=0 inc=0
SUMMARY mink upper=64 min=0.1 n=6 mismatch=0 max_dn_ang=0 max_dgrel=0 sum_rhs=1932 esc=6 dark=0 unres=0 inc=0
SUMMARY mink upper=64 min=1e-06 n=6 mismatch=0 max_dn_ang=0 max_dgrel=0 sum_rhs=1932 esc=6 dark=0 unres=0 inc=0
SUMMARY mink upper=64 min=1e-12 n=6 mismatch=0 max_dn_ang=0 max_dgrel=0 sum_rhs=1932 esc=6 dark=0 unres=0 inc=0
SUMMARY mink upper=256 min=0.1 n=6 mismatch=0 max_dn_ang=0 max_dgrel=0 sum_rhs=1932 esc=6 dark=0 unres=0 inc=0
SUMMARY mink upper=256 min=1e-06 n=6 mismatch=0 max_dn_ang=0 max_dgrel=0 sum_rhs=1932 esc=6 dark=0 unres=0 inc=0
SUMMARY mink upper=256 min=1e-12 n=6 mismatch=0 max_dn_ang=0 max_dgrel=0 sum_rhs=1932 esc=6 dark=0 unres=0 inc=0
TOTAL_RAYS 186
real 0m0.013s
user 0m0.013s
sys 0m0.000s
+ set +x
### command: a_public alcubierre
+ /tmp/opencode/step_bounds/a_public alcubierre
REF alc_v3_s1 dir=0 theta=nan outcome=0 reason=0 stop_t=-16.4338937 steps=347 rejected=1 rhs=2730 g=1.3 thr=nan
REF alc_v3_s1 dir=1 theta=nan outcome=0 reason=0 stop_t=-29.3767055 steps=597 rejected=1 rhs=4480 g=0.7 thr=nan
REF alc_v3_s1 dir=2 theta=nan outcome=0 reason=0 stop_t=-20.2190145 steps=414 rejected=0 rhs=3192 g=1 thr=nan
REF alc_v3_s1 dir=3 theta=nan outcome=0 reason=0 stop_t=-20.2190145 steps=414 rejected=0 rhs=3192 g=1 thr=nan
REF alc_v3_s1 dir=4 theta=nan outcome=0 reason=0 stop_t=-17.6897755 steps=367 rejected=0 rhs=2863 g=1.17815368048 thr=nan
REF alc_v3_s1 dir=5 theta=nan outcome=0 reason=0 stop_t=-24.329102 steps=497 rejected=1 rhs=3780 g=0.822613315483 thr=nan
REF alc_v3_s10 dir=0 theta=nan outcome=0 reason=0 stop_t=-2.53543426 steps=523 rejected=3 rhs=3976 g=1.3 thr=nan
REF alc_v3_s10 dir=1 theta=nan outcome=0 reason=0 stop_t=-3.84949982 steps=775 rejected=0 rhs=5719 g=0.7 thr=nan
REF alc_v3_s10 dir=2 theta=nan outcome=0 reason=0 stop_t=-2.94282517 steps=589 rejected=0 rhs=4417 g=1 thr=nan
REF alc_v3_s10 dir=3 theta=nan outcome=0 reason=0 stop_t=-2.94282517 steps=589 rejected=0 rhs=4417 g=1 thr=nan
REF alc_v3_s10 dir=4 theta=nan outcome=0 reason=0 stop_t=-2.67090915 steps=543 rejected=2 rhs=4109 g=1.17959135733 thr=nan
REF alc_v3_s10 dir=5 theta=nan outcome=0 reason=0 stop_t=-3.3698049 steps=677 rejected=0 rhs=5033 g=0.820579506843 thr=nan
REF alc_v9_s1 dir=0 theta=nan outcome=0 reason=0 stop_t=-11.5627491 steps=283 rejected=1 rhs=2282 g=1.9 thr=nan
REF alc_v9_s1 dir=1 theta=nan outcome=0 reason=0 stop_t=-189.149503 steps=3825 rejected=1 rhs=27069 g=0.1 thr=nan
REF alc_v9_s1 dir=2 theta=nan outcome=0 reason=0 stop_t=-16.1619146 steps=351 rejected=4 rhs=2772 g=1 thr=nan
REF alc_v9_s1 dir=3 theta=nan outcome=0 reason=0 stop_t=-16.1619146 steps=351 rejected=4 rhs=2772 g=1 thr=nan
REF alc_v9_s1 dir=4 theta=nan outcome=0 reason=0 stop_t=-13.0192142 steps=308 rejected=1 rhs=2457 g=1.5041731473 thr=nan
REF alc_v9_s1 dir=5 theta=nan outcome=0 reason=0 stop_t=-22.987334 steps=491 rejected=1 rhs=3738 g=0.54079971046 thr=nan
REF alc_v9_s10 dir=0 theta=nan outcome=0 reason=0 stop_t=-2.03742978 steps=452 rejected=5 rhs=3493 g=1.9 thr=nan
REF alc_v9_s10 dir=1 theta=nan outcome=0 reason=0 stop_t=-19.9638367 steps=4013 rejected=0 rhs=28385 g=0.1 thr=nan
REF alc_v9_s10 dir=2 theta=nan outcome=0 reason=0 stop_t=-2.62069451 steps=525 rejected=0 rhs=3969 g=1 thr=nan
REF alc_v9_s10 dir=3 theta=nan outcome=0 reason=0 stop_t=-2.62069451 steps=525 rejected=0 rhs=3969 g=1 thr=nan
REF alc_v9_s10 dir=4 theta=nan outcome=0 reason=0 stop_t=-2.20704191 steps=469 rejected=3 rhs=3598 g=1.5316539409 thr=nan
REF alc_v9_s10 dir=5 theta=nan outcome=0 reason=0 stop_t=-3.67922549 steps=742 rejected=0 rhs=5488 g=0.483265790771 thr=nan
REF alc_v9_s100 dir=0 theta=nan outcome=0 reason=0 stop_t=-1.10374298 steps=2252 rejected=5 rhs=16093 g=1.9 thr=nan
REF alc_v9_s100 dir=1 theta=nan outcome=0 reason=0 stop_t=-2.89638367 steps=5813 rejected=0 rhs=40978 g=0.1 thr=nan
REF alc_v9_s100 dir=2 theta=nan outcome=0 reason=0 stop_t=-1.18800796 steps=2377 rejected=0 rhs=16926 g=1 thr=nan
REF alc_v9_s100 dir=3 theta=nan outcome=0 reason=0 stop_t=-1.18800796 steps=2377 rejected=0 rhs=16926 g=1 thr=nan
REF alc_v9_s100 dir=4 theta=nan outcome=0 reason=0 stop_t=-1.12678339 steps=2281 rejected=2 rhs=16275 g=1.53910006629 thr=nan
REF alc_v9_s100 dir=5 theta=nan outcome=0 reason=0 stop_t=-1.36694611 steps=2740 rejected=0 rhs=19474 g=0.462933441354 thr=nan
SUMMARY upper alc_v3_s1 upper=0.05 min=0.0001 n=6 mismatch=0 max_dn_ang=7.54397e-14 max_dgrel=7.62723e-13 max_dstopT=1.98952e-13 sum_rhs=19740 esc=6 dark=0 unres=0 inc=0 wall=0.005s
SUMMARY upper alc_v3_s1 upper=0.05 min=1e-08 n=6 mismatch=0 max_dn_ang=7.54397e-14 max_dgrel=7.62723e-13 max_dstopT=1.98952e-13 sum_rhs=19740 esc=6 dark=0 unres=0 inc=0 wall=0.005s
SUMMARY upper alc_v3_s1 upper=0.05 min=1e-12 n=6 mismatch=0 max_dn_ang=7.54397e-14 max_dgrel=7.62723e-13 max_dstopT=1.98952e-13 sum_rhs=19740 esc=6 dark=0 unres=0 inc=0 wall=0.005s
SUMMARY upper alc_v3_s1 upper=0.2 min=0.0001 n=6 mismatch=0 max_dn_ang=1.2079e-10 max_dgrel=3.45157e-10 max_dstopT=4.09095e-10 sum_rhs=6475 esc=6 dark=0 unres=0 inc=0 wall=0.001s
SUMMARY upper alc_v3_s1 upper=0.2 min=1e-08 n=6 mismatch=0 max_dn_ang=1.2079e-10 max_dgrel=3.45157e-10 max_dstopT=4.09095e-10 sum_rhs=6475 esc=6 dark=0 unres=0 inc=0 wall=0.002s
SUMMARY upper alc_v3_s1 upper=0.2 min=1e-12 n=6 mismatch=0 max_dn_ang=1.2079e-10 max_dgrel=3.45157e-10 max_dstopT=4.09095e-10 sum_rhs=6475 esc=6 dark=0 unres=0 inc=0 wall=0.002s
SUMMARY upper alc_v3_s1 upper=0.4 min=0.0001 n=6 mismatch=0 max_dn_ang=1.02989e-10 max_dgrel=3.46442e-10 max_dstopT=3.14323e-10 sum_rhs=4613 esc=6 dark=0 unres=0 inc=0 wall=0.001s
SUMMARY upper alc_v3_s1 upper=0.4 min=1e-08 n=6 mismatch=0 max_dn_ang=1.02989e-10 max_dgrel=3.46442e-10 max_dstopT=3.14323e-10 sum_rhs=4613 esc=6 dark=0 unres=0 inc=0 wall=0.001s
SUMMARY upper alc_v3_s1 upper=0.4 min=1e-12 n=6 mismatch=0 max_dn_ang=1.02989e-10 max_dgrel=3.46442e-10 max_dstopT=3.14323e-10 sum_rhs=4613 esc=6 dark=0 unres=0 inc=0 wall=0.001s
SUMMARY upper alc_v3_s1 upper=0.8 min=0.0001 n=6 mismatch=0 max_dn_ang=7.88763e-11 max_dgrel=7.95433e-10 max_dstopT=7.3689e-10 sum_rhs=3794 esc=6 dark=0 unres=0 inc=0 wall=0.001s
SUMMARY upper alc_v3_s1 upper=0.8 min=1e-08 n=6 mismatch=0 max_dn_ang=7.88763e-11 max_dgrel=7.95433e-10 max_dstopT=7.3689e-10 sum_rhs=3794 esc=6 dark=0 unres=0 inc=0 wall=0.001s
SUMMARY upper alc_v3_s1 upper=0.8 min=1e-12 n=6 mismatch=0 max_dn_ang=7.88763e-11 max_dgrel=7.95433e-10 max_dstopT=7.3689e-10 sum_rhs=3794 esc=6 dark=0 unres=0 inc=0 wall=0.001s
SUMMARY upper alc_v3_s1 upper=1.6 min=0.0001 n=6 mismatch=0 max_dn_ang=1.23935e-10 max_dgrel=1.11826e-09 max_dstopT=1.14768e-09 sum_rhs=3430 esc=6 dark=0 unres=0 inc=0 wall=0.001s
SUMMARY upper alc_v3_s1 upper=1.6 min=1e-08 n=6 mismatch=0 max_dn_ang=1.23935e-10 max_dgrel=1.11826e-09 max_dstopT=1.14768e-09 sum_rhs=3430 esc=6 dark=0 unres=0 inc=0 wall=0.001s
SUMMARY upper alc_v3_s1 upper=1.6 min=1e-12 n=6 mismatch=0 max_dn_ang=1.23935e-10 max_dgrel=1.11826e-09 max_dstopT=1.14768e-09 sum_rhs=3430 esc=6 dark=0 unres=0 inc=0 wall=0.001s
SUMMARY upper alc_v3_s1 upper=3.2 min=0.0001 n=6 mismatch=0 max_dn_ang=1.54539e-10 max_dgrel=1.25996e-09 max_dstopT=1.3457e-09 sum_rhs=3290 esc=6 dark=0 unres=0 inc=0 wall=0.001s
SUMMARY upper alc_v3_s1 upper=3.2 min=1e-08 n=6 mismatch=0 max_dn_ang=1.54539e-10 max_dgrel=1.25996e-09 max_dstopT=1.3457e-09 sum_rhs=3290 esc=6 dark=0 unres=0 inc=0 wall=0.001s
SUMMARY upper alc_v3_s1 upper=3.2 min=1e-12 n=6 mismatch=0 max_dn_ang=1.54539e-10 max_dgrel=1.25996e-09 max_dstopT=1.3457e-09 sum_rhs=3290 esc=6 dark=0 unres=0 inc=0 wall=0.001s
SUMMARY upper alc_v3_s10 upper=0.005 min=0.0001 n=6 mismatch=0 max_dn_ang=5.82867e-15 max_dgrel=3.10862e-14 max_dstopT=4.66294e-14 sum_rhs=27412 esc=6 dark=0 unres=0 inc=0 wall=0.006s
SUMMARY upper alc_v3_s10 upper=0.005 min=1e-08 n=6 mismatch=0 max_dn_ang=5.82867e-15 max_dgrel=3.10862e-14 max_dstopT=4.66294e-14 sum_rhs=27412 esc=6 dark=0 unres=0 inc=0 wall=0.006s
SUMMARY upper alc_v3_s10 upper=0.005 min=1e-12 n=6 mismatch=0 max_dn_ang=5.82867e-15 max_dgrel=3.10862e-14 max_dstopT=4.66294e-14 sum_rhs=27412 esc=6 dark=0 unres=0 inc=0 wall=0.006s
SUMMARY upper alc_v3_s10 upper=0.02 min=0.0001 n=6 mismatch=0 max_dn_ang=6.29929e-12 max_dgrel=2.40162e-10 max_dstopT=1.39897e-11 sum_rhs=8337 esc=6 dark=0 unres=0 inc=0 wall=0.002s
SUMMARY upper alc_v3_s10 upper=0.02 min=1e-08 n=6 mismatch=0 max_dn_ang=6.29929e-12 max_dgrel=2.40162e-10 max_dstopT=1.39897e-11 sum_rhs=8337 esc=6 dark=0 unres=0 inc=0 wall=0.002s
SUMMARY upper alc_v3_s10 upper=0.02 min=1e-12 n=6 mismatch=0 max_dn_ang=6.29929e-12 max_dgrel=2.40162e-10 max_dstopT=1.39897e-11 sum_rhs=8337 esc=6 dark=0 unres=0 inc=0 wall=0.002s
SUMMARY upper alc_v3_s10 upper=0.04 min=0.0001 n=6 mismatch=0 max_dn_ang=3.28758e-11 max_dgrel=3.85361e-10 max_dstopT=6.29403e-11 sum_rhs=5621 esc=6 dark=0 unres=0 inc=0 wall=0.001s
SUMMARY upper alc_v3_s10 upper=0.04 min=1e-08 n=6 mismatch=0 max_dn_ang=3.28758e-11 max_dgrel=3.85361e-10 max_dstopT=6.29403e-11 sum_rhs=5621 esc=6 dark=0 unres=0 inc=0 wall=0.001s
SUMMARY upper alc_v3_s10 upper=0.04 min=1e-12 n=6 mismatch=0 max_dn_ang=3.28758e-11 max_dgrel=3.85361e-10 max_dstopT=6.29403e-11 sum_rhs=5621 esc=6 dark=0 unres=0 inc=0 wall=0.001s
SUMMARY upper alc_v3_s10 upper=0.08 min=0.0001 n=6 mismatch=0 max_dn_ang=1.04151e-11 max_dgrel=2.78111e-10 max_dstopT=8.02363e-11 sum_rhs=4648 esc=6 dark=0 unres=0 inc=0 wall=0.001s
SUMMARY upper alc_v3_s10 upper=0.08 min=1e-08 n=6 mismatch=0 max_dn_ang=1.04151e-11 max_dgrel=2.78111e-10 max_dstopT=8.02363e-11 sum_rhs=4648 esc=6 dark=0 unres=0 inc=0 wall=0.001s
SUMMARY upper alc_v3_s10 upper=0.08 min=1e-12 n=6 mismatch=0 max_dn_ang=1.04151e-11 max_dgrel=2.78111e-10 max_dstopT=8.02363e-11 sum_rhs=4648 esc=6 dark=0 unres=0 inc=0 wall=0.001s
SUMMARY upper alc_v3_s10 upper=0.16 min=0.0001 n=6 mismatch=0 max_dn_ang=1.13121e-11 max_dgrel=7.59968e-10 max_dstopT=9.53793e-11 sum_rhs=4270 esc=6 dark=0 unres=0 inc=0 wall=0.001s
SUMMARY upper alc_v3_s10 upper=0.16 min=1e-08 n=6 mismatch=0 max_dn_ang=1.13121e-11 max_dgrel=7.59968e-10 max_dstopT=9.53793e-11 sum_rhs=4270 esc=6 dark=0 unres=0 inc=0 wall=0.001s
SUMMARY upper alc_v3_s10 upper=0.16 min=1e-12 n=6 mismatch=0 max_dn_ang=1.13121e-11 max_dgrel=7.59968e-10 max_dstopT=9.53793e-11 sum_rhs=4270 esc=6 dark=0 unres=0 inc=0 wall=0.001s
SUMMARY upper alc_v3_s10 upper=0.32 min=0.0001 n=6 mismatch=0 max_dn_ang=3.13081e-11 max_dgrel=9.77839e-10 max_dstopT=1.04124e-10 sum_rhs=4116 esc=6 dark=0 unres=0 inc=0 wall=0.001s
SUMMARY upper alc_v3_s10 upper=0.32 min=1e-08 n=6 mismatch=0 max_dn_ang=3.13081e-11 max_dgrel=9.77839e-10 max_dstopT=1.04124e-10 sum_rhs=4116 esc=6 dark=0 unres=0 inc=0 wall=0.001s
SUMMARY upper alc_v3_s10 upper=0.32 min=1e-12 n=6 mismatch=0 max_dn_ang=3.13081e-11 max_dgrel=9.77839e-10 max_dstopT=1.04124e-10 sum_rhs=4116 esc=6 dark=0 unres=0 inc=0 wall=0.001s
SUMMARY upper alc_v9_s1 upper=0.05 min=0.0001 n=6 mismatch=0 max_dn_ang=6.63192e-13 max_dgrel=2.59086e-11 max_dstopT=1.38662e-11 sum_rhs=39452 esc=6 dark=0 unres=0 inc=0 wall=0.010s
SUMMARY upper alc_v9_s1 upper=0.05 min=1e-08 n=6 mismatch=0 max_dn_ang=6.63192e-13 max_dgrel=2.59086e-11 max_dstopT=1.38662e-11 sum_rhs=39452 esc=6 dark=0 unres=0 inc=0 wall=0.010s
SUMMARY upper alc_v9_s1 upper=0.05 min=1e-12 n=6 mismatch=0 max_dn_ang=6.63192e-13 max_dgrel=2.59086e-11 max_dstopT=1.38662e-11 sum_rhs=39452 esc=6 dark=0 unres=0 inc=0 wall=0.010s
SUMMARY upper alc_v9_s1 upper=0.2 min=0.0001 n=6 mismatch=0 max_dn_ang=1.07764e-10 max_dgrel=2.07282e-09 max_dstopT=6.80462e-10 sum_rhs=11690 esc=6 dark=0 unres=0 inc=0 wall=0.003s
SUMMARY upper alc_v9_s1 upper=0.2 min=1e-08 n=6 mismatch=0 max_dn_ang=1.07764e-10 max_dgrel=2.07282e-09 max_dstopT=6.80462e-10 sum_rhs=11690 esc=6 dark=0 unres=0 inc=0 wall=0.003s
SUMMARY upper alc_v9_s1 upper=0.2 min=1e-12 n=6 mismatch=0 max_dn_ang=1.07764e-10 max_dgrel=2.07282e-09 max_dstopT=6.80462e-10 sum_rhs=11690 esc=6 dark=0 unres=0 inc=0 wall=0.003s
SUMMARY upper alc_v9_s1 upper=0.4 min=0.0001 n=6 mismatch=0 max_dn_ang=6.25e-11 max_dgrel=2.46644e-09 max_dstopT=1.08309e-09 sum_rhs=7413 esc=6 dark=0 unres=0 inc=0 wall=0.002s
SUMMARY upper alc_v9_s1 upper=0.4 min=1e-08 n=6 mismatch=0 max_dn_ang=6.25e-11 max_dgrel=2.46644e-09 max_dstopT=1.08309e-09 sum_rhs=7413 esc=6 dark=0 unres=0 inc=0 wall=0.002s
SUMMARY upper alc_v9_s1 upper=0.4 min=1e-12 n=6 mismatch=0 max_dn_ang=6.25e-11 max_dgrel=2.46644e-09 max_dstopT=1.08309e-09 sum_rhs=7413 esc=6 dark=0 unres=0 inc=0 wall=0.002s
SUMMARY upper alc_v9_s1 upper=0.8 min=0.0001 n=6 mismatch=0 max_dn_ang=5.34924e-11 max_dgrel=2.71772e-09 max_dstopT=1.1859e-09 sum_rhs=5369 esc=6 dark=0 unres=0 inc=0 wall=0.001s
SUMMARY upper alc_v9_s1 upper=0.8 min=1e-08 n=6 mismatch=0 max_dn_ang=5.34924e-11 max_dgrel=2.71772e-09 max_dstopT=1.1859e-09 sum_rhs=5369 esc=6 dark=0 unres=0 inc=0 wall=0.001s
SUMMARY upper alc_v9_s1 upper=0.8 min=1e-12 n=6 mismatch=0 max_dn_ang=5.34924e-11 max_dgrel=2.71772e-09 max_dstopT=1.1859e-09 sum_rhs=5369 esc=6 dark=0 unres=0 inc=0 wall=0.001s
SUMMARY upper alc_v9_s1 upper=1.6 min=0.0001 n=6 mismatch=0 max_dn_ang=1.03537e-10 max_dgrel=2.8194e-09 max_dstopT=9.54927e-10 sum_rhs=4431 esc=6 dark=0 unres=0 inc=0 wall=0.001s
SUMMARY upper alc_v9_s1 upper=1.6 min=1e-08 n=6 mismatch=0 max_dn_ang=1.03537e-10 max_dgrel=2.8194e-09 max_dstopT=9.54927e-10 sum_rhs=4431 esc=6 dark=0 unres=0 inc=0 wall=0.001s
SUMMARY upper alc_v9_s1 upper=1.6 min=1e-12 n=6 mismatch=0 max_dn_ang=1.03537e-10 max_dgrel=2.8194e-09 max_dstopT=9.54927e-10 sum_rhs=4431 esc=6 dark=0 unres=0 inc=0 wall=0.001s
SUMMARY upper alc_v9_s1 upper=3.2 min=0.0001 n=6 mismatch=0 max_dn_ang=1.23927e-10 max_dgrel=2.82251e-09 max_dstopT=3.24928e-09 sum_rhs=3983 esc=6 dark=0 unres=0 inc=0 wall=0.001s
SUMMARY upper alc_v9_s1 upper=3.2 min=1e-08 n=6 mismatch=0 max_dn_ang=1.23927e-10 max_dgrel=2.82251e-09 max_dstopT=3.24928e-09 sum_rhs=3983 esc=6 dark=0 unres=0 inc=0 wall=0.001s
SUMMARY upper alc_v9_s1 upper=3.2 min=1e-12 n=6 mismatch=0 max_dn_ang=1.23927e-10 max_dgrel=2.82251e-09 max_dstopT=3.24928e-09 sum_rhs=3983 esc=6 dark=0 unres=0 inc=0 wall=0.001s
SUMMARY upper alc_v9_s10 upper=0.005 min=0.0001 n=6 mismatch=0 max_dn_ang=8.9373e-14 max_dgrel=1.10281e-11 max_dstopT=3.55271e-13 sum_rhs=48167 esc=6 dark=0 unres=0 inc=0 wall=0.011s
SUMMARY upper alc_v9_s10 upper=0.005 min=1e-08 n=6 mismatch=0 max_dn_ang=8.9373e-14 max_dgrel=1.10281e-11 max_dstopT=3.55271e-13 sum_rhs=48167 esc=6 dark=0 unres=0 inc=0 wall=0.011s
SUMMARY upper alc_v9_s10 upper=0.005 min=1e-12 n=6 mismatch=0 max_dn_ang=8.9373e-14 max_dgrel=1.10281e-11 max_dstopT=3.55271e-13 sum_rhs=48167 esc=6 dark=0 unres=0 inc=0 wall=0.011s
SUMMARY upper alc_v9_s10 upper=0.02 min=0.0001 n=6 mismatch=0 max_dn_ang=5.33142e-11 max_dgrel=6.90633e-10 max_dstopT=1.09151e-10 sum_rhs=13692 esc=6 dark=0 unres=0 inc=0 wall=0.003s
SUMMARY upper alc_v9_s10 upper=0.02 min=1e-08 n=6 mismatch=0 max_dn_ang=5.33142e-11 max_dgrel=6.90633e-10 max_dstopT=1.09151e-10 sum_rhs=13692 esc=6 dark=0 unres=0 inc=0 wall=0.003s
SUMMARY upper alc_v9_s10 upper=0.02 min=1e-12 n=6 mismatch=0 max_dn_ang=5.33142e-11 max_dgrel=6.90633e-10 max_dstopT=1.09151e-10 sum_rhs=13692 esc=6 dark=0 unres=0 inc=0 wall=0.003s
SUMMARY upper alc_v9_s10 upper=0.04 min=0.0001 n=6 mismatch=0 max_dn_ang=1.75204e-10 max_dgrel=9.74943e-10 max_dstopT=3.64615e-10 sum_rhs=8484 esc=6 dark=0 unres=0 inc=0 wall=0.002s
SUMMARY upper alc_v9_s10 upper=0.04 min=1e-08 n=6 mismatch=0 max_dn_ang=1.75204e-10 max_dgrel=9.74943e-10 max_dstopT=3.64615e-10 sum_rhs=8484 esc=6 dark=0 unres=0 inc=0 wall=0.002s
SUMMARY upper alc_v9_s10 upper=0.04 min=1e-12 n=6 mismatch=0 max_dn_ang=1.75204e-10 max_dgrel=9.74943e-10 max_dstopT=3.64615e-10 sum_rhs=8484 esc=6 dark=0 unres=0 inc=0 wall=0.002s
SUMMARY upper alc_v9_s10 upper=0.08 min=0.0001 n=6 mismatch=0 max_dn_ang=1.1957e-10 max_dgrel=1.45708e-09 max_dstopT=2.69508e-10 sum_rhs=6251 esc=6 dark=0 unres=0 inc=0 wall=0.001s
SUMMARY upper alc_v9_s10 upper=0.08 min=1e-08 n=6 mismatch=0 max_dn_ang=1.1957e-10 max_dgrel=1.45708e-09 max_dstopT=2.69508e-10 sum_rhs=6251 esc=6 dark=0 unres=0 inc=0 wall=0.001s
SUMMARY upper alc_v9_s10 upper=0.08 min=1e-12 n=6 mismatch=0 max_dn_ang=1.1957e-10 max_dgrel=1.45708e-09 max_dstopT=2.69508e-10 sum_rhs=6251 esc=6 dark=0 unres=0 inc=0 wall=0.001s
SUMMARY upper alc_v9_s10 upper=0.16 min=0.0001 n=6 mismatch=0 max_dn_ang=1.72733e-11 max_dgrel=1.07679e-09 max_dstopT=1.26013e-10 sum_rhs=5278 esc=6 dark=0 unres=0 inc=0 wall=0.001s
SUMMARY upper alc_v9_s10 upper=0.16 min=1e-08 n=6 mismatch=0 max_dn_ang=1.72733e-11 max_dgrel=1.07679e-09 max_dstopT=1.26013e-10 sum_rhs=5278 esc=6 dark=0 unres=0 inc=0 wall=0.001s
SUMMARY upper alc_v9_s10 upper=0.16 min=1e-12 n=6 mismatch=0 max_dn_ang=1.72733e-11 max_dgrel=1.07679e-09 max_dstopT=1.26013e-10 sum_rhs=5278 esc=6 dark=0 unres=0 inc=0 wall=0.001s
SUMMARY upper alc_v9_s10 upper=0.32 min=0.0001 n=6 mismatch=0 max_dn_ang=5.49931e-11 max_dgrel=8.67977e-10 max_dstopT=2.55501e-10 sum_rhs=4872 esc=6 dark=0 unres=0 inc=0 wall=0.001s
SUMMARY upper alc_v9_s10 upper=0.32 min=1e-08 n=6 mismatch=0 max_dn_ang=5.49931e-11 max_dgrel=8.67977e-10 max_dstopT=2.55501e-10 sum_rhs=4872 esc=6 dark=0 unres=0 inc=0 wall=0.001s
SUMMARY upper alc_v9_s10 upper=0.32 min=1e-12 n=6 mismatch=0 max_dn_ang=5.49931e-11 max_dgrel=8.67977e-10 max_dstopT=2.55501e-10 sum_rhs=4872 esc=6 dark=0 unres=0 inc=0 wall=0.001s
SUMMARY min_stress alc_v9_s100 upper=0.004 min=0.0001 n=6 mismatch=0 max_dn_ang=1.69451e-11 max_dgrel=1.33161e-09 max_dstopT=1.05733e-11 sum_rhs=18095 esc=6 dark=0 unres=0 inc=0 wall=0.004s
SUMMARY min_stress alc_v9_s100 upper=0.004 min=1e-05 n=6 mismatch=0 max_dn_ang=1.69451e-11 max_dgrel=1.33161e-09 max_dstopT=1.05733e-11 sum_rhs=18095 esc=6 dark=0 unres=0 inc=0 wall=0.004s
SUMMARY min_stress alc_v9_s100 upper=0.004 min=1e-06 n=6 mismatch=0 max_dn_ang=1.69451e-11 max_dgrel=1.33161e-09 max_dstopT=1.05733e-11 sum_rhs=18095 esc=6 dark=0 unres=0 inc=0 wall=0.004s
SUMMARY min_stress alc_v9_s100 upper=0.004 min=1e-08 n=6 mismatch=0 max_dn_ang=1.69451e-11 max_dgrel=1.33161e-09 max_dstopT=1.05733e-11 sum_rhs=18095 esc=6 dark=0 unres=0 inc=0 wall=0.004s
SUMMARY min_stress alc_v9_s100 upper=0.004 min=1e-12 n=6 mismatch=0 max_dn_ang=1.69451e-11 max_dgrel=1.33161e-09 max_dstopT=1.05733e-11 sum_rhs=18095 esc=6 dark=0 unres=0 inc=0 wall=0.004s
SUMMARY min_stress alc_v9_s100 upper=0.004 min=1e-14 n=6 mismatch=0 max_dn_ang=1.69451e-11 max_dgrel=1.33161e-09 max_dstopT=1.05733e-11 sum_rhs=18095 esc=6 dark=0 unres=0 inc=0 wall=0.004s
TOTAL_RAYS 498
real 0m0.264s
user 0m0.254s
sys 0m0.010s
+ set +x
@@ -0,0 +1,33 @@
### command: b_actual
+ /tmp/opencode/step_bounds/b_actual
B r30_inward dir=0 ref=1 refstop=-69.5728394 span=69.5728 T=20 target=-20 steps=17 reached=1 term=-1 h=[0.1,1.72575] first=0.1 last=0.839319 boundary=1 rhs=119 rej=0 nullmax=3.01e-12 final_t=-20 wall=0.0001s
B r30_inward dir=1 ref=0 refstop=-226 span=226 T=20 target=-20 steps=13 reached=1 term=-1 h=[0.1,2] first=0.1 last=0.123959 boundary=1 rhs=91 rej=0 nullmax=8.69e-12 final_t=-20 wall=0.0001s
B r30_inward dir=2 ref=1 refstop=-142.175748 span=142.176 T=20 target=-20 steps=20 reached=1 term=-1 h=[0.1,1.40832] first=0.1 last=0.637699 boundary=1 rhs=140 rej=0 nullmax=1.53e-11 final_t=-20 wall=0.0001s
B r30_inward dir=3 ref=0 refstop=-370.180478 span=370.18 T=20 target=-20 steps=20 reached=1 term=-1 h=[0.1,1.40832] first=0.1 last=0.6377 boundary=1 rhs=140 rej=0 nullmax=1.53e-11 final_t=-20 wall=0.0001s
B r30_inward dir=4 ref=1 refstop=-118.245807 span=118.246 T=20 target=-20 steps=20 reached=1 term=-1 h=[0.1,1.40833] first=0.1 last=0.637634 boundary=1 rhs=140 rej=0 nullmax=1.53e-11 final_t=-20 wall=0.0001s
B r30_inward dir=5 ref=0 refstop=-346.252134 span=346.252 T=20 target=-20 steps=20 reached=1 term=-1 h=[0.1,1.40831] first=0.1 last=0.637765 boundary=1 rhs=140 rej=0 nullmax=1.53e-11 final_t=-20 wall=0.0001s
B r100_inward dir=0 ref=1 refstop=-144.299101 span=144.299 T=20 target=-20 steps=12 reached=1 term=-1 h=[0.1,2] first=0.1 last=1.4 boundary=1 rhs=84 rej=0 nullmax=1.45e-14 final_t=-20 wall=0.0001s
B r100_inward dir=1 ref=0 refstop=-156 span=156 T=20 target=-20 steps=12 reached=1 term=-1 h=[0.1,2] first=0.1 last=1.4 boundary=1 rhs=84 rej=0 nullmax=7.66e-15 final_t=-20 wall=0.0001s
B r100_inward dir=2 ref=1 refstop=-301.077405 span=301.077 T=20 target=-20 steps=12 reached=1 term=-1 h=[0.1,2] first=0.1 last=1.4 boundary=1 rhs=84 rej=0 nullmax=1.4e-14 final_t=-20 wall=0.0001s
B r100_inward dir=3 ref=1 refstop=-211.027405 span=211.027 T=20 target=-20 steps=12 reached=1 term=-1 h=[0.1,2] first=0.1 last=1.4 boundary=1 rhs=84 rej=0 nullmax=1.32e-14 final_t=-20 wall=0.0001s
B r2p1_outward dir=0 ref=0 refstop=-253.9 span=253.9 T=20 target=-20 steps=46 reached=1 term=-1 h=[0.1,1.0708] first=0.1 last=1.06594 boundary=1 rhs=322 rej=0 nullmax=6.27e-11 final_t=-20 wall=0.0002s
B r2p1_outward dir=1 ref=0 refstop=-414.940103 span=414.94 T=20 target=-20 steps=105 reached=1 term=-1 h=[0.1,0.211533] first=0.1 last=0.192781 boundary=1 rhs=735 rej=0 nullmax=4.7e-11 final_t=-20 wall=0.0005s
B r2p1_outward dir=2 ref=0 refstop=-333.450704 span=333.451 T=20 target=-20 steps=105 reached=1 term=-1 h=[0.1,0.211533] first=0.1 last=0.192739 boundary=1 rhs=735 rej=0 nullmax=4.7e-11 final_t=-20 wall=0.0005s
B r2p1_outward dir=3 ref=1 refstop=-109.415611 span=109.416 T=20 target=-20 steps=105 reached=1 term=-1 h=[0.1,0.211532] first=0.1 last=0.192823 boundary=1 rhs=735 rej=0 nullmax=4.7e-11 final_t=-20 wall=0.0005s
B r2p1_outward dir=4 ref=1 refstop=-32.2468847 span=32.2469 T=20 target=-20 steps=37 reached=1 term=-1 h=[0.1,0.899361] first=0.1 last=0.332712 boundary=1 rhs=259 rej=0 nullmax=2.99e-11 final_t=-20 wall=0.0002s
B r1p5_freefall dir=0 ref=1 refstop=-30.6580907 span=30.6581 T=20 target=-20 steps=49 reached=1 term=-1 h=[0.1,0.695968] first=0.1 last=0.106174 boundary=1 rhs=343 rej=0 nullmax=4.94e-10 final_t=-20 wall=0.0002s
B r1p5_freefall dir=1 ref=0 refstop=-254.5 span=254.5 T=20 target=-20 steps=52 reached=1 term=-1 h=[0.0920967,1.08419] first=0.1 last=0.22147 boundary=1 rhs=364 rej=0 nullmax=4.03e-11 final_t=-20 wall=0.0002s
B mink_moving dir=0 ref=0 refstop=-51.2640254 span=51.264 T=20 target=-20 steps=3 reached=1 term=-1 h=[1,14] first=1 last=14 boundary=1 rhs=21 rej=0 nullmax=2.22e-16 final_t=-20 wall=0.0000s
B mink_moving dir=1 ref=0 refstop=-71.5846741 span=71.5847 T=20 target=-20 steps=3 reached=1 term=-1 h=[1,14] first=1 last=14 boundary=1 rhs=21 rej=0 nullmax=0 final_t=-20 wall=0.0000s
B alc_v3_s1 dir=0 ref=0 refstop=-16.4338937 span=16.4339 T=16.4339 target=-16.4339 steps=56 reached=1 term=-1 h=[0.05,0.4] first=0.05 last=0.203538 boundary=1 rhs=406 rej=2 nullmax=0 final_t=-16.4338937 wall=0.0001s
B alc_v3_s1 dir=1 ref=0 refstop=-29.3767055 span=29.3767 T=20 target=-20 steps=62 reached=1 term=-1 h=[0.05,0.4] first=0.05 last=0.27784 boundary=1 rhs=441 rej=1 nullmax=0 final_t=-20 wall=0.0001s
B alc_v9_s10 dir=0 ref=0 refstop=-2.03742978 span=2.03743 T=2.03743 target=-2.03743 steps=77 reached=1 term=-1 h=[0.005,0.04] first=0.005 last=0.0388523 boundary=1 rhs=588 rej=7 nullmax=0 final_t=-2.03742978 wall=0.0001s
B alc_v9_s10 dir=1 ref=0 refstop=-19.9638367 span=19.9638 T=19.9638 target=-19.9638 steps=521 reached=1 term=-1 h=[0.005,0.04] first=0.005 last=0.0365282 boundary=1 rhs=3682 rej=5 nullmax=2.22e-16 final_t=-19.9638367 wall=0.0009s
B alc_v9_s100 dir=0 ref=0 refstop=-1.10374298 span=1.10374 T=1.10374 target=-1.10374 steps=302 reached=1 term=-1 h=[0.0005,0.004] first=0.0005 last=0.00388798 boundary=1 rhs=2163 rej=7 nullmax=0 final_t=-1.10374298 wall=0.0005s
B alc_v9_s100 dir=1 ref=0 refstop=-2.89638367 span=2.89638 T=2.89638 target=-2.89638 steps=746 reached=1 term=-1 h=[0.0005,0.004] first=0.0005 last=0.00365282 boundary=1 rhs=5257 rej=5 nullmax=2.22e-16 final_t=-2.89638367 wall=0.0012s
TOTAL_OBSERVED_STEPS 2427
real 0m0.152s
user 0m0.145s
sys 0m0.006s
+ set +x
@@ -0,0 +1,142 @@
{
"r100_tight_reference": {
"vertices": 3158,
"triangles": 6188,
"outcomes": {
"0": 2906,
"1": 252
},
"reasons": {
"0": 2906,
"1": 252
},
"accepted": 2908050,
"rejected": 1963,
"rhs": 21294763,
"accepted_percentiles": {
"0": 659,
"0.5": 885,
"0.9": 1166,
"0.99": 1410,
"1": 1609
},
"rejected_percentiles": {
"0": 0,
"0.5": 0,
"0.9": 2,
"0.99": 3,
"1": 4
},
"rhs_percentiles": {
"0": 4900,
"0.5": 6496,
"0.9": 8463,
"0.99": 10171,
"1": 11564
},
"sha256": "a4f7def4212a7dae2b6290fd8635a5f1b087e11b0f8043e60e48fec71ecdb6e4",
"wall_seconds": 2.6278538939077407
},
"r100_ref_vs_0.5": {
"shared": 3158,
"only_a": 0,
"only_b": 0,
"terminal_mismatches": 0,
"max_sky_angle": 6.236425088081268e-08,
"max_logg_difference": 8.506182824080666e-10
},
"r100_ref_vs_2": {
"shared": 3158,
"only_a": 0,
"only_b": 0,
"terminal_mismatches": 0,
"max_sky_angle": 9.216337364737666e-08,
"max_logg_difference": 8.199086565935376e-10
},
"r100_ref_vs_8": {
"shared": 3158,
"only_a": 0,
"only_b": 0,
"terminal_mismatches": 0,
"max_sky_angle": 8.743723551600822e-08,
"max_logg_difference": 8.257244662329688e-10
},
"r100_ref_vs_32": {
"shared": 3158,
"only_a": 0,
"only_b": 0,
"terminal_mismatches": 0,
"max_sky_angle": 8.743704837242435e-08,
"max_logg_difference": 8.34318713074933e-10
},
"r2p1_tight_reference": {
"vertices": 5496,
"triangles": 10816,
"outcomes": {
"1": 1336,
"0": 4160
},
"reasons": {
"1": 1336,
"0": 4160
},
"accepted": 4515098,
"rejected": 8672,
"rhs": 33269502,
"accepted_percentiles": {
"0": 419,
"0.5": 805,
"0.9": 1034,
"0.99": 1253,
"1": 1860
},
"rejected_percentiles": {
"0": 1,
"0.5": 2,
"0.9": 2,
"0.99": 3,
"1": 3
},
"rhs_percentiles": {
"0": 3227,
"0.5": 5936,
"0.9": 7546,
"0.99": 9072,
"1": 13328
},
"sha256": "a81aac81cff2891627e21c22998ceb51d65ef779bb013922cadeb97140274cba",
"wall_seconds": 3.180392162874341
},
"r2p1_ref_vs_0.5": {
"shared": 5496,
"only_a": 0,
"only_b": 0,
"terminal_mismatches": 0,
"max_sky_angle": 1.4772143877471049e-05,
"max_logg_difference": 2.098608620215714e-09
},
"r2p1_ref_vs_2": {
"shared": 5496,
"only_a": 0,
"only_b": 0,
"terminal_mismatches": 0,
"max_sky_angle": 1.4772101910544689e-05,
"max_logg_difference": 2.0455042104572385e-09
},
"r2p1_ref_vs_8": {
"shared": 5496,
"only_a": 0,
"only_b": 0,
"terminal_mismatches": 0,
"max_sky_angle": 1.4772018211627154e-05,
"max_logg_difference": 2.059625359152051e-09
},
"r2p1_ref_vs_32": {
"shared": 5496,
"only_a": 0,
"only_b": 0,
"terminal_mismatches": 0,
"max_sky_angle": 1.4772020763985666e-05,
"max_logg_difference": 2.068350379857975e-09
}
}
@@ -0,0 +1,354 @@
{
"r100_hmax0.5": {
"vertices": 3158,
"triangles": 6188,
"outcomes": {
"0": 2906,
"1": 252
},
"reasons": {
"0": 2906,
"1": 252
},
"accepted": 2269662,
"rejected": 177,
"rhs": 16813349,
"accepted_percentiles": {
"0": 312,
"0.5": 736,
"0.9": 786,
"0.99": 848,
"1": 899
},
"rejected_percentiles": {
"0": 0,
"0.5": 0,
"0.9": 0,
"0.99": 1,
"1": 1
},
"rhs_percentiles": {
"0": 2471,
"0.5": 5446,
"0.9": 5803,
"0.99": 6223,
"1": 6587
},
"sha256": "787386a026203d846debf25a6a4f431a131b06bd3ab464f75f3e17a1d379992a",
"wall_seconds": 2.0714269301388413
},
"r100_hmax2": {
"vertices": 3158,
"triangles": 6188,
"outcomes": {
"0": 2906,
"1": 252
},
"reasons": {
"0": 2906,
"1": 252
},
"accepted": 723677,
"rejected": 5690,
"rhs": 6030185,
"accepted_percentiles": {
"0": 165,
"0.5": 220,
"0.9": 290,
"0.99": 348,
"1": 397
},
"rejected_percentiles": {
"0": 0,
"0.5": 2,
"0.9": 4,
"0.99": 5,
"1": 5
},
"rhs_percentiles": {
"0": 1442,
"0.5": 1855,
"0.9": 2324,
"0.99": 2737,
"1": 3073
},
"sha256": "187c3cbba6a18d88608cd3859da94d88b58ce9d65e0d800d84b3254a6b139151",
"wall_seconds": 0.9786226029973477
},
"r100_hmax8": {
"vertices": 3158,
"triangles": 6188,
"outcomes": {
"0": 2906,
"1": 252
},
"reasons": {
"0": 2906,
"1": 252
},
"accepted": 463004,
"rejected": 9336,
"rhs": 4230835,
"accepted_percentiles": {
"0": 80,
"0.5": 133,
"0.9": 225,
"0.99": 286,
"1": 357
},
"rejected_percentiles": {
"0": 0,
"0.5": 3,
"0.9": 5,
"0.99": 6,
"1": 7
},
"rhs_percentiles": {
"0": 868,
"0.5": 1253,
"0.9": 1869,
"0.99": 2289,
"1": 2786
},
"sha256": "4c7e9d401f2af237129a6a677ca94ed1ee41472594db57852a08647b1dc34aad",
"wall_seconds": 0.8228706018999219
},
"r100_hmax32": {
"vertices": 3158,
"triangles": 6188,
"outcomes": {
"0": 2906,
"1": 252
},
"reasons": {
"0": 2906,
"1": 252
},
"accepted": 441750,
"rejected": 9336,
"rhs": 4081609,
"accepted_percentiles": {
"0": 72,
"0.5": 126,
"0.9": 222,
"0.99": 285,
"1": 357
},
"rejected_percentiles": {
"0": 0,
"0.5": 3,
"0.9": 5,
"0.99": 6,
"1": 7
},
"rhs_percentiles": {
"0": 812,
"0.5": 1204,
"0.9": 1848,
"0.99": 2282,
"1": 2786
},
"sha256": "3742efd56893bec9e62a01668915ef7dda613d6504b2057043eb97c9b38334f3",
"wall_seconds": 0.8300854018889368
},
"r100_2_vs_0.5": {
"shared": 3158,
"only_a": 0,
"only_b": 0,
"terminal_mismatches": 0,
"max_sky_angle": 3.077090601306577e-08,
"max_logg_difference": 5.28674309191457e-11
},
"r100_2_vs_8": {
"shared": 3158,
"only_a": 0,
"only_b": 0,
"terminal_mismatches": 0,
"max_sky_angle": 7.063214322895989e-09,
"max_logg_difference": 3.2702011237839557e-11
},
"r100_2_vs_32": {
"shared": 3158,
"only_a": 0,
"only_b": 0,
"terminal_mismatches": 0,
"max_sky_angle": 7.063404202987903e-09,
"max_logg_difference": 2.477072019724247e-11
},
"r2p1_hmax0.5": {
"vertices": 5496,
"triangles": 10816,
"outcomes": {
"1": 1336,
"0": 4160
},
"reasons": {
"1": 1336,
"0": 4160
},
"accepted": 2646842,
"rejected": 830,
"rhs": 20136508,
"accepted_percentiles": {
"0": 116,
"0.5": 552,
"0.9": 618,
"0.99": 672,
"1": 823
},
"rejected_percentiles": {
"0": 0,
"0.5": 0,
"0.9": 1,
"0.99": 1,
"1": 2
},
"rhs_percentiles": {
"0": 1099,
"0.5": 4158,
"0.9": 4620,
"0.99": 4991,
"1": 6055
},
"sha256": "3a77a1e7dee3cd18d3ab8a408826aba932f912dc88749989e0c307013d6e7e81",
"wall_seconds": 1.973590083885938
},
"r2p1_hmax2": {
"vertices": 5496,
"triangles": 10816,
"outcomes": {
"1": 1336,
"0": 4160
},
"reasons": {
"1": 1336,
"0": 4160
},
"accepted": 1131104,
"rejected": 4004,
"rhs": 9548434,
"accepted_percentiles": {
"0": 109,
"0.5": 202,
"0.9": 258,
"0.99": 311,
"1": 460
},
"rejected_percentiles": {
"0": 0,
"0.5": 1,
"0.9": 1,
"0.99": 2,
"1": 2
},
"rhs_percentiles": {
"0": 1050,
"0.5": 1708,
"0.9": 2100,
"0.99": 2478,
"1": 3521
},
"sha256": "899331ea41d1612cf66bc7664b50e866f4f3bc7309e9c206440f801238ca455c",
"wall_seconds": 1.177934248931706
},
"r2p1_hmax8": {
"vertices": 5496,
"triangles": 10816,
"outcomes": {
"1": 1336,
"0": 4160
},
"reasons": {
"1": 1336,
"0": 4160
},
"accepted": 822680,
"rejected": 4004,
"rhs": 7389760,
"accepted_percentiles": {
"0": 87,
"0.5": 137,
"0.9": 212,
"0.99": 265,
"1": 386
},
"rejected_percentiles": {
"0": 0,
"0.5": 1,
"0.9": 1,
"0.99": 2,
"1": 2
},
"rhs_percentiles": {
"0": 910,
"0.5": 1260,
"0.9": 1778,
"0.99": 2142,
"1": 3003
},
"sha256": "49edfbe9dfb2948d3472e6ef6287bed103332758953756a7e4089316caa0b1b6",
"wall_seconds": 0.9704615350347012
},
"r2p1_hmax32": {
"vertices": 5496,
"triangles": 10816,
"outcomes": {
"1": 1336,
"0": 4160
},
"reasons": {
"1": 1336,
"0": 4160
},
"accepted": 795354,
"rejected": 4004,
"rhs": 7197806,
"accepted_percentiles": {
"0": 81,
"0.5": 132,
"0.9": 210,
"0.99": 261,
"1": 379
},
"rejected_percentiles": {
"0": 0,
"0.5": 1,
"0.9": 1,
"0.99": 2,
"1": 2
},
"rhs_percentiles": {
"0": 861,
"0.5": 1218,
"0.9": 1757,
"0.99": 2128,
"1": 2954
},
"sha256": "74bbb1e969644d49b7fdf5a6a7a5930ca8b962ec91628cd91feeb9df039100e7",
"wall_seconds": 0.9720155198592693
},
"r2p1_2_vs_0.5": {
"shared": 5496,
"only_a": 0,
"only_b": 0,
"terminal_mismatches": 0,
"max_sky_angle": 1.046601929593161e-10,
"max_logg_difference": 6.900746640781108e-11
},
"r2p1_2_vs_8": {
"shared": 5496,
"only_a": 0,
"only_b": 0,
"terminal_mismatches": 0,
"max_sky_angle": 8.369894549651799e-11,
"max_logg_difference": 1.9082291302652266e-11
},
"r2p1_2_vs_32": {
"shared": 5496,
"only_a": 0,
"only_b": 0,
"terminal_mismatches": 0,
"max_sky_angle": 8.114658658759588e-11,
"max_logg_difference": 2.823297151621773e-11
}
}
@@ -0,0 +1,54 @@
# Experiment A/B environment and source identity
date_utc: 2026-10-05T22:15:50Z
host: Linux ATRI-gentoo 6.18.48-gentoo #1 SMP PREEMPT_DYNAMIC Mon Aug 31 13:33:24 EDT 2026 x86_64 12th Gen Intel(R) Core(TM) i7-12700K GenuineIntel GNU/Linux
nproc: 16
cc:
cc (Gentoo 16.2.1_p20260926 p1) 16.2.1 20260926
Copyright (C) 2026 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
git_head: c894fdb11a0845558fdb67b71a9bd019a2d94ed4
git_status_short:
M Makefile
M mk/reference_images.mk
M nr_spacetime_movie_renderer_design.md
M src/asymptotic.c
M src/frame.c
M src/frame.h
M src/geodesic.c
M src/geodesic.h
M src/lens_map.c
M src/lens_map.h
M src/main.c
M src/ray.c
M src/ray.h
M tests/test_asymptotic.c
M tests/test_camera_cli.py
M tests/test_frame.c
M usage.md
?? nmesh_spacetime_output_format.md
?? tests/test_adaptive_cli.py
?? tests/test_geodesic_adaptive.c
# sha256 of the sources consumed by the harnesses
25f24a2e1c9ce49508fed230dfb3f6d9986e92bb4a5e6347bb2356ac0ee5fffa src/geodesic.c
1e43b95346f484050354631e8682f9793e618cbbd1de6338bd15e092216ae6fb src/geodesic.h
e6c0616461507adb1141ca3caa7e76f30e2497c4d53acfef092597fb60431a4a src/asymptotic.c
db029ef837f12800bbf81fc74e7bab6eb9f18e42a53ceb5f205867d8a329321d src/asymptotic.h
1792a17f432ceee32ee9c802486ecf9d64d96307c249e0d5cfa563ef4a0fefd5 src/asymptotic_schwarzschild.c
cc9ad0b04e11bd08bcf238901125e76a26ec332cd7fe72871e7c46fb7a322aec src/asymptotic_schwarzschild.h
ea0b5838bc56fbfeedec9110cd20653b892127bfc863db91a3a8cabaad4c520b src/asymptotic_gl48.h
359066d78a10f9589a220124147cdbefaff8f97028a9fdd2923b474349599752 src/spacetime.h
4c7ae6e96fe57e2a2ae2491db924bad56af59abfcc305bbb6ab2609f3b405e0d src/spacetime_common.c
690045ed715a951335dc7d654258e0f3b802e0bf6e2815ceb4858fa99cd372d7 src/spacetime_minkowski.c
e5b5935d16e24b07cedb25d184e8f7029075aec9496f54c23cb1061971914a72 src/spacetime_schwarzschild.c
75956034303fe3bab9324ecb87533e054458e35a26132a3e885233acad785767 src/spacetime_alcubierre.c
559f626983c68e06d3223d8381085a0b5ac422529a1ea656f4e24b1b3a50f51a src/observer.c
d761aabfbc277b0989bd20302578302d91f8253a9d900943de62ab3edd3f145b src/observer.h
# sha256 of the harnesses and this script
853018775c335180199aa3a0046445a5f795f83d18de0ff6a664a6368d835dbd a_public_endpoints.c
10a6558815e3ff5fa114aa8ca6dfe3c7db6e860ecb9f7cab20c59145a662d3d2 b_actual_h.c
1cfd93b0c9f187b4c45d169fbeb8c6fea7f02c3317ac24a32691723b0086548c run_experiment.sh
@@ -0,0 +1,318 @@
# Experiment A/B summary tables
## A Schwarzschild references (DP tol=1e-12, max_step=0.25)
| case | dir | theta | outcome | reason | stop_t | steps | rej | rhs | g | thr |
|---|---|---|---|---|---|---|---|---|---|---|
| r30_inward | 0 | 0 | DARK | REDSHIFT | -69.57 | 531 | 0 | 4004 | 0 | 8 |
| r30_inward | 1 | 3.142 | ESC | NONE | -226 | 905 | 0 | 6629 | 1.035 | nan |
| r30_inward | 2 | 1.571 | ESC | NONE | -256.7 | 1028 | 0 | 7490 | 1.035 | nan |
| r30_inward | 3 | 0.1681 | DARK | REDSHIFT | -225.9 | 3746 | 0 | 26509 | 0 | 8 |
| r30_inward | 4 | 0.1671 | DARK | REDSHIFT | -94.28 | 1127 | 0 | 8176 | 0 | 8 |
| r30_inward | 5 | 0.1691 | ESC | NONE | -322.4 | 1834 | 0 | 13132 | 1.035 | nan |
| r30_inward | 6 | 0.1681 | DARK | REDSHIFT | -118.2 | 1606 | 0 | 11529 | 0 | 8 |
| r30_inward | 7 | 0.1681 | ESC | NONE | -346.3 | 2312 | 1 | 16485 | 1.035 | nan |
| r30_inward | 8 | 0.1681 | DARK | REDSHIFT | -142.2 | 2081 | 0 | 14854 | 0 | 8 |
| r30_inward | 9 | 0.1681 | ESC | NONE | -370.2 | 2790 | 1 | 19831 | 1.035 | nan |
| r30_inward | 10 | 0.2181 | ESC | NONE | -302.6 | 1409 | 1 | 10164 | 1.035 | nan |
| r30_inward | 11 | 0.1181 | DARK | REDSHIFT | -73.76 | 665 | 0 | 4942 | 0 | 8 |
| r100_inward | 0 | 0 | DARK | REDSHIFT | -144.3 | 830 | 0 | 6097 | 0 | 8 |
| r100_inward | 1 | 3.142 | ESC | NONE | -156 | 625 | 0 | 4669 | 1.01 | nan |
| r100_inward | 2 | 1.571 | ESC | NONE | -237.7 | 952 | 0 | 6958 | 1.01 | nan |
| r100_inward | 3 | 0.05146 | DARK | REDSHIFT | -301.1 | 4045 | 0 | 28602 | 0 | 8 |
| r100_inward | 4 | 0.05046 | DARK | REDSHIFT | -163.1 | 1292 | 0 | 9331 | 0 | 8 |
| r100_inward | 5 | 0.05246 | ESC | NONE | -391.6 | 2014 | 1 | 14399 | 1.01 | nan |
| r100_inward | 6 | 0.05145 | DARK | REDSHIFT | -187.1 | 1773 | 0 | 12698 | 0 | 8 |
| r100_inward | 7 | 0.05147 | ESC | NONE | -415.4 | 2493 | 0 | 17745 | 1.01 | nan |
| r100_inward | 8 | 0.05146 | DARK | REDSHIFT | -211 | 2252 | 0 | 16051 | 0 | 8 |
| r100_inward | 9 | 0.05146 | ESC | NONE | -439.3 | 2969 | 0 | 21077 | 1.01 | nan |
| r100_inward | 10 | 0.1015 | ESC | NONE | -372.3 | 1571 | 0 | 11291 | 1.01 | nan |
| r100_inward | 11 | 0.001462 | DARK | REDSHIFT | -144.3 | 830 | 0 | 6097 | 0 | 8 |
| r2p1_outward | 0 | 0 | ESC | NONE | -253.9 | 1120 | 1 | 8141 | 4.583 | nan |
| r2p1_outward | 1 | 3.142 | DARK | REDSHIFT | -32.25 | 186 | 0 | 1589 | 0 | 8 |
| r2p1_outward | 2 | 1.571 | DARK | REDSHIFT | -32.77 | 316 | 1 | 2506 | 0 | 8 |
| r2p1_outward | 3 | 0.5704 | ESC | NONE | -414.9 | 4263 | 2 | 30149 | 4.583 | nan |
| r2p1_outward | 4 | 0.5694 | ESC | NONE | -285.6 | 1686 | 1 | 12103 | 4.583 | nan |
| r2p1_outward | 5 | 0.5714 | DARK | REDSHIFT | -61.58 | 995 | 1 | 7259 | 0 | 8 |
| r2p1_outward | 6 | 0.5704 | ESC | NONE | -309.5 | 2162 | 2 | 15442 | 4.583 | nan |
| r2p1_outward | 7 | 0.5704 | DARK | REDSHIFT | -85.49 | 1474 | 1 | 10612 | 0 | 8 |
| r2p1_outward | 8 | 0.5704 | ESC | NONE | -333.5 | 2639 | 1 | 18774 | 4.583 | nan |
| r2p1_outward | 9 | 0.5704 | DARK | REDSHIFT | -109.4 | 1950 | 1 | 13944 | 0 | 8 |
| r2p1_outward | 10 | 0.6204 | DARK | REDSHIFT | -41.99 | 585 | 1 | 4389 | 0 | 8 |
| r2p1_outward | 11 | 0.5204 | ESC | NONE | -265 | 1303 | 2 | 9429 | 4.583 | nan |
| r1p5_freefall | 0 | 0 | DARK | REDSHIFT | -30.66 | 231 | 1 | 1911 | 0 | 8 |
| r1p5_freefall | 1 | 1.571 | ESC | NONE | -255.2 | 1130 | 1 | 8211 | 1 | nan |
| r1p5_freefall | 2 | 3.142 | ESC | NONE | -254.5 | 1143 | 1 | 8302 | 0.4641 | nan |
| r1p5_freefall | 3 | 2.356 | ESC | NONE | -254.6 | 1127 | 1 | 8190 | 0.5505 | nan |
## A Schwarzschild upper scan (min_step=1e-12, tol=1e-9)
| case | upper | mismatch | max_dn_ang | max_dgrel | max_dstopT | sum_rhs | max_rej | ESC | DARK | UNRES | INC |
|---|---|---|---|---|---|---|---|---|---|---|---|
| r100_inward | 0.25 | 0 | 2.604e-05 | 2.048e-09 | 35.2 | 93464 | 0 | 6 | 6 | 0 | 0 |
| r100_inward | 0.5 | 0 | 5.696e-05 | 2.056e-09 | 39.27 | 56595 | 0 | 6 | 6 | 0 | 0 |
| r100_inward | 1 | 0 | 8.348e-05 | 2.051e-09 | 41.25 | 39788 | 1 | 6 | 6 | 0 | 0 |
| r100_inward | 2 | 0 | 8.286e-05 | 2.026e-09 | 41.22 | 32389 | 1 | 6 | 6 | 0 | 0 |
| r100_inward | 4 | 0 | 8.089e-05 | 2.028e-09 | 41.09 | 29393 | 2 | 6 | 6 | 0 | 0 |
| r100_inward | 8 | 0 | 8.034e-05 | 2.034e-09 | 41.06 | 28427 | 3 | 6 | 6 | 0 | 0 |
| r100_inward | 16 | 0 | 8.034e-05 | 2.042e-09 | 41.06 | 28189 | 3 | 6 | 6 | 0 | 0 |
| r100_inward | 32 | 0 | 8.034e-05 | 2.043e-09 | 41.06 | 28182 | 3 | 6 | 6 | 0 | 0 |
| r100_inward | 64 | 0 | 8.034e-05 | 2.043e-09 | 41.06 | 28182 | 3 | 6 | 6 | 0 | 0 |
| r1p5_freefall | 0.25 | 0 | 1.002e-10 | 3.165e-10 | 2.608e-08 | 23597 | 0 | 3 | 1 | 0 | 0 |
| r1p5_freefall | 0.5 | 0 | 8.875e-11 | 3.658e-10 | 3.089e-08 | 12747 | 0 | 3 | 1 | 0 | 0 |
| r1p5_freefall | 1 | 0 | 8.187e-11 | 3.811e-10 | 2.817e-08 | 7553 | 0 | 3 | 1 | 0 | 0 |
| r1p5_freefall | 2 | 0 | 8.165e-11 | 3.719e-10 | 2.571e-08 | 5131 | 0 | 3 | 1 | 0 | 0 |
| r1p5_freefall | 4 | 0 | 8.157e-11 | 3.632e-10 | 2.346e-08 | 4039 | 0 | 3 | 1 | 0 | 0 |
| r1p5_freefall | 8 | 0 | 8.151e-11 | 3.547e-10 | 2.125e-08 | 3591 | 0 | 3 | 1 | 0 | 0 |
| r1p5_freefall | 16 | 0 | 8.146e-11 | 3.469e-10 | 1.925e-08 | 3465 | 0 | 3 | 1 | 0 | 0 |
| r1p5_freefall | 32 | 0 | 8.146e-11 | 3.46e-10 | 1.948e-08 | 3458 | 0 | 3 | 1 | 0 | 0 |
| r1p5_freefall | 64 | 0 | 8.146e-11 | 3.46e-10 | 1.948e-08 | 3458 | 0 | 3 | 1 | 0 | 0 |
| r2p1_outward | 0.25 | 1 | 0.0002872 | 2.661e-09 | 263.1 | 62258 | 0 | 5 | 7 | 0 | 0 |
| r2p1_outward | 0.5 | 1 | 0.0002872 | 2.644e-09 | 263.1 | 42490 | 0 | 5 | 7 | 0 | 0 |
| r2p1_outward | 1 | 1 | 0.0002872 | 2.615e-09 | 263.1 | 33544 | 1 | 5 | 7 | 0 | 0 |
| r2p1_outward | 2 | 1 | 0.0002872 | 2.592e-09 | 263.1 | 29421 | 1 | 5 | 7 | 0 | 0 |
| r2p1_outward | 4 | 1 | 0.0002872 | 2.598e-09 | 263.1 | 27580 | 1 | 5 | 7 | 0 | 0 |
| r2p1_outward | 8 | 1 | 0.0002872 | 2.606e-09 | 263.1 | 26831 | 1 | 5 | 7 | 0 | 0 |
| r2p1_outward | 16 | 1 | 0.0002872 | 2.614e-09 | 263.1 | 26614 | 1 | 5 | 7 | 0 | 0 |
| r2p1_outward | 32 | 1 | 0.0002872 | 2.615e-09 | 263.1 | 26607 | 1 | 5 | 7 | 0 | 0 |
| r2p1_outward | 64 | 1 | 0.0002872 | 2.615e-09 | 263.1 | 26607 | 1 | 5 | 7 | 0 | 0 |
| r30_inward | 0.25 | 0 | 8.667e-05 | 2.262e-09 | 35.08 | 76510 | 0 | 6 | 6 | 0 | 0 |
| r30_inward | 0.5 | 0 | 0.0001866 | 2.268e-09 | 39.06 | 49063 | 1 | 6 | 6 | 0 | 0 |
| r30_inward | 1 | 0 | 0.0002801 | 2.266e-09 | 41.17 | 36974 | 2 | 6 | 6 | 0 | 0 |
| r30_inward | 2 | 0 | 0.0002819 | 2.244e-09 | 41.2 | 31843 | 2 | 6 | 6 | 0 | 0 |
| r30_inward | 4 | 0 | 0.0002819 | 2.25e-09 | 41.2 | 29617 | 2 | 6 | 6 | 0 | 0 |
| r30_inward | 8 | 0 | 0.0002819 | 2.258e-09 | 41.2 | 28714 | 2 | 6 | 6 | 0 | 0 |
| r30_inward | 16 | 0 | 0.0002819 | 2.266e-09 | 41.2 | 28455 | 2 | 6 | 6 | 0 | 0 |
| r30_inward | 32 | 0 | 0.0002819 | 2.266e-09 | 41.2 | 28434 | 2 | 6 | 6 | 0 | 0 |
| r30_inward | 64 | 0 | 0.0002819 | 2.266e-09 | 41.2 | 28434 | 2 | 6 | 6 | 0 | 0 |
## A Schwarzschild min scan (max_step=2, tol=1e-9)
| case | min_step | mismatch | max_dn_ang | max_dgrel | max_dstopT | sum_rhs | max_rej | ESC | DARK | UNRES | INC |
|---|---|---|---|---|---|---|---|---|---|---|---|
| r100_inward | 1e-14 | 0 | 8.286e-05 | 2.026e-09 | 41.22 | 32389 | 1 | 6 | 6 | 0 | 0 |
| r100_inward | 1e-12 | 0 | 8.286e-05 | 2.026e-09 | 41.22 | 32389 | 1 | 6 | 6 | 0 | 0 |
| r100_inward | 1e-10 | 0 | 8.286e-05 | 2.026e-09 | 41.22 | 32389 | 1 | 6 | 6 | 0 | 0 |
| r100_inward | 1e-08 | 0 | 8.286e-05 | 2.026e-09 | 41.22 | 32389 | 1 | 6 | 6 | 0 | 0 |
| r100_inward | 1e-06 | 0 | 8.286e-05 | 2.026e-09 | 41.22 | 32389 | 1 | 6 | 6 | 0 | 0 |
| r100_inward | 1e-05 | 0 | 8.286e-05 | 2.026e-09 | 41.22 | 32389 | 1 | 6 | 6 | 0 | 0 |
| r100_inward | 0.0001 | 0 | 8.286e-05 | 2.026e-09 | 41.22 | 32389 | 1 | 6 | 6 | 0 | 0 |
| r100_inward | 0.001 | 0 | 8.286e-05 | 2.026e-09 | 41.22 | 32389 | 1 | 6 | 6 | 0 | 0 |
| r100_inward | 0.01 | 0 | 8.286e-05 | 2.026e-09 | 41.22 | 32389 | 1 | 6 | 6 | 0 | 0 |
| r100_inward | 0.1 | 0 | 8.286e-05 | 2.026e-09 | 41.22 | 32389 | 1 | 6 | 6 | 0 | 0 |
| r1p5_freefall | 1e-14 | 0 | 8.165e-11 | 3.719e-10 | 2.571e-08 | 5131 | 0 | 3 | 1 | 0 | 0 |
| r1p5_freefall | 1e-12 | 0 | 8.165e-11 | 3.719e-10 | 2.571e-08 | 5131 | 0 | 3 | 1 | 0 | 0 |
| r1p5_freefall | 1e-10 | 0 | 8.165e-11 | 3.719e-10 | 2.571e-08 | 5131 | 0 | 3 | 1 | 0 | 0 |
| r1p5_freefall | 1e-08 | 0 | 8.165e-11 | 3.719e-10 | 2.571e-08 | 5131 | 0 | 3 | 1 | 0 | 0 |
| r1p5_freefall | 1e-06 | 0 | 8.165e-11 | 3.719e-10 | 2.571e-08 | 5131 | 0 | 3 | 1 | 0 | 0 |
| r1p5_freefall | 1e-05 | 0 | 8.165e-11 | 3.719e-10 | 2.571e-08 | 5131 | 0 | 3 | 1 | 0 | 0 |
| r1p5_freefall | 0.0001 | 0 | 8.165e-11 | 3.719e-10 | 2.571e-08 | 5131 | 0 | 3 | 1 | 0 | 0 |
| r1p5_freefall | 0.001 | 0 | 8.165e-11 | 3.719e-10 | 2.571e-08 | 5131 | 0 | 3 | 1 | 0 | 0 |
| r1p5_freefall | 0.01 | 0 | 8.165e-11 | 3.719e-10 | 2.571e-08 | 5131 | 0 | 3 | 1 | 0 | 0 |
| r1p5_freefall | 0.1 | 1 | 8.165e-11 | 3.719e-10 | 254.3 | 3654 | 0 | 2 | 1 | 0 | 1 |
| r2p1_outward | 1e-14 | 1 | 0.0002872 | 2.592e-09 | 263.1 | 29421 | 1 | 5 | 7 | 0 | 0 |
| r2p1_outward | 1e-12 | 1 | 0.0002872 | 2.592e-09 | 263.1 | 29421 | 1 | 5 | 7 | 0 | 0 |
| r2p1_outward | 1e-10 | 1 | 0.0002872 | 2.592e-09 | 263.1 | 29421 | 1 | 5 | 7 | 0 | 0 |
| r2p1_outward | 1e-08 | 1 | 0.0002872 | 2.592e-09 | 263.1 | 29421 | 1 | 5 | 7 | 0 | 0 |
| r2p1_outward | 1e-06 | 1 | 0.0002872 | 2.592e-09 | 263.1 | 29421 | 1 | 5 | 7 | 0 | 0 |
| r2p1_outward | 1e-05 | 1 | 0.0002872 | 2.592e-09 | 263.1 | 29421 | 1 | 5 | 7 | 0 | 0 |
| r2p1_outward | 0.0001 | 1 | 0.0002872 | 2.592e-09 | 263.1 | 29421 | 1 | 5 | 7 | 0 | 0 |
| r2p1_outward | 0.001 | 1 | 0.0002872 | 2.592e-09 | 263.1 | 29421 | 1 | 5 | 7 | 0 | 0 |
| r2p1_outward | 0.01 | 1 | 0.0002872 | 2.592e-09 | 263.1 | 29421 | 1 | 5 | 7 | 0 | 0 |
| r2p1_outward | 0.1 | 1 | 0.0002872 | 2.592e-09 | 263.1 | 29421 | 1 | 5 | 7 | 0 | 0 |
| r30_inward | 1e-14 | 0 | 0.0002819 | 2.244e-09 | 41.2 | 31843 | 2 | 6 | 6 | 0 | 0 |
| r30_inward | 1e-12 | 0 | 0.0002819 | 2.244e-09 | 41.2 | 31843 | 2 | 6 | 6 | 0 | 0 |
| r30_inward | 1e-10 | 0 | 0.0002819 | 2.244e-09 | 41.2 | 31843 | 2 | 6 | 6 | 0 | 0 |
| r30_inward | 1e-08 | 0 | 0.0002819 | 2.244e-09 | 41.2 | 31843 | 2 | 6 | 6 | 0 | 0 |
| r30_inward | 1e-06 | 0 | 0.0002819 | 2.244e-09 | 41.2 | 31843 | 2 | 6 | 6 | 0 | 0 |
| r30_inward | 1e-05 | 0 | 0.0002819 | 2.244e-09 | 41.2 | 31843 | 2 | 6 | 6 | 0 | 0 |
| r30_inward | 0.0001 | 0 | 0.0002819 | 2.244e-09 | 41.2 | 31843 | 2 | 6 | 6 | 0 | 0 |
| r30_inward | 0.001 | 0 | 0.0002819 | 2.244e-09 | 41.2 | 31843 | 2 | 6 | 6 | 0 | 0 |
| r30_inward | 0.01 | 0 | 0.0002819 | 2.244e-09 | 41.2 | 31843 | 2 | 6 | 6 | 0 | 0 |
| r30_inward | 0.1 | 0 | 0.0002819 | 2.244e-09 | 41.2 | 31843 | 2 | 6 | 6 | 0 | 0 |
## A Schwarzschild sensitive RK4 .01 vs .005
| case | dir | theta | out.01 | out.005 | hhalve_dn_ang | |dg| | rhs.01 | rhs.005 |
|---|---|---|---|---|---|---|---|---|
| r2p1_outward | 6 | 0.5704 | ESC | ESC | 1.032e-07 | 7.386e-12 | 124072 | 247880 |
| r2p1_outward | 7 | 0.5704 | DARK | DARK | nan | 0 | 34196 | 68392 |
| r2p1_outward | 8 | 0.5704 | ESC | ESC | 1.04e-05 | 7.618e-12 | 133644 | 267024 |
| r2p1_outward | 9 | 0.5704 | DARK | DARK | nan | 0 | 43768 | 87536 |
| r30_inward | 6 | 0.1681 | DARK | DARK | nan | 0 | 47300 | 94600 |
| r30_inward | 7 | 0.1681 | ESC | ESC | 0 | 8.238e-14 | 138764 | 277264 |
| r30_inward | 8 | 0.1681 | DARK | DARK | nan | 0 | 56872 | 113744 |
| r30_inward | 9 | 0.1681 | ESC | ESC | 1.891e-07 | 7.55e-15 | 148336 | 296408 |
## A Minkowski flat analytic check (n_inf and t)
| upper | min_step | n | max_dn_ang | max_dgrel | max_t_err |
|---|---|---|---|---|---|
| 1 | 1e-12 | 6 | 0 | 0 | 5.258e-13 |
| 1 | 1e-06 | 6 | 0 | 0 | 5.258e-13 |
| 1 | 0.1 | 6 | 0 | 0 | 5.258e-13 |
| 4 | 1e-12 | 6 | 0 | 0 | 1.776e-12 |
| 4 | 1e-06 | 6 | 0 | 0 | 1.776e-12 |
| 4 | 0.1 | 6 | 0 | 0 | 1.776e-12 |
| 16 | 1e-12 | 6 | 0 | 0 | 1.3e-11 |
| 16 | 1e-06 | 6 | 0 | 0 | 1.3e-11 |
| 16 | 0.1 | 6 | 0 | 0 | 1.3e-11 |
| 64 | 1e-12 | 6 | 0 | 0 | 3.894e-11 |
| 64 | 1e-06 | 6 | 0 | 0 | 3.894e-11 |
| 64 | 0.1 | 6 | 0 | 0 | 3.894e-11 |
| 256 | 1e-12 | 6 | 0 | 0 | 7.661e-11 |
| 256 | 1e-06 | 6 | 0 | 0 | 7.661e-11 |
| 256 | 0.1 | 6 | 0 | 0 | 7.661e-11 |
## A Minkowski flat analytic check (crossing x and t)
| upper | min_step | n | max_x_err | max_t_err |
|---|---|---|---|---|
| 1 | 1e-12 | 6 | 4.832e-13 | 5.258e-13 |
| 1 | 1e-06 | 6 | 4.832e-13 | 5.258e-13 |
| 1 | 0.1 | 6 | 4.832e-13 | 5.258e-13 |
| 4 | 1e-12 | 6 | 1.72e-12 | 1.776e-12 |
| 4 | 1e-06 | 6 | 1.72e-12 | 1.776e-12 |
| 4 | 0.1 | 6 | 1.72e-12 | 1.776e-12 |
| 16 | 1e-12 | 6 | 1.268e-11 | 1.3e-11 |
| 16 | 1e-06 | 6 | 1.268e-11 | 1.3e-11 |
| 16 | 0.1 | 6 | 1.268e-11 | 1.3e-11 |
| 64 | 1e-12 | 6 | 3.506e-11 | 3.894e-11 |
| 64 | 1e-06 | 6 | 3.506e-11 | 3.894e-11 |
| 64 | 0.1 | 6 | 3.506e-11 | 3.894e-11 |
| 256 | 1e-12 | 6 | 7.061e-11 | 7.661e-11 |
| 256 | 1e-06 | 6 | 7.061e-11 | 7.661e-11 |
| 256 | 0.1 | 6 | 7.061e-11 | 7.661e-11 |
## A Alcubierre alc_v3_s1 upper scan
| case | upper | mismatch | max_dn_ang | max_dgrel | max_dstopT | sum_rhs | max_rej | ESC | DARK | UNRES | INC |
|---|---|---|---|---|---|---|---|---|---|---|---|
| alc_v3_s1 | 0.05 | 0 | 7.544e-14 | 7.627e-13 | 1.99e-13 | 19740 | 0 | 6 | 0 | 0 | 0 |
| alc_v3_s1 | 0.05 | 0 | 7.544e-14 | 7.627e-13 | 1.99e-13 | 19740 | 0 | 6 | 0 | 0 | 0 |
| alc_v3_s1 | 0.05 | 0 | 7.544e-14 | 7.627e-13 | 1.99e-13 | 19740 | 0 | 6 | 0 | 0 | 0 |
| alc_v3_s1 | 0.2 | 0 | 1.208e-10 | 3.452e-10 | 4.091e-10 | 6475 | 2 | 6 | 0 | 0 | 0 |
| alc_v3_s1 | 0.2 | 0 | 1.208e-10 | 3.452e-10 | 4.091e-10 | 6475 | 2 | 6 | 0 | 0 | 0 |
| alc_v3_s1 | 0.2 | 0 | 1.208e-10 | 3.452e-10 | 4.091e-10 | 6475 | 2 | 6 | 0 | 0 | 0 |
| alc_v3_s1 | 0.4 | 0 | 1.03e-10 | 3.464e-10 | 3.143e-10 | 4613 | 2 | 6 | 0 | 0 | 0 |
| alc_v3_s1 | 0.4 | 0 | 1.03e-10 | 3.464e-10 | 3.143e-10 | 4613 | 2 | 6 | 0 | 0 | 0 |
| alc_v3_s1 | 0.4 | 0 | 1.03e-10 | 3.464e-10 | 3.143e-10 | 4613 | 2 | 6 | 0 | 0 | 0 |
| alc_v3_s1 | 0.8 | 0 | 7.888e-11 | 7.954e-10 | 7.369e-10 | 3794 | 2 | 6 | 0 | 0 | 0 |
| alc_v3_s1 | 0.8 | 0 | 7.888e-11 | 7.954e-10 | 7.369e-10 | 3794 | 2 | 6 | 0 | 0 | 0 |
| alc_v3_s1 | 0.8 | 0 | 7.888e-11 | 7.954e-10 | 7.369e-10 | 3794 | 2 | 6 | 0 | 0 | 0 |
| alc_v3_s1 | 1.6 | 0 | 1.239e-10 | 1.118e-09 | 1.148e-09 | 3430 | 2 | 6 | 0 | 0 | 0 |
| alc_v3_s1 | 1.6 | 0 | 1.239e-10 | 1.118e-09 | 1.148e-09 | 3430 | 2 | 6 | 0 | 0 | 0 |
| alc_v3_s1 | 1.6 | 0 | 1.239e-10 | 1.118e-09 | 1.148e-09 | 3430 | 2 | 6 | 0 | 0 | 0 |
| alc_v3_s1 | 3.2 | 0 | 1.545e-10 | 1.26e-09 | 1.346e-09 | 3290 | 2 | 6 | 0 | 0 | 0 |
| alc_v3_s1 | 3.2 | 0 | 1.545e-10 | 1.26e-09 | 1.346e-09 | 3290 | 2 | 6 | 0 | 0 | 0 |
| alc_v3_s1 | 3.2 | 0 | 1.545e-10 | 1.26e-09 | 1.346e-09 | 3290 | 2 | 6 | 0 | 0 | 0 |
## A Alcubierre alc_v3_s10 upper scan
| case | upper | mismatch | max_dn_ang | max_dgrel | max_dstopT | sum_rhs | max_rej | ESC | DARK | UNRES | INC |
|---|---|---|---|---|---|---|---|---|---|---|---|
| alc_v3_s10 | 0.005 | 0 | 5.829e-15 | 3.109e-14 | 4.663e-14 | 27412 | 0 | 6 | 0 | 0 | 0 |
| alc_v3_s10 | 0.005 | 0 | 5.829e-15 | 3.109e-14 | 4.663e-14 | 27412 | 0 | 6 | 0 | 0 | 0 |
| alc_v3_s10 | 0.005 | 0 | 5.829e-15 | 3.109e-14 | 4.663e-14 | 27412 | 0 | 6 | 0 | 0 | 0 |
| alc_v3_s10 | 0.02 | 0 | 6.299e-12 | 2.402e-10 | 1.399e-11 | 8337 | 4 | 6 | 0 | 0 | 0 |
| alc_v3_s10 | 0.02 | 0 | 6.299e-12 | 2.402e-10 | 1.399e-11 | 8337 | 4 | 6 | 0 | 0 | 0 |
| alc_v3_s10 | 0.02 | 0 | 6.299e-12 | 2.402e-10 | 1.399e-11 | 8337 | 4 | 6 | 0 | 0 | 0 |
| alc_v3_s10 | 0.04 | 0 | 3.288e-11 | 3.854e-10 | 6.294e-11 | 5621 | 6 | 6 | 0 | 0 | 0 |
| alc_v3_s10 | 0.04 | 0 | 3.288e-11 | 3.854e-10 | 6.294e-11 | 5621 | 6 | 6 | 0 | 0 | 0 |
| alc_v3_s10 | 0.04 | 0 | 3.288e-11 | 3.854e-10 | 6.294e-11 | 5621 | 6 | 6 | 0 | 0 | 0 |
| alc_v3_s10 | 0.08 | 0 | 1.042e-11 | 2.781e-10 | 8.024e-11 | 4648 | 12 | 6 | 0 | 0 | 0 |
| alc_v3_s10 | 0.08 | 0 | 1.042e-11 | 2.781e-10 | 8.024e-11 | 4648 | 12 | 6 | 0 | 0 | 0 |
| alc_v3_s10 | 0.08 | 0 | 1.042e-11 | 2.781e-10 | 8.024e-11 | 4648 | 12 | 6 | 0 | 0 | 0 |
| alc_v3_s10 | 0.16 | 0 | 1.131e-11 | 7.6e-10 | 9.538e-11 | 4270 | 13 | 6 | 0 | 0 | 0 |
| alc_v3_s10 | 0.16 | 0 | 1.131e-11 | 7.6e-10 | 9.538e-11 | 4270 | 13 | 6 | 0 | 0 | 0 |
| alc_v3_s10 | 0.16 | 0 | 1.131e-11 | 7.6e-10 | 9.538e-11 | 4270 | 13 | 6 | 0 | 0 | 0 |
| alc_v3_s10 | 0.32 | 0 | 3.131e-11 | 9.778e-10 | 1.041e-10 | 4116 | 13 | 6 | 0 | 0 | 0 |
| alc_v3_s10 | 0.32 | 0 | 3.131e-11 | 9.778e-10 | 1.041e-10 | 4116 | 13 | 6 | 0 | 0 | 0 |
| alc_v3_s10 | 0.32 | 0 | 3.131e-11 | 9.778e-10 | 1.041e-10 | 4116 | 13 | 6 | 0 | 0 | 0 |
## A Alcubierre alc_v9_s1 upper scan
| case | upper | mismatch | max_dn_ang | max_dgrel | max_dstopT | sum_rhs | max_rej | ESC | DARK | UNRES | INC |
|---|---|---|---|---|---|---|---|---|---|---|---|
| alc_v9_s1 | 0.05 | 0 | 6.632e-13 | 2.591e-11 | 1.387e-11 | 39452 | 0 | 6 | 0 | 0 | 0 |
| alc_v9_s1 | 0.05 | 0 | 6.632e-13 | 2.591e-11 | 1.387e-11 | 39452 | 0 | 6 | 0 | 0 | 0 |
| alc_v9_s1 | 0.05 | 0 | 6.632e-13 | 2.591e-11 | 1.387e-11 | 39452 | 0 | 6 | 0 | 0 | 0 |
| alc_v9_s1 | 0.2 | 0 | 1.078e-10 | 2.073e-09 | 6.805e-10 | 11690 | 3 | 6 | 0 | 0 | 0 |
| alc_v9_s1 | 0.2 | 0 | 1.078e-10 | 2.073e-09 | 6.805e-10 | 11690 | 3 | 6 | 0 | 0 | 0 |
| alc_v9_s1 | 0.2 | 0 | 1.078e-10 | 2.073e-09 | 6.805e-10 | 11690 | 3 | 6 | 0 | 0 | 0 |
| alc_v9_s1 | 0.4 | 0 | 6.25e-11 | 2.466e-09 | 1.083e-09 | 7413 | 3 | 6 | 0 | 0 | 0 |
| alc_v9_s1 | 0.4 | 0 | 6.25e-11 | 2.466e-09 | 1.083e-09 | 7413 | 3 | 6 | 0 | 0 | 0 |
| alc_v9_s1 | 0.4 | 0 | 6.25e-11 | 2.466e-09 | 1.083e-09 | 7413 | 3 | 6 | 0 | 0 | 0 |
| alc_v9_s1 | 0.8 | 0 | 5.349e-11 | 2.718e-09 | 1.186e-09 | 5369 | 3 | 6 | 0 | 0 | 0 |
| alc_v9_s1 | 0.8 | 0 | 5.349e-11 | 2.718e-09 | 1.186e-09 | 5369 | 3 | 6 | 0 | 0 | 0 |
| alc_v9_s1 | 0.8 | 0 | 5.349e-11 | 2.718e-09 | 1.186e-09 | 5369 | 3 | 6 | 0 | 0 | 0 |
| alc_v9_s1 | 1.6 | 0 | 1.035e-10 | 2.819e-09 | 9.549e-10 | 4431 | 3 | 6 | 0 | 0 | 0 |
| alc_v9_s1 | 1.6 | 0 | 1.035e-10 | 2.819e-09 | 9.549e-10 | 4431 | 3 | 6 | 0 | 0 | 0 |
| alc_v9_s1 | 1.6 | 0 | 1.035e-10 | 2.819e-09 | 9.549e-10 | 4431 | 3 | 6 | 0 | 0 | 0 |
| alc_v9_s1 | 3.2 | 0 | 1.239e-10 | 2.823e-09 | 3.249e-09 | 3983 | 3 | 6 | 0 | 0 | 0 |
| alc_v9_s1 | 3.2 | 0 | 1.239e-10 | 2.823e-09 | 3.249e-09 | 3983 | 3 | 6 | 0 | 0 | 0 |
| alc_v9_s1 | 3.2 | 0 | 1.239e-10 | 2.823e-09 | 3.249e-09 | 3983 | 3 | 6 | 0 | 0 | 0 |
## A Alcubierre alc_v9_s10 upper scan
| case | upper | mismatch | max_dn_ang | max_dgrel | max_dstopT | sum_rhs | max_rej | ESC | DARK | UNRES | INC |
|---|---|---|---|---|---|---|---|---|---|---|---|
| alc_v9_s10 | 0.005 | 0 | 8.937e-14 | 1.103e-11 | 3.553e-13 | 48167 | 0 | 6 | 0 | 0 | 0 |
| alc_v9_s10 | 0.005 | 0 | 8.937e-14 | 1.103e-11 | 3.553e-13 | 48167 | 0 | 6 | 0 | 0 | 0 |
| alc_v9_s10 | 0.005 | 0 | 8.937e-14 | 1.103e-11 | 3.553e-13 | 48167 | 0 | 6 | 0 | 0 | 0 |
| alc_v9_s10 | 0.02 | 0 | 5.331e-11 | 6.906e-10 | 1.092e-10 | 13692 | 6 | 6 | 0 | 0 | 0 |
| alc_v9_s10 | 0.02 | 0 | 5.331e-11 | 6.906e-10 | 1.092e-10 | 13692 | 6 | 6 | 0 | 0 | 0 |
| alc_v9_s10 | 0.02 | 0 | 5.331e-11 | 6.906e-10 | 1.092e-10 | 13692 | 6 | 6 | 0 | 0 | 0 |
| alc_v9_s10 | 0.04 | 0 | 1.752e-10 | 9.749e-10 | 3.646e-10 | 8484 | 7 | 6 | 0 | 0 | 0 |
| alc_v9_s10 | 0.04 | 0 | 1.752e-10 | 9.749e-10 | 3.646e-10 | 8484 | 7 | 6 | 0 | 0 | 0 |
| alc_v9_s10 | 0.04 | 0 | 1.752e-10 | 9.749e-10 | 3.646e-10 | 8484 | 7 | 6 | 0 | 0 | 0 |
| alc_v9_s10 | 0.08 | 0 | 1.196e-10 | 1.457e-09 | 2.695e-10 | 6251 | 12 | 6 | 0 | 0 | 0 |
| alc_v9_s10 | 0.08 | 0 | 1.196e-10 | 1.457e-09 | 2.695e-10 | 6251 | 12 | 6 | 0 | 0 | 0 |
| alc_v9_s10 | 0.08 | 0 | 1.196e-10 | 1.457e-09 | 2.695e-10 | 6251 | 12 | 6 | 0 | 0 | 0 |
| alc_v9_s10 | 0.16 | 0 | 1.727e-11 | 1.077e-09 | 1.26e-10 | 5278 | 15 | 6 | 0 | 0 | 0 |
| alc_v9_s10 | 0.16 | 0 | 1.727e-11 | 1.077e-09 | 1.26e-10 | 5278 | 15 | 6 | 0 | 0 | 0 |
| alc_v9_s10 | 0.16 | 0 | 1.727e-11 | 1.077e-09 | 1.26e-10 | 5278 | 15 | 6 | 0 | 0 | 0 |
| alc_v9_s10 | 0.32 | 0 | 5.499e-11 | 8.68e-10 | 2.555e-10 | 4872 | 14 | 6 | 0 | 0 | 0 |
| alc_v9_s10 | 0.32 | 0 | 5.499e-11 | 8.68e-10 | 2.555e-10 | 4872 | 14 | 6 | 0 | 0 | 0 |
| alc_v9_s10 | 0.32 | 0 | 5.499e-11 | 8.68e-10 | 2.555e-10 | 4872 | 14 | 6 | 0 | 0 | 0 |
## A Alcubierre v9 s100 lower-bound stress (upper=0.004)
| case | min_step | mismatch | max_dn_ang | max_dgrel | max_dstopT | sum_rhs | max_rej | ESC | DARK | UNRES | INC |
|---|---|---|---|---|---|---|---|---|---|---|---|
| alc_v9_s100 | 1e-14 | 0 | 1.695e-11 | 1.332e-09 | 1.057e-11 | 18095 | 7 | 6 | 0 | 0 | 0 |
| alc_v9_s100 | 1e-12 | 0 | 1.695e-11 | 1.332e-09 | 1.057e-11 | 18095 | 7 | 6 | 0 | 0 | 0 |
| alc_v9_s100 | 1e-08 | 0 | 1.695e-11 | 1.332e-09 | 1.057e-11 | 18095 | 7 | 6 | 0 | 0 | 0 |
| alc_v9_s100 | 1e-06 | 0 | 1.695e-11 | 1.332e-09 | 1.057e-11 | 18095 | 7 | 6 | 0 | 0 | 0 |
| alc_v9_s100 | 1e-05 | 0 | 1.695e-11 | 1.332e-09 | 1.057e-11 | 18095 | 7 | 6 | 0 | 0 | 0 |
| alc_v9_s100 | 0.0001 | 0 | 1.695e-11 | 1.332e-09 | 1.057e-11 | 18095 | 7 | 6 | 0 | 0 | 0 |
## B observed accepted step h (finite T=min(20, ref span))
| case | dir | ref | span | target | steps | reached | term | h_min | h_max | h_first | bnd | rhs | rej | null_max |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| r30_inward | 0 | DARK | 69.57 | -20 | 17 | 1 | -1 | 0.1 | 1.726 | 0.1 | 1 | 119 | 0 | 3.009e-12 |
| r30_inward | 1 | ESC | 226 | -20 | 13 | 1 | -1 | 0.1 | 2 | 0.1 | 1 | 91 | 0 | 8.69e-12 |
| r30_inward | 2 | DARK | 142.2 | -20 | 20 | 1 | -1 | 0.1 | 1.408 | 0.1 | 1 | 140 | 0 | 1.526e-11 |
| r30_inward | 3 | ESC | 370.2 | -20 | 20 | 1 | -1 | 0.1 | 1.408 | 0.1 | 1 | 140 | 0 | 1.526e-11 |
| r30_inward | 4 | DARK | 118.2 | -20 | 20 | 1 | -1 | 0.1 | 1.408 | 0.1 | 1 | 140 | 0 | 1.526e-11 |
| r30_inward | 5 | ESC | 346.3 | -20 | 20 | 1 | -1 | 0.1 | 1.408 | 0.1 | 1 | 140 | 0 | 1.526e-11 |
| r100_inward | 0 | DARK | 144.3 | -20 | 12 | 1 | -1 | 0.1 | 2 | 0.1 | 1 | 84 | 0 | 1.454e-14 |
| r100_inward | 1 | ESC | 156 | -20 | 12 | 1 | -1 | 0.1 | 2 | 0.1 | 1 | 84 | 0 | 7.661e-15 |
| r100_inward | 2 | DARK | 301.1 | -20 | 12 | 1 | -1 | 0.1 | 2 | 0.1 | 1 | 84 | 0 | 1.399e-14 |
| r100_inward | 3 | DARK | 211 | -20 | 12 | 1 | -1 | 0.1 | 2 | 0.1 | 1 | 84 | 0 | 1.321e-14 |
| r2p1_outward | 0 | ESC | 253.9 | -20 | 46 | 1 | -1 | 0.1 | 1.071 | 0.1 | 1 | 322 | 0 | 6.274e-11 |
| r2p1_outward | 1 | ESC | 414.9 | -20 | 105 | 1 | -1 | 0.1 | 0.2115 | 0.1 | 1 | 735 | 0 | 4.698e-11 |
| r2p1_outward | 2 | ESC | 333.5 | -20 | 105 | 1 | -1 | 0.1 | 0.2115 | 0.1 | 1 | 735 | 0 | 4.698e-11 |
| r2p1_outward | 3 | DARK | 109.4 | -20 | 105 | 1 | -1 | 0.1 | 0.2115 | 0.1 | 1 | 735 | 0 | 4.698e-11 |
| r2p1_outward | 4 | DARK | 32.25 | -20 | 37 | 1 | -1 | 0.1 | 0.8994 | 0.1 | 1 | 259 | 0 | 2.991e-11 |
| r1p5_freefall | 0 | DARK | 30.66 | -20 | 49 | 1 | -1 | 0.1 | 0.696 | 0.1 | 1 | 343 | 0 | 4.938e-10 |
| r1p5_freefall | 1 | ESC | 254.5 | -20 | 52 | 1 | -1 | 0.0921 | 1.084 | 0.1 | 1 | 364 | 0 | 4.034e-11 |
| mink_moving | 0 | ESC | 51.26 | -20 | 3 | 1 | -1 | 1 | 14 | 1 | 1 | 21 | 0 | 2.22e-16 |
| mink_moving | 1 | ESC | 71.58 | -20 | 3 | 1 | -1 | 1 | 14 | 1 | 1 | 21 | 0 | 0 |
| alc_v3_s1 | 0 | ESC | 16.43 | -16.43 | 56 | 1 | -1 | 0.05 | 0.4 | 0.05 | 1 | 406 | 2 | 0 |
| alc_v3_s1 | 1 | ESC | 29.38 | -20 | 62 | 1 | -1 | 0.05 | 0.4 | 0.05 | 1 | 441 | 1 | 0 |
| alc_v9_s10 | 0 | ESC | 2.037 | -2.037 | 77 | 1 | -1 | 0.005 | 0.04 | 0.005 | 1 | 588 | 7 | 0 |
| alc_v9_s10 | 1 | ESC | 19.96 | -19.96 | 521 | 1 | -1 | 0.005 | 0.04 | 0.005 | 1 | 3682 | 5 | 2.22e-16 |
| alc_v9_s100 | 0 | ESC | 1.104 | -1.104 | 302 | 1 | -1 | 0.0005 | 0.004 | 0.0005 | 1 | 2163 | 7 | 0 |
| alc_v9_s100 | 1 | ESC | 2.896 | -2.896 | 746 | 1 | -1 | 0.0005 | 0.004 | 0.0005 | 1 | 5257 | 5 | 2.22e-16 |
+124
View File
@@ -0,0 +1,124 @@
#!/usr/bin/env python3
"""One-task, at-most-two-attempt 4K comparison (R100, 3840x2160, FOV45).
This driver does NOT run as part of routine verification. It refuses to do
anything unless ``--authorize-two-4k`` is passed explicitly, and an attempt
ledger makes the task non-repeatable. Any future execution requires a fresh,
explicit user authorization for that task; authorization never extends to later
tasks or routine tests.
Usage:
run_4k_pair.py --authorize-two-4k [--out DIR]
OUT defaults to <repo>/local/adaptive_bounds_4k (distinct from any older
one-off ledger). The renderer binary is expected at
build/Release/schwarzschild_sky (see README for the make command).
"""
import argparse
import hashlib
import json
import os
from pathlib import Path
import shlex
import subprocess
import sys
import time
from mesh_maps import load, compare
ROOT = Path(__file__).resolve().parents[2]
ENV = dict(os.environ, OMP_NUM_THREADS='16', OMP_DYNAMIC='FALSE')
BUILD_CMD = 'make -j4 BUILD_TYPE=Release SPACETIME=schwarzschild backend'
REFUSAL = (
'REFUSING TO RUN: the 4K hmax 2-vs-8 pair is a one-task, at-most-two-attempt '
'experiment. Pass --authorize-two-4k only after an explicit fresh user '
'authorization for this task. It is not a routine verification target.')
def main():
ap = argparse.ArgumentParser(description=__doc__)
ap.add_argument('--authorize-two-4k', action='store_true',
help='explicit authorization for the two-attempt 4K pair')
ap.add_argument('--out', default=str(ROOT / 'local/adaptive_bounds_4k'),
help='output directory (default: local/adaptive_bounds_4k)')
args = ap.parse_args()
if not args.authorize_two_4k:
print(REFUSAL, file=sys.stderr)
return 2
out = Path(args.out).resolve()
binary = ROOT / 'build/Release/schwarzschild_sky'
if not binary.exists():
print(f'missing {binary}; build it first:\n {BUILD_CMD}',
file=sys.stderr)
return 2
out.mkdir(parents=True, exist_ok=True)
ledger = out / 'attempts.json'
attempts = json.loads(ledger.read_text()) if ledger.exists() else []
if attempts:
print('This one-task pair has already been attempted; no reruns '
'authorized.', file=sys.stderr)
return 3
catalog = out / 'single_dim_star.csv'
catalog.write_text('longitude_deg,latitude_deg,temperature_K,amplitude\n'
'262.5,-30,6000,1e-30\n')
with (out / 'cpu.txt').open('w') as f:
subprocess.run(['lscpu'], stdout=f, check=True)
metadata = {
'binary_sha256': hashlib.sha256(binary.read_bytes()).hexdigest(),
'utc': time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime()),
'source_sha256': {
p: hashlib.sha256((ROOT / p).read_bytes()).hexdigest()
for p in ('src/main.c', 'src/geodesic.c', 'src/frame.c')},
'catalog': 'one negligible synthetic point; no survey catalog',
'scope': 'README R100 45-degree 3840x2160 coarse16 refine4 jacobian0.2',
'threads': 16, 'max_attempts': 2,
'authorization': 'explicit --authorize-two-4k for this task only'}
(out / 'metadata.json').write_text(json.dumps(metadata, indent=2) + '\n')
maps = {}
results = {}
for upper in (2, 8):
name = f'r100_4k_hmax{upper}'
cmd = [str(binary), '--integrator', 'dp54', '--width', '3840',
'--height', '2160', '--look-ra-deg', '262.5',
'--look-dec-deg', '-30', '--fov-deg', '45',
'--observer-radius', '100', '--coarse-cell-pixels', '16',
'--refine-max-level', '4', '--refine-jacobian-min', '.2',
'--catalog', str(catalog), '--exposure', '1',
'--tone-map', 'reinhard', '--psf-min-y', '1e-20',
'--psf-relative-tail', '1e-4', '--ode-min-step', '1e-12',
'--ode-max-step', str(upper), '--verbose',
'--lens-map-output', str(out / (name + '.grlens')),
'--output', str(out / (name + '.png'))]
attempts.append({'upper': upper, 'command': shlex.join(cmd),
'state': 'attempted'})
ledger.write_text(json.dumps(attempts, indent=2) + '\n')
start = time.perf_counter()
with (out / (name + '.log')).open('w') as log:
log.write('OMP_NUM_THREADS=16 OMP_DYNAMIC=FALSE ' +
shlex.join(cmd) + '\n')
log.flush()
result = subprocess.run(cmd, cwd=ROOT, env=ENV, stdout=log,
stderr=subprocess.STDOUT, timeout=900)
attempts[-1].update(returncode=result.returncode,
wall_seconds=time.perf_counter() - start,
state='completed')
ledger.write_text(json.dumps(attempts, indent=2) + '\n')
if result.returncode:
raise SystemExit(f'4K attempt failed: {name}; no automatic retry.')
info, maps[upper] = load(out / (name + '.grlens'))
info['wall_seconds'] = attempts[-1]['wall_seconds']
results[name] = info
print(name, json.dumps(info), flush=True)
results['comparison'] = compare(maps[2], maps[8])
p, q = (results[f'r100_4k_hmax{h}']['provenance'] for h in (2, 8))
assert p['max_step'] == 2 and q['max_step'] == 8
assert {k: v for k, v in p.items() if k != 'max_step'} == \
{k: v for k, v in q.items() if k != 'max_step'}
print('comparison', json.dumps(results['comparison']), flush=True)
(out / 'summary.json').write_text(json.dumps(results, indent=2) + '\n')
return 0
if __name__ == '__main__':
sys.exit(main())
@@ -0,0 +1,36 @@
#!/usr/bin/env bash
# Run the standalone critical-classification reference check
# (benchmarks/adaptive_step_bounds_2026-10-05/critical_ref_check.c).
#
# benchmarks/adaptive_step_bounds_2026-10-05/run_critical_ref.sh [OUT_DIR]
#
# OUT_DIR defaults to <repo>/local/adaptive_step_bounds_2026-10-05. All output
# stays under OUT_DIR; the tracked benchmark directory holds only the sources.
# This is a diagnostic probe (see the C file header); it makes no pass/fail
# claim about the exactly-critical physical outcome.
set -euo pipefail
SOURCE=$(cd "$(dirname "$0")" && pwd)
root=$(cd "$SOURCE/../.." && pwd)
OUT=${1:-$root/local/adaptive_step_bounds_2026-10-05}
BIN=/tmp/opencode/step_bounds
mkdir -p "$OUT/raw" "$OUT/logs" "$BIN"
cd "$OUT"
OUT=$PWD
{
echo "### building critical_ref_check"
set -x
cc -std=c11 -O2 -Wall -Wextra -Wpedantic -I"$root/src" \
"$SOURCE/critical_ref_check.c" "$root/src/geodesic.c" \
"$root/src/asymptotic.c" "$root/src/asymptotic_schwarzschild.c" \
"$root/src/spacetime_common.c" "$root/src/observer.c" -lm \
-o "$BIN/critical_ref_check"
echo "### command: critical_ref_check"
time "$BIN/critical_ref_check"
set +x
} > logs/critical_ref.log 2>&1
cat logs/critical_ref.log
echo "outputs under $OUT"
@@ -0,0 +1,36 @@
#!/usr/bin/env bash
# Build and run the failure-path floor diagnostic.
#
# benchmarks/adaptive_step_bounds_2026-10-05/run_failure_floor.sh [OUT_DIR]
#
# OUT_DIR defaults to <repo>/local/adaptive_bounds_mesh. All output stays
# under OUT_DIR; the tracked benchmark directory holds only the sources.
#
# failure_floor.c includes ../../tests/test_geodesic_adaptive.c (depth-2 path
# valid from this directory) and therefore requires -DGEODESIC_EVENT_TESTING
# and the production RayPool source src/ray.c. The two analytic backends are
# textually included by the regression file, so they are not linked here.
set -euo pipefail
SOURCE=$(cd "$(dirname "$0")" && pwd)
root=$(cd "$SOURCE/../.." && pwd)
OUT=${1:-$root/local/adaptive_bounds_mesh}
BIN=/tmp/opencode/step_bounds
mkdir -p "$OUT/logs" "$BIN"
cd "$OUT"
{
set -x
cc -std=c11 -O2 -Wall -Wextra -Wpedantic -fopenmp -DGEODESIC_EVENT_TESTING \
-I"$root/src" \
"$SOURCE/failure_floor.c" "$root/src/geodesic.c" "$root/src/ray.c" \
"$root/src/spacetime_common.c" "$root/src/observer.c" \
"$root/src/asymptotic.c" "$root/src/asymptotic_schwarzschild.c" -lm \
-o "$BIN/failure_floor"
"$BIN/failure_floor"
set +x
} > logs/failure_floor.log 2>&1
cat logs/failure_floor.log
echo "outputs under $OUT"
+84
View File
@@ -0,0 +1,84 @@
#!/usr/bin/env bash
# Long-term reproduction driver for the adaptive step-bound scan (Experiment A/B).
#
# benchmarks/adaptive_step_bounds_2026-10-05/run_limited.sh [OUT_DIR]
#
# OUT_DIR defaults to <repo>/local/adaptive_step_bounds_2026-10-05. All build
# and run output — env/hash record, build log, stdout logs and per-ray CSV —
# is written under OUT_DIR, never into this tracked benchmark directory.
# Scratch binaries go to /tmp/opencode/step_bounds.
set -euo pipefail
SOURCE=$(cd "$(dirname "$0")" && pwd)
root=$(cd "$SOURCE/../.." && pwd)
OUT=${1:-$root/local/adaptive_step_bounds_2026-10-05}
BIN=/tmp/opencode/step_bounds
mkdir -p "$OUT/raw" "$OUT/logs" "$BIN"
cd "$OUT"
OUT=$PWD
SRC_COMMON="$root/src/geodesic.c $root/src/asymptotic.c \
$root/src/asymptotic_schwarzschild.c $root/src/spacetime_common.c \
$root/src/observer.c"
# --- environment + source identity (full shell output) --------------------
{
echo "# adaptive_step_bounds_2026-10-05 environment and source identity"
echo "date_utc: $(date -u +%Y-%m-%dT%H:%M:%SZ)"
echo "host: $(uname -a)"
echo "nproc: $(nproc)"
echo "cc:"; cc --version
echo
echo "git_head: $(git -C "$root" rev-parse HEAD 2>/dev/null || echo none)"
echo "git_status_short:"; git -C "$root" status --short 2>/dev/null || true
echo
echo "# sha256 of the production sources consumed by the harnesses"
sha256sum $SRC_COMMON
echo
echo "# sha256 of the benchmark harnesses"
sha256sum "$SOURCE/a_public_endpoints.c" "$SOURCE/b_actual_h.c" \
"$SOURCE/summarize.py" "$SOURCE/run_limited.sh"
} > logs/env.txt 2>&1
cat logs/env.txt
# --- build ----------------------------------------------------------------
{
echo "### building a_public_endpoints"
set -x
cc -std=c11 -O2 -Wall -Wextra -Wpedantic -I"$root/src" \
"$SOURCE/a_public_endpoints.c" $SRC_COMMON -lm -o "$BIN/a_public"
echo "### building b_actual_h"
cc -std=c11 -O2 -Wall -Wextra -Wpedantic -I"$root/src" \
"$SOURCE/b_actual_h.c" "$root/src/asymptotic.c" \
"$root/src/asymptotic_schwarzschild.c" "$root/src/spacetime_common.c" \
"$root/src/observer.c" -lm -o "$BIN/b_actual"
set +x
} > logs/build.log 2>&1
cat logs/build.log
# --- Experiment A ---------------------------------------------------------
{
echo "### command: a_public schwarzschild"
set -x; time "$BIN/a_public" schwarzschild; set +x
echo "### command: a_public minkowski"
set -x; time "$BIN/a_public" minkowski; set +x
echo "### command: a_public alcubierre"
set -x; time "$BIN/a_public" alcubierre; set +x
} > logs/expA.log 2>&1
grep -E '^(SUMMARY|TOTAL_RAYS|real|user)' logs/expA.log | tail -20
# --- Experiment B ---------------------------------------------------------
{
echo "### command: b_actual"
set -x; time "$BIN/b_actual"; set +x
} > logs/expB.log 2>&1
cat logs/expB.log
# --- summary tables -------------------------------------------------------
python3 "$SOURCE/summarize.py" "$OUT"
echo
echo "rays A = $(grep '^TOTAL_RAYS' logs/expA.log | awk '{s+=$2} END{print s}')"
echo "observed steps B = $(grep '^TOTAL_OBSERVED_STEPS' logs/expB.log | awk '{print $2}')"
echo "outputs under $OUT"
+84
View File
@@ -0,0 +1,84 @@
#!/usr/bin/env python3
"""Bounded 320x180 adaptive-mesh candidates (8 cases; no 4K, no references).
Usage:
run_mesh.py [OUT_DIR]
OUT_DIR defaults to <repo>/local/adaptive_bounds_mesh. The renderer binary is
expected to already exist at build/Release/schwarzschild_sky; build it with
(make command is also in README.md):
make -j4 BUILD_TYPE=Release SPACETIME=schwarzschild backend
No survey catalog is used: the script writes a one-point synthetic dim catalog
with the required column header (longitude_deg,latitude_deg,temperature_K,
amplitude) and a 1e-30 amplitude star. No external CSV is read.
"""
import json
import os
from pathlib import Path
import shlex
import subprocess
import sys
import time
from mesh_maps import load, compare # tracked sibling module (no local/ import)
ROOT = Path(__file__).resolve().parents[2]
OUT = Path(sys.argv[1]).resolve() if len(sys.argv) > 1 else \
ROOT / 'local/adaptive_bounds_mesh'
BIN = ROOT / 'build/Release/schwarzschild_sky'
BUILD_CMD = 'make -j4 BUILD_TYPE=Release SPACETIME=schwarzschild backend'
ENV = dict(os.environ, OMP_NUM_THREADS='8', OMP_DYNAMIC='FALSE')
def scene_args(scene):
if scene == 'r100':
return ['--observer-radius', '100', '--look-ra-deg', '262.5',
'--look-dec-deg', '-30', '--fov-deg', '45',
'--refine-jacobian-min', '.2']
return ['--observer-position', '2.1', '0', '0', '--observer-velocity',
'0', '0', '0', '--look-ra-deg', '0', '--look-dec-deg', '0',
'--fov-deg', '90']
def main():
if not BIN.exists():
raise SystemExit(f'missing {BIN}; build it first:\n {BUILD_CMD}')
OUT.mkdir(parents=True, exist_ok=True)
catalog = OUT / 'single_dim_star.csv'
catalog.write_text('longitude_deg,latitude_deg,temperature_K,amplitude\n'
'262.5,-30,6000,1e-30\n')
results = {}
for scene in ('r100', 'r2p1'):
meshes = {}
for upper in (.5, 2, 8, 32):
name = f'{scene}_hmax{upper:g}'
cmd = [str(BIN), '--integrator', 'dp54',
'--width', '320', '--height', '180',
'--coarse-cell-pixels', '8', '--refine-max-level', '3',
'--catalog', str(catalog), '--exposure', '1',
'--psf-min-y', '1e-20', '--psf-relative-tail', '1e-4',
'--ode-min-step', '1e-12', '--ode-max-step', str(upper),
'--verbose', '--lens-map-output', str(OUT / (name + '.grlens')),
'--output', str(OUT / (name + '.png')), *scene_args(scene)]
start = time.perf_counter()
with (OUT / (name + '.log')).open('w') as log:
log.write('OMP_NUM_THREADS=8 OMP_DYNAMIC=FALSE ' +
shlex.join(cmd) + '\n')
log.flush()
subprocess.run(cmd, cwd=ROOT, env=ENV, stdout=log,
stderr=subprocess.STDOUT, check=True, timeout=180)
info, meshes[upper] = load(OUT / (name + '.grlens'))
info['wall_seconds'] = time.perf_counter() - start
results[name] = info
print(name, json.dumps(info), flush=True)
for upper in (.5, 8, 32):
comparison = compare(meshes[2], meshes[upper])
results[f'{scene}_2_vs_{upper:g}'] = comparison
print(f'{scene} 2 vs {upper:g}', json.dumps(comparison), flush=True)
(OUT / 'summary.json').write_text(json.dumps(results, indent=2) + '\n')
if __name__ == '__main__':
main()
@@ -0,0 +1,82 @@
#!/usr/bin/env python3
"""Two bounded tight-tolerance mesh references and comparisons (no 4K).
Usage:
run_mesh_reference.py [OUT_DIR]
OUT_DIR defaults to <repo>/local/adaptive_bounds_mesh and must already contain
the eight ``<scene>_hmax<h>.grlens`` maps from ``run_mesh.py``. The renderer
binary is expected at build/Release/schwarzschild_sky (see README for the make
command). Same one-point synthetic dim catalog, no external CSV.
"""
import json
import os
from pathlib import Path
import shlex
import subprocess
import sys
import time
from mesh_maps import load, compare
ROOT = Path(__file__).resolve().parents[2]
OUT = Path(sys.argv[1]).resolve() if len(sys.argv) > 1 else \
ROOT / 'local/adaptive_bounds_mesh'
BIN = ROOT / 'build/Release/schwarzschild_sky'
BUILD_CMD = 'make -j4 BUILD_TYPE=Release SPACETIME=schwarzschild backend'
ENV = dict(os.environ, OMP_NUM_THREADS='8', OMP_DYNAMIC='FALSE')
def scene_args(scene):
if scene == 'r100':
return ['--observer-radius', '100', '--look-ra-deg', '262.5',
'--look-dec-deg', '-30', '--fov-deg', '45',
'--refine-jacobian-min', '.2']
return ['--observer-position', '2.1', '0', '0', '--observer-velocity',
'0', '0', '0', '--look-ra-deg', '0', '--look-dec-deg', '0',
'--fov-deg', '90']
def main():
if not BIN.exists():
raise SystemExit(f'missing {BIN}; build it first:\n {BUILD_CMD}')
OUT.mkdir(parents=True, exist_ok=True)
catalog = OUT / 'single_dim_star.csv'
if not catalog.exists():
catalog.write_text('longitude_deg,latitude_deg,temperature_K,amplitude\n'
'262.5,-30,6000,1e-30\n')
results = {}
for scene in ('r100', 'r2p1'):
name = scene + '_tight_reference'
cmd = [str(BIN), '--integrator', 'dp54', '--width', '320',
'--height', '180', '--coarse-cell-pixels', '8',
'--refine-max-level', '3', '--catalog', str(catalog),
'--exposure', '1', '--psf-min-y', '1e-20',
'--psf-relative-tail', '1e-4', '--ode-min-step', '1e-12',
'--ode-max-step', '.5', '--ode-rtol', '1e-12',
'--ode-atol-x', '1e-12', '--ode-atol-pi', '1e-12',
'--ode-atol-l', '1e-12', '--verbose',
'--lens-map-output', str(OUT / (name + '.grlens')),
'--output', str(OUT / (name + '.png')), *scene_args(scene)]
start = time.perf_counter()
with (OUT / (name + '.log')).open('w') as log:
log.write('OMP_NUM_THREADS=8 OMP_DYNAMIC=FALSE ' +
shlex.join(cmd) + '\n')
log.flush()
subprocess.run(cmd, cwd=ROOT, env=ENV, stdout=log,
stderr=subprocess.STDOUT, check=True, timeout=180)
info, ref = load(OUT / (name + '.grlens'))
info['wall_seconds'] = time.perf_counter() - start
results[name] = info
print(name, json.dumps(info), flush=True)
for upper in (.5, 2, 8, 32):
_, vertices = load(OUT / f'{scene}_hmax{upper:g}.grlens')
result = compare(ref, vertices)
results[f'{scene}_ref_vs_{upper:g}'] = result
print(scene, 'ref vs', upper, json.dumps(result), flush=True)
(OUT / 'reference_summary.json').write_text(
json.dumps(results, indent=2) + '\n')
if __name__ == '__main__':
main()
@@ -0,0 +1,261 @@
#!/usr/bin/env python3
"""Summarise the adaptive-step-bounds benchmark raw CSV logs.
Usage:
summarize.py [OUT_DIR]
Reads ``OUT_DIR/raw/*.csv`` (written by ``run_limited.sh``) and writes
``OUT_DIR/logs/summary.txt``. It has no dependency on any untracked script or
on older local data.
Defaults: OUT_DIR = <repo>/local/adaptive_step_bounds_2026-10-05, derived from
this file's location (benchmarks/adaptive_step_bounds_2026-10-05/).
"""
import csv
import math
import os
import sys
HERE = os.path.dirname(os.path.abspath(__file__))
ROOT = os.path.dirname(os.path.dirname(HERE))
DEFAULT_OUT = os.path.join(ROOT, "local", "adaptive_step_bounds_2026-10-05")
OUTCOME = {0: "ESC", 1: "DARK", 2: "UNRES", 3: "INC"}
REASON = {
0: "NONE",
1: "REDSHIFT",
2: "BUDGET",
3: "TIMERANGE",
4: "DOMAIN",
5: "INVMETRIC",
6: "INTEGERR",
7: "UNSUPPORTED",
8: "PROTOCOL",
9: "IO",
}
def fnum(v):
if v is None or v == "" or v == "nan":
return math.nan
return float(v)
def fmt(v):
if isinstance(v, float):
if math.isnan(v):
return "nan"
if v == 0:
return "0"
return f"{v:.4g}"
return str(v)
def table(title, header, recs):
lines = [f"## {title}", ""]
lines.append("| " + " | ".join(header) + " |")
lines.append("|" + "|".join(["---"] * len(header)) + "|")
for r in recs:
lines.append("| " + " | ".join(fmt(x) for x in r) + " |")
lines.append("")
return lines
def ang_between(a, b):
va = [fnum(a["nx"]), fnum(a["ny"]), fnum(a["nz"])]
vb = [fnum(b["nx"]), fnum(b["ny"]), fnum(b["nz"])]
na = math.sqrt(sum(x * x for x in va))
nb = math.sqrt(sum(x * x for x in vb))
if not (na > 0 and nb > 0):
return math.nan
cross = (va[1]*vb[2]-va[2]*vb[1],
va[2]*vb[0]-va[0]*vb[2],
va[0]*vb[1]-va[1]*vb[0])
dot = sum(x * y for x, y in zip(va, vb))
return math.atan2(math.sqrt(sum(x*x for x in cross)), dot)
class Raw:
def __init__(self, out_dir):
self.raw = os.path.join(out_dir, "raw")
self.logs = os.path.join(out_dir, "logs")
def rows(self, name):
with open(os.path.join(self.raw, name)) as f:
return list(csv.DictReader(f))
def summarise_agg(raw, name, title, keycol):
recs = raw.rows(name)
out = []
for r in recs:
out.append((r["case"], float(r[keycol]), int(r["class_mismatch"]),
fnum(r["max_dn_ang"]), fnum(r["max_dgrel"]),
fnum(r["max_dstopT"]), int(r["sum_rhs"]),
int(r["max_rejected"]), int(r["escaped"]), int(r["dark"]),
int(r["unresolved"]), int(r["incomplete"])))
out.sort(key=lambda x: (x[0], x[1]))
return table(title,
["case", keycol, "mismatch", "max_dn_ang", "max_dgrel",
"max_dstopT", "sum_rhs", "max_rej", "ESC", "DARK", "UNRES",
"INC"], out)
def build(raw):
lines = ["# Adaptive-step-bounds benchmark summary tables", ""]
ref = raw.rows("a_sch_reference.csv")
recs = []
for r in ref:
recs.append((r["case"], int(r["dir"]), fnum(r["theta"]),
OUTCOME[int(r["outcome"])], REASON[int(r["reason"])],
fnum(r["stop_t"]), int(r["steps"]), int(r["rejected"]),
int(r["rhs"]), fnum(r["g"]), fnum(r["thr"])))
lines += table("A Schwarzschild references (DP tol=1e-12, max_step=0.25)",
["case", "dir", "theta", "outcome", "reason", "stop_t",
"steps", "rej", "rhs", "g", "thr"], recs)
lines += summarise_agg(raw, "a_sch_upper_summary.csv",
"A Schwarzschild upper scan (min_step=1e-12, "
"tol=1e-9)", "upper")
lines += summarise_agg(raw, "a_sch_min_summary.csv",
"A Schwarzschild min scan (max_step=2, tol=1e-9)",
"min_step")
rk = raw.rows("a_sch_rk4_sensitive.csv")
groups = {}
for r in rk:
groups.setdefault((r["case"], r["dir"]), {})[r["phase"]] = r
recs = []
for (case, d), gg in sorted(groups.items()):
a = gg.get("rk4_0.01")
b = gg.get("rk4_0.005")
if not a or not b:
continue
dn = math.nan if a["outcome"] != b["outcome"] else ang_between(a, b)
dg = (math.nan if a["outcome"] != b["outcome"]
else abs(fnum(a["g"]) - fnum(b["g"])))
recs.append((case, d, fnum(a["theta"]), OUTCOME[int(a["outcome"])],
OUTCOME[int(b["outcome"])], dn, dg, int(a["rhs"]),
int(b["rhs"])))
lines += table("A Schwarzschild sensitive RK4 .01 vs .005",
["case", "dir", "theta", "out.01", "out.005",
"hhalve_dn_ang", "|dg|", "rhs.01", "rhs.005"], recs)
mk = raw.rows("a_mink_analytic.csv")
mkx = raw.rows("a_mink_analytic_x.csv")
groups = {}
for r in mk:
groups.setdefault((r["upper"], r["min_step"]), []).append(r)
recs = []
for (u, f), g in sorted(groups.items(),
key=lambda kv: (float(kv[0][0]), float(kv[0][1]))):
recs.append((u, f, len(g), max(fnum(r["dn_ang"]) for r in g),
max(fnum(r["dgrel"]) for r in g),
max(fnum(r["t_err"]) for r in g)))
lines += table("A Minkowski flat analytic check (n_inf and t)",
["upper", "min_step", "n", "max_dn_ang", "max_dgrel",
"max_t_err"], recs)
groups = {}
for r in mkx:
groups.setdefault((r["upper"], r["min_step"]), []).append(r)
recs = []
for (u, f), g in sorted(groups.items(),
key=lambda kv: (float(kv[0][0]), float(kv[0][1]))):
maxx = max(max(fnum(r["x_err_x"]), fnum(r["x_err_y"]),
fnum(r["x_err_z"])) for r in g)
recs.append((u, f, len(g), maxx, max(fnum(r["t_err"]) for r in g)))
lines += table("A Minkowski flat analytic check (crossing x and t)",
["upper", "min_step", "n", "max_x_err", "max_t_err"], recs)
for case in ["alc_v3_s1", "alc_v3_s10", "alc_v9_s1", "alc_v9_s10"]:
lines += summarise_agg(raw, f"a_alc_{case}_upper_summary.csv",
f"A Alcubierre {case} upper scan", "upper")
lines += summarise_agg(raw, "a_alc_v9_s100_min_summary.csv",
"A Alcubierre v9 s100 lower-bound stress "
"(upper=0.004)", "min_step")
b = raw.rows("b_summary.csv")
recs = []
for r in b:
recs.append((r["case"], int(r["dir"]),
OUTCOME[int(r["ref_outcome"])], fnum(r["span"]),
fnum(r["target"]), int(r["observed_steps"]),
int(r["reached_target"]),
REASON.get(int(r["terminated_reason"]),
r["terminated_reason"]),
fnum(r["h_min"]), fnum(r["h_max"]), fnum(r["h_first"]),
int(r["boundary_steps"]), int(r["sum_rhs"]),
int(r["sum_reject"]), fnum(r["null_residual_max"])))
lines += table("B observed accepted step h (finite T=min(20, ref span))",
["case", "dir", "ref", "span", "target", "steps", "reached",
"term", "h_min", "h_max", "h_first", "bnd", "rhs", "rej",
"null_max"], recs)
if os.path.exists(os.path.join(raw.raw, "critical_ref.csv")):
lines += critical_section(raw)
return lines
def critical_section(raw):
rows = raw.rows("critical_ref.csv")
key = {}
for r in rows:
key[(r["camera"], int(r["dir"]), r["cfg"])] = r
lines = table("critical reference check (raw rows)",
["camera", "dir", "theta", "cfg", "outcome", "reason",
"end_id", "stop_t", "steps", "rejected", "rhs", "g", "thr",
"L", "L0"],
[(r["camera"], int(r["dir"]), fnum(r["theta"]), r["cfg"],
OUTCOME[int(r["outcome"])], REASON[int(r["reason"])],
r["end_id"], fnum(r["stop_t"]), int(r["steps"]),
int(r["rejected"]), int(r["rhs"]), fnum(r["g"]),
fnum(r["thr"]), fnum(r.get("L")), fnum(r.get("L0")))
for r in rows])
# pair comparisons
pairs = [("ref_tol1e-12_h0.25", "ref_tol1e-13_h0.125"),
("tol1e-11_h2", "tol1e-11_h8"),
("ref_tol1e-12_h0.25", "tol1e-11_h2"),
("ref_tol1e-12_h0.25", "tol1e-11_h8")]
for a_cfg, b_cfg in pairs:
recs = []
for (cam, di, cfg), a in sorted(key.items()):
if cfg != a_cfg:
continue
b = key.get((cam, di, b_cfg))
if not b:
continue
same = a["outcome"] == b["outcome"]
dn = ang_between(a, b) if same else math.nan
dg = (math.nan if not same else
abs(fnum(a["g"]) / fnum(b["g"]) - 1.0)
if fnum(a["g"]) > 0 and fnum(b["g"]) > 0 else math.nan)
dstop = (fnum(a["stop_t"]) - fnum(b["stop_t"])
if fnum(a["stop_t"]) == fnum(a["stop_t"]) and
fnum(b["stop_t"]) == fnum(b["stop_t"]) else math.nan)
dmar = (fnum(a["thr"]) - fnum(b["thr"])
if fnum(a["thr"]) == fnum(a["thr"]) and
fnum(b["thr"]) == fnum(b["thr"]) else math.nan)
recs.append((cam, di, fnum(a["theta"]),
OUTCOME[int(a["outcome"])], OUTCOME[int(b["outcome"])],
same, dn, dg, dstop, dmar))
lines += table(f"critical pair {a_cfg} vs {b_cfg}",
["camera", "dir", "theta", "a", "b", "same",
"dn_ang", "dgrel", "dstop_t", "dthr"], recs)
return lines
def main(argv):
out = argv[1] if len(argv) > 1 else DEFAULT_OUT
raw = Raw(out)
os.makedirs(raw.logs, exist_ok=True)
lines = build(raw)
path = os.path.join(raw.logs, "summary.txt")
with open(path, "w") as f:
f.write("\n".join(lines) + "\n")
print(f"wrote {path} ({len(lines)} lines)")
return 0
if __name__ == "__main__":
sys.exit(main(sys.argv))
+67
View File
@@ -0,0 +1,67 @@
#!/usr/bin/env python3
"""Postprocess existing 4K/limited maps only; never invokes a renderer.
Usage:
summarize_4k.py [OUT_DIR]
OUT_DIR defaults to <repo>/local/adaptive_bounds_4k and must contain
``r100_4k_hmax2.grlens``, ``r100_4k_hmax8.grlens`` and ``attempts.json``.
Writes summary.json in OUT_DIR.
Cost scope note: accepted/rejected/RHS sums cover the final persistent map
vertices only. Nonpersistent discarded refinement probes are not stored in the
v3 map, so these sums are not full-render executed RHS totals.
"""
import json
import re
from pathlib import Path
import sys
from mesh_maps import load, compare
ROOT = Path(__file__).resolve().parents[2]
OUT = Path(sys.argv[1]).resolve() if len(sys.argv) > 1 else \
ROOT / 'local/adaptive_bounds_4k'
def main():
summaries = {}
meshes = {}
for upper in (2, 8):
name = f'r100_4k_hmax{upper}'
summaries[name], meshes[upper] = load(OUT / (name + '.grlens'))
text = (OUT / (name + '.log')).read_text()
initial = int(re.search(r'tracing (\d+) initial rays', text).group(1))
generations = [int(n) for n in re.findall(
r'refinement generation \d+ tracing (\d+) samples', text)]
summaries[name]['requested_samples_including_nonpersistent_probes'] = \
initial + sum(generations)
summaries[name]['initial_samples'] = initial
summaries[name]['refinement_samples_per_generation'] = generations
summaries[name]['trace_wall_seconds'] = sum(
float(x) for x in re.findall(
r'(?:initial ray trace|adaptive ray-trace refinement) '
r'finished in ([\d.]+) s', text))
ledger = OUT / 'attempts.json'
if ledger.exists():
for entry in json.loads(ledger.read_text()):
if entry.get('state') == 'completed':
summaries[f'r100_4k_hmax{entry["upper"]}']['wall_seconds'] = \
entry['wall_seconds']
summaries['comparison'] = compare(meshes[2], meshes[8])
a, b = (summaries[f'r100_4k_hmax{upper}'] for upper in (2, 8))
summaries['relative_reduction'] = {
key: 1 - b[key] / a[key]
for key in ('accepted', 'rhs', 'wall_seconds', 'trace_wall_seconds')}
summaries['comparison']['triangle_payload_identical'] = \
a['triangle_sha256'] == b['triangle_sha256']
summaries['cost_scope'] = (
'accepted/rejected/RHS sums cover final persistent vertices only; '
'nonpersistent discarded refinement probes are not in the v3 map. '
'Do not interpret them as full-render executed RHS totals.')
(OUT / 'summary.json').write_text(json.dumps(summaries, indent=2) + '\n')
print(json.dumps(summaries, indent=2))
if __name__ == '__main__':
main()
@@ -0,0 +1 @@
__pycache__/
@@ -0,0 +1,84 @@
# Production chunk geometry diagnostic (2026-09-11)
## Scope
This run measures the event stream that the production HIP sink would receive
for the supplied Schwarzschild Galactic-center render. `PSF_BACKEND=dummy`
keeps the real imported lens map, all-sky prefetch, OpenMP dynamic triangle
scheduling, inverse mapping, redshift/color/flux work, PSF cache eligibility,
and 16,384-event per-worker chunk boundaries. It does not initialize HIP,
allocate a full HDR framebuffer, splat pixels, or write PNG/FITS output.
The run used repository revision `11e703e33dffb1ff168ba11dd922e68b448116b9`
plus the uncommitted dummy-backend work. The complete stdout/stderr, executable
and input hashes, process resource use, and protected-output hashes are in
[`full_catalog.log`](full_catalog.log). An initial harness-only failure before
the renderer started is retained as
[`full_catalog_missing_time.log`](full_catalog_missing_time.log).
## Build and run
```sh
make -j1 PSF_BACKEND=dummy SPACETIME=schwarzschild ENABLE_HDR=1 backend
python3 benchmarks/dummy_psf_chunks_2026-09-11/run.py
```
The runner fixes `OMP_NUM_THREADS=16` and `OMP_DYNAMIC=FALSE`, uses a 600-second
timeout and a process lock, refuses to overwrite its log, and hashes both the
named PNG and companion FITS before and after the run. Its renderer arguments
are exactly the user-supplied command except that the `_hip` executable is
replaced by `_dummy`; the exact expanded command is the first line of the log.
Inputs and protected outputs:
- lens map SHA-256:
`905f960aea2d276f9586c79fba545a72cf742311e9e7e18faea293835c68bf28`
- existing PNG SHA-256 before/after:
`3e01feb911e60acce545a6a86870ca05f96250022e874eb8097bec88a8879bfd`
- existing FITS SHA-256 before/after:
`2408e62dcc22f147da284d87af9a2b0fdd0050eda2dabc23b6ec2554b2f1d38e`
Both protected files retained the same size and nanosecond mtime as well as the
same hash. No HIP backend was run.
## Result
The catalog prefetch loaded 343,363,141 stars for 130,882 lens triangles. The
producer classified 598,264,924 cache events, with zero direct fallbacks,
wing-clipped events, or min-Y discards. Sixteen workers produced 36,524 chunks:
36,508 full chunks and one final partial chunk per worker.
| full-chunk metric | min | p10 | p25 | p50 | p75 | p90 | p99 | max |
|---|---:|---:|---:|---:|---:|---:|---:|---:|
| event-producing triangles | 1 | 1 | 1 | 2 | 3 | 10 | 31 | 59 |
| occupied 32px center tiles | 1 | 1 | 1 | 1 | 2 | 5 | 30 | 45 |
| event bbox diagonal (px) | 0.199 | 0.742 | 3.250 | 12.651 | 57.018 | 429.306 | 3759.261 | 3834.557 |
| triangle-centroid bbox diagonal (px) | 0 | 0 | 0 | 9.618 | 49.477 | 424.149 | 3744.061 | 3824.075 |
| maximum successive centroid jump (px) | 0 | 0 | 0 | 8.724 | 25.157 | 144.000 | 3744.034 | 3792.034 |
All 36,508 full chunks satisfy the replay prototype's current selector:
`events >= 8192 && events / occupied_32px_tiles >= 32`.
Catalog prefetch took 55.469 s. Producer classification and chunk accounting
took 232.340 s; total process wall time was 288.872 s. These are diagnostic CPU
costs and do not estimate HIP tile-kernel speed.
## Interpretation and limits
The measured production event order strongly supports the hypothesis that a
full worker chunk is usually filled by very few image-plane triangles: the
median is two and 75% contain at most three. Center-tile occupancy is even more
concentrated. This is favorable for a tile16 path because the same output pixels
receive many contributions that can be reduced before the final double HDR
write.
The rare tail matters: p99 chunks can contain a few clusters separated by
nearly the full 4K image width. “Few triangles” therefore does not imply one
small contiguous bounding rectangle. A production implementation should use a
sparse occupied-tile list, retain the atomic fallback, and measure the complete
streaming sink including binning and synchronization.
This is one Schwarzschild Galactic-center frame with one 16-worker dynamic
schedule. Worker-to-triangle assignment is nondeterministic, so exact quantiles
may vary between runs. The result establishes event geometry for this input; it
does not by itself establish single-BH/BBH universality or a HIP speedup.
@@ -0,0 +1,235 @@
COMMAND OMP_NUM_THREADS=16 OMP_DYNAMIC=FALSE /home/wyj/Code/C/GR_4d_raytracing/build/Release/schwarzschild_sky_dummy --verbose --psf-relative-tail 1e-8 --psf-min-y 0 --max-cache-psf-flux 1e8 --all-sky-catalog assets/2mass/processed/all_sky --exposure 1e13 --psf-fwhm-pixels 2.7 --psf-moffat-beta 4.5 --catalog-load-workers 4 --hdr-output --lens-map-input output/lens/schwarzschild_galactic_center_R100_45deg_16_4_4k_.grlens --output output/imgs/2mass_galactic_center_schwarzschild_R100_4k_1e13_beta4.5_16_4-full-gpu.png
GIT 11e703e33dffb1ff168ba11dd922e68b448116b9
BINARY_SHA256 c71a843a6064cd730b4694c5fe4e61249a995106526da0fdca97bc625c7db470
LENS_SHA256 905f960aea2d276f9586c79fba545a72cf742311e9e7e18faea293835c68bf28
PROTECTED_BEFORE output/imgs/2mass_galactic_center_schwarzschild_R100_4k_1e13_beta4.5_16_4-full-gpu.png sha256=3e01feb911e60acce545a6a86870ca05f96250022e874eb8097bec88a8879bfd size=13072572 mtime_ns=1788744728751407011
PROTECTED_BEFORE output/imgs/2mass_galactic_center_schwarzschild_R100_4k_1e13_beta4.5_16_4-full-gpu_HDR.fits sha256=2408e62dcc22f147da284d87af9a2b0fdd0050eda2dabc23b6ec2554b2f1d38e size=99535680 mtime_ns=1788744726380022561
Dummy PSF backend: --output and --hdr-output are accepted for command parity but no image files will be written.
PSF cache ready: 64x64 phases, radius 47 px, relative tail 1e-08, tail abs 1e-06, boundary 1e-07, build 0.678 s
Frame 0: finding and prefetching catalog tiles...
Catalog prefetch: 64440 requested, 64440 newly loaded (343363141 stars), 0 unavailable in 55.469 s; 4 loader workers
Frame 0: catalog prefetch finished (64440 candidate tiles).
Frame 0: splatting 130882 lens triangles...
Frame 0: splat worker 2/16 started.
Frame 0: splat worker 1/16 started.
Frame 0: splat worker 4/16 started.
Frame 0: splat worker 3/16 started.
Frame 0: splat worker 5/16 started.
Frame 0: splat worker 10/16 started.
Frame 0: splat worker 7/16 started.
Frame 0: splat worker 8/16 started.
Frame 0: splat worker 13/16 started.
Frame 0: splat worker 11/16 started.
Frame 0: splat worker 6/16 started.
Frame 0: splat worker 12/16 started.
Frame 0: splat worker 9/16 started.
Frame 0: splat worker 14/16 started.
Frame 0: splat worker 16/16 started.
Frame 0: splat worker 15/16 started.
Frame 0: splat worker 1/16 reached 8 local triangles.
Frame 0: splat worker 6/16 reached 8 local triangles.
Frame 0: splat worker 10/16 reached 8 local triangles.
Frame 0: splat worker 14/16 reached 8 local triangles.
Frame 0: splat worker 12/16 reached 8 local triangles.
Frame 0: splat worker 2/16 reached 8 local triangles.
Frame 0: splat worker 5/16 reached 8 local triangles.
Frame 0: splat worker 3/16 reached 8 local triangles.
Frame 0: splat worker 7/16 reached 8 local triangles.
Frame 0: splat worker 15/16 reached 8 local triangles.
Frame 0: splat worker 8/16 reached 8 local triangles.
Frame 0: splat worker 4/16 reached 8 local triangles.
Frame 0: splat worker 11/16 reached 8 local triangles.
Frame 0: splat worker 13/16 reached 8 local triangles.
Frame 0: splat worker 9/16 reached 8 local triangles.
Frame 0: splat worker 16/16 reached 8 local triangles.
Frame 0: splat worker 12/16 reached 16 local triangles.
Frame 0: splat worker 4/16 reached 16 local triangles.
Frame 0: splat worker 14/16 reached 16 local triangles.
Frame 0: splat worker 6/16 reached 16 local triangles.
Frame 0: splat worker 1/16 reached 16 local triangles.
Frame 0: splat worker 8/16 reached 16 local triangles.
Frame 0: splat worker 3/16 reached 16 local triangles.
Frame 0: splat worker 7/16 reached 16 local triangles.
Frame 0: splat worker 2/16 reached 16 local triangles.
Frame 0: splat worker 15/16 reached 16 local triangles.
Frame 0: splat worker 5/16 reached 16 local triangles.
Frame 0: splat worker 11/16 reached 16 local triangles.
Frame 0: splat worker 13/16 reached 16 local triangles.
Frame 0: splat worker 9/16 reached 16 local triangles.
Frame 0: splat worker 16/16 reached 16 local triangles.
Frame 0: splat worker 12/16 reached 32 local triangles.
Frame 0: splat worker 4/16 reached 32 local triangles.
Frame 0: splat worker 7/16 reached 32 local triangles.
Frame 0: splat worker 6/16 reached 32 local triangles.
Frame 0: splat worker 8/16 reached 32 local triangles.
Frame 0: splat worker 2/16 reached 32 local triangles.
Frame 0: splat worker 3/16 reached 32 local triangles.
Frame 0: splat worker 11/16 reached 32 local triangles.
Frame 0: splat worker 9/16 reached 32 local triangles.
Frame 0: splat worker 1/16 reached 32 local triangles.
Frame 0: splat worker 15/16 reached 32 local triangles.
Frame 0: splat worker 16/16 reached 32 local triangles.
Frame 0: splat worker 14/16 reached 32 local triangles.
Frame 0: splat worker 5/16 reached 32 local triangles.
Frame 0: splat worker 13/16 reached 32 local triangles.
Frame 0: splat worker 10/16 reached 16 local triangles.
Frame 0: splat worker 10/16 reached 32 local triangles.
Frame 0: splat worker 4/16 reached 64 local triangles.
Frame 0: splat worker 6/16 reached 64 local triangles.
Frame 0: splat worker 8/16 reached 64 local triangles.
Frame 0: splat worker 2/16 reached 64 local triangles.
Frame 0: splat worker 3/16 reached 64 local triangles.
Frame 0: splat worker 12/16 reached 64 local triangles.
Frame 0: splat worker 11/16 reached 64 local triangles.
Frame 0: splat worker 15/16 reached 64 local triangles.
Frame 0: splat worker 16/16 reached 64 local triangles.
Frame 0: splat worker 14/16 reached 64 local triangles.
Frame 0: splat worker 5/16 reached 64 local triangles.
Frame 0: splat worker 9/16 reached 64 local triangles.
Frame 0: splat worker 1/16 reached 64 local triangles.
Frame 0: splat worker 7/16 reached 64 local triangles.
Frame 0: splat worker 13/16 reached 64 local triangles.
Frame 0: splat worker 10/16 reached 64 local triangles.
Frame 0: splat worker 4/16 reached 128 local triangles.
Frame 0: splat worker 12/16 reached 128 local triangles.
Frame 0: splat worker 11/16 reached 128 local triangles.
Frame 0: splat worker 6/16 reached 128 local triangles.
Frame 0: splat worker 15/16 reached 128 local triangles.
Frame 0: splat worker 2/16 reached 128 local triangles.
Frame 0: splat worker 5/16 reached 128 local triangles.
Frame 0: splat worker 8/16 reached 128 local triangles.
Frame 0: splat worker 3/16 reached 128 local triangles.
Frame 0: splat worker 16/16 reached 128 local triangles.
Frame 0: splat worker 14/16 reached 128 local triangles.
Frame 0: splat worker 7/16 reached 128 local triangles.
Frame 0: splat worker 1/16 reached 128 local triangles.
Frame 0: splat worker 13/16 reached 128 local triangles.
Frame 0: splat worker 9/16 reached 128 local triangles.
Frame 0: splat worker 10/16 reached 128 local triangles.
Frame 0: splat worker 13/16 reached 256 local triangles.
Frame 0: splat worker 15/16 reached 256 local triangles.
Frame 0: splat worker 16/16 reached 256 local triangles.
Frame 0: splat worker 8/16 reached 256 local triangles.
Frame 0: splat worker 11/16 reached 256 local triangles.
Frame 0: splat worker 6/16 reached 256 local triangles.
Frame 0: splat worker 5/16 reached 256 local triangles.
Frame 0: splat worker 3/16 reached 256 local triangles.
Frame 0: splat worker 1/16 reached 256 local triangles.
Frame 0: splat worker 2/16 reached 256 local triangles.
Frame 0: splat worker 7/16 reached 256 local triangles.
Frame 0: splat worker 4/16 reached 256 local triangles.
Frame 0: splat worker 12/16 reached 256 local triangles.
Frame 0: splat worker 10/16 reached 256 local triangles.
Frame 0: splat worker 14/16 reached 256 local triangles.
Frame 0: splat worker 9/16 reached 256 local triangles.
Frame 0: splat worker 8/16 reached 512 local triangles.
Frame 0: splat worker 12/16 reached 512 local triangles.
Frame 0: splat worker 16/16 reached 512 local triangles.
Frame 0: splat worker 5/16 reached 512 local triangles.
Frame 0: splat worker 13/16 reached 512 local triangles.
Frame 0: splat worker 3/16 reached 512 local triangles.
Frame 0: splat worker 7/16 reached 512 local triangles.
Frame 0: splat worker 11/16 reached 512 local triangles.
Frame 0: splat worker 1/16 reached 512 local triangles.
Frame 0: splat worker 15/16 reached 512 local triangles.
Frame 0: splat worker 2/16 reached 512 local triangles.
Frame 0: splat worker 10/16 reached 512 local triangles.
Frame 0: splat worker 4/16 reached 512 local triangles.
Frame 0: splat worker 6/16 reached 512 local triangles.
Frame 0: splat worker 14/16 reached 512 local triangles.
Frame 0: splat worker 9/16 reached 512 local triangles.
Frame 0: splat worker 8/16 reached 1024 local triangles.
Frame 0: splat worker 7/16 reached 1024 local triangles.
Frame 0: splat worker 12/16 reached 1024 local triangles.
Frame 0: splat worker 3/16 reached 1024 local triangles.
Frame 0: splat worker 16/16 reached 1024 local triangles.
Frame 0: splat worker 11/16 reached 1024 local triangles.
Frame 0: splat worker 5/16 reached 1024 local triangles.
Frame 0: splat worker 14/16 reached 1024 local triangles.
Frame 0: splat worker 15/16 reached 1024 local triangles.
Frame 0: splat worker 4/16 reached 1024 local triangles.
Frame 0: splat worker 9/16 reached 1024 local triangles.
Frame 0: splat worker 13/16 reached 1024 local triangles.
Frame 0: splat worker 6/16 reached 1024 local triangles.
Frame 0: splat worker 1/16 reached 1024 local triangles.
Frame 0: splat worker 10/16 reached 1024 local triangles.
Frame 0: splat worker 2/16 reached 1024 local triangles.
Frame 0: splat worker 8/16 reached 2048 local triangles.
Frame 0: splat worker 12/16 reached 2048 local triangles.
Frame 0: splat worker 16/16 reached 2048 local triangles.
Frame 0: splat worker 14/16 reached 2048 local triangles.
Frame 0: splat worker 7/16 reached 2048 local triangles.
Frame 0: splat worker 3/16 reached 2048 local triangles.
Frame 0: splat worker 4/16 reached 2048 local triangles.
Frame 0: splat worker 1/16 reached 2048 local triangles.
Frame 0: splat worker 11/16 reached 2048 local triangles.
Frame 0: splat worker 5/16 reached 2048 local triangles.
Frame 0: splat worker 13/16 reached 2048 local triangles.
Frame 0: splat worker 15/16 reached 2048 local triangles.
Frame 0: splat worker 6/16 reached 2048 local triangles.
Frame 0: splat worker 2/16 reached 2048 local triangles.
Frame 0: splat worker 9/16 reached 2048 local triangles.
Frame 0: splat worker 10/16 reached 2048 local triangles.
Frame 0: splat worker 3/16 reached 4096 local triangles.
Frame 0: splat worker 7/16 reached 4096 local triangles.
Frame 0: splat worker 16/16 reached 4096 local triangles.
Frame 0: splat worker 14/16 reached 4096 local triangles.
Frame 0: splat worker 9/16 reached 4096 local triangles.
Frame 0: splat worker 4/16 reached 4096 local triangles.
Frame 0: splat worker 6/16 reached 4096 local triangles.
Frame 0: splat worker 8/16 reached 4096 local triangles.
Frame 0: splat worker 13/16 reached 4096 local triangles.
Frame 0: splat worker 5/16 reached 4096 local triangles.
Frame 0: splat worker 10/16 reached 4096 local triangles.
Frame 0: splat worker 15/16 reached 4096 local triangles.
Frame 0: splat worker 11/16 reached 4096 local triangles.
Frame 0: splat worker 12/16 reached 4096 local triangles.
Frame 0: splat worker 1/16 reached 4096 local triangles.
Frame 0: splat worker 2/16 reached 4096 local triangles.
Frame 0: splat worker 3/16 reached 8192 local triangles.
Frame 0: splat worker 7/16 reached 8192 local triangles.
Frame 0: splat worker 16/16 reached 8192 local triangles.
Frame 0: splat worker 13/16 reached 8192 local triangles.
Frame 0: splat worker 9/16 reached 8192 local triangles.
Frame 0: splat worker 4/16 reached 8192 local triangles.
Frame 0: splat worker 8/16 reached 8192 local triangles.
Frame 0: splat worker 2/16 finished after 7916 local triangles.
Frame 0: splat worker 8/16 finished after 8212 local triangles.
Frame 0: splat worker 6/16 finished after 8150 local triangles.
Frame 0: splat worker 1/16 finished after 7784 local triangles.
Frame 0: splat worker 4/16 finished after 8227 local triangles.
Frame 0: splat worker 15/16 finished after 7878 local triangles.
Frame 0: splat worker 14/16 finished after 8186 local triangles.
Frame 0: splat worker 11/16 finished after 7962 local triangles.
Frame 0: splat worker 9/16 finished after 8276 local triangles.
Frame 0: splat worker 16/16 finished after 8477 local triangles.
Frame 0: splat worker 3/16 finished after 8967 local triangles.
Frame 0: splat worker 7/16 finished after 8576 local triangles.
Frame 0: splat worker 10/16 finished after 7772 local triangles.
Frame 0: splat worker 13/16 finished after 8295 local triangles.
Frame 0: splat worker 12/16 finished after 8013 local triangles.
Frame 0: splat worker 5/16 finished after 8191 local triangles.
Dummy PSF diagnostic only: no HDR or image was accumulated/written.
Dummy PSF chunks: total=36524 full=36508 partial=16 events=598264924 capacity=16384 selector_tile=32px
Dummy PSF all events: min=263.000 p10=16384.000 p25=16384.000 p50=16384.000 p75=16384.000 p90=16384.000 p99=16384.000 max=16384.000
Dummy PSF all distinct_triangles: min=1.000 p10=1.000 p25=1.000 p50=2.000 p75=4.000 p90=10.000 p99=31.000 max=59.000
Dummy PSF all occupied_32px_tiles: min=1.000 p10=1.000 p25=1.000 p50=1.000 p75=2.000 p90=5.000 p99=30.000 max=45.000
Dummy PSF all event_bbox_diagonal_px: min=0.199 p10=0.743 p25=3.252 p50=12.667 p75=57.123 p90=432.049 p99=3759.261 max=3834.557
Dummy PSF all triangle_centroid_bbox_diagonal_px: min=0.000 p10=0.000 p25=0.000 p50=9.621 p75=49.817 p90=425.680 p99=3744.061 max=3824.075
Dummy PSF all maximum_successive_triangle_jump_px: min=0.000 p10=0.000 p25=0.000 p50=8.750 p75=25.157 p90=144.000 p99=3744.034 max=3792.034
Dummy PSF all adaptive criterion: 36516/36524 chunks tile16-eligible (events>=8192 and events/occupied_32px_tiles>=32)
Dummy PSF full events: min=16384.000 p10=16384.000 p25=16384.000 p50=16384.000 p75=16384.000 p90=16384.000 p99=16384.000 max=16384.000
Dummy PSF full distinct_triangles: min=1.000 p10=1.000 p25=1.000 p50=2.000 p75=3.000 p90=10.000 p99=31.000 max=59.000
Dummy PSF full occupied_32px_tiles: min=1.000 p10=1.000 p25=1.000 p50=1.000 p75=2.000 p90=5.000 p99=30.000 max=45.000
Dummy PSF full event_bbox_diagonal_px: min=0.199 p10=0.742 p25=3.250 p50=12.651 p75=57.018 p90=429.306 p99=3759.261 max=3834.557
Dummy PSF full triangle_centroid_bbox_diagonal_px: min=0.000 p10=0.000 p25=0.000 p50=9.618 p75=49.477 p90=424.149 p99=3744.061 max=3824.075
Dummy PSF full maximum_successive_triangle_jump_px: min=0.000 p10=0.000 p25=0.000 p50=8.724 p75=25.157 p90=144.000 p99=3744.034 max=3792.034
Dummy PSF full adaptive criterion: 36508/36508 chunks tile16-eligible (events>=8192 and events/occupied_32px_tiles>=32)
Dummy PSF producers: 16 workers; classification/chunk wall 232.340 s
Frame 0: catalog classification finished in 232.3 s; reporting chunk statistics...
Dummy PSF classified 598264924 images from 343363141 catalog stars; no HDR, PNG, or PPM was written.
PSF splats: cached 598264924, cached wing-clipped 0, direct fallbacks 0, discarded below min-Y 0
PROCESS_WALL 288.871615309 EXIT 0
PROCESS_USER 3815.986955000 PROCESS_SYSTEM 12.140569000 MAX_RSS_KIB 13769936
PROTECTED_AFTER output/imgs/2mass_galactic_center_schwarzschild_R100_4k_1e13_beta4.5_16_4-full-gpu.png sha256=3e01feb911e60acce545a6a86870ca05f96250022e874eb8097bec88a8879bfd size=13072572 mtime_ns=1788744728751407011 unchanged=yes
PROTECTED_AFTER output/imgs/2mass_galactic_center_schwarzschild_R100_4k_1e13_beta4.5_16_4-full-gpu_HDR.fits sha256=2408e62dcc22f147da284d87af9a2b0fdd0050eda2dabc23b6ec2554b2f1d38e size=99535680 mtime_ns=1788744726380022561 unchanged=yes
@@ -0,0 +1,6 @@
COMMAND OMP_NUM_THREADS=16 OMP_DYNAMIC=FALSE /usr/bin/time -v /home/wyj/Code/C/GR_4d_raytracing/build/Release/schwarzschild_sky_dummy --verbose --psf-relative-tail 1e-8 --psf-min-y 0 --max-cache-psf-flux 1e8 --all-sky-catalog assets/2mass/processed/all_sky --exposure 1e13 --psf-fwhm-pixels 2.7 --psf-moffat-beta 4.5 --catalog-load-workers 4 --hdr-output --lens-map-input output/lens/schwarzschild_galactic_center_R100_45deg_16_4_4k_.grlens --output output/imgs/2mass_galactic_center_schwarzschild_R100_4k_1e13_beta4.5_16_4-full-gpu.png
GIT 11e703e33dffb1ff168ba11dd922e68b448116b9
BINARY_SHA256 c71a843a6064cd730b4694c5fe4e61249a995106526da0fdca97bc625c7db470
LENS_SHA256 905f960aea2d276f9586c79fba545a72cf742311e9e7e18faea293835c68bf28
PROTECTED_BEFORE output/imgs/2mass_galactic_center_schwarzschild_R100_4k_1e13_beta4.5_16_4-full-gpu.png sha256=3e01feb911e60acce545a6a86870ca05f96250022e874eb8097bec88a8879bfd size=13072572 mtime_ns=1788744728751407011
PROTECTED_BEFORE output/imgs/2mass_galactic_center_schwarzschild_R100_4k_1e13_beta4.5_16_4-full-gpu_HDR.fits sha256=2408e62dcc22f147da284d87af9a2b0fdd0050eda2dabc23b6ec2554b2f1d38e size=99535680 mtime_ns=1788744726380022561
@@ -0,0 +1,99 @@
#!/usr/bin/env python3
"""Run the fixed full-catalog dummy diagnostic once without touching images."""
import fcntl
import hashlib
import os
from pathlib import Path
import resource
import shlex
import signal
import subprocess
import time
ROOT = Path(__file__).resolve().parents[2]
LOG = Path(__file__).with_name("full_catalog.log")
BINARY = ROOT / "build/Release/schwarzschild_sky_dummy"
LENS = ROOT / "output/lens/schwarzschild_galactic_center_R100_45deg_16_4_4k_.grlens"
PNG = ROOT / "output/imgs/2mass_galactic_center_schwarzschild_R100_4k_1e13_beta4.5_16_4-full-gpu.png"
FITS = ROOT / "output/imgs/2mass_galactic_center_schwarzschild_R100_4k_1e13_beta4.5_16_4-full-gpu_HDR.fits"
def digest(path):
return hashlib.sha256(path.read_bytes()).hexdigest()
def main():
if LOG.exists():
raise RuntimeError(f"refusing to overwrite {LOG}")
for path in (BINARY, LENS, PNG, FITS):
if not path.is_file():
raise RuntimeError(f"required file is missing: {path}")
protected_before = {
path: (digest(path), path.stat().st_size, path.stat().st_mtime_ns)
for path in (PNG, FITS)
}
command = [
str(BINARY), "--verbose",
"--psf-relative-tail", "1e-8", "--psf-min-y", "0",
"--max-cache-psf-flux", "1e8",
"--all-sky-catalog", "assets/2mass/processed/all_sky",
"--exposure", "1e13", "--psf-fwhm-pixels", "2.7",
"--psf-moffat-beta", "4.5", "--catalog-load-workers", "4",
"--hdr-output", "--lens-map-input",
"output/lens/schwarzschild_galactic_center_R100_45deg_16_4_4k_.grlens",
"--output",
"output/imgs/2mass_galactic_center_schwarzschild_R100_4k_1e13_beta4.5_16_4-full-gpu.png",
]
guard = open("/tmp/gr_dummy_psf_chunks.lock", "w")
fcntl.flock(guard, fcntl.LOCK_EX | fcntl.LOCK_NB)
env = dict(os.environ, OMP_NUM_THREADS="16", OMP_DYNAMIC="FALSE")
with LOG.open("x") as out:
out.write("COMMAND OMP_NUM_THREADS=16 OMP_DYNAMIC=FALSE " +
shlex.join(command) + "\n")
out.write("GIT " + subprocess.check_output(
["git", "rev-parse", "HEAD"], cwd=ROOT, text=True))
out.write("BINARY_SHA256 " + digest(BINARY) + "\n")
out.write("LENS_SHA256 " + digest(LENS) + "\n")
for path, state in protected_before.items():
out.write(
f"PROTECTED_BEFORE {path.relative_to(ROOT)} sha256={state[0]} "
f"size={state[1]} mtime_ns={state[2]}\n")
out.flush()
start = time.monotonic()
usage_start = resource.getrusage(resource.RUSAGE_CHILDREN)
process = subprocess.Popen(command, cwd=ROOT, env=env, stdout=out,
stderr=subprocess.STDOUT,
start_new_session=True)
try:
returncode = process.wait(timeout=600)
except subprocess.TimeoutExpired:
os.killpg(process.pid, signal.SIGKILL)
process.wait()
out.write("TIMEOUT killed and reaped process group\n")
raise
out.write(
f"PROCESS_WALL {time.monotonic() - start:.9f} EXIT {returncode}\n")
usage_end = resource.getrusage(resource.RUSAGE_CHILDREN)
out.write(
f"PROCESS_USER {usage_end.ru_utime - usage_start.ru_utime:.9f} "
f"PROCESS_SYSTEM {usage_end.ru_stime - usage_start.ru_stime:.9f} "
f"MAX_RSS_KIB {usage_end.ru_maxrss}\n")
protected_after = {
path: (digest(path), path.stat().st_size, path.stat().st_mtime_ns)
for path in (PNG, FITS)
}
if protected_after != protected_before:
raise RuntimeError("a protected render output changed")
with LOG.open("a") as out:
for path, state in protected_after.items():
out.write(
f"PROTECTED_AFTER {path.relative_to(ROOT)} sha256={state[0]} "
f"size={state[1]} mtime_ns={state[2]} unchanged=yes\n")
if returncode:
raise RuntimeError(f"dummy diagnostic exited {returncode}")
print(LOG)
if __name__ == "__main__":
main()
+108
View File
@@ -0,0 +1,108 @@
# Fast-mode CPU benchmark (2026-09-18)
Compares the default per-event phase-cache PSF splat with `--fast-mode` on a
7.4-degree 2MASS galactic-center field. Commands, raw terminal output, and
wall-clock totals are preserved below.
## Environment
- Git revision: `7ddc585` plus the uncommitted fast-mode work.
- Build: `make -j4 PSF_BACKEND=cpu SPACETIME=minkowski backend`
(`-O2 -DNDEBUG -fopenmp`, libpng).
- Host: 12th Gen Intel Core i7-12700K, 16 hardware threads.
## Commands
All runs use the same catalog, geometry, and exposure; only the accumulation
mode changes. `--all-sky-catalog assets/2mass/processed/all_sky`,
`--width 320 --height 240 --fov-deg 10 --look-ra-deg 266 --look-dec-deg -29
--exposure 1e13 --coarse-cell-pixels 16 --refine-max-level 0`.
```sh
./build/Release/minkowski_sky --all-sky-catalog assets/2mass/processed/all_sky \
--width 320 --height 240 --fov-deg 10 --look-ra-deg 266 --look-dec-deg -29 \
--exposure 1e13 --coarse-cell-pixels 16 --refine-max-level 0 \
--output /tmp/fastmode/bench/normal.png
./build/Release/minkowski_sky --all-sky-catalog assets/2mass/processed/all_sky \
--width 320 --height 240 --fov-deg 10 --look-ra-deg 266 --look-dec-deg -29 \
--exposure 1e13 --coarse-cell-pixels 16 --refine-max-level 0 \
--fast-mode --fast-supersample 2 \
--output /tmp/fastmode/bench/fast_n2.png
./build/Release/minkowski_sky --all-sky-catalog assets/2mass/processed/all_sky \
--width 320 --height 240 --fov-deg 10 --look-ra-deg 266 --look-dec-deg -29 \
--exposure 1e13 --coarse-cell-pixels 16 --refine-max-level 0 \
--fast-mode --fast-supersample 4 \
--output /tmp/fastmode/bench/fast_n4.png
./build/Release/minkowski_sky --all-sky-catalog assets/2mass/processed/all_sky \
--width 320 --height 240 --fov-deg 10 --look-ra-deg 266 --look-dec-deg -29 \
--exposure 1e13 --coarse-cell-pixels 16 --refine-max-level 0 \
--fast-mode --fast-supersample 2 --fast-deposit bilinear \
--output /tmp/fastmode/bench/fast_bil_n2.png
```
## Wall-clock totals
Measured with `date +%s.%N` around each command.
| run | wall time | images |
| --- | --- | --- |
| normal (phase cache) | 16.645 s | 5,912,840 |
| fast nearest N=2 | 1.663 s | 5,912,840 |
| fast bilinear N=2 | 1.648 s | 5,912,840 |
| fast nearest N=4 | 12.229 s | 5,912,840 |
Fast nearest N=2 is about 10x faster than the phase-cache path on this
PSF-dominated field. N=4 increases the supersampled buffer and kernel area by
4x each and becomes convolution-bound.
## Raw terminal output
```text
===== normal.log =====
Blackbody LUT: 1024 CIE 1931 2-deg 1 nm-linear XYZ nodes, T=[670.146556, 101408.88] K, loaded assets/blackbody/cie1931_2deg_xyz_1024.grbblut in 0.000056 s; payload fnv1a64=0e39867b0e70a809
Blackbody backend: lut
PSF cache ready: 64x64 phases, radius 47 px, relative tail 1e-08, tail abs 1e-06, boundary 1e-07, build 0.725 s
Catalog prefetch: 96 requested, 96 newly loaded (6618807 stars), 0 unavailable in 0.696 s; 4 loader workers
Rendered 5912840 images from 6618807 catalog stars to /tmp/fastmode/bench/normal.png (ok)
PSF splats: cached 5912840, cached wing-clipped 0, direct fallbacks 0, discarded below min-Y 0
===== fast_n2.log =====
Fast mode is a preview approximation; --max-cache-psf-flux is ignored and one global kernel is used for every event.
Blackbody LUT: 1024 CIE 1931 2-deg 1 nm-linear XYZ nodes, T=[670.146556, 101408.88] K, loaded assets/blackbody/cie1931_2deg_xyz_1024.grbblut in 0.000045 s; payload fnv1a64=0e39867b0e70a809
Blackbody backend: lut
Fast PSF: supersample 2x, deposit nearest, kernel radius 93 ss px (46.50 final px), retained flux 1.000000, cached 4-point quadrature
Catalog prefetch: 96 requested, 96 newly loaded (6618807 stars), 0 unavailable in 0.708 s; 4 loader workers
Rendered 5912840 images from 6618807 catalog stars to /tmp/fastmode/bench/fast_n2.png (ok)
Fast PSF splats: deposited 5912840, wing-clipped 0, discarded below min-Y 0
===== fast_n4.log =====
Fast mode is a preview approximation; --max-cache-psf-flux is ignored and one global kernel is used for every event.
Blackbody LUT: 1024 CIE 1931 2-deg 1 nm-linear XYZ nodes, T=[670.146556, 101408.88] K, loaded assets/blackbody/cie1931_2deg_xyz_1024.grbblut in 0.000058 s; payload fnv1a64=0e39867b0e70a809
Blackbody backend: lut
Fast PSF: supersample 4x, deposit nearest, kernel radius 185 ss px (46.25 final px), retained flux 1.000000, cached 4-point quadrature
Catalog prefetch: 96 requested, 96 newly loaded (6618807 stars), 0 unavailable in 0.709 s; 4 loader workers
Rendered 5912840 images from 6618807 catalog stars to /tmp/fastmode/bench/fast_n4.png (ok)
Fast PSF splats: deposited 5912840, wing-clipped 0, discarded below min-Y 0
===== fast_bil_n2.log =====
Fast mode is a preview approximation; --max-cache-psf-flux is ignored and one global kernel is used for every event.
Blackbody LUT: 1024 CIE 1931 2-deg 1 nm-linear XYZ nodes, T=[670.146556, 101408.88] K, loaded assets/blackbody/cie1931_2deg_xyz_1024.grbblut in 0.000047 s; payload fnv1a64=0e39867b0e70a809
Blackbody backend: lut
Fast PSF: supersample 2x, deposit bilinear, kernel radius 93 ss px (46.50 final px), retained flux 1.000000, cached 4-point quadrature
Catalog prefetch: 96 requested, 96 newly loaded (6618807 stars), 0 unavailable in 0.712 s; 4 loader workers
Rendered 5912840 images from 6618807 catalog stars to /tmp/fastmode/bench/fast_bil_n2.png (ok)
Fast PSF splats: deposited 5912840, wing-clipped 0, discarded below min-Y 0
```
## Tone-mapped difference vs the normal render
```text
fast_n2 mean=1.1213 rms=1.7255 max=14 px>16=0/76800
fast_n4 mean=0.5516 rms=0.9146 max=8 px>16=0/76800
fast_bil_n2 mean=0.2091 rms=0.4793 max=16 px>16=0/76800
```
`mean`/`rms` are per-channel 8-bit differences; `px>16` counts pixels with any
channel more than 16 levels from the normal render. No pixel exceeds 16 in any
run. These are display-scale differences from the measured deposition tradeoff;
they are not a bit-exact regression baseline.
+128
View File
@@ -0,0 +1,128 @@
# Fast-mode deposition error experiment (2026-09-18)
Decision this note settles: whether `--fast-mode` should deposit each point
source image as a single nearest supersampled pixel or as 4 adjacent
(bilinear) pixels before the one global PSF convolution and downscale.
## Command
```sh
python3 scripts/fast_mode_deposit_error.py --phases 12 --grid 48 --tail 1e-6 --max-radius 64
```
## Model
Reference = pixel-area integral of the normalized circular Moffat
`M(r; α, β)`, `α = FWHM / (2 sqrt(2^(1/β) - 1))`, on the final grid, using
8-point Gauss-Legendre quadrature. Fast image with supersample factor `N`:
- deposit the event into the `N x N` supersampled grid (nearest = 1 cell,
bilinear = 4 adjacent cells);
- convolve the whole ss buffer with the single global kernel
`k[m] = ∫_ss-cell m M(z; Nα, β) dz` (4-point quadrature);
- downscale by averaging each `N x N` block, which together with the
unnormalised `N`-scaled kernel reproduces the final pixel-area integral.
Metrics: `maxErr`/`rmsErr` are whole-image errors vs the direct image at the
true position; `coreErr` is the worst central-3x3 pixel error; `FWHMerr`
compares the fast image with a direct image at the same centroid, so it is a
pure shape error (0 when deposition is exact at its snapped centre); `centErr`
is the position quantization vs the true continuous star position; `beterr` is
the deposition-induced Moffat beta change, isolated from the radial fit's own
pixel-integration bias by comparing with a reference fit (reported only for
FWHM >= 2 px). FWHM 1.0 / β 3.5 rows are sub-Nyquist and are not meaningful
for the shape metrics.
## Raw output
```text
Fast-mode deposition error experiment
grid=48 phases=12 tail=1e-06 max_radius=64
kernel quadrature = 4-point Gauss; reference = 8-point Gauss
FWHM beta N deposit R_ss retain maxErr rmsErr coreErr centErr FWHMerr beterr
---------------------------------------------------------------------------------------------------
1.00 8.00 2 nearest 10 1.00000 6.333e-01 1.714e-02 6.333e-01 3.043e-01 1.733e-02 nan
1.00 8.00 2 bilinear 10 1.00000 1.805e-01 3.972e-03 1.805e-01 2.722e-03 3.187e-01 nan
1.00 8.00 3 nearest 14 1.00000 3.907e-01 1.061e-02 3.907e-01 1.847e-01 7.491e-03 nan
1.00 8.00 3 bilinear 14 1.00000 7.587e-02 1.676e-03 7.587e-02 5.562e-03 1.816e-01 nan
1.00 8.00 4 nearest 18 1.00000 2.608e-01 7.142e-03 2.608e-01 1.237e-01 3.665e-02 nan
1.00 8.00 4 bilinear 18 1.00000 4.428e-02 9.775e-04 4.428e-02 3.395e-03 3.646e-02 nan
2.70 8.00 2 nearest 24 1.00000 1.635e-01 8.693e-03 1.635e-01 2.946e-01 2.325e-08 5.061e-07
2.70 8.00 2 bilinear 24 1.00000 4.339e-02 1.476e-03 4.339e-02 6.018e-09 4.046e-02 8.414e-02
2.70 8.00 3 nearest 35 1.00000 9.597e-02 5.229e-03 9.597e-02 1.768e-01 1.465e-08 1.067e-06
2.70 8.00 3 bilinear 35 1.00000 1.842e-02 6.387e-04 1.842e-02 2.437e-08 1.747e-02 4.029e-02
2.70 8.00 4 nearest 46 1.00000 6.308e-02 3.488e-03 6.308e-02 1.179e-01 1.563e-08 2.905e-05
2.70 8.00 4 bilinear 46 1.00000 1.011e-02 3.418e-04 1.011e-02 1.778e-08 9.355e-03 3.091e-02
6.00 8.00 2 nearest 51 1.00000 7.012e-02 7.714e-03 7.012e-02 2.946e-01 1.617e-06 3.132e-06
6.00 8.00 2 bilinear 51 1.00000 9.563e-03 6.146e-04 9.563e-03 8.749e-08 6.686e-03 1.039e-02
6.00 8.00 3 nearest 64 1.00000 4.199e-02 4.631e-03 4.199e-02 1.768e-01 7.456e-10 3.315e-08
6.00 8.00 3 bilinear 64 1.00000 4.090e-03 2.640e-04 4.090e-03 9.147e-06 2.683e-03 4.463e-03
6.00 8.00 4 nearest 64 0.99994 2.795e-02 3.088e-03 2.795e-02 1.179e-01 2.631e-07 9.889e-06
6.00 8.00 4 bilinear 64 0.99994 2.195e-03 1.409e-04 2.195e-03 9.262e-06 1.528e-03 2.354e-03
1.00 4.50 2 nearest 19 1.00000 6.006e-01 1.643e-02 6.006e-01 3.041e-01 1.516e-02 nan
1.00 4.50 2 bilinear 19 1.00000 1.745e-01 3.823e-03 1.745e-01 2.673e-03 2.485e-01 nan
1.00 4.50 3 nearest 28 1.00000 3.712e-01 1.016e-02 3.712e-01 1.846e-01 6.881e-03 nan
1.00 4.50 3 bilinear 28 1.00000 7.354e-02 1.616e-03 7.354e-02 5.429e-03 1.432e-01 nan
1.00 4.50 4 nearest 36 1.00000 2.480e-01 6.842e-03 2.480e-01 1.236e-01 3.167e-02 nan
1.00 4.50 4 bilinear 36 1.00000 4.269e-02 9.383e-04 4.269e-02 3.322e-03 3.640e-02 nan
2.70 4.50 2 nearest 49 1.00000 1.625e-01 8.537e-03 1.625e-01 2.946e-01 9.993e-07 1.210e-06
2.70 4.50 2 bilinear 49 1.00000 4.413e-02 1.439e-03 4.413e-02 5.868e-07 4.453e-02 4.843e-02
2.70 4.50 3 nearest 64 1.00000 9.571e-02 5.135e-03 9.571e-02 1.768e-01 1.482e-07 2.493e-07
2.70 4.50 3 bilinear 64 1.00000 1.871e-02 6.228e-04 1.871e-02 3.673e-06 1.867e-02 2.057e-02
2.70 4.50 4 nearest 64 0.99999 6.299e-02 3.426e-03 6.299e-02 1.179e-01 1.817e-07 4.228e-07
2.70 4.50 4 bilinear 64 0.99999 1.030e-02 3.333e-04 1.030e-02 3.726e-06 9.995e-03 1.353e-02
6.00 4.50 2 nearest 64 0.99998 6.924e-02 7.554e-03 6.924e-02 2.945e-01 1.290e-04 1.735e-04
6.00 4.50 2 bilinear 64 0.99998 9.859e-03 6.016e-04 9.859e-03 2.462e-06 7.468e-03 9.748e-03
6.00 4.50 3 nearest 64 0.99978 4.153e-02 4.535e-03 4.153e-02 1.775e-01 2.110e-08 3.706e-08
6.00 4.50 3 bilinear 64 0.99978 4.214e-03 2.585e-04 4.214e-03 7.436e-04 3.203e-03 4.204e-03
6.00 4.50 4 nearest 64 0.99872 2.767e-02 3.024e-03 2.767e-02 1.185e-01 3.310e-06 1.891e-04
6.00 4.50 4 bilinear 64 0.99872 2.264e-03 1.485e-04 2.264e-03 7.451e-04 1.709e-03 2.399e-03
1.00 3.50 2 nearest 35 1.00000 5.809e-01 1.600e-02 5.809e-01 3.038e-01 1.370e-02 nan
1.00 3.50 2 bilinear 35 1.00000 1.708e-01 3.732e-03 1.708e-01 2.601e-03 2.192e-01 nan
1.00 3.50 3 nearest 52 1.00000 3.594e-01 9.895e-03 3.594e-01 1.843e-01 6.403e-03 nan
1.00 3.50 3 bilinear 52 1.00000 7.210e-02 1.579e-03 7.210e-02 5.255e-03 1.252e-01 nan
1.00 3.50 4 nearest 64 1.00000 2.402e-01 6.660e-03 2.402e-01 1.234e-01 2.661e-02 nan
1.00 3.50 4 bilinear 64 1.00000 4.170e-02 9.143e-04 4.170e-02 3.223e-03 3.644e-02 nan
2.70 3.50 2 nearest 64 1.00000 1.619e-01 8.440e-03 1.619e-01 2.946e-01 2.790e-05 2.602e-05
2.70 3.50 2 bilinear 64 1.00000 4.461e-02 1.417e-03 4.461e-02 3.036e-07 4.689e-02 3.892e-02
2.70 3.50 3 nearest 64 0.99997 9.553e-02 5.077e-03 9.553e-02 1.769e-01 3.421e-07 3.302e-07
2.70 3.50 3 bilinear 64 0.99997 1.889e-02 6.133e-04 1.889e-02 8.121e-05 2.016e-02 1.646e-02
2.70 3.50 4 nearest 64 0.99989 6.293e-02 3.387e-03 6.293e-02 1.179e-01 8.537e-07 5.529e-06
2.70 3.50 4 bilinear 64 0.99989 1.042e-02 3.282e-04 1.042e-02 8.142e-05 1.066e-02 1.038e-02
Worst case over all tested configurations, by deposit scheme:
nearest: maxErr=6.333e-01 rmsErr=1.714e-02 coreErr=6.333e-01 centErr=3.043e-01 FWHMerr=3.665e-02 beterr=1.891e-04
bilinear: maxErr=1.805e-01 rmsErr=3.972e-03 coreErr=1.805e-01 centErr=5.562e-03 FWHMerr=3.187e-01 beterr=8.414e-02
```
## Conclusion
For the production PSF (FWHM 2.7, β 4.5):
| N | deposit | core HDR err | image RMS | centroid err | FWHM err | beta change |
|---|---|---|---|---|---|---|
| 2 | nearest | 16.3% | 0.85% | 0.295 px | ~0 | ~1.2e-6 |
| 2 | bilinear | 4.4% | 0.14% | ~0 | +4.45% | +4.8% |
| 3 | nearest | 9.6% | 0.51% | 0.177 px | ~0 | ~2.5e-7 |
| 3 | bilinear | 1.9% | 0.06% | ~0 | +1.87% | +2.1% |
| 4 | nearest | 6.3% | 0.34% | 0.118 px | ~0 | ~4.2e-7 |
| 4 | bilinear | 1.0% | 0.03% | ~0 | +1.0% | +1.4% |
- Nearest preserves the specified FWHM/β exactly (kernel-only shape and beta
error at the numerical floor); its only error is a bounded position
quantization of `0.5/N` output pixels.
- Bilinear recovers the sub-pixel centroid exactly and roughly quarters the
HDR error, but broadens the profile because it interpolates the kernel
samples rather than the continuous kernel; it therefore changes the
specified FWHM and beta unless separately compensated.
- A single fixed global convolution cannot provide both. `--fast-mode` default
is therefore `nearest`; `--fast-deposit bilinear` is available as an
explicit position-over-shape approximation.
+509
View File
@@ -0,0 +1,509 @@
# Fast-mode FFTW convolution benchmark (2026-09-25)
Replaces the spatial fast-mode global convolution with a reusable FFTW linear
convolution. This record separates one-time plan/setup from steady-state
execution and repeats the bounded Galactic-center comparison. Raw resolver and
end-to-end output is pasted verbatim from the runs below.
The later production-density 4K comparison is recorded separately against the
first committed FFTW implementation, revision
`229f50cd864d9768324042c10edbb56bfc120f08`.
## Environment
- Git revision: `3deebfb` plus the uncommitted FFTW work.
- Host: 12th Gen Intel Core i7-12700K, 16 hardware threads, 128 GB.
- FFTW: `pkg-config --modversion fftw3_omp` = `3.3.10`;
`pkg-config --libs fftw3_omp` = `-lfftw3_omp -lfftw3`.
- Build:
`make -j8 BUILD_TYPE=Release PSF_BACKEND=cpu SPACETIME=minkowski backend`
(`-O2 -DNDEBUG -fopenmp -march=native`, libpng, `-DFAST_PSF_FFTW`).
- Binary SHA-256 (this run):
- `build/Release/minkowski_sky`:
`ead2a543b8166abe6f82bc1cd41b2e985a6db517aa45a6416d08d188138b8c47`
- `build/Release/obj/minkowski/standard_sink1_cpu/benchmark_fast_psf_fftw`:
`8da8bbd532104a0c4f524aabf40b66a50c8c715e44479c7db467669ab5a21215`
- Timing wrapper: `/usr/bin/time` is not installed on this host. The
reproducible wrapper used for the end-to-end runs is zsh's built-in `time`
with `TIMEFMT='real=%*E user=%U sys=%S cpu=%P'`, i.e. each command was run as
`TIMEFMT='real=%*E user=%U sys=%S cpu=%P'; time <command>`. The `real=...`
lines below are the verbatim wrapper output.
## Correctness
```sh
make -j8 BUILD_TYPE=Debug PSF_BACKEND=cpu SPACETIME=minkowski test
```
All C tests pass, including the dedicated FFTW-vs-spatial test (258 comparisons
over sizes `17x13`/`16x16`/`23x31`/`33x17`, `N = 1..4`, nearest and bilinear,
eight scenes; worst `max_abs = 1.8e-14`), the `test_frame` fast-mode
regressions, the non-fast FITS references, and both camera CLI checks. HIP and
dummy renderers compile and link without FFTW; `make PSF_BACKEND=dummy test`
now fails fast with `make test requires PSF_BACKEND=cpu` instead of reusing a
stale CPU test binary.
## Resolver-only benchmark
One deterministic sparse impulse buffer, default PSF (FWHM 2.7, beta 4.5,
relative tail 1e-8), `OMP_NUM_THREADS=16`. `--spatial` additionally runs the
reference resolver on the identical buffer. Binary:
`build/Release/obj/minkowski/standard_sink1_cpu/benchmark_fast_psf_fftw`.
### Default 320x240 N=2, FFTW_ESTIMATE
```sh
OMP_NUM_THREADS=16 ./build/Release/obj/minkowski/standard_sink1_cpu/benchmark_fast_psf_fftw \
--width 320 --height 240 --supersample 2 --repeats 7 --spatial
```
```text
impulse: 320x240 supersample=2 deposit=nearest repeats=7 spatial=1
plan_mode=estimate
setup: init=0.039444 s fftw_plan=0.008085 s kernel_fft=0.005237 s
Fast FFTW: linear min=666x826, fft=672x840, workers=16, plan=estimate, plan=0.008085 s, kernel_fft=0.005237 s, scratch=30.2 MiB
impulse_hash=5334fa90cfbb1089
fftw: min=0.005602 s median=0.006455 s max=0.008144 s
fftw samples: 0.006697 0.005784 0.005602 0.005898 0.006455 0.007675 0.008144
fftw_hdr_hash=9ad60d92992c9bbd
spatial: 0.702470 s
spatial_hdr_hash=9327ac3e8e10d670
difference: max_abs=7.49e-16 peak=0.359 speedup=108.831x
rss_max_kb=52908
```
### Default 320x240 N=4, FFTW_ESTIMATE
```sh
OMP_NUM_THREADS=16 ./build/Release/obj/minkowski/standard_sink1_cpu/benchmark_fast_psf_fftw \
--width 320 --height 240 --supersample 4 --repeats 7 --spatial
```
```text
impulse: 320x240 supersample=4 deposit=nearest repeats=7 spatial=1
plan_mode=estimate
setup: init=0.114719 s fftw_plan=0.007169 s kernel_fft=0.011942 s
Fast FFTW: linear min=1330x1650, fft=1344x1680, workers=16, plan=estimate, plan=0.007169 s, kernel_fft=0.011942 s, scratch=120.7 MiB
impulse_hash=2639864ea9d3a26a
fftw: min=0.034756 s median=0.039591 s max=0.042474 s
fftw samples: 0.041352 0.039591 0.034756 0.040866 0.042474 0.035364 0.036241
fftw_hdr_hash=1ff070fdaac85f4a
spatial: 11.054385 s
spatial_hdr_hash=7682ee8550f88efe
difference: max_abs=5.38e-15 peak=0.533 speedup=279.214x
rss_max_kb=161032
```
### Medium 960x540 N=2, FFTW_ESTIMATE (FFTW only)
```sh
OMP_NUM_THREADS=16 ./build/Release/obj/minkowski/standard_sink1_cpu/benchmark_fast_psf_fftw \
--width 960 --height 540 --supersample 2 --repeats 7
```
```text
impulse: 960x540 supersample=2 deposit=nearest repeats=7 spatial=0
plan_mode=estimate
setup: init=0.042270 s fftw_plan=0.006317 s kernel_fft=0.010302 s
Fast FFTW: linear min=1266x2106, fft=1280x2160, workers=16, plan=estimate, plan=0.006317 s, kernel_fft=0.010302 s, scratch=147.7 MiB
impulse_hash=6e2de17f6859cd33
fftw: min=0.038361 s median=0.039872 s max=0.055834 s
fftw samples: 0.055834 0.038745 0.039872 0.038823 0.038361 0.048436 0.040141
fftw_hdr_hash=c493dbb793d04706
rss_max_kb=216272
```
### 4K 3840x2160 N=2, FFTW_ESTIMATE (FFTW only)
```sh
OMP_NUM_THREADS=16 ./build/Release/obj/minkowski/standard_sink1_cpu/benchmark_fast_psf_fftw \
--width 3840 --height 2160 --supersample 2 --repeats 5
```
```text
impulse: 3840x2160 supersample=2 deposit=nearest repeats=5 spatial=0
plan_mode=estimate
setup: init=0.524840 s fftw_plan=0.008154 s kernel_fft=0.482906 s
Fast FFTW: linear min=4506x7866, fft=4536x7875, workers=16, plan=estimate, plan=0.008154 s, kernel_fft=0.482906 s, scratch=1907.8 MiB
impulse_hash=e3b6d7f3d621630d
fftw: min=2.368634 s median=2.481927 s max=2.553895 s
fftw samples: 2.552212 2.553895 2.481927 2.389895 2.368634
fftw_hdr_hash=1c5720f72a040e6d
rss_max_kb=2879596
```
### 4K 3840x2160 N=4, FFTW_ESTIMATE (FFTW only)
```sh
OMP_NUM_THREADS=16 ./build/Release/obj/minkowski/standard_sink1_cpu/benchmark_fast_psf_fftw \
--width 3840 --height 2160 --supersample 4 --repeats 5
```
```text
impulse: 3840x2160 supersample=4 deposit=nearest repeats=5 spatial=0
plan_mode=estimate
setup: init=0.738771 s fftw_plan=0.003636 s kernel_fft=0.599235 s
Fast FFTW: linear min=9010x15730, fft=9072x15750, workers=16, plan=estimate, plan=0.003636 s, kernel_fft=0.599235 s, scratch=7631.4 MiB
impulse_hash=e6a528db0fb16c33
fftw: min=3.276609 s median=3.339285 s max=3.369411 s
fftw samples: 3.309935 3.369411 3.276609 3.345614 3.339285
fftw_hdr_hash=e55bed24ef3f5506
rss_max_kb=10919208
```
### FFTW_ESTIMATE versus FFTW_MEASURE
`FFTW_MEASURE` cuts steady-state time but costs a large one-time plan. Because
the plan is created once per process and reused across frames, it only pays off
for long movie renders; production therefore defaults to `FFTW_ESTIMATE`.
Wisdom import/export would make `FFTW_MEASURE` the better default and remains a
follow-up. Measured FFTW_MEASURE plan output is not bit-reproducible (plan
measurement is timing-dependent), so its `fftw_hdr_hash` may differ run to run;
the spatial comparison stays at roundoff.
```sh
OMP_NUM_THREADS=16 ./build/Release/obj/minkowski/standard_sink1_cpu/benchmark_fast_psf_fftw \
--width 320 --height 240 --supersample 2 --repeats 7 --measure --spatial
```
```text
impulse: 320x240 supersample=2 deposit=nearest repeats=7 spatial=1
plan_mode=measure
setup: init=1.584388 s fftw_plan=1.091687 s kernel_fft=0.467405 s
Fast FFTW: linear min=666x826, fft=672x840, workers=16, plan=measure, plan=1.091687 s, kernel_fft=0.467405 s, scratch=30.2 MiB
impulse_hash=5334fa90cfbb1089
fftw: min=0.003995 s median=0.004702 s max=0.005804 s
fftw samples: 0.003995 0.004702 0.004330 0.005804 0.004939 0.004986 0.004619
fftw_hdr_hash=626e386cba92ffa5
spatial: 0.706244 s
spatial_hdr_hash=9327ac3e8e10d670
difference: max_abs=8.05e-16 peak=0.359 speedup=150.198x
rss_max_kb=51860
```
```sh
OMP_NUM_THREADS=16 ./build/Release/obj/minkowski/standard_sink1_cpu/benchmark_fast_psf_fftw \
--width 3840 --height 2160 --supersample 2 --repeats 5 --measure
```
```text
impulse: 3840x2160 supersample=2 deposit=nearest repeats=5 spatial=0
plan_mode=measure
setup: init=41.408673 s fftw_plan=41.239987 s kernel_fft=0.134272 s
Fast FFTW: linear min=4506x7866, fft=4536x7875, workers=16, plan=measure, plan=41.239987 s, kernel_fft=0.134272 s, scratch=1907.8 MiB
impulse_hash=e3b6d7f3d621630d
fftw: min=0.518707 s median=0.522181 s max=0.539465 s
fftw samples: 0.523380 0.539465 0.518707 0.520357 0.522181
fftw_hdr_hash=ab90c4b076c775e1
rss_max_kb=2884132
```
## End-to-end bounded comparison
Same catalog, geometry, exposure, supersample factors, and worker environment as
`benchmarks/fast_mode_cpu_2026-09-18.md`. Raw terminal output including the
timing wrapper:
```sh
OMP_NUM_THREADS=16 TIMEFMT='real=%*E user=%U sys=%S cpu=%P' \
time ./build/Release/minkowski_sky --all-sky-catalog assets/2mass/processed/all_sky \
--width 320 --height 240 --fov-deg 10 --look-ra-deg 266 --look-dec-deg -29 \
--exposure 1e13 --coarse-cell-pixels 16 --refine-max-level 0 \
--output /tmp/opencode/fastmode_fftw_bench/normal.png
```
```text
Blackbody LUT: 1024 CIE 1931 2-deg 1 nm-linear XYZ nodes, T=[670.146556, 101408.88] K, loaded assets/blackbody/cie1931_2deg_xyz_1024.grbblut in 0.000046 s; payload fnv1a64=0e39867b0e70a809
Blackbody backend: lut
PSF cache ready: 64x64 phases, radius 47 px, relative tail 1e-08, tail abs 1e-06, boundary 1e-07, build 0.776 s
Catalog prefetch: 96 requested, 96 newly loaded (6618807 stars), 0 unavailable in 0.729 s; 4 loader workers
Rendered 5912840 images from 6618807 catalog stars to /tmp/opencode/fastmode_fftw_bench/normal.png (ok)
PSF splats: cached 5912840, cached wing-clipped 0, direct fallbacks 0, discarded below min-Y 0
real=17.526 user=225.46s sys=2.44s cpu=1300%
```
```sh
OMP_NUM_THREADS=16 TIMEFMT='real=%*E user=%U sys=%S cpu=%P' \
time ./build/Release/minkowski_sky --all-sky-catalog assets/2mass/processed/all_sky \
--width 320 --height 240 --fov-deg 10 --look-ra-deg 266 --look-dec-deg -29 \
--exposure 1e13 --coarse-cell-pixels 16 --refine-max-level 0 \
--fast-mode --fast-supersample 2 \
--output /tmp/opencode/fastmode_fftw_bench/fast_n2.png
```
```text
Fast mode is a preview approximation; --max-cache-psf-flux is ignored and one global kernel is used for every event.
Blackbody LUT: 1024 CIE 1931 2-deg 1 nm-linear XYZ nodes, T=[670.146556, 101408.88] K, loaded assets/blackbody/cie1931_2deg_xyz_1024.grbblut in 0.000049 s; payload fnv1a64=0e39867b0e70a809
Blackbody backend: lut
Fast PSF: supersample 2x, deposit nearest, kernel radius 93 ss px (46.50 final px), retained flux 1.000000, cached 4-point quadrature
Fast FFTW: linear min=666x826, fft=672x840, workers=16, plan=estimate, plan=0.007770 s, kernel_fft=0.005020 s, scratch=30.2 MiB
Catalog prefetch: 96 requested, 96 newly loaded (6618807 stars), 0 unavailable in 0.735 s; 4 loader workers
Rendered 5912840 images from 6618807 catalog stars to /tmp/opencode/fastmode_fftw_bench/fast_n2.png (ok)
Fast PSF splats: deposited 5912840, wing-clipped 0, discarded below min-Y 0
real=0.995 user=5.30s sys=0.18s cpu=550%
```
```sh
OMP_NUM_THREADS=16 TIMEFMT='real=%*E user=%U sys=%S cpu=%P' \
time ./build/Release/minkowski_sky --all-sky-catalog assets/2mass/processed/all_sky \
--width 320 --height 240 --fov-deg 10 --look-ra-deg 266 --look-dec-deg -29 \
--exposure 1e13 --coarse-cell-pixels 16 --refine-max-level 0 \
--fast-mode --fast-supersample 4 \
--output /tmp/opencode/fastmode_fftw_bench/fast_n4.png
```
```text
Fast mode is a preview approximation; --max-cache-psf-flux is ignored and one global kernel is used for every event.
Blackbody LUT: 1024 CIE 1931 2-deg 1 nm-linear XYZ nodes, T=[670.146556, 101408.88] K, loaded assets/blackbody/cie1931_2deg_xyz_1024.grbblut in 0.000044 s; payload fnv1a64=0e39867b0e70a809
Blackbody backend: lut
Fast PSF: supersample 4x, deposit nearest, kernel radius 185 ss px (46.25 final px), retained flux 1.000000, cached 4-point quadrature
Fast FFTW: linear min=1330x1650, fft=1344x1680, workers=16, plan=estimate, plan=0.007294 s, kernel_fft=0.012307 s, scratch=120.7 MiB
Catalog prefetch: 96 requested, 96 newly loaded (6618807 stars), 0 unavailable in 0.722 s; 4 loader workers
Rendered 5912840 images from 6618807 catalog stars to /tmp/opencode/fastmode_fftw_bench/fast_n4.png (ok)
Fast PSF splats: deposited 5912840, wing-clipped 0, discarded below min-Y 0
real=1.033 user=5.56s sys=0.22s cpu=559%
```
Image counts are identical across normal and both fast runs (5,912,840), so the
FFTW resolver did not change catalog/deposit behavior. Output SHA-256:
```text
normal.png e9f0a98ae7a3c3db546a3f276f400be98c96446fab7bfbc632f388702d4722d1
fast_n2.png 1f144aefb4a5520d9d76a13ab69026a72580663e5e45f53128a87a0801176ccf
fast_n4.png 679f14a67a085f76c144ecbe36af51b3b2534c152e8ef59708a7884a3f7c8464
```
## Production-density 4K Galactic-center comparison
This is the full 3840x2160, 50-degree-field run over the local processed 2MASS
all-sky catalog, not the bounded 320x240 comparison above.
### Provenance
- Git revision: `229f50cd864d9768324042c10edbb56bfc120f08`
(`Feat: Use FFTW linear convolution for CPU fast-mode PSF resolve`).
- The tracked worktree matched that revision when this record was written; the
unrelated untracked `nmesh_spacetime_output_format.md` was not an input.
- Executable: `build/Release/minkowski_sky`, built at
`2026-09-25 23:16:45 -0400`, before the three runs below; size 146,856 bytes;
SHA-256
`7f6486285b2ff498adb2d4f1acaf62dc96b11125c9cec114f572b9379648962c`.
A Make dry-run after the commit requested only the Makefile's unconditional
`FORCE` relink and no object recompilation, so the recorded binary used the
object set corresponding to the committed tracked sources.
- Host: 12th Gen Intel Core i7-12700K, 16 hardware threads, 128 GB. The commands
did not explicitly set `OMP_NUM_THREADS`; fast-mode initialization reported
`workers=16`.
- Input: `assets/2mass/processed/all_sky`, observed when recording as 64,801
regular files and 16,207,861,727 bytes. The renderer selected 1,742 tiles and
loaded 54,509,992 stars in each run. No content manifest hash was recorded for
this external processed catalog.
- Timing: zsh built-in `time`; its final timing line is included verbatim for
each command.
### Standard cached spatial PSF
```sh
time ./build/Release/minkowski_sky \
--psf-relative-tail 1e-6 --psf-min-y 1e-8 --max-cache-psf-flux 1e8 \
--all-sky-catalog assets/2mass/processed/all_sky \
--width 3840 --height 2160 \
--look-ra-deg 262.5 --look-dec-deg -30 \
--fov-deg 50 \
--coarse-cell-pixels 16 \
--exposure 1e13 \
--psf-fwhm-pixels 2.7 --psf-moffat-beta 3 \
--catalog-load-workers 4 \
--hdr-output \
--output output/imgs/2mass_galactic_center_flat_4k_50deg_1e13_beta3-base.png
```
```text
Blackbody LUT: 1024 CIE 1931 2-deg 1 nm-linear XYZ nodes, T=[670.146556, 101408.88] K, loaded assets/blackbody/cie1931_2deg_xyz_1024.grbblut in 0.000130 s; payload fnv1a64=0e39867b0e70a809
Blackbody backend: lut
PSF cache ready: 64x64 phases, radius 85 px, relative tail 1e-06, tail abs 1e-06, boundary 1e-07, build 2.176 s
Catalog prefetch: 1742 requested, 1742 newly loaded (54509992 stars), 0 unavailable in 5.886 s; 4 loader workers
Rendered 52544535 images from 54509992 catalog stars to output/imgs/2mass_galactic_center_flat_4k_50deg_1e13_beta3-base.png (ok)
PSF splats: cached 52477581, cached wing-clipped 0, direct fallbacks 0, discarded below min-Y 66954
Warning: --psf-min-y discarded one or more PSF events.
./build/Release/minkowski_sky --psf-relative-tail 1e-6 --psf-min-y 1e-8 1e8 938.60s user 15.80s system 1391% cpu 1:08.61 total
```
### Fast mode, N=2
```sh
time ./build/Release/minkowski_sky --fast-mode --fast-supersample 2 \
--psf-relative-tail 1e-6 --psf-min-y 1e-8 --max-cache-psf-flux 1e8 \
--all-sky-catalog assets/2mass/processed/all_sky \
--width 3840 --height 2160 \
--look-ra-deg 262.5 --look-dec-deg -30 \
--fov-deg 50 \
--coarse-cell-pixels 16 \
--exposure 1e13 \
--psf-fwhm-pixels 2.7 --psf-moffat-beta 3 \
--catalog-load-workers 4 \
--hdr-output \
--output output/imgs/2mass_galactic_center_flat_4k_50deg_1e13_beta3-fast-2.png
```
```text
Fast mode is a preview approximation; --max-cache-psf-flux is ignored and one global kernel is used for every event.
Blackbody LUT: 1024 CIE 1931 2-deg 1 nm-linear XYZ nodes, T=[670.146556, 101408.88] K, loaded assets/blackbody/cie1931_2deg_xyz_1024.grbblut in 0.000101 s; payload fnv1a64=0e39867b0e70a809
Blackbody backend: lut
Fast PSF: supersample 2x, deposit nearest, kernel radius 169 ss px (84.50 final px), retained flux 0.999999, cached 4-point quadrature
Fast FFTW: linear min=4658x8018, fft=4704x8064, workers=16, plan=estimate, plan=0.005275 s, kernel_fft=0.141445 s, scratch=2026.1 MiB
Catalog prefetch: 1742 requested, 1742 newly loaded (54509992 stars), 0 unavailable in 5.873 s; 4 loader workers
Rendered 52544535 images from 54509992 catalog stars to output/imgs/2mass_galactic_center_flat_4k_50deg_1e13_beta3-fast-2.png (ok)
Fast PSF splats: deposited 52477581, wing-clipped 0, discarded below min-Y 66954
./build/Release/minkowski_sky --fast-mode --fast-supersample 2 1e-6 1e-8 115.74s user 2.08s system 763% cpu 15.439 total
```
### Fast mode, N=4
```sh
time ./build/Release/minkowski_sky --fast-mode --fast-supersample 4 \
--psf-relative-tail 1e-6 --psf-min-y 1e-8 --max-cache-psf-flux 1e8 \
--all-sky-catalog assets/2mass/processed/all_sky \
--width 3840 --height 2160 \
--look-ra-deg 262.5 --look-dec-deg -30 \
--fov-deg 50 \
--coarse-cell-pixels 16 \
--exposure 1e13 \
--psf-fwhm-pixels 2.7 --psf-moffat-beta 3 \
--catalog-load-workers 4 \
--hdr-output \
--output output/imgs/2mass_galactic_center_flat_4k_50deg_1e13_beta3-fast-4.png
```
```text
Fast mode is a preview approximation; --max-cache-psf-flux is ignored and one global kernel is used for every event.
Blackbody LUT: 1024 CIE 1931 2-deg 1 nm-linear XYZ nodes, T=[670.146556, 101408.88] K, loaded assets/blackbody/cie1931_2deg_xyz_1024.grbblut in 0.000043 s; payload fnv1a64=0e39867b0e70a809
Blackbody backend: lut
Fast PSF: supersample 4x, deposit nearest, kernel radius 336 ss px (84.00 final px), retained flux 0.999999, cached 4-point quadrature
Fast FFTW: linear min=9312x16032, fft=9375x16128, workers=16, plan=estimate, plan=0.005384 s, kernel_fft=0.743673 s, scratch=8075.5 MiB
Catalog prefetch: 1742 requested, 1742 newly loaded (54509992 stars), 0 unavailable in 5.796 s; 4 loader workers
Rendered 52544535 images from 54509992 catalog stars to output/imgs/2mass_galactic_center_flat_4k_50deg_1e13_beta3-fast-4.png (ok)
Fast PSF splats: deposited 52477581, wing-clipped 0, discarded below min-Y 66954
./build/Release/minkowski_sky --fast-mode --fast-supersample 4 1e-6 1e-8 135.62s user 5.04s system 722% cpu 19.469 total
```
### Artifacts and comparison
```text
05517bde1383327043691ac4b713f638b03ebf6dc72207fe8710a8dce747a03e output/imgs/2mass_galactic_center_flat_4k_50deg_1e13_beta3-base.png
86e9220feac277d77eba87aa8d0febadca5f4eea35cb56164a4eb1578b20fccd output/imgs/2mass_galactic_center_flat_4k_50deg_1e13_beta3-fast-2.png
5dfef3b4bd39d9809463594a1065c32c65ad397396514664c8aa22a5da6d780b output/imgs/2mass_galactic_center_flat_4k_50deg_1e13_beta3-fast-4.png
1ea508d1ee787c2e5f35ccdf37ca5f4a58e9ff5e9984b50928d66ecf88c44c3d output/imgs/2mass_galactic_center_flat_4k_50deg_1e13_beta3-base_HDR.fits
71de3f1e11cb9f811f5d08ea45b51baf5968e8523873873d6f7c414c1849ba53 output/imgs/2mass_galactic_center_flat_4k_50deg_1e13_beta3-fast-2_HDR.fits
554848e39fdfb3b4815fb8f2a591b8d356cbdeaaea235a73f19b46017a18e42a output/imgs/2mass_galactic_center_flat_4k_50deg_1e13_beta3-fast-4_HDR.fits
```
All three runs produced 52,544,535 images and applied the same event filtering:
52,477,581 cached/deposited events, no wing clipping or direct fallback, and
66,954 events (0.12742334% of rendered images) discarded by `--psf-min-y`.
Using the standard HDR buffer as the reference, with
`relative_L2 = ||fast - base||_2 / ||base||_2`, the existing FITS artifacts give:
| Mode | Wall time | Wall speedup | Approx. speedup after subtracting catalog prefetch | User-CPU speedup | Scratch | HDR relative L2 | HDR total-flux ratio | Tone-mapped PNG normalized RMSE |
|---|---:|---:|---:|---:|---:|---:|---:|---:|
| Standard | 68.610 s | 1.000x | 1.000x | 1.000x | n/a | 0 | 1 | 0 |
| Fast N=2 | 15.439 s | 4.444x | 6.557x | 8.110x | 2026.1 MiB | 10.4384% | 1.000176588 | 0.00678916 |
| Fast N=4 | 19.469 s | 3.524x | 4.587x | 6.921x | 8075.5 MiB | 4.37249% | 1.000178510 | 0.00365798 |
The post-prefetch figures subtract only the renderer-reported catalog prefetch
duration from wall time; they are useful context, not isolated PSF timings. N=4
costs 26.1% more wall time and 3.986x the scratch of N=2, while reducing the HDR
relative-L2 difference by about 58% and the tone-mapped PNG RMSE by about 46%.
The nearly identical `+0.0177%` total-flux offset for N=2 and N=4 shows that the
larger N primarily improves spatial placement rather than global photometry.
For the intended rapid single-frame exposure/PSF preview, N=2 is therefore the
default throughput point; N=4 is the higher-fidelity preview option.
### Error distribution across the image
The unweighted relative L2 above is dominated by a small number of very bright
PSF cores, so it understates how well the dense faint-star texture is
reproduced in this still frame. `scripts/fast_mode_error_decomposition.py`
reports the error over the flattened scalar RGB channel samples:
```sh
python3 scripts/fast_mode_error_decomposition.py \
output/imgs/2mass_galactic_center_flat_4k_50deg_1e13_beta3-base_HDR.fits \
output/imgs/2mass_galactic_center_flat_4k_50deg_1e13_beta3-fast-2_HDR.fits \
output/imgs/2mass_galactic_center_flat_4k_50deg_1e13_beta3-fast-4_HDR.fits
```
```text
===== 2mass_galactic_center_flat_4k_50deg_1e13_beta3-fast-2_HDR.fits ===== relative_L2=10.4384%
top |d| RGB samples: sq-error energy base energy linear-RGB sum sample share
top 0.0010%: 69.136% 48.948% 2.822% 0.0010%
top 0.0100%: 95.732% 87.994% 9.141% 0.0100%
top 0.1000%: 99.365% 97.633% 16.396% 0.1000%
top 1.0000%: 99.893% 99.224% 25.984% 1.0000%
top 10.0000%: 99.988% 99.679% 46.006% 10.0000%
base-value range (disjoint): rel_RMS signed bias base energy % linear-RGB sum % samples
[1e-06,0.001): 4.7788% +0.7665% 0.000% 0.001% 67026
[0.001,0.0599): 4.5658% +0.1902% 0.013% 11.063% 12374574
[0.0599,0.1): 4.6294% +0.1297% 0.027% 10.881% 4486724
[0.1,0.229): 4.9079% +0.0866% 0.124% 25.365% 5466556
[0.229,0.769): 6.9340% +0.0100% 0.301% 24.638% 2239488
[0.769,4.62): 11.4421% -0.0990% 0.615% 10.315% 223948
[4.62,inf): 10.4475% -0.1789% 98.921% 17.738% 24884
===== 2mass_galactic_center_flat_4k_50deg_1e13_beta3-fast-4_HDR.fits ===== relative_L2=4.3725%
top |d| RGB samples: sq-error energy base energy linear-RGB sum sample share
top 0.0010%: 65.911% 35.557% 2.418% 0.0010%
top 0.0100%: 94.540% 86.397% 8.879% 0.0100%
top 0.1000%: 99.108% 96.708% 16.179% 0.1000%
top 1.0000%: 99.848% 99.208% 25.909% 1.0000%
top 10.0000%: 99.982% 99.694% 45.966% 10.0000%
base-value range (disjoint): rel_RMS signed bias base energy % linear-RGB sum % samples
[1e-06,0.001): 2.4187% +0.5689% 0.000% 0.001% 67026
[0.001,0.0599): 2.2772% +0.0729% 0.013% 11.063% 12374574
[0.0599,0.1): 2.3129% +0.0550% 0.027% 10.881% 4486724
[0.1,0.229): 2.4542% +0.0393% 0.124% 25.365% 5466556
[0.229,0.769): 3.4700% +0.0166% 0.301% 24.638% 2239488
[0.769,4.62): 5.6752% -0.0189% 0.615% 10.315% 223948
[4.62,inf): 4.3682% -0.0469% 98.921% 17.738% 24884
```
The FITS RGB channels are flattened into scalar samples: `sq-error energy` is
the fraction of `||fast-base||^2`, `linear-RGB sum` is the sum of baseline
linear-RGB sample values (proportional to total flux, not a per-source
photometry), and the base-value ranges partition all samples and sum to 100%.
The top 0.01% of RGB channel samples account for 95.7% (`N=2`) or 94.5%
(`N=4`) of squared-error energy and about 9% of the baseline linear-RGB sum.
The flux-bearing faint ranges (`[1e-3,0.0599)`, `[0.0599,0.1)`, `[0.1,0.229)`,
together ~47% of the linear-RGB sum) have 2.3-4.9% local relative RMS and
signed bias of `+0.04%` to `+0.19%`; the many faint PSFs partially cancel. This
is consistent with the concentrated bright-core difference being predominantly a
bounded sub-pixel redistribution rather than a large net linear-RGB loss, and
explains why this tone-mapped still PNG remains smooth despite the global
relative L2.
This comparison contains one independent frame only. It does not measure
temporal coherence: nearest deposition jumps by `1/N` output pixel per axis
when a moving image crosses a supersampled-cell boundary (`0.5 px` at `N=2`,
`0.25 px` at `N=4`). Both can produce visible movie flicker and are not
qualified here as visually faithful movie-output paths.
## Reading
- Steady-state FFTW is ~109x (N=2) and ~279x (N=4) faster than the spatial
reference at 320x240, and stays under ~0.06 s per frame at 960x540.
- 4K N=2 resolves in ~2.5 s (ESTIMATE) or ~0.52 s (MEASURE) on this host; 4K N=4
needs ~7.6 GiB scratch and ~3.3 s (ESTIMATE).
- FFTW-versus-spatial differences are floating-point roundoff (`max_abs` at the
`1e-15` level against peaks near `0.5`), not crop, wrap, channel, or
normalization errors.
- At the committed revision, the production-density 4K Galactic-center run
completes in 15.439 s at N=2 versus 68.610 s for the standard path (4.444x
end-to-end), with identical catalog image/deposit/filter counts. N=4 trades
26.1% more wall time for materially lower spatial error.
- The 4K still-frame error is concentrated: the top 0.01% of RGB channel
samples hold ~95% of the squared-error energy but only ~9% of the baseline
linear-RGB sum, while the flux-bearing faint-value ranges stay at ~2-5% local
relative RMS with signed bias at or below ~0.2%. This does not establish
temporal fidelity.
+500
View File
@@ -0,0 +1,500 @@
# HIP PSF 有界真实事件回放与像素归约实验(2026-09-07)
## 结论与交付
**当前方向(2026-09-13):搁置旧串行 adaptive 的慢因追溯,在新版 worker 私有预分桶
adaptive 上优化生产管线。以下各日期记录保留历史结论;当前结果和下一步目标以
“2026-09-13 全天复测与下一步目标”一节为准。**
已实施原计划的有界捕获/回放、16×16 和 32×32 按像素归约原型、独立 CPU producer
诊断及正确性回归。**原型保留在测试程序中,未替换生产 HIP 路径。**
实现于 2026-09-11 提交为 `7f5ec1a`;以下日志和 hash 保留 2026-09-07 测量时的状态。
RX 9070 上,65,536 个真实银心视场事件的累积回放中位数从 104.107 ms 降至
69.823 ms(16×16,约 1.49×)。含公共 GPU 初始化为 137.111 → 102.323 ms(约 1.34×)。
但同等贡献的分散对照中,16×16 从 85.302 ms 退化至 104.389 ms;32×32 为 79.899 ms。
强放大样本的 32×32 结果波动区间与 atomic 重叠,不能确认稳定收益。因此尚不足以选择
一个通用生产默认算法;后续集成应先考虑分布选择及生产流式 producer 的端到端对照。
没有运行完整全天渲染,也没有推断新的全天加速比。
## 2026-09-11 自适应选择后续实验
在提交 `11e703e33dffb1ff168ba11dd922e68b448116b9` 之上增加了仅用于回放的
`adaptive` 模式,production sink 仍未改变。选择器逐个 16,384-event chunk 扫描
32×32 中心 tile 占用;chunk 至少有 8,192 events、且平均每个占用中心 tile 至少
32 events 时选择 tile16,否则选择现有 atomic。该阈值是基于本页固定输入提出的实验
假设,不是跨场景或跨设备参数。
选择扫描不构建 support 引用,四个样本的中位成本为 0.037--0.455 ms。tile 路径使用
独立的有界 event device buffer,不复用 production 双 staging slot,因此同一 stream 内
可以按 chunk 混合 atomic/tile;mixed fixture 实际覆盖 2 个 tile chunk、1 个 atomic chunk
和中途 direct fallback。所有额外 scratch 仍在 replay sink 创建时一次分配,未进入 renderer。
同一新 binary(SHA256
`121b85ade12680929cf0f560e04485e2ad3d8a56ff9dcbba950a323f840c5151`)串行运行,
每项三次;表中为包含选择、分桶、上传、kernel、合并、下载和清理的 `replay_wall`
中位数:
| 65,536-event 输入 | paired atomic | paired tile16 | adaptive | adaptive 选择 |
| --- | ---: | ---: | ---: | ---: |
| 银心密集 | 95.018 ms | 67.354 ms | 67.834 ms | 0.177 ms |
| 同贡献分散 | 78.203 ms | 99.693 ms | 80.092 ms | 0.455 ms |
自适应路径在密集输入相对 paired atomic 快约 1.40×,距固定 tile16 中位数 0.7%;在分散
输入保留 atomic,距其 paired 中位数 2.4%。另外两个真实输入的自适应中位数为强放大
21.617 ms、普通区域 18.347 ms,分别选择 1/1 tile chunk。银心选择 4/4 tile chunks,
分散对照选择 4/4 atomic chunks。此结果支持继续研究 production 流式集成,但尚未包含
OpenMP producer 与 sink 锁竞争,也没有授权用本回放结果宣称完整全天加速。
全部 adaptive/mixed 检查通过原有 finite、double HDR 和 RGB/Y 通量阈值;最坏
`max_abs=5.96856e-11`、`max_rel=5.95958e-13`、RGB 通量相对差
`<=2.83233e-14`、Y `<=1.15036e-14`。`make -j1 test` 与 production HIP primitive
也通过。第一次在受限沙箱内运行明确失败为 `no ROCm-capable device is detected`,随后只在
获准的主机 GPU 环境执行;失败记录保留,没有删除或覆盖。
原始证据:
- 构建:[adaptive_build_host.log](hip_psf_replay_2026-09-07/adaptive_build_host.log);
- adaptive 三次:`adaptive_{center_65536,dispersed_65536,lensed_16384,ordinary_12765}_host_{0,1,2}.log`;
- paired 基线:`paired_{center,dispersed}_{atomic,16}_{0,1,2}.log`;
- mixed、CPU 与 HIP 回归:`adaptive_boundary_mixed_host_0.log`、
`adaptive_cpu_regression.log`、`adaptive_hip_primitive_host.log`;
- 受限环境失败:`adaptive_center_65536_0.log`。
每份日志均保留完整命令、45/90 s timeout、Git hash、binary hash(适用时)、程序原始输出、
process wall 和 exit status。所有性能进程均由现有独占 runner 串行执行,未与其他 renderer
或 profiler 并发。
## 2026-09-12 持续回放与 production 集成
在提交 `2d01c2c101ccea8193a64bb46ceafca3009f0ef5` 之上的未提交实现中,回放器增加了
1--512 轮有界重复模式,用同一真实事件流测试持续负载。重复模式不把累计 128/256 轮的
GPU HDR 与单轮 CPU reference 比较,因而输出明确标记 `validation=skipped-for-sustained-timing`;
单轮真实输入与 mixed boundary 仍执行原有 double HDR、RGB/Y 通量和 finite 检查。
原 replay tile16 在密集输入的 256 轮完整 wall 为 12.968 s,atomic 为 14.326 s,只有
1.10×--1.18× 的持续收益;tile accumulation 本身仍约快 1.4×,CPU 的整屏嵌套列表分桶
约占 1.8--1.9 s。不同运行顺序下的 128 轮 adaptive 为 6.372--6.880 s,对应 atomic
7.149--7.165 s,证明短回放的 1.40× 完整收益不能直接外推。
production sink 随后接入稀疏 touched-tile 分桶和可复用有界 scratch。默认保持 atomic;
`HIP_PSF_ACCUMULATION=adaptive` 启用与 replay 相同的中心密度选择规则。32 MiB references、
2 MiB tasks 或 128 MiB partials 超限时按 chunk 回退 atomic,不改变 double RGB、四点 phase
cache、圆形 support、wing clipping 或 direct fallback 顺序。
最终同 binary(SHA-256
`c560c193e1dc2104030ed804ea68e16ab7576592191dbf147b917a6e097a66b6`)连续回放
65,536 个真实银心事件 128 轮:
| production sink | 完整 replay wall | GPU 阶段 | selector | CPU bin | upload | batches |
| --- | ---: | ---: | ---: | ---: | ---: | ---: |
| atomic | 7.164 s | 7.132 s | 0 | 0 | 0.023 s | 512 atomic |
| adaptive | 4.631 s | 3.875 s | 0.018 s | 0.607 s | 0.091 s | 512 tile16 |
完整 replay 为 **1.55×**,记录的 GPU 阶段为 **1.84×**。同 binary 的 64 轮同贡献分散
输入中,adaptive 选择 256/256 atomic chunks,完整 wall 为 3.167 s,直接 atomic 为
3.169 s,差异在 0.1% 内。最终 dense 单轮检查的
`max_abs=2.71051e-19`、`max_rel=1.96115e-14`。最终 mixed boundary
覆盖 2 个 tile16、1 个 atomic chunk 和中途 direct fallback,最坏 `max_abs=5.96856e-11`、
`max_rel=5.95958e-13`,RGB/Y 通量阈值均通过。production primitive 在 adaptive 环境下也
通过,`max_abs=2.84217e-14`、`max_rel=7.53192e-16`。
三 tile、21,087-star renderer 配对使用同一 4K lens map 和同一 production binary
(SHA-256 `f51cbccac135502440f005c5d61d95d6004be7d4ec5cd09bfe04bab53053143d`)。
atomic/adaptive 均产生 156,837 events;adaptive 选择 14 tile16 + 2 atomic batches,kernel
为 0.118894 s,对照 0.169212 s,splat wall 为 0.236/0.285 s。两张 PNG 的 SHA-256 都是
`99a971fac7f5e66f0a1aafd0921b61f16fcb933c9488320f95e423542d3b6a6d`。约 1.4 s 的完整
进程受 cache build 等固定成本波动支配,不能用 process wall 判断这项优化。
随后使用同一 4K lens map、598,264,924 events 和 36,530 batches 运行了完整全天
adaptive 渲染。它推翻了上述有界样本的外推:
| 完整全天 | splat wall | kernel | CPU bin | selector | upload | process wall |
| --- | ---: | ---: | ---: | ---: | ---: | ---: |
| atomic | 480.500 s | 477.302449 s | 0 | 0 | 1.411367 s | 533.62 s |
| adaptive | 586.763 s | 416.265471 s | 155.302 s | 2.212 s | 7.506981 s | 640.35 s |
adaptive 的 GPU kernel 只减少 61.037 s(12.79%),而串行关键路径上的 CPU 分桶增加
155.302 s,splat wall 因而增加 106.263 s(22.12%),完整进程增加 106.73 s(20.00%)。
36,515/36,530 batches 被选为 tile16,说明中心 32px tile 密度无法预测完整 47px PSF
support 扩张后的 references、tasks、列表长度和分桶成本。atomic 从有界回放的
13.93 ms/batch 到全天的 13.07 ms/batch 没有恶化;tile kernel 则从有界样本的
7.57 ms/batch 变为全天的 11.40 ms/batch,CPU 分桶另需 4.25 ms/batch。串行分桶是已确认的额外成本;GPU 阶段变慢的具体原因未定位,
不能仅凭这些时间排除时钟或其他系统因素。
正确性仍成立:atomic/adaptive PNG 的 SHA-256 都是
`c63df730c7f927fc6b6ae17df5ffbad1d2bb44631a5821557150d00d6269a3e4`。两个 HDR FITS
共有 24,883,200 个 float,113 个因累积顺序不同;`max_abs=2.38418579e-07`、
`max_rel=1.18905923e-07`。这项旧串行分桶 adaptive 实现是历史负结果,不能外推为新版并行预分桶的结论;
默认继续保持 atomic。当时提出的下一轮实验是直接度量 support-expanded 引用工作量,并在
重新跑完整全天前用真实流式 producer 验证并行预分桶或 GPU 分桶能否把成本移出串行关键路径。
完整 adaptive 原始输出保存在 `full_production_adaptive_user.log`(SHA-256
`ec7b41d56a76cb93383737c30c6c6055bdb53b9b0cff54034333d96a841b1f36`);该用户命令未嵌入
Git/binary hash,运行后工作区 binary 的 SHA-256 为
`f51cbccac135502440f005c5d61d95d6004be7d4ec5cd09bfe04bab53053143d`,不可仅凭事后 hash
证明执行期间 binary。atomic 数字来自同一任务先前保留的终端输出。
### 2026-09-12 producer 私有并行预分桶原型
在上述完整全天负结果之后,将 adaptive 选择与 support-expanded CPU 分桶移到每个 OpenMP
producer 私有的 `HipPsfPreparedChunk`,在获取 sink 共享锁前完成;单个 sink 仍独占 GPU
HDR、stream、device scratch 和稳定的上传 staging。direct fallback 先准备本 worker 的待提交
chunk,再在同一锁内完成提交、HDR 下载、CPU splat、HDR 上传。原 `hip_psf_sink_submit` 仍用于
单线程回放兼容,正常生产默认 atomic 未变。新日志记录 tile references、tasks、merges 和
单 chunk 峰值,以便下一次评估完整 support 工作量。
同一 65,536-event 银心固定输入重复 128 轮,均为 512 个 tile16 batches。新 binary 的配对
回放结果如下(两者均通过 `128 × CPU double reference`,`max_rel=2.14616e-14`):
| 生产 sink 回放 | replay wall | 累计 CPU bin | GPU 阶段 | process wall |
| --- | ---: | ---: | ---: | ---: |
| sink 内串行分桶 | 3.886 s | 0.549 s | 3.659 s | 5.778 s |
| 16 worker 私有预分桶 | 3.958 s | 0.709 s(各 worker 求和) | 3.670 s | 5.873 s |
此输入上并行预分桶没有端到端收益,且累计 CPU 工作与 RSS 上升(约 716→770 MiB)。由于这
份输入已被全天结果证明低估真实分桶与 tile kernel 成本,此试验仍不能判断全天会否受益,
更不能宣称 61 s 的 kernel 收益已被回收。**不据此再跑完整全天。**需要先取得代表实际
36,530 chunks 的 support-expanded references/tasks 分布和并行分桶 wall,再决定是否继续此方向。
真实小型 4K lens-map renderer 中,16 workers 处理 156,837 events,13 tile +3 atomic
batches;13 个 tile chunk 共 6,145,194 references、64,056 tasks、5,465 merges,单 chunk
最多 561,449 references。PNG SHA-256 与先前 atomic 输出同为
`99a971fac7f5e66f0a1aafd0921b61f16fcb933c9488320f95e423542d3b6a6d`。另一个
32,771-event mixed boundary 回放包含 2 tile +1 atomic chunk 和 direct fallback,通过 CPU
double reference,`max_abs=5.96856e-11`、`max_rel=5.95958e-13`。HIP primitive 与
`make -j4 ENABLE_PNG=1 test` 均通过。
新原始日志:`parallel_prebin_{serial_128_validated,16workers_128_validated}.log`、
`parallel_prebin_renderer_workload.log`、`parallel_prebin_mixed_boundary.log`、
`parallel_prebin_hip_primitive.log`。先前 `parallel_prebin_16workers_128.log` 因 OpenMP
`reduction(max:failed)` 的私有初值而没有提交事件;原始失败保留,修正为 `reduction(+:failed)`
后的 `*_v2.log` 才是首次有效回放,最终数字以上述带 scaled reference 校验的日志为准。
为获取不经 GPU 的真实全天 support 分布,dummy 后端增加显式
`DUMMY_PSF_SUPPORT_STATS=1` 诊断:每 worker 保存最多 16,384 个事件,在 chunk flush 时按
production 的 cache-limited 矩形 support 统计 16px references、touched tiles、按 256
references 切分的 tasks、最大单 tile 列表和第一遍计数耗时。它不生成 HDR、不 materialize
references、不上传 GPU,不能把第一遍耗时等同于完整两遍分桶成本。21,087-star 小样通过,
原始记录为 `parallel_prebin_dummy_support_small.log`;该样的 chunk 边界受 OpenMP 动态调度
影响,不与 HIP renderer 的逐 chunk 列表配对。完整全天诊断结果见下文。
下一次完整全天诊断使用与已跑的 dummy 任务相同的参数,只额外设置环境变量;输出路径仅
满足 CLI,dummy 不写图像:
```sh
OMP_NUM_THREADS=16 OMP_DYNAMIC=FALSE DUMMY_PSF_SUPPORT_STATS=1 \
./build/Release/schwarzschild_sky_dummy --verbose \
--psf-relative-tail 1e-8 --psf-min-y 0 --max-cache-psf-flux 1e8 \
--all-sky-catalog assets/2mass/processed/all_sky --exposure 1e13 \
--psf-fwhm-pixels 2.7 --psf-moffat-beta 4.5 --catalog-load-workers 4 \
--lens-map-input output/lens/schwarzschild_galactic_center_R100_45deg_16_4_4k_.grlens \
--output /tmp/2mass_dummy_support_diagnostic.png
```
用户随后运行了上述完整全天 dummy 诊断;原始终端输出为
[`full_dummy_support_user.log`](hip_psf_replay_2026-09-07/full_dummy_support_user.log),
SHA-256 `992a3109de28a338c53af229b6a3b4083659a835f78929c36d36178358a6d5e0`。
日志未嵌入执行时 Git/binary hash;运行后本地 dummy binary 的 SHA-256 为
`2550fbdc7367ec4d56bdf87894e1322d7f4af5165e93a17af3e6a37806c0649a`。
同一 343,363,141 stars 产生 598,264,924 cached events,0 direct/wing/discard;
64,440 catalog tiles 全部加载,49.020 s;16 worker 分类/chunk wall 81.760 s。zsh `time`
给出总时间 2:11.91;zsh 对 pipeline 中的 `tee` 另列一行,不能把两个 2:11.91 相加。
该次动态调度产生 36,508 个满 chunk、16 个 partial;与 HIP 的 36,530 batches 不作逐批
配对,但总事件数一致。
| 全天满 chunk support 统计 | p50 | p90 | p99 | max |
| --- | ---: | ---: | ---: | ---: |
| 16px references | 746,748.5 | 802,816 | 802,816 | 802,816 |
| touched 16px tiles | 49 | 168 | 1,036 | 1,521 |
| tile tasks | 2,975 | 3,136 | 3,435.93 | 3,733 |
| 最大 tile 列表 | 16,384 | 16,384 | 16,384 | 16,384 |
| 第一遍计数 | 0.807 ms | 0.919 ms | 1.049 ms | 7.969 ms |
全部 chunk 合计 27,216,790,943 references、107,847,441 tasks,worker 第一遍计数时间之和
29.347 s。这是并行 worker 时间之和,**不是**额外 wall time,也不包括第二遍写 references、
任务构造、锁内 staging 或 GPU 上传。全天 HIP 串行完整分桶为 155.302 s,不能拿 29.347 s
直接替换它。第一遍显示每个事件平均覆盖约 45.5 个 16px tile;满 chunk 的 p90 已到
`16,384 × 49`,且最大列表从中位数起就是整批事件。
对旧真实 `center_65536.events` 逐 chunk 用相同 support 矩形计算,四批 references 为
745,430 / 725,200 / 753,474 / 749,671,接近全天 p50;但 touched tiles 为
96 / 162 / 203 / 222,最大列表仅 14,637 / 9,099 / 11,188 / 9,220。因此先前有界
样本只匹配了引用总量,没匹配热点集中度。为区分这两个量,`make_hotspot_fixture.py` 把
原事件平移到相同整数像素,或保留约 8×8px 位置散布;颜色、flux、support 原样保留,
亚像素余数仅受 double 舍入影响。这两份**明确是反事实 GPU workload,不是物理星像**。
固定热点每批恰好 802,816 references、49 tiles、3,136 tasks、最大列表 16,384;
输入 SHA-256 分别为 `de39e07d420f70aaa2f7309d209e58a1091d2bea4ca6d8332366e6944f19347b`
与 `87f90c2e43845962702e1643f9b7a635108b75b6e21a30080650442745cadcf6`。
| 128 轮、512 批回放 | atomic wall | tile 串行 wall | tile 并行 wall | atomic GPU 阶段 | tile GPU 阶段 |
| --- | ---: | ---: | ---: | ---: | ---: |
| 同一整数像素 | 7.711 s | 4.001 s | 4.071 s | 7.677 s | 3.760 s |
| 8×8px 散布 | 6.482 s | 3.949 s | 4.046 s | 6.447 s | 3.714 s |
全部回放通过按轮数缩放的 CPU double reference,tile 的最大相对误差不超过
`3.30e-14`。此对照说明 refs/tile/list 聚合量不足以重现全天 tile GPU 阶段
`416.265/36,530 = 11.40 ms/batch`:即使强制匹配 p90 热点,回放仍约
`7.3 ms/batch`。另外在 `center_65536.events` 的同一回放进程内放入 15 个 CPU 忙等线程,
atomic/tile GPU 阶段为 7.126/3.669 s(512 批),几乎仍是无忙等线程的
7.13/3.66 s;简单主机抢占也未重现全天差距。上述 workload 与争用实验均为诊断性
反事实,不能改变真实全天 adaptive 慢 20% 的结论。
原始配对日志:`hotspot_{atomic,adaptive_serial,adaptive_parallel}_128.log`、
`hotspot_jitter8_{atomic,adaptive_serial,adaptive_parallel}_128.log`、
`busy_center_{atomic,adaptive}_128.log`。全天 adaptive 原始进度每隔约 5 秒报告累计 HIP
阶段:首尾约 7–8 ms/batch,中间约 12–13 ms/batch 持续数万批。这提示当前固定 65,536
events 输入未覆盖真实流中的长期困难区段,但也不能排除其他随时间变化的系统因素;
原因仍未定位。当时提出从该区段捕获真实 events 和逐批 GPU/CPU 明细;
2026-09-13 已搁置这项旧版追溯,不再作为新版推进的前置条件。
其余原始证据为 `final_production_{atomic,adaptive}_128.log`、
`final_production_adaptive_dense.log`、
`final_production_dispersed_{atomic,adaptive}_64.log`、
`final_production_adaptive_mixed.log`、`final_hip_test_adaptive.log` 和
`final_renderer_{atomic,adaptive}.log`。每份日志包含完整命令、timeout、Git hash、binary hash
及原始输出。production 默认值没有改变。
实现入口:
- [capture_psf.c](../tests/capture_psf.c):调用真实 producer 的测试专用 consumer,捕获或诊断,不生成 HDR。
- [replay_psf.hip](../tests/replay_psf.hip):CPU double reference、现有 atomic、两种 tile 原型。
- [make_psf_fixture.c](../tests/make_psf_fixture.c):单独标记的合成边界/热点/wing fixture。
- [test_psf_capture.py](../tests/test_psf_capture.py):边界限制、分类、串行/并行/索引摘要、拒绝覆盖验证。
- [全部原始证据与索引](hip_psf_replay_2026-09-07/README.md)。
## 2026-09-13 全天复测与下一步目标
用户在重新构建 worker 私有预分桶版本后,再次完成同配置全天 adaptive 渲染;随后
`git stash` 回到 `2d01c2c`,重新构建并复测原 atomic,之后用 `git stash pop` 恢复修改。
该 HEAD 的 HIP 实现不读取 `HIP_PSF_ACCUMULATION`,所以 atomic 复测命令虽仍写着
`adaptive`,实际是 atomic;不能把输出文件名或环境变量当作算法证据。
| 全天实现 | splat wall | GPU event 阶段 | CPU bin | upload | process wall |
| --- | ---: | ---: | ---: | ---: | ---: |
| 历史 atomic | 480.500 s | 477.302449 s | 0 | 1.411367 s | 533.62 s |
| 旧串行 adaptive | 586.763 s | 416.265471 s | 155.302 s,串行 | 7.506981 s | 640.35 s |
| 新并行预分桶 adaptive | 282.944 s | 256.184375 s | 134.374 s,worker 累加 | 7.184765 s | 335.75 s |
| 本次 atomic 复测 | 481.417 s | 478.336515 s | 0 | 1.432135 s | 534.37 s |
四次总事件数均为 598,264,924、batches 均为 36,530;两次 adaptive 都选择 36,515 tile16
和 15 atomic batches。新 adaptive 无 direct/wing/discard,references 为 27,216,530,468、
tasks 为 107,238,420、merges 为 2,802,462,峰值 references/chunk 为 802,816。
新 adaptive 和旧 adaptive 均已使用相同 payload 的黑体 LUT;catalog 加载分别为
49.334/50.104 s。新版 bin 时间是各 worker 的经过时间之和,可以与 GPU 重叠,不能加到
splat wall 上,也不能与旧版串行 bin 作等口径的关键路径比较。
atomic 的 splat/GPU 复测仅比历史值高约 0.2%。相对本次 atomic,新 adaptive 的 splat
快约 1.70×、GPU event 阶段快约 1.87×、完整进程快约 1.59×。这支持继续推进新版;
尚不是相同 binary 内的 atomic/adaptive 配对,也不证明新版全天 HDR 数值正确性。
新旧 adaptive 的 splat 差 303.819 s,其中 GPU event 阶段差 160.081 s;不能把全部收益
归因于分桶并行化。旧版 GPU 阶段为何更慢仍未知,保留历史证据,**停止专项追溯**;仅当
新版出现可重复退化或正确性问题且旧版信息有助定位时重新调查。
新 adaptive 完整原文见
[full_parallel_prebin_adaptive_user_2026-09-13.log](hip_psf_replay_2026-09-07/full_parallel_prebin_adaptive_user_2026-09-13.log);
atomic 复测仅收到结尾摘录,原样保存为
[full_atomic_redo_user_2026-09-13_excerpt.log](hip_psf_replay_2026-09-07/full_atomic_redo_user_2026-09-13_excerpt.log)。
两者均未提供运行时 binary hash,摘录不能代替完整命令和完整运行日志;本次只更新文档,
没有重新运行 benchmark 或比较新生成的全天 HDR。
### 新版优化目标与验证顺序(待实施)
目标是在相同 RX 9070、4K lens map、全天 catalog、PSF/曝光/黑体参数和 HDR/PNG 输出下,
将完整进程从 335.75 s 推进到 **240 s/张以内**。这是待验证目标,不是性能承诺;不能通过
降低精度、删减事件、改变 tail/min-Y、缩小输入或省略输出来达标。atomic 保留为参考和
显式可选路径,本次不修改默认算法。
用户全程观察新版的 btop:GPU 常在约 94%,会反复降至约 80%,并非偶发;整机 CPU
持续满载。用户另报告原 atomic 能吃满 GPU。旧串行 adaptive 当时没有观测,不能推断它
不存在 GPU 不满载现象。上述是人工观测,未保存同步遥测,不能据此量化净算力利用率。
新版 generation/submission 累计分别为 814.275/3712.364 s,后者包含分桶、锁等待和
提交/完成等待;atomic 复测的 GPU 阶段占 splat wall 约 99.36%,进程仍为 1461% CPU。
CPU 满载不等于有效 producer 工作,忙等是需测量的嫌疑,尚未定量确认。
新版非 splat 阶段约 52.806 s;即使消除 splat wall 与 GPU event 阶段之间的全部
26.760 s,总进程仍约 309 s。若其他阶段不变,240 s 目标要求 splat 不超过约 187.2 s,
比当前 GPU event 阶段还低约 27%。该 event 区间包围 prepare/accumulate/merge,可能含
提交间隙,不等同于三个 kernel 的净执行时间。因此同时调查管线空隙和 GPU 执行成本,
不能把 btop 达到 100% 当作验收标准。
1. 先比较已有新版 adaptive 与 atomic 全天 HDR:finite、逐像素误差、RGB/Y 总通量,
使用现有正确性阈值;记录输出 hash,不为这一步重跑全天。
2. 增加可关闭的有界诊断,拆分 CPU 分桶、锁等待、锁持有、GPU 完成等待、staging 和
提交时间,记录线程 CPU time;GPU 分别测 prepare、accumulate、merge,并保留原总区间。
在新版代表性真实流式小样上同步记录 GPU busy、时钟、功耗、温度,先验证测量开销。
固定事件回放用于隔离成本,不能单独替代生产 producer/sink 的端到端证据。
3. 若批间空隙显著,优先评估双缓冲 staging/上传,使下一批准备与当前批 GPU 执行重叠;
若共享锁争用显著,再对照专用提交线程加有界队列。这些是待验证候选,不是已选定实现。
明确缓冲 ownership、完成后复用和有界背压;单 sink 持有 GPU HDR,保留 direct fallback
的 finish/download/CPU/upload 顺序,不引入 per-event task 或无界排队。
4. 管线改善后重测剩余成本;若主要时间仍在 kernel,则优化占比最大的实际 kernel;若
catalog 加载成为主要限制,再单独评估输入阶段。保留密集、分散和 mixed/direct 回归。
有界配对采用相同 binary/输入、预热后至少三次交错顺序复测,报告 wall、CPU time、
GPU 分阶段及波动,不累加重叠 worker 时间。每次预设 timeout,串行独占执行,保留完整
命令、Git/diff/binary/input hash、原始日志与退出码;GPU 不可用直接失败。
5. 有界正确性与收益验证后再另行安排全天配对确认,同时报告完整进程和分阶段时间。
未达到 240 s 时记录剩余差距及实测瓶颈;不为解释旧版而额外运行全天。
## 环境与测量纪律
Git 基线 `5eccc31c99db96de2a0597babf2fd4c2149e91e7`,测量时在此基础上有未提交修改。
没有覆盖用户已有的计划修改。生产 `src/hip_psf.hip` 未改;`src/frame.c` 的诊断钩子
仅在 standalone 测试编译时启用。每次直接执行的 binary SHA256 在相应日志中;
[源码、binary、lens map hash](hip_psf_replay_2026-09-07/source_binary_manifest.json)、
[宿主环境](hip_psf_replay_2026-09-07/metadata.log)、
[构建命令](hip_psf_replay_2026-09-07/build_commands.txt)与 `build*.log` 保存完整配置。
Release / C `-O2 -march=native` / HIP `-O2 --offload-arch=gfx1201`,HIP 7.2,RX 9070。
回放 CPU reference 为串行;diagnostic 最多 16 workers;混合 renderer fixture 为 4 workers。
各进程重建相同 immutable cache:FWHM=2.7、beta=4.5、tail=1e-8,64 phase intervals、
47px cache radius。没有清除文件系统 page cache;输入是重复读取的固定小文件。
所有测试进程串行,回放超时 45 s、缩小 renderer 超时 60 s;未出现测试超时。
早期 `v3_*` 期间部分编译活动重叠,全部 `v3_*` 仅用作探索/正确性证据。
下表只用构建和回归结束后的 `final_*` 三次独立复测,不引用受构建干扰的时间。
`run.py` 记录命令、原始 stdout/stderr、退出码和进程 wall,失败立即停止,限时进程被 kill
后会 wait/reap;独占锁及启动前的进程检查防止本套工具重叠运行。
## 固定输入、选择规则与实际覆盖
使用已有 3840×2160 Schwarzschild lens map,不重新 tracing/refine。只读取两个指定
catalog tile 的均匀 8,192 行子集,见 [输入 manifest](hip_psf_replay_2026-09-07/input_manifest.json)
和 [重建脚本](hip_psf_replay_2026-09-07/prepare_inputs.py)。没有遍历完整全天 catalog。
捕获器限制 CSV≤8 MiB、stars≤32,768、lens map≤64 MiB/单帧、triangle 范围≤131,072、
缓存事件≤65,536、分类总数≤131,072。按 triangle ID、原 catalog 顺序捕获,保留所有
7 个 event double,文本用 17 位有效数字 round-trip;header 保存实际数量与 PSF 参数。
triangle 范围 `[0,130882)`;按未截断的局部 magnification 再筛选:
| 区域 | 原始 tile | magnification | 最大捕获实际数 | 占用 32px 中心 tiles | 最大中心密度 |
| --- | --- | --- | ---: | ---: | ---: |
| 普通区域 | RA252/Dec048(Dec −42°) | [0,1.2) | 12,765 | 8 | 4,691 |
| 银心视场密集区域 | RA262/Dec060(Dec −30°) | [0,2) | 65,536(到上限) | 30 | 7,778 |
| 强放大区域 | 同上 | [2,1e6) | 16,454 | 367 | 176 |
普通、强放大子集用完后没有复制事件凑足 65,536。事件文件名后缀表示请求上限,实际数量
以 header 和 manifest 为准。实际 bbox、flux/support 范围、中心 tile 分布及事件 hash 见
[events_manifest.json](hip_psf_replay_2026-09-07/events_manifest.json)。三种真实输入的
support 均为 45.84777786185942px;变化 support/wing/边缘另由合成 fixture 覆盖。
分散对照只平移完整处于画面内部的事件中心,保留 fractional phase(浮点平移舍入以内)、
flux 和 support;本来裁切的事件不移动。每次都重新计算并断言实际 event–pixel 贡献数
完全不变:真实和分散的 65,536 事件均为 **432,818,979** 个贡献。没有以裁切减少工作量。
## 原型与 ownership
每 chunk≤16,384 events。CPU 按 cache 遍历 support 的完整包围矩形建立所有相交 tile
引用,PSF wings 可以进入多个 tile;GPU 用原来的圆形行范围再筛选,继续四点 phase
cache 插值和 double RGB。每个像素由一个线程累计,不使用全局 double atomic。
第一次朴素实现反复计算 phase、sqrt/行范围,4,096 普通事件的回放约 25–27 ms,慢于
atomic。第二版为每个 chunk 在 GPU 预计算 phase、颜色×flux 和行范围,然后供像素线程复用。
分散对照随后触发 128 MiB 部分和限制,进程已停止。最终版让≤256 引用的单列表 tile
直接写回独占 HDR 像素;只有长列表分段才写部分和,第二阶段按固定 task 次序相加。
这种修正保持内存上限,避免为整屏稀疏 tiles 分配一幅额外 double HDR。
设备上固定复用:references 32 MiB、tasks 2 MiB、starts 128 KiB、partials 128 MiB,
以及最多 16,384 事件的 Prepared/行范围约 12.875 MiB;合计额外预留 **175 MiB**。
超出引用/任务/部分和容量立即报错,无隐式切换。全部缓冲由单个实验 sink 持有,单 stream
顺序消费、同步后复用;每个 partial 元素都被覆盖写入,不需要 memset。最终样本实际
scratch 使用峰值约 37.26 MiB,整个 CPU-reference+GPU 进程 RSS 最大 717,172 KiB。
预留量和实际用量不同,RSS 包含 CPU HDR/reference/cache,不能当作生产额外 RAM。
## 独立最终回放结果
下表是 `replay_wall` 中位数(ms,三次):包含 scratch 分配、分桶、上传、预计算、累积、
合并、下载、清理,排除公共 sink/cache 初始化和 CPU reference。日志另报 `complete_replay`
(加公共 GPU sink 创建)、`CPU_reference`、cache build、完整 `PROCESS_WALL`,避免混淆。
| 输入 | 实际 events | atomic | tile16 | tile32 |
| --- | ---: | ---: | ---: | ---: |
| 普通 | 12,765 | 26.423 | 18.511 | 19.286 |
| 银心视场 | 16,384 | 31.803 | 22.621 | 23.247 |
| 强放大 | 16,384 | 26.536 | 23.814 | 25.388 |
| 银心视场 | 65,536 | 104.107 | 69.823 | 73.093 |
| 同等贡献分散对照 | 65,536 | 85.302 | 104.389 | 79.899 |
含公共 GPU 创建的 65,536 密集回放为 137.111 / 102.323 / 105.949 ms。
强放大 tile32 回放范围 22.801–29.410 ms,atomic 25.932–27.395 ms;三次样本不足以
证明这里的稳定提升。完整数值、范围和全部重复见 [summary.log](hip_psf_replay_2026-09-07/summary.log)
与 `final_*.log`,由 [final_cases.py](hip_psf_replay_2026-09-07/final_cases.py) 串行生成。
分阶段日志同时记录实际贡献吞吐量。atomic 上传/kernel/download 使用 HIP event;
候选分桶为 CPU wall,prepare/accumulation/merge 为包含 launch+stream sync 的 host wall。
它们不能拿来做精确的纯 kernel 周期归因,完整回放 wall 才是算法比较依据。
分散 tile16 的分桶本身约数十 ms,足以抵消其累积优势。
[编译器资源记录](hip_psf_replay_2026-09-07/device_resources.log) 显示 atomic kernel
62 VGPR,prepare 37,tile accumulation 21,merge 18,private segment 均为 0。
生成的 atomic 代码仍有三个 `global_atomic_cmpswap_b64` 循环;候选不需要它们。
这不是运行时 cache/occupancy/FP64 counter 测量,不能据此分摊 atomic contention 的比例。
没有使用降低 HDR 精度、近似黑体颜色或改变 min-Y/tail 的方法。
## CPU producer 独立测量
诊断 consumer 在正常查询、inverse mapping、频移、黑体积分与 prepare/classification
之后,仅计数与计算摘要。输出明确标记 `DIAGNOSTIC ONLY, no HDR`。
parallel 模式每 worker 计数/摘要独占;汇总 checksum 与事件顺序无关,串行捕获仍保留顺序。
indexed 模式从同一有界 CSV 预构建原生一度 tile 索引,worker 查询前已完全只读,不执行 I/O。
为了比较完整相同工作而不受事件上限/调度停止次序影响,银心诊断 triangle 范围缩为
`[0,40151)`,其他仍 `[0,130882)`。所有以下运行均未触顶,四种模式逐项核对
cached/wing/direct/discarded/events 和 checksum 完全一致。各三次中位数:
| 输入 | events | memory/1 worker | memory/16 | indexed/1 | indexed/16 |
| --- | ---: | ---: | ---: | ---: | ---: |
| 普通 | 12,765 | 2.8123 s | 0.3502 s | 0.0729 s | 0.0125 s |
| 银心视场 | 16,895 | 1.1472 s | 0.1383 s | 0.0535 s | 0.00986 s |
| 强放大 | 16,454 | 1.3845 s | 0.1493 s | 0.6836 s | 0.0751 s |
CSV 全扫描明显夸大查询成本;生产判断应使用 indexed 列。强放大子集遍历大量分散 triangle,
其独立 producer 时间在这一小输入上高于 GPU 回放,说明进一步加速 GPU 未必改善同等比例的
端到端时间。这不是全天 CPU 下限,也不能与另一事件数量的回放直接相减。
未修改黑体积分;没有把 `summed generation / workers` 当作独立计时。
## 正确性与失败记录
- 全部真实回放、分散对照和最终 45 次独立复测通过 finite/double HDR 检验。
- [边界 fixture](hip_psf_replay_2026-09-07/fixture_generate.log):32,771 events,33 wing-clipped,
exact/intermediate phases、屏幕内外、热点、三 chunk/缓冲复用。atomic、tile16、tile32
均覆盖中途 finish/download → CPU direct → upload → 继续累积。
- 全部最终+边界最大 `max_abs=5.96856e-11`、`max_rel=5.98529e-13`;最坏 RGB 总通量
相对差≤2.83419e-14,Y≤1.15193e-14。沿用旧 replay 的 abs/rel<1e-10,另增加总 RGB/Y
相对误差≤1e-10 的检查,没有为结果放宽门槛;现有生产 primitive 的 rel≤1e-12 也通过。
- [捕获/索引诊断回归](hip_psf_replay_2026-09-07/capture_indexed_regression.log)通过:真实 mixed
classification cached=2/direct=1,min-Y 场 discarded=3;串行/并行/索引摘要一致;验证
event cap、非法范围、拒绝覆盖已有文件。未用提高 min-Y 代替 producer 测量。
- [HIP primitive](hip_psf_replay_2026-09-07/hip_primitive.log)、
[Minkowski mixed/min-Y integration](hip_psf_replay_2026-09-07/minkowski_integration.log)通过。
- [Schwarzschild CPU](hip_psf_replay_2026-09-07/schwarzschild_cpu.log) /
[HIP](hip_psf_replay_2026-09-07/schwarzschild_hip.log)同一 8,192 星子集分类一致;
[24,883,200 个 FITS float32 样本完全一致](hip_psf_replay_2026-09-07/schwarzschild_hdr.log)。
此处测试的是保留的生产路径;tile 原型的 double 正确性由回放验证,不冒称已接入 renderer。
- [`make -j1 test`](hip_psf_replay_2026-09-07/cpu_regression.log)通过(33.44 s)。
保留三类早期非零退出:沙箱未暴露 GPU、v2 分散输入的 scratch 超限、读取器误拒绝合法
wing-clipped support。后者的修复保留 event 的物理 support,仅在实际遍历时限制 cache 范围。
未删失败日志,未在任何失败后不加分析自动扩大测试规模。
## 最小复现
从仓库根目录先按 [build_commands.txt](hip_psf_replay_2026-09-07/build_commands.txt) 构建。
固定输入已随报告保留;原大 catalog/lens map hash 在 manifest。已有日志拒绝覆盖,重复
运行请使用新标签和新的事件输出路径:
```sh
python3 benchmarks/hip_psf_replay_2026-09-07/run.py repeat_capture 60 \
build/Release/capture_psf \
output/lens/schwarzschild_galactic_center_R100_45deg_16_4_4k_.grlens \
benchmarks/hip_psf_replay_2026-09-07/center.csv \
0 130882 65536 /tmp/gr-psf-repeat.events 1e13 1e8 0 0 2
python3 benchmarks/hip_psf_replay_2026-09-07/run.py repeat_atomic 45 \
build/Release/replay_psf /tmp/gr-psf-repeat.events 65536 atomic
python3 benchmarks/hip_psf_replay_2026-09-07/run.py repeat_tile16 45 \
build/Release/replay_psf /tmp/gr-psf-repeat.events 65536 16
python3 benchmarks/hip_psf_replay_2026-09-07/run.py repeat_tile32 45 \
build/Release/replay_psf /tmp/gr-psf-repeat.events 65536 32
```
以上是重跑示例,`repeat_*` 标签本次未执行;实际执行命令逐条保存在各原始日志。
@@ -0,0 +1 @@
__pycache__/
@@ -0,0 +1,41 @@
# 回放原始证据
结果与限制见 [上级报告](../hip_psf_replay_2026-09-07.md)。
- `build_commands.txt` / `build*.log`:构建命令与完整编译输出。
- `input_manifest.json`:真实 catalog 的来源、均匀抽样规则、输入 hash;固定 CSV 随本目录保留。
- `capture_*.log`:输入、triangle 范围、magnification 筛选、实际分类/事件数、停止位置与 producer 时间。
- `*.events`:版本化文本文件,头含尺寸/实际事件数/PSF 参数,后续为 7 个 round-trip double。
文件名后缀表示请求上限,实际数量以头部为准,不能假定所有样本都有 65,536 项。
- `events_manifest.json`:事件文件 hash、实际 bbox/flux/support 分布、32px 中心分桶统计。
- `final_*.log`:构建完成后的独立性能对照;每种输入/算法三次。`v1/v2/v3` 属于探索记录。
- `producer_*.log`:同一有限输入上的独立 producer 测量,memory 与 indexed-subset 必须分开解释。
- `boundary_validated_*.log`:合成边界/热点/wing/multi-chunk/CPU direct 恢复的 double HDR 对照。
- `*_regression.log` / `*_integration.log` / `schwarzschild_*.log`:集成和回归输出。
- `device_resources.log`:编译器资源报告,不是运行时性能计数器。
- `full_production_adaptive_user.log`:用户执行的旧串行分桶全天 adaptive 原始终端输出;命令和
HIP 计时在日志内,未嵌入执行时 binary/Git hash,不能当作 runner 的 provenance。
- `full_parallel_prebin_adaptive_user_2026-09-13.log`:新版并行预分桶全天运行的用户完整附件原文。
- `full_atomic_redo_user_2026-09-13_excerpt.log`:stash 回 HEAD 重编译后的 atomic 复测结尾摘录,
不是完整日志;该 HEAD 忽略命令中的 adaptive 环境变量。两份新记录均缺少运行时 binary hash。
当前方向为搁置旧 adaptive 慢因追溯、优化新版生产管线,240 s/张为待验证目标,详见上级报告。
- `parallel_prebin_*.log`:producer 私有预分桶的有界回放、混合 direct 边界、HIP primitive、
小型真实 renderer 与可选 dummy support 诊断。`parallel_prebin_16workers_128.log` 是
OpenMP reduction 初值错误导致的零提交无效运行;有效数字以 `*_validated.log` 为准。
- `full_dummy_support_user.log`:用户运行的真实全天 dummy support 分位数与第一遍计数原始输出;
没有 GPU/HDR,也没有在日志中记录执行时 binary hash。
- `make_hotspot_fixture.py` / `center_hotspot*.events` / `hotspot_*.log`:从捕获的真实事件
保留颜色、flux、support 和亚像素余数,重排整数像素位置构成的明确反事实热点,验证
聚合 references/tile/list 指标的预测力,不作为物理星像。
- `busy_center_*.log`:同一进程中额外 15 个 CPU 忙等线程的有界 HIP 回放对照。
`run.py` 对测试进程使用独占锁,启动前检查已有 renderer/replay 进程,单独进程组限时;
超时后 kill 并 wait/reap,任何失败停止后续执行。日志用独占创建,重跑应使用新的输出目录
或新日志标签,不能覆盖本次证据。每个日志记录命令、超时、Git hash、直接执行的 binary hash、
原始 stdout/stderr、进程 wall 和退出码。Python 集成脚本涉及的 binary hash 另在 metadata 中记录。
用户粘贴的完整全天 adaptive 输出是上述例外,按原文另存并保留事后 binary hash 与
输出图像的独立校验,不把事后 hash 误称为运行时记录。
初次沙箱探测没有 ROCm 设备;宿主运行成功。`atomic_first.log` 不是 GPU 硬件故障证据。
`v2_disperse_*_16_0.log` 的 scratch 超限后已停止,修正的是单列表 tile 的 ownership,未提高上限。
`boundary_atomic.log` 是合法 wing-clipped 事件被读取器误拒绝,随后保留物理 support 后通过。
@@ -0,0 +1,8 @@
COMMAND OMP_NUM_THREADS=16 build/Release/replay_psf benchmarks/hip_psf_replay_2026-09-07/boundary.events 32771 adaptive mixed
TIMEOUT 45s
GIT 11e703e33dffb1ff168ba11dd922e68b448116b9
BINARY_SHA256 121b85ade12680929cf0f560e04485e2ad3d8a56ff9dcbba950a323f840c5151
PSF cache ready: 64x64 phases, radius 47 px, relative tail 1e-08, tail abs 1e-06, boundary 1e-07, build 0.691 s
device=AMD Radeon RX 9070 arch=gfx1201 events=32771 frame=128x96 mode=adaptive distribution=fixture-mixed-direct contributions=142133685 CPU_reference=0.271268845 create=0.036700010
complete_replay=0.060321093 replay_wall=0.023621082 select=0.000166893 bin=0.002514124 upload=0.000438220 prepare=0.000985861 accumulation=0.016374943 merge=0.000088215 download=0.000132840 cleanup=0.000163078 events_s=1387362.339 contributions_s=6017238463.474 center_tiles=26 tile_chunks=2 atomic_chunks=1 refs=829409 tasks=3275 scratch_used_peak=25249440 scratch_device_reserved=184549376 RSS_KiB=319696 max_abs=5.9685589803848416e-11 max_rel=5.9595772318269279e-13 flux_R=2.8323267191886195e-14 flux_G=-5.5281251977629701e-15 flux_B=9.6507636840237455e-15 flux_Y=1.1503592402127278e-14
PROCESS_WALL 1.117062220 EXIT 0
@@ -0,0 +1,7 @@
COMMAND OMP_NUM_THREADS=16 make -B -j1 PSF_BACKEND=hip 'HIP_CXXFLAGS=--offload-arch=gfx1201 -std=c++17 -O2 -Wall -Wextra -Wpedantic' hip-psf-replay
TIMEOUT 60s
GIT 11e703e33dffb1ff168ba11dd922e68b448116b9
cc -DENABLE_PNG -DFRAME_PSF_EVENT_SINK=1 -DPSF_BACKEND_HIP -DSPACETIME_MINKOWSKI -std=c11 -march=native -pipe -Wall -Wextra -Wpedantic -O2 -DNDEBUG -fopenmp -Isrc -MMD -MP -c src/optics.c -o build/Release/obj/minkowski/standard_sink1_hip/src/optics.o
mkdir -p build/Release
hipcc --offload-arch=gfx1201 -std=c++17 -O2 -Wall -Wextra -Wpedantic -fopenmp -Isrc -x hip tests/replay_psf.hip -x none build/Release/obj/minkowski/standard_sink1_hip/src/optics.o -lm -lpng -o build/Release/replay_psf
PROCESS_WALL 1.266911305 EXIT 0
@@ -0,0 +1,7 @@
COMMAND OMP_NUM_THREADS=16 build/Release/replay_psf benchmarks/hip_psf_replay_2026-09-07/center_65536.events 65536 adaptive
TIMEOUT 45s
GIT 11e703e33dffb1ff168ba11dd922e68b448116b9
BINARY_SHA256 121b85ade12680929cf0f560e04485e2ad3d8a56ff9dcbba950a323f840c5151
no ROCm-capable device is detected
PSF cache ready: 64x64 phases, radius 47 px, relative tail 1e-08, tail abs 1e-06, boundary 1e-07, build 0.667 s
PROCESS_WALL 1.667466220 EXIT 1
@@ -0,0 +1,8 @@
COMMAND OMP_NUM_THREADS=16 build/Release/replay_psf benchmarks/hip_psf_replay_2026-09-07/center_65536.events 65536 adaptive
TIMEOUT 45s
GIT 11e703e33dffb1ff168ba11dd922e68b448116b9
BINARY_SHA256 121b85ade12680929cf0f560e04485e2ad3d8a56ff9dcbba950a323f840c5151
PSF cache ready: 64x64 phases, radius 47 px, relative tail 1e-08, tail abs 1e-06, boundary 1e-07, build 0.679 s
device=AMD Radeon RX 9070 arch=gfx1201 events=65536 frame=3840x2160 mode=adaptive distribution=captured contributions=432818979 CPU_reference=0.824280024 create=0.050632000
complete_replay=0.121458054 replay_wall=0.070826054 select=0.000172138 bin=0.007817984 upload=0.001097918 prepare=0.001653194 accumulation=0.051779747 merge=0.000582457 download=0.004020136 cleanup=0.000195980 events_s=925309.214 contributions_s=6111013629.616 center_tiles=35 tile_chunks=4 atomic_chunks=0 refs=2973775 tasks=11935 scratch_used_peak=35382764 scratch_device_reserved=184549376 RSS_KiB=713084 max_abs=2.7105054312137611e-19 max_rel=1.9611487209714066e-14 flux_R=-2.8081518355845397e-17 flux_G=4.7080671715585728e-17 flux_B=5.9271432925574641e-17 flux_Y=2.0330567515243999e-17
PROCESS_WALL 1.968497664 EXIT 0
@@ -0,0 +1,8 @@
COMMAND OMP_NUM_THREADS=16 build/Release/replay_psf benchmarks/hip_psf_replay_2026-09-07/center_65536.events 65536 adaptive
TIMEOUT 45s
GIT 11e703e33dffb1ff168ba11dd922e68b448116b9
BINARY_SHA256 121b85ade12680929cf0f560e04485e2ad3d8a56ff9dcbba950a323f840c5151
PSF cache ready: 64x64 phases, radius 47 px, relative tail 1e-08, tail abs 1e-06, boundary 1e-07, build 0.662 s
device=AMD Radeon RX 9070 arch=gfx1201 events=65536 frame=3840x2160 mode=adaptive distribution=captured contributions=432818979 CPU_reference=0.812095881 create=0.036637783
complete_replay=0.104471922 replay_wall=0.067834139 select=0.000179052 bin=0.007610083 upload=0.001078129 prepare=0.001619816 accumulation=0.051049709 merge=0.000552416 download=0.004829631 cleanup=0.000203133 events_s=966121.205 contributions_s=6380547998.522 center_tiles=35 tile_chunks=4 atomic_chunks=0 refs=2973775 tasks=11935 scratch_used_peak=35382764 scratch_device_reserved=184549376 RSS_KiB=713056 max_abs=2.7105054312137611e-19 max_rel=1.9611487209714066e-14 flux_R=-2.8081518355845397e-17 flux_G=4.7080671715585728e-17 flux_B=5.9271432925574641e-17 flux_Y=2.0330567515243999e-17
PROCESS_WALL 1.918472017 EXIT 0
@@ -0,0 +1,8 @@
COMMAND OMP_NUM_THREADS=16 build/Release/replay_psf benchmarks/hip_psf_replay_2026-09-07/center_65536.events 65536 adaptive
TIMEOUT 45s
GIT 11e703e33dffb1ff168ba11dd922e68b448116b9
BINARY_SHA256 121b85ade12680929cf0f560e04485e2ad3d8a56ff9dcbba950a323f840c5151
PSF cache ready: 64x64 phases, radius 47 px, relative tail 1e-08, tail abs 1e-06, boundary 1e-07, build 0.664 s
device=AMD Radeon RX 9070 arch=gfx1201 events=65536 frame=3840x2160 mode=adaptive distribution=captured contributions=432818979 CPU_reference=0.806693077 create=0.036690950
complete_replay=0.103733778 replay_wall=0.067042828 select=0.000176907 bin=0.007581234 upload=0.001075745 prepare=0.001624107 accumulation=0.051224947 merge=0.000552177 download=0.004083938 cleanup=0.000195026 events_s=977524.403 contributions_s=6455858060.497 center_tiles=35 tile_chunks=4 atomic_chunks=0 refs=2973775 tasks=11935 scratch_used_peak=35382764 scratch_device_reserved=184549376 RSS_KiB=713112 max_abs=2.7105054312137611e-19 max_rel=1.9611487209714066e-14 flux_R=-2.8081518355845397e-17 flux_G=4.7080671715585728e-17 flux_B=5.9271432925574641e-17 flux_Y=2.0330567515243999e-17
PROCESS_WALL 1.918304047 EXIT 0
@@ -0,0 +1,38 @@
COMMAND OMP_NUM_THREADS=16 make -j1 test
TIMEOUT 90s
GIT 11e703e33dffb1ff168ba11dd922e68b448116b9
make SPACETIME=minkowski ENABLE_HDR=1 backend
make[1]: Entering directory '/home/wyj/Code/C/GR_4d_raytracing'
cc -O2 -DNDEBUG -fopenmp build/Release/obj/minkowski/hdr_sink1_cpu/src/catalog.o build/Release/obj/minkowski/hdr_sink1_cpu/src/frame.o build/Release/obj/minkowski/hdr_sink1_cpu/src/geodesic.o build/Release/obj/minkowski/hdr_sink1_cpu/src/lens_map.o build/Release/obj/minkowski/hdr_sink1_cpu/src/movie.o build/Release/obj/minkowski/hdr_sink1_cpu/src/observer.o build/Release/obj/minkowski/hdr_sink1_cpu/src/observer_track.o build/Release/obj/minkowski/hdr_sink1_cpu/src/optics.o build/Release/obj/minkowski/hdr_sink1_cpu/src/ray.o build/Release/obj/minkowski/hdr_sink1_cpu/src/spacetime_common.o build/Release/obj/minkowski/hdr_sink1_cpu/src/spacetime_minkowski.o build/Release/obj/minkowski/hdr_sink1_cpu/src/main.o -lm -lpng -lcfitsio -o build/Release/minkowski_sky
make[1]: Leaving directory '/home/wyj/Code/C/GR_4d_raytracing'
mkdir -p /tmp/gr_psf_event_sink_reference
OMP_NUM_THREADS=16 build/Release/minkowski_sky --catalog assets/sky_grid_5deg.csv --output /tmp/gr_psf_event_sink_reference/minkowski_ra1_dec1_640x360.png --hdr-output --width 640 --height 360 --fov-deg 30 --look-ra-deg 1 --look-dec-deg 1 --exposure 0.1 --observer-radius 30 --observer-velocity 0 0 0 --psf-fwhm-pixels 2.7 --psf-moffat-beta 4.5 --max-magnification 1e300 --max-cache-psf-flux 1 --psf-relative-tail 1e-8 --psf-min-y 0 --coarse-cell-pixels 16 --refine-max-level 0 --refine-angle-abs-deg 0.001 --refine-angle-rel 0.1 --refine-jacobian-min 1e-3 --refine-min-edge-pixels 0.5 --refine-min-area-pixels2 0.25 --catalog-load-workers 4
PSF cache ready: 64x64 phases, radius 47 px, relative tail 1e-08, tail abs 1e-06, boundary 1e-07, build 0.667 s
Rendered 35 images from 5654 catalog stars to /tmp/gr_psf_event_sink_reference/minkowski_ra1_dec1_640x360.png (ok)
PSF splats: cached 35, cached wing-clipped 0, direct fallbacks 0, discarded below min-Y 0
python3 scripts/fits_floatdiff.py tests/data/psf_event_sink_reference/minkowski_ra1_dec1_640x360_HDR.fits /tmp/gr_psf_event_sink_reference/minkowski_ra1_dec1_640x360_HDR.fits
floatdiff: shape=(640, 360, 3) samples=691200 mismatches=0 max_abs=0 max_rel=0 worst_sample=0
make SPACETIME=schwarzschild ENABLE_HDR=1 backend
make[1]: Entering directory '/home/wyj/Code/C/GR_4d_raytracing'
cc -O2 -DNDEBUG -fopenmp build/Release/obj/schwarzschild/hdr_sink1_cpu/src/catalog.o build/Release/obj/schwarzschild/hdr_sink1_cpu/src/frame.o build/Release/obj/schwarzschild/hdr_sink1_cpu/src/geodesic.o build/Release/obj/schwarzschild/hdr_sink1_cpu/src/lens_map.o build/Release/obj/schwarzschild/hdr_sink1_cpu/src/movie.o build/Release/obj/schwarzschild/hdr_sink1_cpu/src/observer.o build/Release/obj/schwarzschild/hdr_sink1_cpu/src/observer_track.o build/Release/obj/schwarzschild/hdr_sink1_cpu/src/optics.o build/Release/obj/schwarzschild/hdr_sink1_cpu/src/ray.o build/Release/obj/schwarzschild/hdr_sink1_cpu/src/spacetime_common.o build/Release/obj/schwarzschild/hdr_sink1_cpu/src/spacetime_schwarzschild.o build/Release/obj/schwarzschild/hdr_sink1_cpu/src/main.o -lm -lpng -lcfitsio -o build/Release/schwarzschild_sky
make[1]: Leaving directory '/home/wyj/Code/C/GR_4d_raytracing'
OMP_NUM_THREADS=16 build/Release/schwarzschild_sky --catalog assets/sky_grid_5deg.csv --output /tmp/gr_psf_event_sink_reference/schwarzschild_ra1_dec1_fov60_640x360.png --hdr-output --width 640 --height 360 --fov-deg 60 --look-ra-deg 1 --look-dec-deg 1 --exposure 0.1 --observer-radius 30 --observer-velocity 0 0 0 --psf-fwhm-pixels 2.7 --psf-moffat-beta 4.5 --max-magnification 1e300 --max-cache-psf-flux 1 --psf-relative-tail 1e-8 --psf-min-y 0 --coarse-cell-pixels 16 --refine-max-level 0 --refine-angle-abs-deg 0.001 --refine-angle-rel 0.1 --refine-jacobian-min 1e-3 --refine-min-edge-pixels 0.5 --refine-min-area-pixels2 0.25 --catalog-load-workers 4
PSF cache ready: 64x64 phases, radius 47 px, relative tail 1e-08, tail abs 1e-06, boundary 1e-07, build 0.665 s
Rendered 5206 images from 5654 catalog stars to /tmp/gr_psf_event_sink_reference/schwarzschild_ra1_dec1_fov60_640x360.png (ok)
PSF splats: cached 5206, cached wing-clipped 0, direct fallbacks 0, discarded below min-Y 0
python3 scripts/fits_floatdiff.py tests/data/psf_event_sink_reference/schwarzschild_ra1_dec1_fov60_640x360_HDR.fits /tmp/gr_psf_event_sink_reference/schwarzschild_ra1_dec1_fov60_640x360_HDR.fits
floatdiff: shape=(640, 360, 3) samples=691200 mismatches=0 max_abs=0 max_rel=0 worst_sample=0
./build/Release/test_observer_minkowski
coordinate-camera regression passed
./build/Release/test_observer_schwarzschild
coordinate-camera regression passed
./build/Release/test_geodesic
./build/Release/test_frame
./build/Release/test_schwarzschild
./build/Release/test_observer_track
./build/Release/test_catalog_prefetch
python3 tests/test_camera_cli.py build/Release
minkowski: CLI checks passed; single/movie PNG identical, map max error 0
schwarzschild: movie lens map identical with 1, 4 and 16 threads
schwarzschild: CLI checks passed; single/movie PNG identical, map max error 4.44e-16
PROCESS_WALL 26.018675067 EXIT 0
@@ -0,0 +1,8 @@
COMMAND OMP_NUM_THREADS=16 build/Release/replay_psf benchmarks/hip_psf_replay_2026-09-07/center_65536.events 65536 adaptive disperse
TIMEOUT 45s
GIT 11e703e33dffb1ff168ba11dd922e68b448116b9
BINARY_SHA256 121b85ade12680929cf0f560e04485e2ad3d8a56ff9dcbba950a323f840c5151
PSF cache ready: 64x64 phases, radius 47 px, relative tail 1e-08, tail abs 1e-06, boundary 1e-07, build 0.682 s
device=AMD Radeon RX 9070 arch=gfx1201 events=65536 frame=3840x2160 mode=adaptive distribution=synthetic-phase-preserving-dispersal contributions=432818979 CPU_reference=1.491110802 create=0.037611008
complete_replay=0.117703199 replay_wall=0.080092192 select=0.000455141 bin=0.000000000 upload=0.000191523 prepare=0.000000000 accumulation=0.075263899 merge=0.000000000 download=0.004099738 cleanup=0.000207186 events_s=818257.044 contributions_s=5404009677.272 center_tiles=26986 tile_chunks=0 atomic_chunks=4 refs=0 tasks=0 scratch_used_peak=0 scratch_device_reserved=184549376 RSS_KiB=705516 max_abs=3.3881317890172014e-21 max_rel=8.4356460581299069e-16 flux_R=1.2382136141425945e-18 flux_G=1.811942792627668e-18 flux_B=1.5829277137138293e-18 flux_Y=1.5978644712371554e-18
PROCESS_WALL 2.620178348 EXIT 0
@@ -0,0 +1,8 @@
COMMAND OMP_NUM_THREADS=16 build/Release/replay_psf benchmarks/hip_psf_replay_2026-09-07/center_65536.events 65536 adaptive disperse
TIMEOUT 45s
GIT 11e703e33dffb1ff168ba11dd922e68b448116b9
BINARY_SHA256 121b85ade12680929cf0f560e04485e2ad3d8a56ff9dcbba950a323f840c5151
PSF cache ready: 64x64 phases, radius 47 px, relative tail 1e-08, tail abs 1e-06, boundary 1e-07, build 0.733 s
device=AMD Radeon RX 9070 arch=gfx1201 events=65536 frame=3840x2160 mode=adaptive distribution=synthetic-phase-preserving-dispersal contributions=432818979 CPU_reference=1.488748074 create=0.038790941
complete_replay=0.121706009 replay_wall=0.082915068 select=0.000465870 bin=0.000000000 upload=0.000181281 prepare=0.000000000 accumulation=0.077964972 merge=0.000000000 download=0.004236780 cleanup=0.000192881 events_s=790399.162 contributions_s=5220028049.767 center_tiles=26986 tile_chunks=0 atomic_chunks=4 refs=0 tasks=0 scratch_used_peak=0 scratch_device_reserved=184549376 RSS_KiB=705940 max_abs=3.3881317890172014e-21 max_rel=8.4356460581299069e-16 flux_R=1.377382799700594e-18 flux_G=1.939309838343059e-18 flux_B=2.0425953472603454e-18 flux_Y=1.7396938046841301e-18
PROCESS_WALL 2.720085292 EXIT 0
@@ -0,0 +1,8 @@
COMMAND OMP_NUM_THREADS=16 build/Release/replay_psf benchmarks/hip_psf_replay_2026-09-07/center_65536.events 65536 adaptive disperse
TIMEOUT 45s
GIT 11e703e33dffb1ff168ba11dd922e68b448116b9
BINARY_SHA256 121b85ade12680929cf0f560e04485e2ad3d8a56ff9dcbba950a323f840c5151
PSF cache ready: 64x64 phases, radius 47 px, relative tail 1e-08, tail abs 1e-06, boundary 1e-07, build 0.671 s
device=AMD Radeon RX 9070 arch=gfx1201 events=65536 frame=3840x2160 mode=adaptive distribution=synthetic-phase-preserving-dispersal contributions=432818979 CPU_reference=1.462161779 create=0.037038088
complete_replay=0.115585089 replay_wall=0.078547001 select=0.000451088 bin=0.000000000 upload=0.000188241 prepare=0.000000000 accumulation=0.073739567 merge=0.000000000 download=0.004098460 cleanup=0.000214100 events_s=834353.944 contributions_s=5510318333.269 center_tiles=26986 tile_chunks=0 atomic_chunks=4 refs=0 tasks=0 scratch_used_peak=0 scratch_device_reserved=184549376 RSS_KiB=705560 max_abs=3.3881317890172014e-21 max_rel=8.4356460581299069e-16 flux_R=1.4160413575526434e-18 flux_G=1.6738012163520145e-18 flux_B=2.0518958448496421e-18 flux_Y=1.5923904683351809e-18
PROCESS_WALL 2.568827678 EXIT 0
@@ -0,0 +1,6 @@
COMMAND OMP_NUM_THREADS=16 build/Release/test_hip_psf
TIMEOUT 45s
GIT 11e703e33dffb1ff168ba11dd922e68b448116b9
BINARY_SHA256 39cd23b6d9aef423ba97ba0085b9a411a47a49e4b66cf59197f471de419ef9b8
HIP PSF cache comparison: max_abs=2.8421709430404007e-14 max_rel=7.5319184269262976e-16
PROCESS_WALL 0.816928134 EXIT 0
@@ -0,0 +1,8 @@
COMMAND OMP_NUM_THREADS=16 build/Release/replay_psf benchmarks/hip_psf_replay_2026-09-07/lensed_16384.events 16384 adaptive
TIMEOUT 45s
GIT 11e703e33dffb1ff168ba11dd922e68b448116b9
BINARY_SHA256 121b85ade12680929cf0f560e04485e2ad3d8a56ff9dcbba950a323f840c5151
PSF cache ready: 64x64 phases, radius 47 px, relative tail 1e-08, tail abs 1e-06, boundary 1e-07, build 0.714 s
device=AMD Radeon RX 9070 arch=gfx1201 events=16384 frame=3840x2160 mode=adaptive distribution=captured contributions=107949448 CPU_reference=0.213827133 create=0.041162014
complete_replay=0.062693119 replay_wall=0.021531105 select=0.000054836 bin=0.003102064 upload=0.000283003 prepare=0.000669003 accumulation=0.012633085 merge=0.000146866 download=0.004084578 cleanup=0.000169992 events_s=760945.617 contributions_s=5013651077.913 center_tiles=359 tile_chunks=1 atomic_chunks=0 refs=740784 tasks=5251 scratch_used_peak=31785268 scratch_device_reserved=184549376 RSS_KiB=710652 max_abs=5.3290705182007514e-15 max_rel=3.8619817275125971e-15 flux_R=-5.5779263000586243e-18 flux_G=-2.9489947183383731e-19 flux_B=4.3765760168230462e-18 flux_Y=-2.1608907287060103e-18
PROCESS_WALL 1.268419138 EXIT 0
@@ -0,0 +1,8 @@
COMMAND OMP_NUM_THREADS=16 build/Release/replay_psf benchmarks/hip_psf_replay_2026-09-07/lensed_16384.events 16384 adaptive
TIMEOUT 45s
GIT 11e703e33dffb1ff168ba11dd922e68b448116b9
BINARY_SHA256 121b85ade12680929cf0f560e04485e2ad3d8a56ff9dcbba950a323f840c5151
PSF cache ready: 64x64 phases, radius 47 px, relative tail 1e-08, tail abs 1e-06, boundary 1e-07, build 0.667 s
device=AMD Radeon RX 9070 arch=gfx1201 events=16384 frame=3840x2160 mode=adaptive distribution=captured contributions=107949448 CPU_reference=0.214478970 create=0.036618948
complete_replay=0.058495998 replay_wall=0.021877050 select=0.000056028 bin=0.003196001 upload=0.000288010 prepare=0.000689983 accumulation=0.012602091 merge=0.000144958 download=0.004350181 cleanup=0.000192165 events_s=748912.660 contributions_s=4934369397.489 center_tiles=359 tile_chunks=1 atomic_chunks=0 refs=740784 tasks=5251 scratch_used_peak=31785268 scratch_device_reserved=184549376 RSS_KiB=710384 max_abs=5.3290705182007514e-15 max_rel=3.8619817275125971e-15 flux_R=-5.5779263000586243e-18 flux_G=-2.9489947183383731e-19 flux_B=4.3765760168230462e-18 flux_Y=-2.1608907287060103e-18
PROCESS_WALL 1.216200115 EXIT 0
@@ -0,0 +1,8 @@
COMMAND OMP_NUM_THREADS=16 build/Release/replay_psf benchmarks/hip_psf_replay_2026-09-07/lensed_16384.events 16384 adaptive
TIMEOUT 45s
GIT 11e703e33dffb1ff168ba11dd922e68b448116b9
BINARY_SHA256 121b85ade12680929cf0f560e04485e2ad3d8a56ff9dcbba950a323f840c5151
PSF cache ready: 64x64 phases, radius 47 px, relative tail 1e-08, tail abs 1e-06, boundary 1e-07, build 0.664 s
device=AMD Radeon RX 9070 arch=gfx1201 events=16384 frame=3840x2160 mode=adaptive distribution=captured contributions=107949448 CPU_reference=0.214956999 create=0.038650990
complete_replay=0.060267925 replay_wall=0.021616936 select=0.000054121 bin=0.003103971 upload=0.000282049 prepare=0.000669956 accumulation=0.012650013 merge=0.000149012 download=0.004124364 cleanup=0.000187874 events_s=757924.259 contributions_s=4993744226.675 center_tiles=359 tile_chunks=1 atomic_chunks=0 refs=740784 tasks=5251 scratch_used_peak=31785268 scratch_device_reserved=184549376 RSS_KiB=710600 max_abs=5.3290705182007514e-15 max_rel=3.8619817275125971e-15 flux_R=-5.5779263000586243e-18 flux_G=-2.9489947183383731e-19 flux_B=4.3765760168230462e-18 flux_Y=-2.1608907287060103e-18
PROCESS_WALL 1.216335608 EXIT 0
@@ -0,0 +1,8 @@
COMMAND OMP_NUM_THREADS=16 build/Release/replay_psf benchmarks/hip_psf_replay_2026-09-07/ordinary_16384.events 12765 adaptive
TIMEOUT 45s
GIT 11e703e33dffb1ff168ba11dd922e68b448116b9
BINARY_SHA256 121b85ade12680929cf0f560e04485e2ad3d8a56ff9dcbba950a323f840c5151
PSF cache ready: 64x64 phases, radius 47 px, relative tail 1e-08, tail abs 1e-06, boundary 1e-07, build 0.683 s
device=AMD Radeon RX 9070 arch=gfx1201 events=12765 frame=3840x2160 mode=adaptive distribution=captured contributions=84287857 CPU_reference=0.161495924 create=0.036530018
complete_replay=0.054877043 replay_wall=0.018347025 select=0.000042915 bin=0.001914978 upload=0.000241995 prepare=0.000617027 accumulation=0.009811878 merge=0.000136137 download=0.005169831 cleanup=0.000195026 events_s=695753.129 contributions_s=4594088544.521 center_tiles=8 tile_chunks=1 atomic_chunks=0 refs=575476 tasks=2331 scratch_used_peak=27265820 scratch_device_reserved=184549376 RSS_KiB=708332 max_abs=2.1371793224034263e-15 max_rel=1.6186841366251043e-14 flux_R=1.3070869891010463e-16 flux_G=2.5758793226204442e-16 flux_B=1.7069617471680846e-16 flux_Y=2.1355251009923229e-16
PROCESS_WALL 1.166123833 EXIT 0
@@ -0,0 +1,8 @@
COMMAND OMP_NUM_THREADS=16 build/Release/replay_psf benchmarks/hip_psf_replay_2026-09-07/ordinary_16384.events 12765 adaptive
TIMEOUT 45s
GIT 11e703e33dffb1ff168ba11dd922e68b448116b9
BINARY_SHA256 121b85ade12680929cf0f560e04485e2ad3d8a56ff9dcbba950a323f840c5151
PSF cache ready: 64x64 phases, radius 47 px, relative tail 1e-08, tail abs 1e-06, boundary 1e-07, build 0.679 s
device=AMD Radeon RX 9070 arch=gfx1201 events=12765 frame=3840x2160 mode=adaptive distribution=captured contributions=84287857 CPU_reference=0.164183140 create=0.036640882
complete_replay=0.054260731 replay_wall=0.017619848 select=0.000036955 bin=0.001922131 upload=0.000246048 prepare=0.000601053 accumulation=0.010066986 merge=0.000137806 download=0.004148300 cleanup=0.000171900 events_s=724467.079 contributions_s=4783688020.331 center_tiles=8 tile_chunks=1 atomic_chunks=0 refs=575476 tasks=2331 scratch_used_peak=27265820 scratch_device_reserved=184549376 RSS_KiB=707824 max_abs=2.1371793224034263e-15 max_rel=1.6186841366251043e-14 flux_R=1.3070869891010463e-16 flux_G=2.5758793226204442e-16 flux_B=1.7069617471680846e-16 flux_Y=2.1355251009923229e-16
PROCESS_WALL 1.167055415 EXIT 0
@@ -0,0 +1,8 @@
COMMAND OMP_NUM_THREADS=16 build/Release/replay_psf benchmarks/hip_psf_replay_2026-09-07/ordinary_16384.events 12765 adaptive
TIMEOUT 45s
GIT 11e703e33dffb1ff168ba11dd922e68b448116b9
BINARY_SHA256 121b85ade12680929cf0f560e04485e2ad3d8a56ff9dcbba950a323f840c5151
PSF cache ready: 64x64 phases, radius 47 px, relative tail 1e-08, tail abs 1e-06, boundary 1e-07, build 0.674 s
device=AMD Radeon RX 9070 arch=gfx1201 events=12765 frame=3840x2160 mode=adaptive distribution=captured contributions=84287857 CPU_reference=0.159490824 create=0.036442041
complete_replay=0.056708097 replay_wall=0.020266056 select=0.000033855 bin=0.001877069 upload=0.000234127 prepare=0.000597954 accumulation=0.010081053 merge=0.000137806 download=0.004184938 cleanup=0.000163078 events_s=629870.951 contributions_s=4159065619.239 center_tiles=8 tile_chunks=1 atomic_chunks=0 refs=575476 tasks=2331 scratch_used_peak=27265820 scratch_device_reserved=184549376 RSS_KiB=707952 max_abs=2.1371793224034263e-15 max_rel=1.6186841366251043e-14 flux_R=1.3070869891010463e-16 flux_G=2.5758793226204442e-16 flux_B=1.7069617471680846e-16 flux_Y=2.1355251009923229e-16
PROCESS_WALL 1.167496176 EXIT 0
@@ -0,0 +1,32 @@
#!/usr/bin/env python3
"""Summarize raw runs; create artifact provenance and actual coverage metadata."""
from pathlib import Path
import hashlib,json,re,statistics
base=Path(__file__).resolve().parent
manifest={}
for p in sorted(base.glob('*.events')):
lines=p.read_text().splitlines();header=lines[0].split();events=[list(map(float,s.split())) for s in lines[1:]]
assert len(events)==int(header[3])
tiles={}
for e in events:
tile=f'{int(e[0]//32)},{int(e[1]//32)}';tiles[tile]=tiles.get(tile,0)+1
manifest[p.name]={'sha256':hashlib.sha256(p.read_bytes()).hexdigest(),'events':len(events),
'bbox_xy':[min(e[0] for e in events),min(e[1] for e in events),max(e[0] for e in events),max(e[1] for e in events)] if events else [],
'flux_range':[min(e[5] for e in events),max(e[5] for e in events)] if events else [],
'support_range':[min(e[6] for e in events),max(e[6] for e in events)] if events else [],
'occupied_center_tiles_32':len(tiles),'max_centers_per_tile_32':max(tiles.values(),default=0),
'centers_per_tile_32':tiles}
(base/'events_manifest.json').write_text(json.dumps(manifest,indent=2)+'\n')
for version in ['v2','v3','final']:
groups={}
for p in sorted(base.glob(version+'_*.log')):
text=p.read_text();matches=re.findall(r'(\w+)=([-+0-9.eE]+)',text)
row=dict(matches)
if 'replay_wall' not in row or 'EXIT 0' not in text:continue
key=p.stem.rsplit('_',1)[0];groups.setdefault(key,[]).append(row)
print(version)
for key,rows in groups.items():
ms=statistics.median(float(r['replay_wall'])*1000 for r in rows)
complete=statistics.median((float(r['replay_wall'])+float(r['create']))*1000 for r in rows)
print(key,'repeats',len(rows),'replay_ms',round(ms,3),'with_create_ms',round(complete,3),
'range_ms',[round(min(float(r['replay_wall'])*1000 for r in rows),3),round(max(float(r['replay_wall'])*1000 for r in rows),3)])
@@ -0,0 +1,7 @@
COMMAND OMP_NUM_THREADS=16 build/Release/replay_psf benchmarks/hip_psf_replay_2026-09-07/first.events 4096 atomic
TIMEOUT 45s
GIT 5eccc31c99db96de2a0597babf2fd4c2149e91e7
BINARY_SHA256 cbe8c8d341ca33323d0978f1f9e3c3c4e05fe6c95edeae633000e4968c82b099
no ROCm-capable device is detected
PSF cache ready: 64x64 phases, radius 47 px, relative tail 1e-08, tail abs 1e-06, boundary 1e-07, build 0.673 s
PROCESS_WALL 0.865592575 EXIT 1
@@ -0,0 +1,8 @@
COMMAND OMP_NUM_THREADS=16 build/Release/replay_psf benchmarks/hip_psf_replay_2026-09-07/first.events 4096 atomic
TIMEOUT 45s
GIT 5eccc31c99db96de2a0597babf2fd4c2149e91e7
BINARY_SHA256 cbe8c8d341ca33323d0978f1f9e3c3c4e05fe6c95edeae633000e4968c82b099
PSF cache ready: 64x64 phases, radius 47 px, relative tail 1e-08, tail abs 1e-06, boundary 1e-07, build 0.664 s
device=AMD Radeon RX 9070 arch=gfx1201 events=4096 frame=3840x2160 mode=atomic distribution=captured contributions=27048367 CPU_reference=0.051717043 create=0.048879862
replay_wall=0.014458895 bin=0.000000000 upload=0.000024041 accumulation=0.009698097 merge=0.000000000 download=0.004648505 cleanup=0.000000000 events_s=283285.830 contributions_s=1870707789.621 refs=0 tasks=0 scratch_used_peak=0 scratch_device_reserved=0 RSS_KiB=701872 max_abs=3.3306690738754696e-16 max_rel=3.5711901395269354e-15 flux_R=2.5760342802383037e-17 flux_G=-6.2162685431951786e-17 flux_B=9.745619860663276e-18 flux_Y=-3.1106275640600945e-17
PROCESS_WALL 1.015501968 EXIT 0
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,6 @@
COMMAND OMP_NUM_THREADS=16 build/Release/replay_psf benchmarks/hip_psf_replay_2026-09-07/boundary.events 32771 atomic mixed
TIMEOUT 45s
GIT 5eccc31c99db96de2a0597babf2fd4c2149e91e7
BINARY_SHA256 b1974af030c3eb47bcc36873e51890f5ae499b816b977806ce56d87bb134de8d
PSF cache ready: 64x64 phases, radius 47 px, relative tail 1e-08, tail abs 1e-06, boundary 1e-07, build 0.659 s
PROCESS_WALL 0.715381890 EXIT 2
@@ -0,0 +1,8 @@
COMMAND OMP_NUM_THREADS=16 build/Release/replay_psf benchmarks/hip_psf_replay_2026-09-07/boundary.events 32771 16 mixed
TIMEOUT 45s
GIT 5eccc31c99db96de2a0597babf2fd4c2149e91e7
BINARY_SHA256 944468b1bef5b03189d0bdb9140bb5d60a88e7e96e7aae5be899adefd10e3e7b
PSF cache ready: 64x64 phases, radius 47 px, relative tail 1e-08, tail abs 1e-06, boundary 1e-07, build 0.746 s
device=AMD Radeon RX 9070 arch=gfx1201 events=32771 frame=128x96 mode=16 distribution=fixture-mixed-direct contributions=142133685 CPU_reference=0.272168159 create=0.040422916
complete_replay=0.062302828 replay_wall=0.021879911 bin=0.002384901 upload=0.000565052 prepare=0.000978708 accumulation=0.014849901 merge=0.000107288 download=0.000136280 cleanup=0.000193834 events_s=1497766.575 contributions_s=6496081371.351 refs=829484 tasks=3317 scratch_used_peak=25249440 scratch_device_reserved=183500800 RSS_KiB=319220 max_abs=5.9685589803848416e-11 max_rel=5.9595772318269279e-13 flux_R=2.8322714747205163e-14 flux_G=-5.5281420425357588e-15 flux_B=9.6527238727116329e-15 flux_Y=1.1503550136356763e-14
PROCESS_WALL 1.169268463 EXIT 0
@@ -0,0 +1,8 @@
COMMAND OMP_NUM_THREADS=16 build/Release/replay_psf benchmarks/hip_psf_replay_2026-09-07/boundary.events 32771 32 mixed
TIMEOUT 45s
GIT 5eccc31c99db96de2a0597babf2fd4c2149e91e7
BINARY_SHA256 944468b1bef5b03189d0bdb9140bb5d60a88e7e96e7aae5be899adefd10e3e7b
PSF cache ready: 64x64 phases, radius 47 px, relative tail 1e-08, tail abs 1e-06, boundary 1e-07, build 0.674 s
device=AMD Radeon RX 9070 arch=gfx1201 events=32771 frame=128x96 mode=32 distribution=fixture-mixed-direct contributions=142133685 CPU_reference=0.274095058 create=0.037914991
complete_replay=0.060758829 replay_wall=0.022843838 bin=0.000917673 upload=0.000444174 prepare=0.000966072 accumulation=0.017579794 merge=0.000150204 download=0.000171601 cleanup=0.000211954 events_s=1434566.310 contributions_s=6221970521.325 refs=262738 tasks=1047 scratch_used_peak=26764544 scratch_device_reserved=183500800 RSS_KiB=316720 max_abs=5.95719029661268e-11 max_rel=5.9852906417219664e-13 flux_R=2.8341868565408803e-14 flux_G=-5.5261969901934673e-15 flux_B=9.708255356583196e-15 flux_Y=1.1519202588118778e-14
PROCESS_WALL 1.083576745 EXIT 0
@@ -0,0 +1,8 @@
COMMAND OMP_NUM_THREADS=16 build/Release/replay_psf benchmarks/hip_psf_replay_2026-09-07/boundary.events 32771 atomic mixed
TIMEOUT 45s
GIT 5eccc31c99db96de2a0597babf2fd4c2149e91e7
BINARY_SHA256 944468b1bef5b03189d0bdb9140bb5d60a88e7e96e7aae5be899adefd10e3e7b
PSF cache ready: 64x64 phases, radius 47 px, relative tail 1e-08, tail abs 1e-06, boundary 1e-07, build 0.692 s
device=AMD Radeon RX 9070 arch=gfx1201 events=32771 frame=128x96 mode=atomic distribution=fixture-mixed-direct contributions=142133685 CPU_reference=0.271338940 create=0.038436890
complete_replay=0.070170879 replay_wall=0.031733990 bin=0.000000000 upload=0.000115762 prepare=0.000000000 accumulation=0.028868371 merge=0.000000000 download=0.000130440 cleanup=0.000000000 events_s=1032678.220 contributions_s=4478910035.388 refs=0 tasks=0 scratch_used_peak=0 scratch_device_reserved=0 RSS_KiB=315252 max_abs=3.637978807091713e-12 max_rel=2.3282634352172539e-14 flux_R=3.8945990570006271e-16 flux_G=8.3996100262067062e-17 flux_B=-1.7783686053977817e-16 flux_Y=1.9378678705416098e-16
PROCESS_WALL 1.116430788 EXIT 0
@@ -0,0 +1 @@
cc -DENABLE_PNG -std=c11 -march=native -pipe -Wall -Wextra -Wpedantic -O2 -DNDEBUG -fopenmp -Isrc tests/capture_psf.c src/catalog.c src/geodesic.c src/lens_map.c src/movie.c src/observer.c src/observer_track.c src/optics.c src/ray.c src/spacetime_common.c src/spacetime_minkowski.c -lm -lpng -o build/Release/capture_psf
@@ -0,0 +1 @@
cc -DENABLE_PNG -std=c11 -march=native -pipe -Wall -Wextra -Wpedantic -O2 -DNDEBUG -fopenmp -Isrc tests/capture_psf.c src/catalog.c src/geodesic.c src/lens_map.c src/movie.c src/observer.c src/observer_track.c src/optics.c src/ray.c src/spacetime_common.c src/spacetime_minkowski.c -lm -lpng -o build/Release/capture_psf
@@ -0,0 +1 @@
cc -DENABLE_PNG -std=c11 -march=native -pipe -Wall -Wextra -Wpedantic -O2 -DNDEBUG -fopenmp -Isrc tests/capture_psf.c src/catalog.c src/geodesic.c src/lens_map.c src/movie.c src/observer.c src/observer_track.c src/optics.c src/ray.c src/spacetime_common.c src/spacetime_minkowski.c -lm -lpng -o build/Release/capture_psf
@@ -0,0 +1 @@
cc -DENABLE_PNG -std=c11 -march=native -pipe -Wall -Wextra -Wpedantic -O2 -DNDEBUG -fopenmp -Isrc tests/capture_psf.c src/catalog.c src/geodesic.c src/lens_map.c src/movie.c src/observer.c src/observer_track.c src/optics.c src/ray.c src/spacetime_common.c src/spacetime_minkowski.c -lm -lpng -o build/Release/capture_psf
@@ -0,0 +1,10 @@
# Repository root; all builds complete before final_cases.py is started.
make psf-capture
make PSF_BACKEND=hip HIP_CXXFLAGS='--offload-arch=gfx1201 -std=c++17 -O2 -Wall -Wextra -Wpedantic' hip-psf-replay
make build/Release/make_psf_fixture
make -j4 SPACETIME=minkowski PSF_BACKEND=cpu ENABLE_HDR=1 backend
make -j4 SPACETIME=minkowski PSF_BACKEND=hip ENABLE_HDR=1 HIP_CXXFLAGS='--offload-arch=gfx1201 -std=c++17 -O2 -Wall -Wextra -Wpedantic' backend hip-psf-test
make -j4 SPACETIME=schwarzschild PSF_BACKEND=cpu ENABLE_HDR=1 backend
make -j4 SPACETIME=schwarzschild PSF_BACKEND=hip ENABLE_HDR=1 HIP_CXXFLAGS='--offload-arch=gfx1201 -std=c++17 -O2 -Wall -Wextra -Wpedantic' backend
hipcc --offload-arch=gfx1201 --cuda-device-only -std=c++17 -O2 -Isrc -S tests/replay_psf.hip -o /tmp/gr-psf-replay-device.s
rg -n '\.name:|\.vgpr_count:|\.sgpr_count:|\.private_segment_fixed_size:|\.group_segment_fixed_size:|\.max_flat_workgroup_size:' /tmp/gr-psf-replay-device.s
@@ -0,0 +1,2 @@
hipcc --offload-arch=gfx1201 -std=c++17 -O2 -Wall -Wextra -Wpedantic -fopenmp -Isrc -x hip tests/replay_psf.hip -x none build/Release/obj/minkowski/standard_sink1_hip/src/optics.o -lm -lpng -o build/Release/replay_psf
cc -DENABLE_PNG -std=c11 -march=native -pipe -Wall -Wextra -Wpedantic -O2 -DNDEBUG -fopenmp -Isrc tests/capture_psf.c src/catalog.c src/geodesic.c src/lens_map.c src/movie.c src/observer.c src/observer_track.c src/optics.c src/ray.c src/spacetime_common.c src/spacetime_minkowski.c -lm -lpng -o build/Release/capture_psf
@@ -0,0 +1 @@
cc -DENABLE_PNG -std=c11 -march=native -pipe -Wall -Wextra -Wpedantic -O2 -DNDEBUG -fopenmp -Isrc tests/make_psf_fixture.c src/optics.c -lm -lpng -o build/Release/make_psf_fixture
@@ -0,0 +1,2 @@
cc -DENABLE_PNG -DFRAME_PSF_EVENT_SINK=1 -DSPACETIME_MINKOWSKI -DENABLE_HDR_OUTPUT -std=c11 -march=native -pipe -Wall -Wextra -Wpedantic -O2 -DNDEBUG -fopenmp -Isrc -MMD -MP -c src/frame.c -o build/Release/obj/minkowski/hdr_sink1_cpu/src/frame.o
cc -O2 -DNDEBUG -fopenmp build/Release/obj/minkowski/hdr_sink1_cpu/src/catalog.o build/Release/obj/minkowski/hdr_sink1_cpu/src/frame.o build/Release/obj/minkowski/hdr_sink1_cpu/src/geodesic.o build/Release/obj/minkowski/hdr_sink1_cpu/src/lens_map.o build/Release/obj/minkowski/hdr_sink1_cpu/src/movie.o build/Release/obj/minkowski/hdr_sink1_cpu/src/observer.o build/Release/obj/minkowski/hdr_sink1_cpu/src/observer_track.o build/Release/obj/minkowski/hdr_sink1_cpu/src/optics.o build/Release/obj/minkowski/hdr_sink1_cpu/src/ray.o build/Release/obj/minkowski/hdr_sink1_cpu/src/spacetime_common.o build/Release/obj/minkowski/hdr_sink1_cpu/src/spacetime_minkowski.o build/Release/obj/minkowski/hdr_sink1_cpu/src/main.o -lm -lpng -lcfitsio -o build/Release/minkowski_sky
@@ -0,0 +1,3 @@
make: Nothing to be done for 'hip-psf-test'.
cc -DENABLE_PNG -DFRAME_PSF_EVENT_SINK=1 -DPSF_BACKEND_HIP -DSPACETIME_MINKOWSKI -DENABLE_HDR_OUTPUT -std=c11 -march=native -pipe -Wall -Wextra -Wpedantic -O2 -DNDEBUG -fopenmp -Isrc -MMD -MP -c src/frame.c -o build/Release/obj/minkowski/hdr_sink1_hip/src/frame.o
hipcc -O2 -DNDEBUG -fopenmp build/Release/obj/minkowski/hdr_sink1_hip/src/catalog.o build/Release/obj/minkowski/hdr_sink1_hip/src/frame.o build/Release/obj/minkowski/hdr_sink1_hip/src/geodesic.o build/Release/obj/minkowski/hdr_sink1_hip/src/lens_map.o build/Release/obj/minkowski/hdr_sink1_hip/src/movie.o build/Release/obj/minkowski/hdr_sink1_hip/src/observer.o build/Release/obj/minkowski/hdr_sink1_hip/src/observer_track.o build/Release/obj/minkowski/hdr_sink1_hip/src/optics.o build/Release/obj/minkowski/hdr_sink1_hip/src/ray.o build/Release/obj/minkowski/hdr_sink1_hip/src/spacetime_common.o build/Release/obj/minkowski/hdr_sink1_hip/src/spacetime_minkowski.o build/Release/obj/minkowski/hdr_sink1_hip/src/main.o build/Release/obj/minkowski/hdr_sink1_hip/src/hip_psf.o -lm -lpng -lcfitsio -o build/Release/minkowski_sky_hip
@@ -0,0 +1 @@
hipcc --offload-arch=gfx1201 -std=c++17 -O2 -Wall -Wextra -Wpedantic -fopenmp -Isrc -x hip tests/replay_psf.hip -x none build/Release/obj/minkowski/standard_sink1_hip/src/optics.o -lm -lpng -o build/Release/replay_psf
@@ -0,0 +1 @@
hipcc --offload-arch=gfx1201 -std=c++17 -O2 -Wall -Wextra -Wpedantic -fopenmp -Isrc -x hip tests/replay_psf.hip -x none build/Release/obj/minkowski/standard_sink1_hip/src/optics.o -lm -lpng -o build/Release/replay_psf
@@ -0,0 +1,2 @@
cc -DENABLE_PNG -DFRAME_PSF_EVENT_SINK=1 -DSPACETIME_SCHWARZSCHILD -DENABLE_HDR_OUTPUT -std=c11 -march=native -pipe -Wall -Wextra -Wpedantic -O2 -DNDEBUG -fopenmp -Isrc -MMD -MP -c src/frame.c -o build/Release/obj/schwarzschild/hdr_sink1_cpu/src/frame.o
cc -O2 -DNDEBUG -fopenmp build/Release/obj/schwarzschild/hdr_sink1_cpu/src/catalog.o build/Release/obj/schwarzschild/hdr_sink1_cpu/src/frame.o build/Release/obj/schwarzschild/hdr_sink1_cpu/src/geodesic.o build/Release/obj/schwarzschild/hdr_sink1_cpu/src/lens_map.o build/Release/obj/schwarzschild/hdr_sink1_cpu/src/movie.o build/Release/obj/schwarzschild/hdr_sink1_cpu/src/observer.o build/Release/obj/schwarzschild/hdr_sink1_cpu/src/observer_track.o build/Release/obj/schwarzschild/hdr_sink1_cpu/src/optics.o build/Release/obj/schwarzschild/hdr_sink1_cpu/src/ray.o build/Release/obj/schwarzschild/hdr_sink1_cpu/src/spacetime_common.o build/Release/obj/schwarzschild/hdr_sink1_cpu/src/spacetime_schwarzschild.o build/Release/obj/schwarzschild/hdr_sink1_cpu/src/main.o -lm -lpng -lcfitsio -o build/Release/schwarzschild_sky
@@ -0,0 +1,2 @@
cc -DENABLE_PNG -DFRAME_PSF_EVENT_SINK=1 -DPSF_BACKEND_HIP -DSPACETIME_SCHWARZSCHILD -DENABLE_HDR_OUTPUT -std=c11 -march=native -pipe -Wall -Wextra -Wpedantic -O2 -DNDEBUG -fopenmp -Isrc -MMD -MP -c src/frame.c -o build/Release/obj/schwarzschild/hdr_sink1_hip/src/frame.o
hipcc -O2 -DNDEBUG -fopenmp build/Release/obj/schwarzschild/hdr_sink1_hip/src/catalog.o build/Release/obj/schwarzschild/hdr_sink1_hip/src/frame.o build/Release/obj/schwarzschild/hdr_sink1_hip/src/geodesic.o build/Release/obj/schwarzschild/hdr_sink1_hip/src/lens_map.o build/Release/obj/schwarzschild/hdr_sink1_hip/src/movie.o build/Release/obj/schwarzschild/hdr_sink1_hip/src/observer.o build/Release/obj/schwarzschild/hdr_sink1_hip/src/observer_track.o build/Release/obj/schwarzschild/hdr_sink1_hip/src/optics.o build/Release/obj/schwarzschild/hdr_sink1_hip/src/ray.o build/Release/obj/schwarzschild/hdr_sink1_hip/src/spacetime_common.o build/Release/obj/schwarzschild/hdr_sink1_hip/src/spacetime_schwarzschild.o build/Release/obj/schwarzschild/hdr_sink1_hip/src/main.o build/Release/obj/schwarzschild/hdr_sink1_hip/src/hip_psf.o -lm -lpng -lcfitsio -o build/Release/schwarzschild_sky_hip
@@ -0,0 +1 @@
hipcc --offload-arch=gfx1201 -std=c++17 -O2 -Wall -Wextra -Wpedantic -fopenmp -Isrc -x hip tests/replay_psf.hip -x none build/Release/obj/minkowski/standard_sink1_hip/src/optics.o -lm -lpng -o build/Release/replay_psf
@@ -0,0 +1,8 @@
COMMAND OMP_NUM_THREADS=16 OMP_DYNAMIC=FALSE env HIP_PSF_ACCUMULATION=adaptive build/Release/replay_psf benchmarks/hip_psf_replay_2026-09-07/center_65536.events 65536 production-busy 128
TIMEOUT 45s
GIT 2d01c2c101ccea8193a64bb46ceafca3009f0ef5
BINARY_SHA256 876b6c3d92312e42b8521887d3ad15a95d28185ec6d7fe480bb765bd597ce85e
PSF cache ready: 64x64 phases, radius 47 px, relative tail 1e-08, tail abs 1e-06, boundary 1e-07, build 0.706 s
device=AMD Radeon RX 9070 arch=gfx1201 events=65536 rounds=128 frame=3840x2160 mode=production-busy distribution=captured contributions_per_round=432818979 CPU_reference=0.819939137 create=0.042913914
complete_replay=3.962181807 replay_wall=3.919267893 select=0.054163949 bin=1.240586689 upload=0.092119292 prepare=0.000000000 accumulation=3.668894874 merge=0.000000000 download=0.005043460 cleanup=0.000000000 events_s=2140350.757 contributions_s=14135504595.959 center_tiles=0 tile_chunks=512 atomic_chunks=0 refs=0 tasks=0 scratch_used_peak=0 scratch_device_reserved=0 RSS_KiB=716016 max_abs=4.2500725161431774e-17 max_rel=2.146162751251728e-14 flux_R=-1.871866178468806e-16 flux_G=1.3413216273651358e-16 flux_B=8.2669907468878767e-17 flux_Y=1.6595004964231178e-17 validation=scaled-cpu-double-reference
PROCESS_WALL 5.826439530 EXIT 0
@@ -0,0 +1,9 @@
COMMAND OMP_NUM_THREADS=16 OMP_DYNAMIC=FALSE env HIP_PSF_ACCUMULATION=atomic build/Release/replay_psf benchmarks/hip_psf_replay_2026-09-07/center_65536.events 65536 production-busy 128
TIMEOUT 45s
GIT 2d01c2c101ccea8193a64bb46ceafca3009f0ef5
BINARY_SHA256 876b6c3d92312e42b8521887d3ad15a95d28185ec6d7fe480bb765bd597ce85e
PSF cache ready: 64x64 phases, radius 47 px, relative tail 1e-08, tail abs 1e-06, boundary 1e-07, build 0.691 s
device=AMD Radeon RX 9070 arch=gfx1201 events=65536 rounds=128 frame=3840x2160 mode=production-busy distribution=captured contributions_per_round=432818979 CPU_reference=0.824468851 create=0.039535046
HIP PSF progress: 5832704 submitted / 5799936 completed events; 354 / 356 batches timed; kernel 4.947 s
complete_replay=7.198877096 replay_wall=7.159342051 select=0.000000000 bin=0.000000000 upload=0.024048809 prepare=0.000000000 accumulation=7.125524449 merge=0.000000000 download=0.005060978 cleanup=0.000000000 events_s=1171700.966 contributions_s=7738257080.164 center_tiles=0 tile_chunks=0 atomic_chunks=512 refs=0 tasks=0 scratch_used_peak=0 scratch_device_reserved=0 RSS_KiB=706576 max_abs=2.8777327742979253e-14 max_rel=4.2863124632598364e-12 flux_R=-2.8216587351205239e-13 flux_G=-4.377441999141077e-13 flux_B=-9.6631266798699205e-13 flux_Y=-3.9782880312410178e-13 validation=scaled-cpu-double-reference
PROCESS_WALL 9.081153592 EXIT 0
@@ -0,0 +1,10 @@
#!/usr/bin/env python3
from run import run
from pathlib import Path
import sys
base='benchmarks/hip_psf_replay_2026-09-07/'
for region,source,lo,hi in [('ordinary','ordinary',0,1.2),('center','center',0,2),('lensed','center',2,1e6)]:
for n in [4096,16384,65536]:
run(f'capture_{region}_{n}', ['build/Release/capture_psf',
'output/lens/schwarzschild_galactic_center_R100_45deg_16_4_4k_.grlens',
base+source+'.csv','0','130882',str(n),base+f'{region}_{n}.events','1e13','1e8','0',str(lo),str(hi)],60)
@@ -0,0 +1,7 @@
COMMAND OMP_NUM_THREADS=16 build/Release/capture_psf output/lens/schwarzschild_galactic_center_R100_45deg_16_4_4k_.grlens benchmarks/hip_psf_replay_2026-09-07/center.csv 0 130882 16384 benchmarks/hip_psf_replay_2026-09-07/center_16384.events 1e13 1e8 0 0 2
TIMEOUT 60s
GIT 5eccc31c99db96de2a0597babf2fd4c2149e91e7
BINARY_SHA256 7bc79ef3753b17b8f9a2bbc8627476642fb659012e559bef584edd294b2280ce
selection: raw_magnification=[0,2) exposure=10000000000000 max_cache_flux=100000000 min_y=0
DIAGNOSTIC ONLY, no HDR: workers=1 catalog=memory stars=8192 triangles=[0,130882) emitting_triangles=46 last_emitting_triangle=40150 cached=16384 wing=0 direct=0 discarded=0 events=16384 capped=1 producer_wall=1.128368688 digest=2a68ffbfc7c8d223
PROCESS_WALL 1.924610762 EXIT 0
@@ -0,0 +1,7 @@
COMMAND OMP_NUM_THREADS=16 build/Release/capture_psf output/lens/schwarzschild_galactic_center_R100_45deg_16_4_4k_.grlens benchmarks/hip_psf_replay_2026-09-07/center.csv 0 130882 4096 benchmarks/hip_psf_replay_2026-09-07/center_4096.events 1e13 1e8 0 0 2
TIMEOUT 60s
GIT 5eccc31c99db96de2a0597babf2fd4c2149e91e7
BINARY_SHA256 7bc79ef3753b17b8f9a2bbc8627476642fb659012e559bef584edd294b2280ce
selection: raw_magnification=[0,2) exposure=10000000000000 max_cache_flux=100000000 min_y=0
DIAGNOSTIC ONLY, no HDR: workers=1 catalog=memory stars=8192 triangles=[0,130882) emitting_triangles=5 last_emitting_triangle=38989 cached=4096 wing=0 direct=0 discarded=0 events=4096 capped=1 producer_wall=1.054716730 digest=0fcab7f1830f7b0c
PROCESS_WALL 1.870937289 EXIT 0
@@ -0,0 +1,7 @@
COMMAND OMP_NUM_THREADS=16 build/Release/capture_psf output/lens/schwarzschild_galactic_center_R100_45deg_16_4_4k_.grlens benchmarks/hip_psf_replay_2026-09-07/center.csv 0 130882 65536 benchmarks/hip_psf_replay_2026-09-07/center_65536.events 1e13 1e8 0 0 2
TIMEOUT 60s
GIT 5eccc31c99db96de2a0597babf2fd4c2149e91e7
BINARY_SHA256 7bc79ef3753b17b8f9a2bbc8627476642fb659012e559bef584edd294b2280ce
selection: raw_magnification=[0,2) exposure=10000000000000 max_cache_flux=100000000 min_y=0
DIAGNOSTIC ONLY, no HDR: workers=1 catalog=memory stars=8192 triangles=[0,130882) emitting_triangles=226 last_emitting_triangle=65353 cached=65536 wing=0 direct=0 discarded=0 events=65536 capped=1 producer_wall=2.027659164 digest=84eca82d422fd527
PROCESS_WALL 2.920336974 EXIT 0
@@ -0,0 +1,6 @@
COMMAND OMP_NUM_THREADS=16 build/Release/capture_psf output/lens/schwarzschild_galactic_center_R100_45deg_16_4_4k_.grlens benchmarks/hip_psf_2026-09-07/catalog_8192.csv 0 130882 4096 benchmarks/hip_psf_replay_2026-09-07/first.events 1e13
TIMEOUT 60s
GIT 5eccc31c99db96de2a0597babf2fd4c2149e91e7
BINARY_SHA256 de14134db38f96df42889730c90be0405417ed5e8813126d28aa2b74d8294835
DIAGNOSTIC ONLY, no HDR: workers=1 catalog=memory stars=8192 triangles=[0,130882) emitting_triangles=8 last_emitting_triangle=21059 cached=4096 wing=0 direct=0 discarded=0 events=4096 capped=1 producer_wall=0.677953599 digest=27a7bc1430888c23
PROCESS_WALL 1.466103541 EXIT 0
@@ -0,0 +1,69 @@
COMMAND OMP_NUM_THREADS=16 python3 tests/test_psf_capture.py build/Release/minkowski_sky build/Release/capture_psf
TIMEOUT 60s
GIT 5eccc31c99db96de2a0597babf2fd4c2149e91e7
RUN [PosixPath('/home/wyj/Code/C/GR_4d_raytracing/build/Release/minkowski_sky'), '--catalog', PosixPath('/home/wyj/Code/C/GR_4d_raytracing/tests/data/hip_psf_mixed_catalog.csv'), '--width', '96', '--height', '64', '--fov-deg', '30', '--look-ra-deg', '2', '--look-dec-deg', '1', '--coarse-cell-pixels', '16', '--refine-max-level', '0', '--exposure', '1000', '--lens-map-output', PosixPath('/tmp/gr-capture-test-fkhumcsd/mixed.grlens'), '--output', PosixPath('/tmp/gr-capture-test-fkhumcsd/reference.png')]
PSF cache ready: 64x64 phases, radius 47 px, relative tail 1e-08, tail abs 1e-06, boundary 1e-07, build 1.652 s
Wrote lens map: /tmp/gr-capture-test-fkhumcsd/mixed.grlens (35 vertices, 48 triangles)
Rendered 3 images from 3 catalog stars to /tmp/gr-capture-test-fkhumcsd/reference.png (ok)
PSF splats: cached 2, cached wing-clipped 0, direct fallbacks 1, discarded below min-Y 0
RUN [PosixPath('/home/wyj/Code/C/GR_4d_raytracing/build/Release/capture_psf'), PosixPath('/tmp/gr-capture-test-fkhumcsd/mixed.grlens'), PosixPath('/home/wyj/Code/C/GR_4d_raytracing/tests/data/hip_psf_mixed_catalog.csv'), '0', '48', '65536', '--diagnose', '1000', '1', '0']
selection: raw_magnification=[0,1.0000000000000001e+300) exposure=1000 max_cache_flux=1 min_y=0
DIAGNOSTIC ONLY, no HDR: workers=1 catalog=memory stars=3 triangles=[0,48) emitting_triangles=3 last_emitting_triangle=31 cached=2 wing=0 direct=1 discarded=0 events=2 capped=0 producer_wall=0.000052110 digest=42ac8bead3c61e6d
checksum=5815cdd7db8c543d
RUN [PosixPath('/home/wyj/Code/C/GR_4d_raytracing/build/Release/capture_psf'), PosixPath('/tmp/gr-capture-test-fkhumcsd/mixed.grlens'), PosixPath('/home/wyj/Code/C/GR_4d_raytracing/tests/data/hip_psf_mixed_catalog.csv'), '0', '48', '65536', '--diagnose-parallel', '1000', '1', '0']
selection: raw_magnification=[0,1.0000000000000001e+300) exposure=1000 max_cache_flux=1 min_y=0
DIAGNOSTIC ONLY, no HDR: workers=4 catalog=memory stars=3 triangles=[0,48) events=2 cached=2 wing=0 direct=1 discarded=0 checksum=5815cdd7db8c543d producer_wall=0.000363505 capped_or_failed=0
RUN [PosixPath('/home/wyj/Code/C/GR_4d_raytracing/build/Release/capture_psf'), PosixPath('/tmp/gr-capture-test-fkhumcsd/mixed.grlens'), PosixPath('/home/wyj/Code/C/GR_4d_raytracing/tests/data/hip_psf_mixed_catalog.csv'), '0', '48', '65536', '--diagnose-indexed-serial', '1000', '1', '0']
selection: raw_magnification=[0,1.0000000000000001e+300) exposure=1000 max_cache_flux=1 min_y=0
DIAGNOSTIC ONLY, no HDR: workers=1 catalog=indexed-subset stars=3 triangles=[0,48) emitting_triangles=3 last_emitting_triangle=31 cached=2 wing=0 direct=1 discarded=0 events=2 capped=0 producer_wall=0.000045902 digest=42ac8bead3c61e6d
checksum=5815cdd7db8c543d
RUN [PosixPath('/home/wyj/Code/C/GR_4d_raytracing/build/Release/capture_psf'), PosixPath('/tmp/gr-capture-test-fkhumcsd/mixed.grlens'), PosixPath('/home/wyj/Code/C/GR_4d_raytracing/tests/data/hip_psf_mixed_catalog.csv'), '0', '48', '65536', '--diagnose-indexed', '1000', '1', '0']
selection: raw_magnification=[0,1.0000000000000001e+300) exposure=1000 max_cache_flux=1 min_y=0
DIAGNOSTIC ONLY, no HDR: workers=4 catalog=indexed-subset stars=3 triangles=[0,48) events=2 cached=2 wing=0 direct=1 discarded=0 checksum=5815cdd7db8c543d producer_wall=0.000226217 capped_or_failed=0
RUN [PosixPath('/home/wyj/Code/C/GR_4d_raytracing/build/Release/capture_psf'), PosixPath('/tmp/gr-capture-test-fkhumcsd/mixed.grlens'), PosixPath('/home/wyj/Code/C/GR_4d_raytracing/tests/data/hip_psf_mixed_catalog.csv'), '0', '48', '65536', '--diagnose', '1000', '1', '1e30']
selection: raw_magnification=[0,1.0000000000000001e+300) exposure=1000 max_cache_flux=1 min_y=1e+30
DIAGNOSTIC ONLY, no HDR: workers=1 catalog=memory stars=3 triangles=[0,48) emitting_triangles=3 last_emitting_triangle=31 cached=0 wing=0 direct=0 discarded=3 events=0 capped=0 producer_wall=0.000013502 digest=7380f783f2041648
checksum=589d94d7dbff8cfa
RUN [PosixPath('/home/wyj/Code/C/GR_4d_raytracing/build/Release/capture_psf'), PosixPath('/tmp/gr-capture-test-fkhumcsd/mixed.grlens'), PosixPath('/home/wyj/Code/C/GR_4d_raytracing/tests/data/hip_psf_mixed_catalog.csv'), '0', '48', '65536', '--diagnose-parallel', '1000', '1', '1e30']
selection: raw_magnification=[0,1.0000000000000001e+300) exposure=1000 max_cache_flux=1 min_y=1e+30
DIAGNOSTIC ONLY, no HDR: workers=4 catalog=memory stars=3 triangles=[0,48) events=0 cached=0 wing=0 direct=0 discarded=3 checksum=589d94d7dbff8cfa producer_wall=0.000221779 capped_or_failed=0
RUN [PosixPath('/home/wyj/Code/C/GR_4d_raytracing/build/Release/capture_psf'), PosixPath('/tmp/gr-capture-test-fkhumcsd/mixed.grlens'), PosixPath('/home/wyj/Code/C/GR_4d_raytracing/tests/data/hip_psf_mixed_catalog.csv'), '0', '48', '65536', '--diagnose-indexed-serial', '1000', '1', '1e30']
selection: raw_magnification=[0,1.0000000000000001e+300) exposure=1000 max_cache_flux=1 min_y=1e+30
DIAGNOSTIC ONLY, no HDR: workers=1 catalog=indexed-subset stars=3 triangles=[0,48) emitting_triangles=3 last_emitting_triangle=31 cached=0 wing=0 direct=0 discarded=3 events=0 capped=0 producer_wall=0.000040233 digest=7380f783f2041648
checksum=589d94d7dbff8cfa
RUN [PosixPath('/home/wyj/Code/C/GR_4d_raytracing/build/Release/capture_psf'), PosixPath('/tmp/gr-capture-test-fkhumcsd/mixed.grlens'), PosixPath('/home/wyj/Code/C/GR_4d_raytracing/tests/data/hip_psf_mixed_catalog.csv'), '0', '48', '65536', '--diagnose-indexed', '1000', '1', '1e30']
selection: raw_magnification=[0,1.0000000000000001e+300) exposure=1000 max_cache_flux=1 min_y=1e+30
DIAGNOSTIC ONLY, no HDR: workers=4 catalog=indexed-subset stars=3 triangles=[0,48) events=0 cached=0 wing=0 direct=0 discarded=3 checksum=589d94d7dbff8cfa producer_wall=0.000232244 capped_or_failed=0
RUN [PosixPath('/home/wyj/Code/C/GR_4d_raytracing/build/Release/capture_psf'), PosixPath('/tmp/gr-capture-test-fkhumcsd/mixed.grlens'), PosixPath('/home/wyj/Code/C/GR_4d_raytracing/tests/data/hip_psf_mixed_catalog.csv'), '0', '48', '65536', PosixPath('/tmp/gr-capture-test-fkhumcsd/mixed.events'), '1000', '1', '0']
selection: raw_magnification=[0,1.0000000000000001e+300) exposure=1000 max_cache_flux=1 min_y=0
DIAGNOSTIC ONLY, no HDR: workers=1 catalog=memory stars=3 triangles=[0,48) emitting_triangles=3 last_emitting_triangle=31 cached=2 wing=0 direct=1 discarded=0 events=2 capped=0 producer_wall=0.000024640 digest=42ac8bead3c61e6d
checksum=5815cdd7db8c543d
RUN [PosixPath('/home/wyj/Code/C/GR_4d_raytracing/build/Release/capture_psf'), PosixPath('/tmp/gr-capture-test-fkhumcsd/mixed.grlens'), PosixPath('/home/wyj/Code/C/GR_4d_raytracing/tests/data/hip_psf_mixed_catalog.csv'), '0', '48', '65536', PosixPath('/tmp/gr-capture-test-fkhumcsd/mixed.events'), '1000', '1', '0']
/tmp/gr-capture-test-fkhumcsd/mixed.events: File exists
selection: raw_magnification=[0,1.0000000000000001e+300) exposure=1000 max_cache_flux=1 min_y=0
DIAGNOSTIC ONLY, no HDR: workers=1 catalog=memory stars=3 triangles=[0,48) emitting_triangles=3 last_emitting_triangle=31 cached=2 wing=0 direct=1 discarded=0 events=2 capped=0 producer_wall=0.000026209 digest=42ac8bead3c61e6d
checksum=5815cdd7db8c543d
RUN [PosixPath('/home/wyj/Code/C/GR_4d_raytracing/build/Release/capture_psf'), PosixPath('/tmp/gr-capture-test-fkhumcsd/mixed.grlens'), PosixPath('/home/wyj/Code/C/GR_4d_raytracing/tests/data/hip_psf_mixed_catalog.csv'), '0', '49', '1', '--diagnose', '1000']
selection: raw_magnification=[0,1.0000000000000001e+300) exposure=1000 max_cache_flux=100000000 min_y=0
RUN [PosixPath('/home/wyj/Code/C/GR_4d_raytracing/build/Release/capture_psf'), PosixPath('/tmp/gr-capture-test-fkhumcsd/mixed.grlens'), PosixPath('/home/wyj/Code/C/GR_4d_raytracing/tests/data/hip_psf_mixed_catalog.csv'), '0', '48', '65537', '--diagnose', '1000']
invalid bound
RUN [PosixPath('/home/wyj/Code/C/GR_4d_raytracing/build/Release/capture_psf'), PosixPath('/tmp/gr-capture-test-fkhumcsd/mixed.grlens'), PosixPath('/home/wyj/Code/C/GR_4d_raytracing/tests/data/hip_psf_mixed_catalog.csv'), '0', '48', '1', PosixPath('/tmp/gr-capture-test-fkhumcsd/capped.events'), '1000']
selection: raw_magnification=[0,1.0000000000000001e+300) exposure=1000 max_cache_flux=100000000 min_y=0
DIAGNOSTIC ONLY, no HDR: workers=1 catalog=memory stars=3 triangles=[0,48) emitting_triangles=1 last_emitting_triangle=29 cached=1 wing=0 direct=0 discarded=0 events=1 capped=1 producer_wall=0.000016109 digest=89788c40baf06e69
checksum=89788c40baf06e69
PASS: capture bounds, classifications, exclusive output, serial/parallel checksum
PROCESS_WALL 19.905413062 EXIT 0
Loaded 100 of 506 files, more files were not shown because too many files have changed in this diff. Show more