Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 29 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,46 +44,46 @@ environment, ensure that your system has the following tools installed:
## Build

```shell
git clone https://github.com/BNLNPPS/eic-opticks.git
cmake -S eic-opticks -B build
git clone https://github.com/BNLNPPS/simphony.git
cmake -S simphony -B build
cmake --build build
```

## Docker

Build latest `eic-opticks` image by hand:
Build latest `simphony` image by hand:

```shell
docker build -t ghcr.io/bnlnpps/eic-opticks:latest https://github.com/BNLNPPS/eic-opticks.git
docker build -t ghcr.io/bnlnpps/simphony:latest https://github.com/BNLNPPS/simphony.git
```

Build and run for development:

```shell
docker build -t ghcr.io/bnlnpps/eic-opticks:develop --target=develop .
docker build -t ghcr.io/bnlnpps/simphony:develop --target=develop .
```

Example commands for interactive and non-interactive tests:

```shell
docker run --rm -it -v $HOME/.Xauthority:/root/.Xauthority -e DISPLAY=$DISPLAY --net=host ghcr.io/bnlnpps/eic-opticks:develop
docker run --rm -it -v $HOME/.Xauthority:/root/.Xauthority -e DISPLAY=$DISPLAY --net=host ghcr.io/bnlnpps/simphony:develop

docker run --rm -it -v $HOME:/esi -v $HOME/eic-opticks:/workspaces/eic-opticks -e DISPLAY=$DISPLAY -e HOME=/esi --net=host ghcr.io/bnlnpps/eic-opticks:develop
docker run --rm -it -v $HOME:/esi -v $HOME/simphony:/workspaces/simphony -e DISPLAY=$DISPLAY -e HOME=/esi --net=host ghcr.io/bnlnpps/simphony:develop
Comment thread
plexoos marked this conversation as resolved.

docker run ghcr.io/bnlnpps/eic-opticks bash -c 'simg4ox -g tests/geom/sphere_leak.gdml -m tests/run.mac -c sphere_leak'
docker run ghcr.io/bnlnpps/simphony bash -c 'simg4ox -g tests/geom/sphere_leak.gdml -m tests/run.mac -c sphere_leak'
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

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

This docker run example uses ghcr.io/bnlnpps/simphony without an explicit tag, while the other examples in this section use :develop. Consider using a consistent tag (e.g. :develop or :latest) so readers don’t accidentally run a different image than intended.

Suggested change
docker run ghcr.io/bnlnpps/simphony bash -c 'simg4ox -g tests/geom/sphere_leak.gdml -m tests/run.mac -c sphere_leak'
docker run ghcr.io/bnlnpps/simphony:develop bash -c 'simg4ox -g tests/geom/sphere_leak.gdml -m tests/run.mac -c sphere_leak'

Copilot uses AI. Check for mistakes.
```


## Singularity

```shell
singularity run --nv -B eic-opticks-prefix/:/opt/eic-opticks -B eic-opticks:/workspaces/eic-opticks docker://ghcr.io/bnlnpps/eic-opticks:develop
singularity run --nv -B simphony-prefix/:/opt/simphony -B simphony:/workspaces/simphony docker://ghcr.io/bnlnpps/simphony:develop
Comment thread
plexoos marked this conversation as resolved.
```


## Running a test job at NERSC (Perlmutter)

To submit a test run of `eic-opticks` on Perlmutter, use the following example. Make sure to update
To submit a test run of `simphony` on Perlmutter, use the following example. Make sure to update
any placeholder values as needed.

