Skip to content
Open
8 changes: 8 additions & 0 deletions Common/SimConfig/include/SimConfig/G4Params.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,14 @@ struct G4Params : public o2::conf::ConfigurableParamHelper<G4Params> {

bool g4scoring = false;
bool g4fluenceweight = false;

// Fast simulation. Empty fastSimModels (the default) disables the feature
// entirely; see Detectors/gconfig/include/SimSetup/G4FastSimulation.h.
std::string fastSimModels = ""; // comma-separated model names to activate
std::string fastSimEnvelope = ""; // volume a model stands in for, e.g. AFaM; the media of its
// subtree are collected automatically
std::string fastSimRegions = ""; // optional explicit media, overriding the subtree walk
float fastSimMinEnergy = 1.f; // GeV; below this the detailed transport runs
O2ParamDef(G4Params, "G4");
};

Expand Down
1 change: 1 addition & 0 deletions Detectors/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ add_subdirectory(ForwardAlign)


if(BUILD_SIMULATION)
add_subdirectory(FastSim)
add_subdirectory(gconfig)
o2_data_file(COPY gconfig DESTINATION Detectors)
endif()
Expand Down
18 changes: 18 additions & 0 deletions Detectors/FastSim/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Copyright 2019-2026 CERN and copyright holders of ALICE O2.
# See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
# All rights not expressly granted are reserved.
#
# This software is distributed under the terms of the GNU General Public
# License v3 (GPL Version 3), copied verbatim in the file "COPYING".
#
# In applying this license CERN does not waive the privileges and immunities
# granted to it by virtue of its status as an Intergovernmental Organization
# or submit itself to any jurisdiction.

o2_add_library(FastSim
SOURCES src/FastSimModel.cxx
src/FastSimRegions.cxx
src/ToyAbsorberFastSim.cxx
src/G4FastSimulation.cxx
PUBLIC_LINK_LIBRARIES MC::Geant4VMC MC::Geant4 O2::SimConfig
)
105 changes: 105 additions & 0 deletions Detectors/FastSim/include/FastSim/FastSimModel.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
// Copyright 2019-2026 CERN and copyright holders of ALICE O2.
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
// All rights not expressly granted are reserved.
//
// This software is distributed under the terms of the GNU General Public
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
//
// In applying this license CERN does not waive the privileges and immunities
// granted to it by virtue of its status as an Intergovernmental Organization
// or submit itself to any jurisdiction.

#ifndef O2_FASTSIM_MODEL_H_
#define O2_FASTSIM_MODEL_H_

/// Base class for fast simulation models.
///
/// A fast simulation model replaces the detailed transport through a region of
/// the geometry by a function from the particle that enters it to the particles
/// that leave it. `DoIt()` is Geant4's own entry point
/// (`G4VFastSimulationModel::DoIt`); the implementation here wraps the logic
/// common to every model and delegates the physics to `sample()`. A model that
/// needs a different shape can still override `DoIt()`.

#include "G4VFastSimulationModel.hh"

#include <vector>

class G4FastStep;
class G4FastTrack;
class G4ParticleDefinition;

