diff --git a/CMakeLists.txt b/CMakeLists.txt index e7095e914..f5c89fe20 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -70,6 +70,7 @@ math(EXPR DD4HEP_HIGH_MEM_POOL_DEPTH "${HOST_RAM_MB} / 2000" OUTPUT_FORMAT DECIM option(DD4HEP_USE_XERCESC "Enable 'Detector Builders' based on XercesC" OFF) option(DD4HEP_USE_GEANT4 "Enable the simulation part based on Geant4" OFF) +option(DD4HEP_USE_CELERITAS "Enable offloading tracks to Celeritas" OFF) option(DD4HEP_IGNORE_GEANT4_TLS "Ignore the tls flag Geant4 was compiled with" OFF) option(DD4HEP_USE_GEAR "Build gear wrapper for backward compatibility" OFF) option(DD4HEP_USE_LCIO "Build lcio extensions" OFF) @@ -154,6 +155,10 @@ if(DD4HEP_USE_GEANT4) SET_DIRECTORY_PROPERTIES(PROPERTIES INCLUDE_DIRECTORIES "") endif() +if(DD4HEP_USE_CELERITAS) + find_package(Celeritas REQUIRED) +endif() + if(DD4HEP_USE_LCIO) find_package(LCIO REQUIRED CONFIG) DD4HEP_SETUP_LCIO_TARGETS() diff --git a/DDG4/CMakeLists.txt b/DDG4/CMakeLists.txt index 0a341469d..3bbd6e46d 100644 --- a/DDG4/CMakeLists.txt +++ b/DDG4/CMakeLists.txt @@ -102,6 +102,18 @@ IF(TARGET LCIO::lcio) ENDIF() +IF(DD4HEP_USE_CELERITAS) + + dd4hep_add_plugin(DDG4Celeritas + SOURCES celeritas/*.cpp + INCLUDES $ + USES DD4hep::DDG4 Celeritas::accel Celeritas::corecel + ) + install(TARGETS DDG4Celeritas EXPORT DD4hep LIBRARY DESTINATION lib) + set_target_properties(DDG4Celeritas PROPERTIES VERSION ${DD4hep_VERSION} SOVERSION ${DD4hep_SOVERSION}) + +ENDIF() + IF(TARGET EDM4HEP::edm4hep) dd4hep_add_plugin(DDG4EDM4HEP SOURCES edm4hep/*.cpp diff --git a/DDG4/celeritas/Celeritas.cpp b/DDG4/celeritas/Celeritas.cpp new file mode 100644 index 000000000..1134c79ed --- /dev/null +++ b/DDG4/celeritas/Celeritas.cpp @@ -0,0 +1,104 @@ +#include "Celeritas.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +using namespace dd4hep::sim; + +// Global shared setup options +celeritas::SetupOptions& dd4hep::sim::CelerSetupOptions() +{ + static celeritas::SetupOptions options = [] { + // Construct setup options the first time CelerSetupOptions is invoked + celeritas::SetupOptions so; + + // Set along-step factory + so.make_along_step = celeritas::UniformAlongStepFactory(); + // NOTE: these numbers are appropriate for CPU execution + so.max_num_tracks = 1024; + so.initializer_capacity = 1024 * 128; + // Celeritas does not support EmStandard MSC physics above 100 MeV + so.ignore_processes = {"CoulombScat"}; + + // Use Celeritas "hit processor" to call back to Geant4 SDs. + so.sd.enabled = false; + + // Only call back for nonzero energy depositions: this is currently a + // global option for all detectors, so if any SDs extract data from tracks + // with no local energy deposition over the step, it must be set to false. + so.sd.ignore_zero_deposition = false; + + // Using the pre-step point, reconstruct the G4 touchable handle. + so.sd.locate_touchable = true; + + // Pre-step time is used + so.sd.pre.global_time = true; + return so; + }(); + return options; +} + +// Shared data and GPU setup +celeritas::SharedParams& dd4hep::sim::CelerSharedParams() +{ + static celeritas::SharedParams sp; + return sp; +} + +// Thread-local transporter +celeritas::LocalTransporter& dd4hep::sim::CelerLocalTransporter() +{ + static G4ThreadLocal celeritas::LocalTransporter lt; + return lt; +} + +// Thread-local offload interface +celeritas::SimpleOffload& dd4hep::sim::CelerSimpleOffload() +{ + static G4ThreadLocal celeritas::SimpleOffload so; + return so; +} + +void EMPhysicsConstructor::ConstructProcess() +{ + CELER_LOG_LOCAL(status) << "Setting up tracking manager offload"; + G4EmStandardPhysics::ConstructProcess(); + + // Add Celeritas tracking manager to electron, positron, gamma. + auto* celer_tracking = new celeritas::TrackingManagerOffload( + &CelerSharedParams(), &CelerLocalTransporter()); + + G4Electron::Definition()->SetTrackingManager(celer_tracking); + G4Positron::Definition()->SetTrackingManager(celer_tracking); + G4Gamma::Definition()->SetTrackingManager(celer_tracking); +} + +struct EmptyPhysics : public G4VModularPhysicsList { + EmptyPhysics() = default; // Default constructor, does nothing + virtual ~EmptyPhysics() = default; // Virtual destructor, does nothing +}; + +G4VUserPhysicsList* CeleritasPhysicsListActionSequence::activateCeleritas() { + G4VModularPhysicsList* physics = ( m_extends.empty() ) + ? new EmptyPhysics() + : G4PhysListFactory().GetReferencePhysList(m_extends); + +physics->ReplacePhysics(new EMPhysicsConstructor); + +return physics; +} + diff --git a/DDG4/celeritas/Celeritas.h b/DDG4/celeritas/Celeritas.h new file mode 100644 index 000000000..fe4282e3e --- /dev/null +++ b/DDG4/celeritas/Celeritas.h @@ -0,0 +1,46 @@ +#ifndef Celeritas_h +#define Celeritas_h 1 + +#include +#include +#include + +/// Namespace for the AIDA detector description toolkit +namespace dd4hep { + + /// Namespace for the Geant4 based simulation part of the AIDA detector description toolkit + namespace sim { + + // Global shared setup options + celeritas::SetupOptions& CelerSetupOptions(); + // Shared data and GPU setup + celeritas::SharedParams& CelerSharedParams(); + // Thread-local transporter + celeritas::LocalTransporter& CelerLocalTransporter(); + // Thread-local offload + celeritas::SimpleOffload& CelerSimpleOffload(); + + class EMPhysicsConstructor final : public G4EmStandardPhysics + { + public: + using G4EmStandardPhysics::G4EmStandardPhysics; + + void ConstructProcess() override; + }; + + class CeleritasPhysicsListActionSequence : public + Geant4PhysicsListActionSequence { + + public: + /// Standard constructor + CeleritasPhysicsListActionSequence(Geant4Context* context, const std::string& nam); + /// Default destructor + virtual ~CeleritasPhysicsListActionSequence(); + + G4VUserPhysicsList* activateCeleritas(); + }; + + } /* End namespace sim */ +} /* End namespace dd4hep*/ + +#endif