Skip to content

feat(qudarap): add GPU wavelength shifting (WLS) physics#269

Merged
plexoos merged 8 commits into
mainfrom
feat/wls-physics
Apr 28, 2026
Merged

feat(qudarap): add GPU wavelength shifting (WLS) physics#269
plexoos merged 8 commits into
mainfrom
feat/wls-physics

Conversation

@ggalgoczi
Copy link
Copy Markdown
Contributor

Add wavelength shifting (WLS) physics to the GPU optical photon simulation. Implements WLS absorption and re-emission using material properties (WLSABSLENGTH, WLSCOMPONENT, WLSTIMECONSTANT) with ICDF-based wavelength sampling via texture lookup. Adds U4WLS.h for extracting WLS properties from Geant4 materials during geometry conversion. Includes exponential time delay for re-emitted photons matching G4OpWLS behavior. Validated on wls_test.gdml geometry with 990/1000 photon detection rate.

@ggalgoczi ggalgoczi requested a review from plexoos April 4, 2026 02:52
@ggalgoczi ggalgoczi mentioned this pull request Apr 4, 2026
@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.

@plexoos
Copy link
Copy Markdown
Member

plexoos commented Apr 16, 2026

@ggalgoczi ping

Implement WLS absorption and re-emission in the GPU optical photon
simulation. Adds material property scanning (WLSABSLENGTH, WLSCOMPONENT,
WLSTIMECONSTANT), ICDF-based wavelength sampling via texture lookup,
and exponential time delay for re-emitted photons.

Key files: QWls.cc/hh (host), qwls.h (device), U4WLS.h (G4 property
extraction), qsim.h (propagation integration).

Includes wls_test.gdml validation geometry.
@ggalgoczi ggalgoczi changed the title Feat/wls physics feat(qudarap): add GPU wavelength shifting (WLS) physics Apr 17, 2026
@ggalgoczi
Copy link
Copy Markdown
Contributor Author

@plexoos rebased. Needed fixes because #260 used the same slot on GPU that I intended for WLS. Please ping me here once you have finished with review.

@plexoos
Copy link
Copy Markdown
Member

plexoos commented Apr 17, 2026

Thank you for cleaning up the PR branch, @ggalgoczi — that’s very helpful.

One conceptual question: how does this new implementation differ from the existing re-emission physics already implemented in the codebase?

@ggalgoczi
Copy link
Copy Markdown
Contributor Author

ggalgoczi commented Apr 17, 2026

Thank you for cleaning up the PR branch, @ggalgoczi — that’s very helpful.

One conceptual question: how does this new implementation differ from the existing re-emission physics already implemented in the codebase?

The short answer is that the existing re-emission is really just scintillation reemission, it was built for JUNO's liquid scintillator where the scintillation spectrum happens to be the same as the re-emission spectrum. So it piggybacks on normal bulk absorption (ABSLENGTH) and samples the wavelength from FAST/SLOWCOMPONENT.

WLS is a different physical process. The main differences:

  • It has its own absorption length (WLSABSLENGTH) that competes with normal absorption and Rayleigh every step, instead of only kicking in after bulk absorption
  • It uses its own emission spectrum (WLSCOMPONENT), for EIC/DUNE wavelength shifters this is completely different from any scintillation spectrum
  • It adds an exponential time delay (WLSTIMECONSTANT), the existing path doesn't
  • It's material-indexed so only specific materials act as wavelength shifters

Basically it mirrors how Geant4 treats G4OpWLS as separate from G4Scintillation. We couldn't integrate WLS into the existing path without getting the wrong absorption behavior and the wrong emission spectrum.

@plexoos
Copy link
Copy Markdown
Member

plexoos commented Apr 17, 2026

I agree with your summary — it matches my understanding as well. I think this point is important enough to include in the PR description as part of the motivation.

@plexoos
Copy link
Copy Markdown
Member

plexoos commented Apr 17, 2026

Since this PR doesn’t currently include a test command, how should someone verify at a basic level that WLS is working correctly? For example, would the following command be an appropriate way to test it?

GPUPhotonSourceMinimal -g tests/geom/wls_test.gdml -c wls_test -m tests/run.mac -s 42

@ggalgoczi
Copy link
Copy Markdown
Contributor Author

Since this PR doesn’t currently include a test command, how should someone verify at a basic level that WLS is working correctly? For example, would the following command be an appropriate way to test it?

GPUPhotonSourceMinimal -g tests/geom/wls_test.gdml -c wls_test -m tests/run.mac -s 42

README under "Example 6: Wavelength Shifting" shows that the command you shared is indeed the correct way to test the implementation.

For a more thorough GPU vs G4 statistical validation, PR #270 adds tests/test_wavelength_shifting.sh which runs 10k photons and does KS tests on the wavelength and timing distributions.

@plexoos
Copy link
Copy Markdown
Member

plexoos commented Apr 20, 2026

I was able to confirm what appears to be the expected output from the test command:

GPUPhotonSourceMinimal -g tests/geom/wls_test.gdml -c wls_test -m tests/run.mac -s 42

The recorded hit wavelengths are all above 350 nm, with a minimum of 405.174 nm and a maximum of 675.975 nm. That looks consistent with the expected wavelength-shifting (WLS) behavior.

@plexoos
Copy link
Copy Markdown
Member

plexoos commented Apr 20, 2026

Please address the cpp-linter comments: https://github.com/BNLNPPS/eic-opticks/actions/runs/24686507193/job/72197171472?pr=269

These appear to be valid, e.g. there are many lines with whitespace before the closing semicolon, etc.

Please run clang-format on the new files, and also on the modified hunks in the existing files.

Comment thread qudarap/qsim.h Outdated
Comment thread u4/U4WLS.h Outdated
Comment thread qudarap/qsim.h Outdated
@plexoos
Copy link
Copy Markdown
Member

plexoos commented Apr 24, 2026

We are approaching our two-week cadence, and it would be good to cut a new 0.5.0 release soon. This PR can be included once you address the pending comments.

@ggalgoczi
Copy link
Copy Markdown
Contributor Author

We are approaching our two-week cadence, and it would be good to cut a new 0.5.0 release soon. This PR can be included once you address the pending comments.

I asked you to tag/ping me when you are ready with the full review of a PR. I assume you are ready, correct?

@plexoos
Copy link
Copy Markdown
Member

plexoos commented Apr 24, 2026

Go ahead!

@ggalgoczi
Copy link
Copy Markdown
Contributor Author

Thanks! Getting at it.

- Gate WLS competition on has_wls(mat_idx) so non-WLS materials
  no longer take an extra absorption channel via the stale
  wls_absorption_distance comparison
- Replace WLS reemission polarization with the qscint::mom_pol_wavelength
  pattern (perpendicular by construction) to avoid the near-parallel
  random-cross-product instability
- Drop unused const NPFold* materials parameter from U4WLS::Create
- clang-format (Microsoft style) on the new WLS files and on the
  PR-modified hunks of existing files
@ggalgoczi
Copy link
Copy Markdown
Contributor Author

None of the issues raised resulted in a bug in current geometries but I agree it can lead to problems down the road so addressed in the following changes:

  1. WLS competition (qsim.h:787) _ gated wls_wins on has_wls(mat_idx) so non-WLS materials no longer take an extra absorption channel via the WLS distance race; they fall through to the normal absorb/scatter competition. Removed the now-dead inner BULK_ABSORB branch.

  2. Unused parameter (U4WLS.h:86) _ dropped const NPFold* materials from U4WLS::Create and updated the sole caller in U4Tree::initWLS.

  3. Polarization sampling (qsim.h:829) _ replaced normalize(cross(uniform_sphere(...), p.mom)) with the qscint::mom_pol_wavelength pattern: pol = (cost·cosp, cost·sinp, -sint) (perpendicular to mom by construction) then a random rotation around mom. Avoids the near-parallel cross-product instability. Drops one RNG draw per reemission (4_3).

  4. clang-format _ Microsoft style applied: whole-file on the new WLS sources, changed-line-only on the PR-modified hunks of existing files.

ggalgoczi and others added 2 commits April 28, 2026 17:00
cpp-linter v20.1.2 (style: microsoft, lines-changed-only) flagged
qudarap/qsim.h and sysrap/sstate.h after the previous format pass
(done with local clang-format v18) missed some hunks. No code or
behaviour changes; only whitespace, pointer/reference placement,
brace style, and line wrapping inside lines already touched by the
WLS PR diff vs origin/main.
@plexoos plexoos self-requested a review April 28, 2026 21:04
@plexoos plexoos merged commit 281e8da into main Apr 28, 2026
21 of 22 checks passed
@plexoos plexoos deleted the feat/wls-physics branch April 28, 2026 22:26
@plexoos plexoos restored the feat/wls-physics branch April 28, 2026 22:28
@plexoos plexoos deleted the feat/wls-physics branch April 28, 2026 22:32
ggalgoczi added a commit that referenced this pull request May 9, 2026
PR #269 added tests/geom/wls_test.gdml and config/wls_test.json
specifically for WLS validation, but they were not used by any test.
This PR was originally adding a second WLS geometry (wls_scatter_viz)
with a Rayleigh-scattering medium. The scattering is incidental to a
WLS-physics validation, so consolidate onto the simpler wls_test
geometry already on main and drop the duplicate assets.

The four physics tests (hit count, WLS fraction, shifted-wavelength
KS, shifted-time KS) remain meaningful: with WLSABSLENGTH=0.1mm at
350nm in a 20mm sphere, both GPU and G4 should produce >99% shifted
photons, and the KS tests on the shifted-photon populations are
unaffected.
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