namespace o2::fastsim
{

/// The particle entering the envelope, plus the geometric context a model needs.
/// Units are the O2/VMC ones: cm, GeV, ns.
struct FastSimInput {
int pdg = 0;
double position[3] = {}; ///< global, on the envelope surface
double direction[3] = {}; ///< unit vector
double kineticEnergy = 0.; ///< GeV
double mass = 0.; ///< GeV
double time = 0.; ///< ns
double exitDistance = 0.; ///< cm from `position` to the ENVELOPE surface along `direction`
};

/// One particle leaving the envelope.
struct FastSimOutput {
int pdg = 0;
double position[3] = {}; ///< global; put it outside the envelope surface
double momentum[3] = {}; ///< GeV/c
double time = 0.; ///< ns
};

/// A secondary created exactly on the envelope surface is located by the
/// navigator in whichever daughter owns that point, which costs two extra
/// zero-length steps before it gets out. Models should emit just beyond it.
constexpr double kSurfaceEpsilonCm = 1e-5;

/// Base class for fast simulation models.
///
/// The model is attached to regions (see G4FastSimulation.h) purely so that
/// Geant4 consults it; what it encloses is the ENVELOPE VOLUME named below,
/// which is normally the mother volume of a whole module. The two are
/// deliberately separate, because a Geant4 region in O2 can only ever be "every
/// volume of a given material" -- the VMC special cuts make every logical volume
/// a root of its own material's region, and Geant4 stops propagating a region at
/// any such daughter. So `G4FastTrack::GetEnvelopeSolid()` would hand back one
/// absorber piece rather than the absorber, and this class does not use it.
///
/// Containment and the exit distance are taken from the track's own touchable,
/// which already carries the full ancestry and the transform of every level.
class FastSimModel : public G4VFastSimulationModel
{
public:
FastSimModel(const G4String& name, const G4String& envelopeVolume, double minEnergyGeV);

G4bool IsApplicable(const G4ParticleDefinition& particle) override;
G4bool ModelTrigger(const G4FastTrack& fastTrack) override;

/// Wraps the common logic of a fast simulation action and delegates the
/// physics to `sample()`: it measures the distance to the envelope surface,
/// kills the incident particle, stacks what `sample()` returned and books the
/// energy difference as a deposit. Override it for a model that does not fit
/// that shape.
void DoIt(const G4FastTrack& fastTrack, G4FastStep& fastStep) override;

protected:
/// Given the particle that entered, return everything that leaves. This is
/// the function a trained model implements.
virtual std::vector<FastSimOutput> sample(const FastSimInput& input) const = 0;

private:
/// The track's ancestry level at which the envelope volume sits, or -1 when
/// the track is not inside it at all.
int envelopeDepth(const G4Track* track) const;

G4String mEnvelope; ///< logical volume the model encloses
double mMinEnergy = 0.; ///< internal Geant4 units; below this the detailed transport runs
mutable bool mWarned = false;
};

} // namespace o2::fastsim

#endif // O2_FASTSIM_MODEL_H_
65 changes: 65 additions & 0 deletions Detectors/FastSim/include/FastSim/FastSimRegions.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// Copyright 2019-2026 CERN and copyright holders of ALICE O2.
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
// All rights not expressly granted are reserved.
//
// This software is distributed under the terms of the GNU General Public
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
//
// In applying this license CERN does not waive the privileges and immunities
// granted to it by virtue of its status as an Intergovernmental Organization
// or submit itself to any jurisdiction.

#ifndef O2_FASTSIM_REGIONS_H_
#define O2_FASTSIM_REGIONS_H_

/// Deriving a model's regions from its envelope volume.
///
/// Geant4-VMC attaches a fast simulation model to regions, and in O2 a region
/// can only be "every volume of a given material" (see FastSimModel.h). To have
/// the model consulted everywhere inside a module, it must therefore be attached
/// to every material that module is built from -- which is a list nobody should
/// maintain by hand, because it changes whenever the geometry does.
///
/// So walk the envelope's subtree and collect the media as they actually are.

#include "TG4VUserPostDetConstruction.h"

#include <set>
#include <string>
#include <vector>

class TGeoVolume;

namespace o2::fastsim
{

/// Every tracking medium used by `volume` or anything below it.
/// Takes a non-const pointer because TGeo's accessors are not const.
std::set<std::string> mediaInSubtree(TGeoVolume* volume);

/// Same, looked up by volume name in the current TGeo geometry. Empty if there
/// is no such volume.
std::set<std::string> mediaInSubtree(const std::string& volumeName);

/// Sets each model's regions from its envelope, in the one window where that is
/// possible: after the geometry is built and before Geant4-VMC turns the media
/// into regions.
class FastSimRegionConstruction : public TG4VUserPostDetConstruction
{
public:
struct ModelRegions {
std::string model;
std::string envelope; ///< volume whose subtree supplies the media
std::string regions; ///< explicit media, used instead of the walk if given
};

explicit FastSimRegionConstruction(std::vector<ModelRegions> models);
void Construct() override;

private:
std::vector<ModelRegions> mModels;
};

} // namespace o2::fastsim

#endif // O2_FASTSIM_REGIONS_H_
68 changes: 68 additions & 0 deletions Detectors/FastSim/include/FastSim/G4FastSimulation.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// Copyright 2019-2026 CERN and copyright holders of ALICE O2.
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
// All rights not expressly granted are reserved.
//
// This software is distributed under the terms of the GNU General Public
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
//
// In applying this license CERN does not waive the privileges and immunities
// granted to it by virtue of its status as an Intergovernmental Organization
// or submit itself to any jurisdiction.

#ifndef O2_FASTSIM_G4_FAST_SIMULATION_H_
#define O2_FASTSIM_G4_FAST_SIMULATION_H_

/// Wiring of the fast simulation models into the Geant4 engine.
///
/// The feature is OFF unless `G4.fastSimModels` names a model.
///
/// o2-sim -n 10 -g pythia8pp -e TGeant4 -m PIPE ABSO
/// --configKeyValues "G4.fastSimModels=toyAbsorber;
/// G4.fastSimEnvelope=AFaM"
///
/// `G4.fastSimEnvelope` names the VOLUME the model stands in for. The regions
/// Geant4 needs in order to consult the model are derived from it by walking its
/// subtree and collecting the media (FastSimRegions.h) -- a region in O2 can only
/// be "every volume of a given material", so covering a module means naming all
/// of its materials, and that list should not be maintained by hand.
///
/// `G4.fastSimRegions` overrides the walk with an explicit space-separated list
/// of media, for when a model should see less than a whole subtree.

#include "TG4RunConfiguration.h"
#include "TG4VUserFastSimulation.h"
#include "TG4VUserPostDetConstruction.h"

#include <string>
#include <vector>

namespace o2::fastsim
{

/// Creates and registers the models named in `G4.fastSimModels`.
class G4FastSimulation : public TG4VUserFastSimulation
{
public:
G4FastSimulation(std::vector<std::string> models, const std::string& envelope,
double minEnergyGeV);
void Construct() override;

private:
std::vector<std::string> mModels;
std::string mEnvelope;
double mMinEnergy = 1.;
};

/// Supplies Geant4-VMC with the fast simulation models and their regions.
/// Returns nullptr when no model is configured, so nothing is set up.
class G4RunConfiguration : public TG4RunConfiguration
{
public:
using TG4RunConfiguration::TG4RunConfiguration;
TG4VUserFastSimulation* CreateUserFastSimulation() override;
TG4VUserPostDetConstruction* CreateUserPostDetConstruction() override;
};

} // namespace o2::fastsim

#endif // O2_FASTSIM_G4_FAST_SIMULATION_H_
34 changes: 34 additions & 0 deletions Detectors/FastSim/include/FastSim/ToyAbsorberFastSim.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright 2019-2026 CERN and copyright holders of ALICE O2.
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
// All rights not expressly granted are reserved.
//
// This software is distributed under the terms of the GNU General Public
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
//
// In applying this license CERN does not waive the privileges and immunities
// granted to it by virtue of its status as an Intergovernmental Organization
// or submit itself to any jurisdiction.

#ifndef O2_FASTSIM_TOY_ABSORBER_H_
#define O2_FASTSIM_TOY_ABSORBER_H_

#include "FastSim/FastSimModel.h"

namespace o2::fastsim
{

/// A toy fast simulation model for the absorber: one particle out, continuing
/// along the incident direction with the energy exponentially attenuated over
/// the path through the envelope.
class ToyAbsorberFastSim : public FastSimModel
{
public:
using FastSimModel::FastSimModel;

protected:
std::vector<FastSimOutput> sample(const FastSimInput& input) const override;
};

} // namespace o2::fastsim

#endif // O2_FASTSIM_TOY_ABSORBER_H_
Loading