Skip to content

feat(src): add G4 validation executables for aligned-mode comparison#271

Open
ggalgoczi wants to merge 15 commits into
mainfrom
feat/aligned-validation
Open

feat(src): add G4 validation executables for aligned-mode comparison#271
ggalgoczi wants to merge 15 commits into
mainfrom
feat/aligned-validation

Conversation

@ggalgoczi
Copy link
Copy Markdown
Contributor

@ggalgoczi ggalgoczi commented Apr 4, 2026

Add infrastructure for photon-by-photon aligned comparison between GPU and G4. StandAloneGeant4Validation provides a CPU-only G4 simulation with --aligned mode using precooked curand sequences via U4Random. Includes AlignedOpticalPhysics with ShimG4Op* wrappers for random number consumption alignment. G4ValidationGenstep enables electron-primary genstep validation. Achieves 97.7% flag match on fresnel_single.gdml.

@ggalgoczi ggalgoczi requested a review from plexoos April 4, 2026 02:54
@ggalgoczi ggalgoczi mentioned this pull request Apr 4, 2026
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How is this new file used? Is it supposed to replace the same functionality in QCurandStateMonolithicTest https://github.com/BNLNPPS/eic-opticks/blob/main/tests/test_opticks.sh#L5-L11?

@plexoos
Copy link
Copy Markdown
Member

plexoos commented Apr 15, 2026

Please update or rebase the branch, and change the PR title to better reflect the intended change using conventional commit format.

@ggalgoczi
Copy link
Copy Markdown
Contributor Author

Please update or rebase the branch, and change the PR title to better reflect the intended change using conventional commit format.

I'll rebase 271-273 once 269 and 270 are merged — otherwise they'll just need rebasing again.

@plexoos
Copy link
Copy Markdown
Member

plexoos commented Apr 17, 2026

ggalgoczi added a commit that referenced this pull request May 9, 2026
…ise hit paths

Three corrections to test_wavelength_shifting.sh:

1. The GPU hit-file path was a literal "/tmp/MISSING_USER/opticks/GEOM/GEOM/...".
   "MISSING_USER" is opticks' fallback when $USER is unset (sysrap/spath.h:294),
   and the trailing "GEOM" is the unset $GEOM env var. The script never
   exported either, so the GPUPhotonSourceMinimal run wrote to a different
   path than the one the script then loaded. Set USER=fakeuser and
   GEOM=fakegeom (matching tests/test_GPURaytrace.sh and
   tests/test_GPUPhotonSource_8x8SiPM.sh) and reference the path through
   the env vars.

2. Drop the hard-coded "/opt/eic-opticks/bin/" prefix on both binaries.
   The install dir is on $PATH in the CI image and in the local
   eic-opticks-env.sh, matching the convention of every other test.

3. StandAloneGeant4Validation is provided by PR #271, not by anything
   currently on main. SKIP cleanly rather than failing when the binary
   isn't installed, so this test is benign on branches where #271 has
   not yet landed.

Also pre-clean stale GPU/G4 hit files at the top of the run so a
silently-failing binary cannot make the comparison succeed against
leftover data.
ggalgoczi added 13 commits May 9, 2026 17:16
…hmark

Pure Geant4 optical photon simulation with no opticks/GPU dependencies.
Loads GDML, fires torch photons, collects hits via G4VSensitiveDetector,
saves g4_hits.npy for comparison with GPU output.

Supports multi-threaded mode via G4MTRunManager (-t N flag) by splitting
photons across multiple events. Sequential mode (-t 0) for reproducibility.
Adds photon-by-photon aligned comparison with GPU via U4Random
precooked curand sequences. Includes PhotonFateAccumulator for
indexed g4_photon.npy output, AlignedOpticalPhysics with
InstrumentedG4OpBoundaryProcess, and U4Recorder integration
for SEvt lifecycle and random alignment.
…ess dependency

Use standard G4OpticalPhysics and direct U4Random::SetSequenceIndex.
Only requires linking U4 (for U4Random) — no u4/ source modifications needed.
Uses ShimG4OpAbsorption/ShimG4OpRayleigh instead of standard
G4OpticalPhysics when --aligned. Improves match from 95.7% to 97.7%
by matching the GPU's RNILL random consumption pattern.
Generates Philox random streams matching GPU seeding for U4Random
aligned mode. 113 lines, compiles with nvcc, no opticks dependencies
beyond NP.hh.
Compares GPU and G4 photon.npy arrays element-by-element:
flag match, position match, distributions, divergent photon listing.
Fires configurable electron in LAr, G4 produces scintillation/Cerenkov
photons and tracks them to SiPM detection. For comparison with GPURaytrace
which uses G4CXOpticks to hand gensteps to GPU for optical propagation.

