Skip to content

Commit 6cc3be0

Browse files
authored
Initial setup for G4 FastSim hooks with a toy example for Absorber (#15699)
Introduce end-to-end fast simulation support for Geant4 in O2, including a new `Detectors/FastSim` module, a reusable fast-simulation hook, and a toy absorber model. The new infrastructure allows models to replace detailed particle transport inside detector envelopes, while preserving energy deposition and particle propagation. Models are triggered by their envelope volume, with the required Geant4 regions derived automatically from the envelope's geometry and materials. For the absorber, add a dedicated envelope material so the front absorber can be represented as a single fast-simulation region without changing its physics. Provide a runnable `FastSim_Absorber` example that compares detailed and fast transport and demonstrates the resulting reduction in tracked steps. Fast simulation remains opt-in: runs without configured models behave exactly as before.
1 parent 9cda446 commit 6cc3be0

17 files changed

Lines changed: 950 additions & 4 deletions

File tree

Common/SimConfig/include/SimConfig/G4Params.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,14 @@ struct G4Params : public o2::conf::ConfigurableParamHelper<G4Params> {
5454

5555
bool g4scoring = false;
5656
bool g4fluenceweight = false;
57+
58+
// Fast simulation. Empty fastSimModels (the default) disables the feature
59+
// entirely; see Detectors/gconfig/include/SimSetup/G4FastSimulation.h.
60+
std::string fastSimModels = ""; // comma-separated model names to activate
61+
std::string fastSimEnvelope = ""; // volume a model stands in for, e.g. AFaM; the media of its
62+
// subtree are collected automatically
63+
std::string fastSimRegions = ""; // optional explicit media, overriding the subtree walk
64+
float fastSimMinEnergy = 1.f; // GeV; below this the detailed transport runs
5765
O2ParamDef(G4Params, "G4");
5866
};
5967

Detectors/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ add_subdirectory(ForwardAlign)
5353

5454

5555
if(BUILD_SIMULATION)
56+
add_subdirectory(FastSim)
5657
add_subdirectory(gconfig)
5758
o2_data_file(COPY gconfig DESTINATION Detectors)
5859
endif()

Detectors/FastSim/CMakeLists.txt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Copyright 2019-2026 CERN and copyright holders of ALICE O2.
2+
# See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3+
# All rights not expressly granted are reserved.
4+
#
5+
# This software is distributed under the terms of the GNU General Public
6+
# License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7+
#
8+
# In applying this license CERN does not waive the privileges and immunities
9+
# granted to it by virtue of its status as an Intergovernmental Organization
10+
# or submit itself to any jurisdiction.
11+
12+
o2_add_library(FastSim
13+
SOURCES src/FastSimModel.cxx
14+
src/FastSimRegions.cxx
15+
src/ToyAbsorberFastSim.cxx
16+
src/G4FastSimulation.cxx
17+
PUBLIC_LINK_LIBRARIES MC::Geant4VMC MC::Geant4 O2::SimConfig
18+
)
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
// Copyright 2019-2026 CERN and copyright holders of ALICE O2.
2+
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3+
// All rights not expressly granted are reserved.
4+
//
5+
// This software is distributed under the terms of the GNU General Public
6+
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7+
//
8+
// In applying this license CERN does not waive the privileges and immunities
9+
// granted to it by virtue of its status as an Intergovernmental Organization
10+
// or submit itself to any jurisdiction.
11+
12+
#ifndef O2_FASTSIM_MODEL_H_
13+
#define O2_FASTSIM_MODEL_H_
14+
15+
/// Base class for fast simulation models.
16+
///
17+
/// A fast simulation model replaces the detailed transport through a region of
18+
/// the geometry by a function from the particle that enters it to the particles
19+
/// that leave it. `DoIt()` is Geant4's own entry point
20+
/// (`G4VFastSimulationModel::DoIt`); the implementation here wraps the logic
21+
/// common to every model and delegates the physics to `sample()`. A model that
22+
/// needs a different shape can still override `DoIt()`.
23+
24+
#include "G4VFastSimulationModel.hh"
25+
26+
#include <vector>
27+
28+
class G4FastStep;
29+
class G4FastTrack;
30+
class G4ParticleDefinition;
31+
32+
namespace o2::fastsim
33+
{
34+
35+
/// The particle entering the envelope, plus the geometric context a model needs.
36+
/// Units are the O2/VMC ones: cm, GeV, ns.
37+
struct FastSimInput {
38+
int pdg = 0;
39+
double position[3] = {}; ///< global, on the envelope surface
40+
double direction[3] = {}; ///< unit vector
41+
double kineticEnergy = 0.; ///< GeV
42+
double mass = 0.; ///< GeV
43+
double time = 0.; ///< ns
44+
double exitDistance = 0.; ///< cm from `position` to the ENVELOPE surface along `direction`
45+
};
46+
47+
/// One particle leaving the envelope.
48+
struct FastSimOutput {
49+
int pdg = 0;
50+
double position[3] = {}; ///< global; put it outside the envelope surface
51+
double momentum[3] = {}; ///< GeV/c
52+
double time = 0.; ///< ns
53+
};
54+
55+
/// A secondary created exactly on the envelope surface is located by the
56+
/// navigator in whichever daughter owns that point, which costs two extra
57+
/// zero-length steps before it gets out. Models should emit just beyond it.
58+
constexpr double kSurfaceEpsilonCm = 1e-5;
59+
60+
/// Base class for fast simulation models.
61+
///
62+
/// The model is attached to regions (see G4FastSimulation.h) purely so that
63+
/// Geant4 consults it; what it encloses is the ENVELOPE VOLUME named below,
64+
/// which is normally the mother volume of a whole module. The two are
65+
/// deliberately separate, because a Geant4 region in O2 can only ever be "every
66+
/// volume of a given material" -- the VMC special cuts make every logical volume
67+
/// a root of its own material's region, and Geant4 stops propagating a region at
68+
/// any such daughter. So `G4FastTrack::GetEnvelopeSolid()` would hand back one
69+
/// absorber piece rather than the absorber, and this class does not use it.
70+
///
71+
/// Containment and the exit distance are taken from the track's own touchable,
72+
/// which already carries the full ancestry and the transform of every level.
73+
class FastSimModel : public G4VFastSimulationModel
74+
{
75+
public:
76+
FastSimModel(const G4String& name, const G4String& envelopeVolume, double minEnergyGeV);
77+
78+
G4bool IsApplicable(const G4ParticleDefinition& particle) override;
79+
G4bool ModelTrigger(const G4FastTrack& fastTrack) override;
80+
81+
/// Wraps the common logic of a fast simulation action and delegates the
82+
/// physics to `sample()`: it measures the distance to the envelope surface,
83+
/// kills the incident particle, stacks what `sample()` returned and books the
84+
/// energy difference as a deposit. Override it for a model that does not fit
85+
/// that shape.
86+
void DoIt(const G4FastTrack& fastTrack, G4FastStep& fastStep) override;
87+
88+
protected:
89+
/// Given the particle that entered, return everything that leaves. This is
90+
/// the function a trained model implements.
91+
virtual std::vector<FastSimOutput> sample(const FastSimInput& input) const = 0;
92+
93+
private:
94+
/// The track's ancestry level at which the envelope volume sits, or -1 when
95+
/// the track is not inside it at all.
96+
int envelopeDepth(const G4Track* track) const;
97+
98+
G4String mEnvelope; ///< logical volume the model encloses
99+
double mMinEnergy = 0.; ///< internal Geant4 units; below this the detailed transport runs
100+
mutable bool mWarned = false;
101+
};
102+
103+
} // namespace o2::fastsim
104+
105+
#endif // O2_FASTSIM_MODEL_H_
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
// Copyright 2019-2026 CERN and copyright holders of ALICE O2.
2+
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3+
// All rights not expressly granted are reserved.
4+
//
5+
// This software is distributed under the terms of the GNU General Public
6+
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7+
//
8+
// In applying this license CERN does not waive the privileges and immunities
9+
// granted to it by virtue of its status as an Intergovernmental Organization
10+
// or submit itself to any jurisdiction.
11+
12+
#ifndef O2_FASTSIM_REGIONS_H_
13+
#define O2_FASTSIM_REGIONS_H_
14+
15+
/// Deriving a model's regions from its envelope volume.
16+
///
17+
/// Geant4-VMC attaches a fast simulation model to regions, and in O2 a region
18+
/// can only be "every volume of a given material" (see FastSimModel.h). To have
19+
/// the model consulted everywhere inside a module, it must therefore be attached
20+
/// to every material that module is built from -- which is a list nobody should
21+
/// maintain by hand, because it changes whenever the geometry does.
22+
///
23+
/// So walk the envelope's subtree and collect the media as they actually are.
24+
25+
#include "TG4VUserPostDetConstruction.h"
26+
27+
#include <set>
28+
#include <string>
29+
#include <vector>
30+
31+
class TGeoVolume;
32+
33+
namespace o2::fastsim
34+
{
35+
36+
/// Every tracking medium used by `volume` or anything below it.
37+
/// Takes a non-const pointer because TGeo's accessors are not const.
38+
std::set<std::string> mediaInSubtree(TGeoVolume* volume);
39+
40+
/// Same, looked up by volume name in the current TGeo geometry. Empty if there
41+
/// is no such volume.
42+
std::set<std::string> mediaInSubtree(const std::string& volumeName);
43+
44+
/// Sets each model's regions from its envelope, in the one window where that is
45+
/// possible: after the geometry is built and before Geant4-VMC turns the media
46+
/// into regions.
47+
class FastSimRegionConstruction : public TG4VUserPostDetConstruction
48+
{
49+
public:
50+
struct ModelRegions {
51+
std::string model;
52+
std::string envelope; ///< volume whose subtree supplies the media
53+
std::string regions; ///< explicit media, used instead of the walk if given
54+
};
55+
56+
explicit FastSimRegionConstruction(std::vector<ModelRegions> models);
57+
void Construct() override;
58+
59+
private:
60+
std::vector<ModelRegions> mModels;
61+
};
62+
63+
} // namespace o2::fastsim
64+
65+
#endif // O2_FASTSIM_REGIONS_H_
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// Copyright 2019-2026 CERN and copyright holders of ALICE O2.
2+
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3+
// All rights not expressly granted are reserved.
4+
//
5+
// This software is distributed under the terms of the GNU General Public
6+
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7+
//
8+
// In applying this license CERN does not waive the privileges and immunities
9+
// granted to it by virtue of its status as an Intergovernmental Organization
10+
// or submit itself to any jurisdiction.
11+
12+
#ifndef O2_FASTSIM_G4_FAST_SIMULATION_H_
13+
#define O2_FASTSIM_G4_FAST_SIMULATION_H_
14+
15+
/// Wiring of the fast simulation models into the Geant4 engine.
16+
///
17+
/// The feature is OFF unless `G4.fastSimModels` names a model.
18+
///
19+
/// o2-sim -n 10 -g pythia8pp -e TGeant4 -m PIPE ABSO
20+
/// --configKeyValues "G4.fastSimModels=toyAbsorber;
21+
/// G4.fastSimEnvelope=AFaM"
22+
///
23+
/// `G4.fastSimEnvelope` names the VOLUME the model stands in for. The regions
24+
/// Geant4 needs in order to consult the model are derived from it by walking its
25+
/// subtree and collecting the media (FastSimRegions.h) -- a region in O2 can only
26+
/// be "every volume of a given material", so covering a module means naming all
27+
/// of its materials, and that list should not be maintained by hand.
28+
///
29+
/// `G4.fastSimRegions` overrides the walk with an explicit space-separated list
30+
/// of media, for when a model should see less than a whole subtree.
31+
32+
#include "TG4RunConfiguration.h"
33+
#include "TG4VUserFastSimulation.h"
34+
#include "TG4VUserPostDetConstruction.h"
35+
36+
#include <string>
37+
#include <vector>
38+
39+
namespace o2::fastsim
40+
{
41+
42+
/// Creates and registers the models named in `G4.fastSimModels`.
43+
class G4FastSimulation : public TG4VUserFastSimulation
44+
{
45+
public:
46+
G4FastSimulation(std::vector<std::string> models, const std::string& envelope,
47+
double minEnergyGeV);
48+
void Construct() override;
49+
50+
private:
51+
std::vector<std::string> mModels;
52+
std::string mEnvelope;
53+
double mMinEnergy = 1.;
54+
};
55+
56+
/// Supplies Geant4-VMC with the fast simulation models and their regions.
57+
/// Returns nullptr when no model is configured, so nothing is set up.
58+
class G4RunConfiguration : public TG4RunConfiguration
59+
{
60+
public:
61+
using TG4RunConfiguration::TG4RunConfiguration;
62+
TG4VUserFastSimulation* CreateUserFastSimulation() override;
63+
TG4VUserPostDetConstruction* CreateUserPostDetConstruction() override;
64+
};
65+
66+
} // namespace o2::fastsim
67+
68+
#endif // O2_FASTSIM_G4_FAST_SIMULATION_H_
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright 2019-2026 CERN and copyright holders of ALICE O2.
2+
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3+
// All rights not expressly granted are reserved.
4+
//
5+
// This software is distributed under the terms of the GNU General Public
6+
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7+
//
8+
// In applying this license CERN does not waive the privileges and immunities
9+
// granted to it by virtue of its status as an Intergovernmental Organization
10+
// or submit itself to any jurisdiction.
11+
12+
#ifndef O2_FASTSIM_TOY_ABSORBER_H_
13+
#define O2_FASTSIM_TOY_ABSORBER_H_
14+
15+
#include "FastSim/FastSimModel.h"
16+
17+
namespace o2::fastsim
18+
{
19+
20+
/// A toy fast simulation model for the absorber: one particle out, continuing
21+
/// along the incident direction with the energy exponentially attenuated over
22+
/// the path through the envelope.
23+
class ToyAbsorberFastSim : public FastSimModel
24+
{
25+
public:
26+
using FastSimModel::FastSimModel;
27+
28+
protected:
29+
std::vector<FastSimOutput> sample(const FastSimInput& input) const override;
30+
};
31+
32+
} // namespace o2::fastsim
33+
34+
#endif // O2_FASTSIM_TOY_ABSORBER_H_

0 commit comments

Comments
 (0)