```
Expand All @@ -97,15 +97,15 @@ sbatch scripts/submit.sh
#SBATCH -C gpu # constraint: use GPU partition
#SBATCH -G 1 # request 1 GPU
#SBATCH -q regular # queue
#SBATCH -J eic-opticks # job name
#SBATCH -J simphony # job name
#SBATCH --mail-user=<USER_EMAIL>
#SBATCH --mail-type=ALL
#SBATCH -A m4402 # allocation account
#SBATCH -t 00:05:00 # time limit (hh:mm:ss)

# Path to your image on Perlmutter
IMAGE="docker:bnlnpps/eic-opticks:develop"
CMD='cd /src/eic-opticks && simg4ox -g $OPTICKS_HOME/tests/geom/sphere_leak.gdml -m $OPTICKS_HOME/tests/run.mac -c sphere_leak'
IMAGE="docker:bnlnpps/simphony:develop"
CMD='cd /src/simphony && simg4ox -g $OPTICKS_HOME/tests/geom/sphere_leak.gdml -m $OPTICKS_HOME/tests/run.mac -c sphere_leak'

# Launch the container using Shifter
srun -n 1 -c 8 --cpu_bind=cores -G 1 --gpu-bind=single:1 shifter --image=$IMAGE /bin/bash -l -c "$CMD"
Expand All @@ -122,7 +122,7 @@ In Geant4, optical surface properties such as **finish**, **model**, and **type*

These enums allow users to configure how optical photons interact with surfaces, controlling behaviors like reflection,
transmission, and absorption based on physical models and surface qualities. The string values corresponding to these
enums (e.g. `"ground"`, `"glisur"`, `"dielectric_dielectric"`) can also be used directly in **GDML** files when defining
enums (e.g. "ground", "glisur", "dielectric_dielectric") can also be used directly in **GDML** files when defining
`<opticalsurface>` elements for geometry. Geant4 will parse these attributes and apply the corresponding surface
behavior.

Expand Down Expand Up @@ -167,21 +167,21 @@ JSON config file (default `config/dev.json`). Key fields:
| Torch photon generation | ✗ | ✗ | ✓ | ✓ | ✗ |
| Photon input from text file | ✗ | ✗ | ✗ | ✗ | ✓ |
| G4 optical photon tracking | ✓ | ✓ | ✓ | ✗ | ✗ |
| GPU simulation (eic-opticks) | ✓ | ✓ | ✓ | ✓ | ✓ |
| GPU simulation (Simphony) | ✓ | ✓ | ✓ | ✓ | ✓ |
| Multi-threaded | ✓ | ✓ | ✗ | ✗ | ✗ |

`GPUCerenkov` and `GPURaytrace` collect gensteps from charged particle interactions and
pass them to eic-opticks for GPU photon generation and tracing. `GPUPhotonSource` and
pass them to Simphony for GPU photon generation and tracing. `GPUPhotonSource` and
`GPUPhotonSourceMinimal` instead generate photons directly from a torch configuration.
`GPUPhotonSource` runs both G4 and GPU tracking for validation, while
`GPUPhotonSourceMinimal` skips G4 tracking entirely for a lean simplistic code so showcase what is needed for GPU only.
`GPUPhotonFileSource` reads photons from a user-provided text file, enabling custom photon
distributions without code changes.


### GDML Scintillation Properties for Geant4 11.x + eic-opticks
### GDML Scintillation Properties for Geant4 11.x + Simphony

For scintillation to work with both Geant4 11.x and eic-opticks GPU simulation, the GDML
For scintillation to work with both Geant4 11.x and Simphony GPU simulation, the GDML
must define properties using the correct syntax:

1. **Const properties** (yield, time constants) must use `coldim="1"` matrices:
Expand All @@ -192,7 +192,7 @@ must define properties using the correct syntax:
</define>
```

2. **Both old and new style property names** are required for eic-opticks compatibility:
2. **Both old and new style property names** are required for Simphony compatibility:
```xml
<material name="Crystal">
<!-- New Geant4 11.x names -->
Expand Down Expand Up @@ -227,23 +227,23 @@ and the **number of G4 threads**. For example:
```

Here setStackPhotons defines **whether G4 will propagate optical photons or
not**. In production eic-opticks (GPU) takes care of the optical photon propagation.
not**. In production Simphony (GPU) takes care of the optical photon propagation.
Additionally the user has to define the **starting position**, **momentum** etc
of the primary particles define in the **GeneratePrimaries** function in
```src/GPUCerenkov.h```. The hits of the optical photons are returned in the
**EndOfRunAction** function. If more photons are simulated than can fit in the
GPU RAM the execution of a GPU call should be moved to **EndOfEventAction**
together with retriving the hits.

### Loading in geometry into EIC-Opticks
### Loading in geometry into Simphony

EIC-Opticks can import geometries with GDML format automatically. There are
Simphony can import geometries with GDML format automatically. There are
about 10 primitives supported now, eg. G4Box. G4Trd or G4Trap are not supported
yet, we are working on them. ```GPUCerenkov``` takes GDML files through
arguments, eg. ```GPUCerenkov -g mygdml.gdml```.

The GDML must define all optical properties of surfaces of materials including:
- Efficiency (used by EIC-Opticks to specify detection efficiency and assign
- Efficiency (used by Simphony to specify detection efficiency and assign
sensitive surfaces)
- Refractive index
- Group velocity
Expand All @@ -253,21 +253,21 @@ The GDML must define all optical properties of surfaces of materials including:

## Performance studies

In order to quantify the speed-up achieved by EIC-Opticks compared to G4 we
In order to quantify the speed-up achieved by Simphony compared to G4 we
provide a python code that runs the same G4 simulation with and without tracking
optical photons in G4. The difference of the runs will yield the time required
to simulate photons. Meanwhile the same photons are simulated on GPU with
EIC-Opticks and the simulation time is saved.
Simphony and the simulation time is saved.

```
mkdir -p /tmp/out/dev
mkdir -p /tmp/out/rel

docker build -t eic-opticks:perf-dev --target=develop
docker run --rm -t -v /tmp/out:/tmp/out eic-opticks:perf-dev run-performance -o /tmp/out/dev
docker build -t simphony:perf-dev --target=develop
docker run --rm -t -v /tmp/out:/tmp/out simphony:perf-dev run-performance -o /tmp/out/dev

docker build -t eic-opticks:perf-rel --target=release
docker run --rm -t -v /tmp/out:/tmp/out eic-opticks:perf-rel run-performance -o /tmp/out/rel
docker build -t simphony:perf-rel --target=release
docker run --rm -t -v /tmp/out:/tmp/out simphony:perf-rel run-performance -o /tmp/out/rel
Comment on lines +266 to +270
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

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

These docker build commands are missing the required build context argument (e.g. .). As written, docker build -t ... --target=... will fail; please add the context path (and optionally -f Dockerfile if needed).

Copilot uses AI. Check for mistakes.
```

### Debug Analysis with `optiphy/ana/photon_history_summary.py`
Expand Down
30 changes: 15 additions & 15 deletions dd4hepplugins/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
#------------------------------- -*- cmake -*- -------------------------------#
# eic-opticks DD4hep integration plugins
# simphony DD4hep integration plugins
#
# Builds DD4hep action plugins that integrate eic-opticks GPU-accelerated
# Builds DD4hep action plugins that integrate simphony GPU-accelerated
# optical photon simulation into DD4hep/Geant4.
#
# Works both as part of the top-level eic-opticks build (in-tree) and as a
# standalone project against an installed eic-opticks.
# Works both as part of the top-level simphony build (in-tree) and as a
# standalone project against an installed simphony.
#
# Usage from a DD4hep steering file:
# OpticsRun -- initializes/finalizes G4CXOpticks per run
Expand All @@ -15,13 +15,13 @@
# Detect standalone vs in-tree build
if(NOT TARGET G4CX)
cmake_minimum_required(VERSION 3.18 FATAL_ERROR)
project(ddeicopticks VERSION 0.1.0 LANGUAGES CXX)
project(ddsimphony VERSION 0.1.0 LANGUAGES CXX)
find_package(DD4hep REQUIRED COMPONENTS DDG4 DDCore)
find_package(eic-opticks REQUIRED)
find_package(simphony REQUIRED)
find_package(Geant4 REQUIRED)
set(_g4cx eic-opticks::G4CX)
set(_u4 eic-opticks::U4)
set(_sysrap eic-opticks::SysRap)
set(_g4cx simphony::G4CX)
set(_u4 simphony::U4)
set(_sysrap simphony::SysRap)
else()
# In-tree: DD4hep already found by parent, targets use local names
find_package(Geant4 REQUIRED)
Expand All @@ -35,7 +35,7 @@ dd4hep_set_compiler_flags()
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
set(LIBRARY_OUTPUT_PATH "${CMAKE_CURRENT_BINARY_DIR}")

dd4hep_add_plugin(ddeicopticks
dd4hep_add_plugin(ddsimphony
SOURCES
OpticsRun.cc
OpticsEvent.cc
Expand All @@ -47,17 +47,17 @@ dd4hep_add_plugin(ddeicopticks
${_u4}
${_sysrap}
)
# STANDALONE changes class export macros in eic-opticks headers;
# only needed when building outside the main eic-opticks tree.
# STANDALONE changes class export macros in simphony headers;
# only needed when building outside the main simphony tree.
if(NOT TARGET G4CX)
target_compile_definitions(ddeicopticks PRIVATE STANDALONE)
target_compile_definitions(ddsimphony PRIVATE STANDALONE)
endif()

install(TARGETS ddeicopticks
install(TARGETS ddsimphony
LIBRARY DESTINATION lib
)

install(FILES
${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_SHARED_MODULE_PREFIX}ddeicopticks.components
${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_SHARED_MODULE_PREFIX}ddsimphony.components
DESTINATION lib
)
6 changes: 3 additions & 3 deletions dd4hepplugins/OpticsEvent.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
#include <map>
#include <sphoton.h>

namespace ddeicopticks
namespace ddsimphony
{
//---------------------------------------------------------------------------//
OpticsEvent::OpticsEvent(dd4hep::sim::Geant4Context *ctxt, std::string const &name)
Expand Down Expand Up @@ -220,6 +220,6 @@ dd4hep::sim::Geant4Tracker::Hit *OpticsEvent::createTrackerHit(sphoton const &ph
}

//---------------------------------------------------------------------------//
} // namespace ddeicopticks
} // namespace ddsimphony

DECLARE_GEANT4ACTION_NS(ddeicopticks, OpticsEvent)
DECLARE_GEANT4ACTION_NS(ddsimphony, OpticsEvent)
6 changes: 3 additions & 3 deletions dd4hepplugins/OpticsEvent.hh
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@
class SEvt;
struct sphoton;

namespace ddeicopticks
namespace ddsimphony
{
//---------------------------------------------------------------------------//
/*!
* DDG4 action plugin for eic-opticks event-level GPU simulation.
* DDG4 action plugin for simphony event-level GPU simulation.
*
* At begin-of-event: prepares GPU event buffer (SEvt).
* At end-of-event: triggers GPU optical photon simulation via
Expand Down Expand Up @@ -47,4 +47,4 @@ class OpticsEvent final : public dd4hep::sim::Geant4EventAction
};

//---------------------------------------------------------------------------//
} // namespace ddeicopticks
} // namespace ddsimphony
6 changes: 3 additions & 3 deletions dd4hepplugins/OpticsRun.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

#include "DD4hepSensorIdentifier.hh"

namespace ddeicopticks
namespace ddsimphony
{

//---------------------------------------------------------------------------//
Expand Down Expand Up @@ -150,6 +150,6 @@ void OpticsRun::end(G4Run const *run)
}

//---------------------------------------------------------------------------//
} // namespace ddeicopticks
} // namespace ddsimphony

DECLARE_GEANT4ACTION_NS(ddeicopticks, OpticsRun)
DECLARE_GEANT4ACTION_NS(ddsimphony, OpticsRun)
6 changes: 3 additions & 3 deletions dd4hepplugins/OpticsRun.hh
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
#include <DDG4/Geant4RunAction.h>
#include <string>

namespace ddeicopticks
namespace ddsimphony
{
//---------------------------------------------------------------------------//
/*!
* DDG4 action plugin for eic-opticks run-level lifecycle.
* DDG4 action plugin for simphony run-level lifecycle.
*
* At begin-of-run: initializes G4CXOpticks geometry from the Geant4 world
* volume, translating the geometry to OptiX acceleration structures on GPU.
Expand All @@ -35,4 +35,4 @@ class OpticsRun final : public dd4hep::sim::Geant4RunAction
};

//---------------------------------------------------------------------------//
} // namespace ddeicopticks
} // namespace ddsimphony
6 changes: 3 additions & 3 deletions dd4hepplugins/OpticsSteppingAction.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ namespace
G4Mutex genstep_mutex = G4MUTEX_INITIALIZER;
}

namespace ddeicopticks
namespace ddsimphony
{
//---------------------------------------------------------------------------//
OpticsSteppingAction::OpticsSteppingAction(dd4hep::sim::Geant4Context *ctxt, std::string const &name)
Expand Down Expand Up @@ -139,6 +139,6 @@ void OpticsSteppingAction::operator()(const G4Step *step, G4SteppingManager *mgr
}

//---------------------------------------------------------------------------//
} // namespace ddeicopticks
} // namespace ddsimphony

DECLARE_GEANT4ACTION_NS(ddeicopticks, OpticsSteppingAction)
DECLARE_GEANT4ACTION_NS(ddsimphony, OpticsSteppingAction)
6 changes: 3 additions & 3 deletions dd4hepplugins/OpticsSteppingAction.hh
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
#include <DDG4/Geant4SteppingAction.h>
#include <string>

namespace ddeicopticks
namespace ddsimphony
{
//---------------------------------------------------------------------------//
/*!
* DDG4 stepping action that intercepts standard Geant4 Cerenkov and
* Scintillation processes and collects gensteps for GPU simulation.
*
* This follows the same approach as eic-opticks GPUCerenkov example:
* This follows the same approach as simphony GPUCerenkov example:
* use standard G4Cerenkov / G4Scintillation, then read back the photon
* count via GetNumPhotons() and pack gensteps for the GPU.
*/
Expand All @@ -31,4 +31,4 @@ class OpticsSteppingAction final : public dd4hep::sim::Geant4SteppingAction
};

//---------------------------------------------------------------------------//
} // namespace ddeicopticks
} // namespace ddsimphony
10 changes: 5 additions & 5 deletions dd4hepplugins/examples/benchmark_drich.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@

cpu -- Optical photons generated AND tracked on CPU by Geant4
baseline -- Optical photons generated but NOT tracked (SetStackPhotons=false)
gpu -- Optical photons simulated on GPU via eic-opticks
gpu -- Optical photons simulated on GPU via simphony

Speedup = CPU_optical_time / GPU_simulate_time
where CPU_optical_time = T(cpu) - T(baseline)
and GPU_simulate_time = wall time of G4CXOpticks::simulate()

Prerequisites:
- Spack environment activated with DD4hep, Geant4, eic-opticks
- Spack environment activated with DD4hep, Geant4, simphony
- `spack load epic` (sets DETECTOR_PATH to EPIC geometry)
- DD4HEP_LIBRARY_PATH includes /opt/local/lib (eic-opticks plugins)
- DD4HEP_LIBRARY_PATH includes /opt/local/lib (simphony plugins)

Usage:
python3 benchmark_drich.py # all modes, 10 events
Expand Down Expand Up @@ -134,7 +134,7 @@ def run_single_mode(mode, num_events, photon_threshold=0, multiplicity=100,
filt.Cut = 1e12
seq.adopt(filt)

# eic-opticks DDG4 plugins
# simphony DDG4 plugins
stepping = DDG4.SteppingAction(
kernel, "OpticsSteppingAction/OpticsStep1"
)
Expand Down Expand Up @@ -253,7 +253,7 @@ def run_all(num_events, photon_threshold=0, multiplicity=100, geometry="1sector"
label = {
"baseline": "baseline (no photon tracking)",
"cpu": "cpu (photons tracked on CPU)",
"gpu": "gpu (photons on GPU via eic-opticks)",
"gpu": "gpu (photons on GPU via simphony)",
}[mode]
extra = f", threshold={pt}" if pt > 0 else ""
print(f"\n{'='*60}")
Expand Down
Loading
Loading