Tested: 1 MeV e- in det.gdml produces ~170 SiPM hits/event.
Relax MaxRecord assert to permit values above sseq::SLOTS (32).
In DebugLite mode, respect OPTICKS_MAX_RECORD env var if set,
falling back to the default record_limit (32) otherwise. This
enables full step history recording (e.g. 1000 steps) for photon
path analysis without affecting production performance.
G4OpticalPhysics defaults to delta time profile for G4OpWLS,
which applies a fixed delay equal to WLSTIMECONSTANT. The
physically correct model is exponential decay sampling:
dt = -WLSTIMECONSTANT * log(u). The GPU implementation already
uses exponential. This fix aligns G4 with GPU and with the
correct stochastic decay physics.
SetWLSTimeProfile in GPURaytrace changed G4OpticalParameters
during physics list initialization, inadvertently altering the
electron tracking (different genstep count). The WLS time profile
setting only matters for StandAloneGeant4Validation where G4
tracks optical photons directly. In GPURaytrace, the GPU handles
optical physics so the G4 time profile is irrelevant.
Apply repository .clang-format (Microsoft base) to the four files
introduced in this PR. Resolves the cpp-linter complaint from the
PR-open check; sysrap/SEventConfig.cc keeps its existing aligned-assert
style for consistency with surrounding code (the new lines already
conform to the project style).
…Test

Expand the file's leading docblock to make the distinction explicit:
QCurandStateMonolithicTest produces curand internal STATE structs used
to initialise the GPU kernel; generate_precooked_rng produces pre-
evaluated random SAMPLES that U4Random reads in --aligned mode so each
G4 draw matches the corresponding GPU draw byte-for-byte. Different
artifacts, different consumers; both needed for the validation workflow.
@ggalgoczi ggalgoczi force-pushed the feat/aligned-validation branch from 71da757 to 5888c19 Compare May 9, 2026 17:19
@ggalgoczi
Copy link
Copy Markdown
Contributor Author

Pushed a force-with-lease rebase + two follow-up commits. The rebase onto current main auto-cleaned several problems in sysrap/SEventConfig.cc that were never part of this PR but came from a stale main-merge predating #307 (the empty _MaxSlotDefault, the RNG_PHILITEOX branch, and the Initialize_EventName() body), plus the three G4MultiUnion commits already upstream via #249. On tools/generate_precooked_rng.cu (your inline question): it doesn't replace QCurandStateMonolithicTest — that one writes curand internal state structs (~/.opticks/rngcache/RNG/QCurandState_*.bin) used to initialise the GPU kernel, while this one writes pre-evaluated random samples (~/.opticks/precooked/.../rng_sequence_*.npy) that U4Random reads in --aligned mode so each G4 draw matches the corresponding GPU draw byte-for-byte; expanded the file's docblock to spell that out. On the new-executables-per-feature concern: I'd rather keep them separate, StandAloneGeant4Validation takes optical-photon primaries from a gphox::Config torch and without simplifying the code, and example/validation binaries that do one thing well are easier to read and reason about than a configurable do-everything binary. Clang-format applied to the four new files in full; for sysrap/SEventConfig.cc only the touched lines were considered, and they already conform, line 777's spaced-paren assert(...) is intentional to match lines 778-779 right next to it. One scope question: commit cd86a851 (OPTICKS_MAX_RECORD env-var override in DebugLite) is bundled because aligned-mode runs need long step histories, but it's a project-wide DebugLite tweak — happy to split it into its own PR if you'd prefer.

@ggalgoczi ggalgoczi changed the title Feat/aligned validation feat(src): add G4 validation executables for aligned-mode comparison May 9, 2026
cpp-linter runs with lines-changed-only=true, which checks only PR-
modified lines against the project .clang-format. The previous push
left line 777 in the surrounding spaced-paren `assert(...)` style for
local consistency with lines 778-779, but the bot rightly flags this
line because *it* was the one the PR changed.

Apply the project style to that single line. Surrounding pre-existing
code keeps its style; cpp-linter does not check unchanged lines.
Copy link
Copy Markdown
Member

@plexoos plexoos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still do not quite understand how this study is intended to be performed, or what it is meant to demonstrate.

A few points are unclear to me:

  • Where is fresnel_single.gdml? Why is it not included?
  • Why is there not a 100% match when using pre-cooked random numbers?
  • Why is the CUDA file not compiled with CMake?
  • In what order should the executables be run in order to verify the claims?
  • Should the new executables become part of the test suite?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants