|
| 1 | +## Architecture overview |
| 2 | + |
| 3 | +Simphony is a Geant4 plus OptiX optical photon transport stack. Geant4 owns the |
| 4 | +detector construction, material definitions, event loop, and optional reference |
| 5 | +tracking. `G4CXOpticks` is the bridge into the GPU stack: `SetGeometry(world)` |
| 6 | +translates a Geant4 world into Opticks/CSG data once, and `simulate(eventID, |
| 7 | +reset)` launches GPU photon generation and propagation for each event. |
| 8 | + |
| 9 | +Application-facing code lives mainly in `src/`, `config/`, `tests/`, and |
| 10 | +`optiphy/`. The lower-level packages are Opticks-derived framework libraries: |
| 11 | +`sysrap`, `CSG`, `qudarap`, `CSGOptiX`, `u4`, and `g4cx`. Optional DD4hep |
| 12 | +integration plugins live in `dd4hepplugins/` and are built only when DD4hep is |
| 13 | +available. |
| 14 | + |
| 15 | +### Layered view |
| 16 | + |
| 17 | +```mermaid |
| 18 | +%%{init: { |
| 19 | + "flowchart": { |
| 20 | + "nodeSpacing": 14, |
| 21 | + "rankSpacing": 36, |
| 22 | + "htmlLabels": true |
| 23 | + } |
| 24 | +}}%% |
| 25 | +
|
| 26 | +flowchart TB |
| 27 | + subgraph Inputs["Inputs"] |
| 28 | + direction TB |
| 29 | + userinputs["GDML<br/>Geant4 macro<br/>config/*.json"] |
| 30 | + end |
| 31 | +
|
| 32 | + subgraph Apps["Application layer"] |
| 33 | + direction TB |
| 34 | + appcode["installed targets<br/>simg4ox<br/>GPUCerenkov<br/>GPURaytrace"] |
| 35 | + end |
| 36 | +
|
| 37 | + subgraph Bridge["Geant4 bridge"] |
| 38 | + direction TB |
| 39 | + u4["u4<br/>Geant4 translation<br/>materials<br/>surfaces<br/>recorder utilities"] |
| 40 | + g4cx["g4cx<br/>G4CXOpticks"] |
| 41 | + end |
| 42 | +
|
| 43 | + subgraph Runtime["GPU runtime"] |
| 44 | + direction TB |
| 45 | + sysrap["sysrap<br/>NP arrays<br/>SEvt/SSim<br/>config<br/>photon types"] |
| 46 | + csg["CSG<br/>CSGFoundry<br/>primitives<br/>geometry model"] |
| 47 | + qudarap["qudarap<br/>QSim/QEvt<br/>RNG<br/>optical physics"] |
| 48 | + csgoptix["CSGOptiX<br/>OptiX module<br/>GAS/IAS/SBT<br/>launch control"] |
| 49 | + end |
| 50 | +
|
| 51 | + subgraph Outputs["Outputs"] |
| 52 | + direction TB |
| 53 | + persisted["NumPy arrays<br/>hit.npy<br/>photon.npy<br/>record.npy<br/>seq.npy"] |
| 54 | + analysis["analysis with optiphy tools"] |
| 55 | + end |
| 56 | +
|
| 57 | + userinputs --> appcode |
| 58 | + appcode --> u4 |
| 59 | + u4 --> g4cx |
| 60 | + u4 --> sysrap |
| 61 | + u4 --> csg |
| 62 | + sysrap --> csg |
| 63 | + sysrap --> qudarap |
| 64 | + csg --> csgoptix |
| 65 | + qudarap --> csgoptix |
| 66 | + g4cx --> csgoptix |
| 67 | +
|
| 68 | + csgoptix --> persisted |
| 69 | + persisted --> analysis |
| 70 | +``` |
| 71 | + |
| 72 | +### Build targets and packages |
| 73 | + |
| 74 | +The top-level CMake project is `simphony` and builds these core libraries in |
| 75 | +dependency order: |
| 76 | + |
| 77 | +| Layer | CMake target | Directory | Main role | |
| 78 | +|---|---|---|---| |
| 79 | +| System utilities | `SysRap` | `sysrap/` | `NP`/`NPFold`, `SEvt`, `SSim`, logging, config, photon and genstep types | |
| 80 | +| CSG geometry | `CSG` | `CSG/` | `CSGFoundry` and CSG primitive/intersection data | |
| 81 | +| CUDA simulation support | `QUDARap` | `qudarap/` | `QSim`, `QEvt`, RNG, and optical physics tables | |
| 82 | +| OptiX runtime | `CSGOptiX` | `CSGOptiX/` | OptiX PTX/module setup, acceleration structures, SBT, and launches | |
| 83 | +| Geant4 utilities | `U4` | `u4/` | Geant4 material/surface/geometry translation and recorder support | |
| 84 | +| G4-to-GPU bridge | `G4CX` | `g4cx/` | `G4CXOpticks` geometry setup, GPU simulation, and reset/finalization | |
| 85 | + |
| 86 | +The installed application targets from `src/` are: |
| 87 | + |
| 88 | +| Target | Purpose | |
| 89 | +|---|---| |
| 90 | +| `simg4ox` | General Geant4 application that loads GDML, reads a torch JSON config, runs Geant4, and launches GPU simulation at event end | |
| 91 | +| `GPUCerenkov` | Cerenkov-focused example using charged-particle genstep collection | |
| 92 | +| `GPURaytrace` | Cerenkov plus scintillation example with GPU ray tracing | |
| 93 | +| `GPUPhotonSource` | Torch-generated optical photons, with Geant4 and GPU tracking side by side | |
| 94 | +| `GPUPhotonSourceMinimal` | Torch-generated optical photons with GPU-only photon transport | |
| 95 | +| `GPUPhotonFileSource` | User-provided photon text file with GPU-only photon transport | |
| 96 | +| `consgeo` | GDML-to-CSG conversion helper | |
| 97 | +| `simtox` | Torch photon generator that writes `out/photons.npy` | |
| 98 | + |
| 99 | +`simphony_argparse` and `simphony_g4_deps` are interface targets used to share |
| 100 | +third-party argparse headers and common Geant4/G4CX link dependencies. The |
| 101 | +standalone `examples/` tree contains small consumer examples that use an |
| 102 | +installed `simphony` package; it is not added by the top-level `CMakeLists.txt`. |
| 103 | + |
| 104 | +### Runtime data flow |
| 105 | + |
| 106 | +There are two main runtime input modes: |
| 107 | + |
| 108 | +- **Charged-particle driven:** Geant4 tracks charged particles, Cerenkov and/or |
| 109 | + scintillation gensteps are collected into `SEvt`, and the GPU generates and |
| 110 | + propagates optical photons from those gensteps. |
| 111 | +- **Direct photon input:** the application injects an `NP` array of photons into |
| 112 | + `SEvt` with `SetInputPhoton`, using photons generated from a torch JSON config |
| 113 | + or parsed from a user-provided photon file. |
| 114 | + |
| 115 | +```mermaid |
| 116 | +%%{init: { |
| 117 | + "flowchart": { |
| 118 | + "nodeSpacing": 12, |
| 119 | + "rankSpacing": 34, |
| 120 | + "htmlLabels": true |
| 121 | + } |
| 122 | +}}%% |
| 123 | +
|
| 124 | +flowchart TB |
| 125 | + subgraph Geometry["Geometry setup, once"] |
| 126 | + direction TB |
| 127 | + gdml2["GDML file"] |
| 128 | + det["DetectorConstruction<br/>G4GDMLParser"] |
| 129 | + sens["ConstructSDandField<br/>attach SensDet<br/>logical volumes"] |
| 130 | + setgeo["G4CXOpticks::SetGeometry(world)"] |
| 131 | + u4tree["U4Tree<br/>builds stree in SSim"] |
| 132 | + foundry["CSGFoundry<br/>CreateFromSim"] |
| 133 | + create["CSGOptiX::Create<br/>upload geometry<br/>build GAS/IAS/SBT<br/>load PTX"] |
| 134 | + end |
| 135 | +
|
| 136 | + subgraph Event["Per-event work"] |
| 137 | + direction TB |
| 138 | + begin["SEvt::beginOfEvent"] |
| 139 | + eventinput["event input mode<br/>Geant4 tracking to gensteps<br/>or direct photons to SetInputPhoton"] |
| 140 | + evtend["SEvt gather<br/>endOfEvent"] |
| 141 | + simulate["G4CXOpticks::simulate(eventID, false)"] |
| 142 | + qsim["QSim<br/>generate and propagate"] |
| 143 | + launch["OptiX launch<br/>CSG intersections"] |
| 144 | + hits["GPU hits<br/>and event arrays"] |
| 145 | + reset["G4CXOpticks::reset(eventID)"] |
| 146 | + end |
| 147 | +
|
| 148 | + subgraph Persist["Persist and inspect"] |
| 149 | + direction TB |
| 150 | + eventout["opticks_hits_output.txt<br/>g4_hits_output.txt<br/>or o_hits.npy/g_hits.npy<br/><br/>/tmp/$USER/opticks/GEOM/...<br/>hit.npy<br/>photon.npy<br/>record.npy<br/>seq.npy"] |
| 151 | + py["optiphy/ana<br/>optiphy/tools<br/>tests"] |
| 152 | + end |
| 153 | +
|
| 154 | + gdml2 --> det --> sens --> setgeo --> u4tree --> foundry --> create |
| 155 | + create --> simulate |
| 156 | +
|
| 157 | + begin --> eventinput |
| 158 | + eventinput --> evtend |
| 159 | + evtend --> simulate |
| 160 | + simulate --> qsim --> launch --> hits --> reset |
| 161 | +
|
| 162 | + hits --> eventout |
| 163 | + eventout --> py |
| 164 | +``` |
| 165 | + |
| 166 | +### OptiX pipeline and extension points |
| 167 | + |
| 168 | +The fixed OptiX programs are built from `CSGOptiX/CSGOptiX7.cu` into a PTX |
| 169 | +object during the CMake build and installed with the libraries. User code |
| 170 | +usually changes scene content, photon/genstep inputs, or Geant4 actions rather |
| 171 | +than editing the OptiX programs directly. |
| 172 | + |
| 173 | +```mermaid |
| 174 | +%%{init: { |
| 175 | + "flowchart": { |
| 176 | + "nodeSpacing": 12, |
| 177 | + "rankSpacing": 34, |
| 178 | + "htmlLabels": true |
| 179 | + } |
| 180 | +}}%% |
| 181 | +
|
| 182 | +flowchart TB |
| 183 | + subgraph User["User-controlled inputs"] |
| 184 | + direction TB |
| 185 | + usercontrolled["GDML scene<br/>optical properties<br/>sensor tags<br/><br/>gensteps<br/>or input photons<br/><br/>Geant4 app logic<br/>primary generator<br/>event/stepping/tracking actions"] |
| 186 | + end |
| 187 | +
|
| 188 | + subgraph Launch["Launch preparation"] |
| 189 | + direction TB |
| 190 | + launchdata["SEvt/QEvt<br/>event buffers<br/><br/>CSGFoundry<br/>geometry buffers"] |
| 191 | + sbt["CSGOptiX<br/>module<br/>pipeline<br/>SBT"] |
| 192 | + end |
| 193 | +
|
| 194 | + subgraph Programs["CSGOptiX7.cu programs"] |
| 195 | + direction TB |
| 196 | + rg["__raygen__rg<br/>render<br/>simtrace<br/>simulate"] |
| 197 | + simrg["simulate path<br/>qsim generate_photon<br/>qsim propagate"] |
| 198 | + trace["optixTrace"] |
| 199 | + shaderprograms["__intersection__is<br/>CSG primitive tests<br/><br/>__closesthit__ch<br/>boundary payload<br/><br/>__miss__ms<br/>miss payload"] |
| 200 | + end |
| 201 | +
|
| 202 | + subgraph Extend["Lower-level extension points"] |
| 203 | + direction TB |
| 204 | + csgext["CSG/<br/>new primitives<br/>import rules"] |
| 205 | + physext["qudarap/<br/>transport physics<br/>optical models"] |
| 206 | + u4ext["u4/<br/>Geant4 mapping<br/>materials<br/>surfaces<br/>sensors"] |
| 207 | + end |
| 208 | +
|
| 209 | + usercontrolled --> launchdata |
| 210 | + launchdata --> sbt |
| 211 | + sbt --> rg --> simrg --> trace |
| 212 | + trace --> shaderprograms |
| 213 | + csgext -.-> shaderprograms |
| 214 | + physext -.-> simrg |
| 215 | + u4ext -.-> launchdata |
| 216 | +``` |
| 217 | + |
| 218 | +### What users typically provide |
| 219 | + |
| 220 | +| You provide | Where it enters | Purpose | |
| 221 | +|---|---|---| |
| 222 | +| GDML geometry with material and surface properties, plus `SensDet` aux tags when needed | `DetectorConstruction` -> `G4CXOpticks::SetGeometry` | Defines the world, optical media, and sensitive surfaces | |
| 223 | +| Geant4 macro | Geant4 run manager | Controls threads, `/run/beamOn`, visualization, and G4 optical-photon tracking settings | |
| 224 | +| Geant4 user actions in `src/` | Executable-specific app headers | Defines primary generation, event flow, optional G4 reference tracking, and output writing | |
| 225 | +| Torch JSON config in `config/` | `generate_photons` -> `SEvt::SetInputPhoton` | Direct optical photon injection without charged primaries | |
| 226 | +| Photon text file | `GPUPhotonFileSource` -> `SEvt::SetInputPhoton` | Replay or externally generated photon distributions | |
| 227 | +| DD4hep detector/application configuration, when enabled | `dd4hepplugins/` actions | Integrates Simphony GPU optical transport into DD4hep/DDG4 workflows | |
| 228 | + |
| 229 | +### Where to start in the tree |
| 230 | + |
| 231 | +- Start in `src/` if you are adding or changing an installed executable, input |
| 232 | + mode, Geant4 primary generator, or Geant4 action. |
| 233 | +- Use `config/` for torch-source JSON presets and `tests/geom/` for GDML test |
| 234 | + geometries. |
| 235 | +- Move to `g4cx/` and `u4/` when changing Geant4 integration, geometry |
| 236 | + translation, materials, surfaces, sensitive-detector mapping, or event |
| 237 | + recording. |
| 238 | +- Move to `CSG/` when adding a CSG primitive, changing CSG import, or debugging |
| 239 | + geometry intersections. |
| 240 | +- Move to `qudarap/` and `CSGOptiX/` only when extending GPU transport physics, |
| 241 | + event buffers, OptiX launches, or OptiX device programs. |
| 242 | +- Use `dd4hepplugins/` for DD4hep/DDG4 action plugin work. |
| 243 | +- Use `optiphy/ana/`, `optiphy/tools/`, and `tests/` to inspect outputs and |
| 244 | + validate behavior. |
0 commit comments