Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-10-31 09:24:05

0001 //==========================================================================
0002 //  AIDA Detector description implementation 
0003 //--------------------------------------------------------------------------
0004 // Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
0005 // All rights reserved.
0006 //
0007 // For the licensing terms see $DD4hepINSTALL/LICENSE.
0008 // For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
0009 //
0010 // Author     : M.Frank
0011 //
0012 //==========================================================================
0013 #ifndef DDG4_GEANT4KERNEL_H
0014 #define DDG4_GEANT4KERNEL_H
0015 
0016 // Framework include files
0017 #include <DDG4/Geant4ActionContainer.h>
0018 
0019 // C/C++ include files
0020 #include <map>
0021 #include <typeinfo>
0022 #include <functional>
0023 
0024 // Forward declarations
0025 class G4RunManager;
0026 class G4UIdirectory;
0027 class G4VPhysicalVolume;
0028 
0029 /// Namespace for the AIDA detector description toolkit
0030 namespace dd4hep {
0031 
0032   // Forward declarations
0033   class Geant4Interrupts;
0034 
0035   /// Namespace for the Geant4 based simulation part of the AIDA detector description toolkit
0036   namespace sim {
0037 
0038     // Forward declarations
0039     class Geant4Interrupts;
0040     class Geant4ActionPhase;
0041 
0042     /// Helper class to indicate the end of the input file
0043     class DD4hep_End_Of_File : public std::exception {
0044     public:
0045       DD4hep_End_Of_File() : std::exception() {}
0046       virtual const char* what() const noexcept override { return "Reached end of input file"; }
0047     };
0048 
0049     /// Helper class to indicate the stop of processing
0050     class DD4hep_Stop_Processing : public std::exception {
0051     public:
0052       DD4hep_Stop_Processing() : std::exception() {}
0053       virtual const char* what() const noexcept override { return "Event loop STOP signalled. Processing stops"; }
0054     };
0055 
0056     /// Class, which allows all Geant4Action derivatives to access the DDG4 kernel structures.
0057     /**
0058      *  To implement access to a user specified framework please see class Geant4Context.
0059      *
0060      *  \author  M.Frank
0061      *  \version 1.0
0062      *  \ingroup DD4HEP_SIMULATION
0063      */
0064     class Geant4Kernel : public Geant4ActionContainer  {
0065     public:
0066       typedef std::map<unsigned long, Geant4Kernel*>    Workers;
0067       typedef std::map<std::string, Geant4ActionPhase*> Phases;
0068       typedef std::map<std::string, Geant4Action*>      GlobalActions;
0069       typedef std::map<std::string,int>                 ClientOutputLevels;
0070       typedef std::pair<void*, const std::type_info*>   UserFramework;
0071       using UserCallbacks = std::vector<std::function<void()> >;
0072 
0073       enum event_loop_status  {
0074         EVENTLOOP_HALT = 0,
0075         EVENTLOOP_RUNNING = 1,
0076       };
0077       
0078     protected:
0079       /// Reference to the run manager
0080       G4RunManager*      m_runManager  { nullptr };
0081       /// Top level control directory
0082       G4UIdirectory*     m_control     { nullptr };
0083       /// Reference to Geant4 track manager
0084       G4TrackingManager* m_trackMgr    { nullptr };
0085       /// Detector description object
0086       Detector*          m_detDesc     { nullptr };
0087       /// Property pool
0088       PropertyManager    m_properties          { };
0089       /// Reference to the user framework
0090       UserFramework      m_userFramework       { };
0091 
0092       /// Action phases
0093       Phases        m_phases                   { };
0094       /// Worker threads
0095       Workers       m_workers                  { };
0096       /// Globally registered actions
0097       GlobalActions m_globalActions            { };
0098       /// Globally registered filters of sensitive detectors
0099       GlobalActions m_globalFilters            { };
0100       /// Property: Client output levels
0101       ClientOutputLevels m_clientLevels        { };
0102       /// Property: Name of the G4UI command tree
0103       std::string   m_controlName              { };
0104       /// Property: Name of the UI action. Must be member of the global actions
0105       std::string   m_uiName                   { };
0106       /// Property: Name of the G4 run manager factory to be used. Default: Geant4RunManager
0107       std::string   m_runManagerType;
0108       /// Property: Name of the default factory to create G4VSensitiveDetector instances
0109       std::string   m_dfltSensitiveDetectorType;
0110       /// Property: Names with specialized factories to create G4VSensitiveDetector instances
0111       std::map<std::string, std::string> m_sensitiveDetectorTypes;
0112       /// Property: Number of events to be executed in batch mode
0113       long          m_numEvent       = 10;
0114       /// Property: Output level
0115       int           m_outputLevel    = 0;
0116 
0117       /// Master property: Number of execution threads in multi threaded mode.
0118       int           m_numThreads     = 0;
0119       /// Master property: Instantiate the Geant4 scoring manager object
0120       int           m_haveScoringMgr = false;
0121       /// Master property: Flag if event loop is enabled
0122       int           m_processEvents  = EVENTLOOP_RUNNING;
0123 
0124       
0125       /// Registered action callbacks on configure
0126       UserCallbacks m_actionConfigure  { };
0127       /// Registered action callbacks on initialize
0128       UserCallbacks m_actionInitialize { };
0129       /// Registered action callbacks on terminate
0130       UserCallbacks m_actionTerminate  { };
0131 
0132 
0133       /// Flag: Master instance (id<0) or worker (id >= 0)
0134       unsigned long      m_id = 0, m_ident = 0;
0135       /// Access to geometry world
0136       G4VPhysicalVolume* m_world  = 0;
0137 
0138       /// Parent reference
0139       Geant4Kernel*      m_master         { nullptr };
0140       /// Interrupt/signal handler: only on master instance
0141       Geant4Interrupts*  m_interrupts     { nullptr };
0142 
0143       bool isMaster() const  { return this == m_master; }
0144       bool isWorker() const  { return this != m_master; }
0145 
0146 #ifndef __CINT__
0147       /// Standard constructor for workers
0148       Geant4Kernel(Geant4Kernel* m, unsigned long identifier);
0149 #endif
0150 
0151     public:
0152       /// Standard constructor for the master instance
0153       Geant4Kernel(Detector& description);
0154 
0155       /// Thread's master context
0156       Geant4Kernel& master()  const  { return *m_master; }
0157 
0158       //bool isMultiThreaded() const { return m_multiThreaded; }
0159       bool isMultiThreaded() const { return m_numThreads > 0; }
0160       int numThreads()       const { return m_numThreads; }
0161 
0162       /// Access thread identifier
0163       static unsigned long int thread_self();
0164 
0165     public:
0166 
0167       /// Embedded helper class to facilitate map access to the phases.
0168       /** @class PhaseSelector Geant4Kernel.h DDG4/Geant4Kernel.h
0169        *
0170        * @author  M.Frank
0171        * @version 1.0
0172        */
0173       class PhaseSelector {
0174       public:
0175         /// Reference to embedding object
0176         Geant4Kernel* m_kernel;
0177         /// Standard constructor
0178         PhaseSelector(Geant4Kernel* kernel);
0179         /// Copy constructor
0180         PhaseSelector(const PhaseSelector& c);
0181         /// Assignment operator
0182         PhaseSelector& operator=(const PhaseSelector& c);
0183         /// Phase access to the map
0184         Geant4ActionPhase& operator[](const std::string& name) const;
0185       } phase;
0186 
0187       enum State {
0188         SETTING_UP, INITIALIZED
0189       };
0190       /// Default destructor
0191       virtual ~Geant4Kernel();
0192 
0193 #ifndef __CINT__
0194       /// Instance accessor
0195       static Geant4Kernel& instance(Detector& description);
0196 #endif
0197       /// Access phase phases
0198       const Phases& phases() const              {        return m_phases;          }
0199       /// Access to detector description
0200       Detector& detectorDescription() const     {        return *m_detDesc;        }
0201       /// Access the tracking manager
0202       G4TrackingManager* trackMgr() const       {        return m_trackMgr;        }
0203       /// Access the tracking manager
0204       void setTrackMgr(G4TrackingManager* mgr)  {        m_trackMgr = mgr;         }
0205       /// Access the command directory
0206       const std::string& directoryName() const  {        return m_controlName;     }
0207       /// Access worker identifier
0208       unsigned long id()  const                 {        return m_ident;           }
0209       /// Access to the Geant4 run manager
0210       G4RunManager& runManager();
0211       /// Generic framework access
0212       UserFramework& userFramework()            {        return m_userFramework;   }
0213       /// Set the framework context to the kernel object
0214       template <typename T> void setUserFramework(T* object)   {
0215         m_userFramework = UserFramework(object,&typeid(T));
0216       }
0217       /// Property access: Name of the default factory to create G4VSensitiveDetector instances
0218       const std::string defaultSensitiveDetectorType()  const  {
0219         return m_dfltSensitiveDetectorType;
0220       }
0221       /// Property access: Names with specialized factories to create G4VSensitiveDetector instances
0222       const std::map<std::string, std::string>& sensitiveDetectorTypes()  const   {
0223         return m_sensitiveDetectorTypes;
0224       }
0225       /// Add new sensitive type to factory list
0226       /** This is present mainly for debugging purposes and tests.
0227        * Never necessary in real life!
0228        * For all practical purpose the default type Geant4SensDet is sufficient.
0229        *
0230        */
0231       void defineSensitiveDetectorType(const std::string& type, const std::string& factory);
0232       /// Access to geometry world
0233       G4VPhysicalVolume* world()  const;
0234       /// Set the geometry world
0235       void setWorld(G4VPhysicalVolume* volume);
0236       
0237       /** Property access                            */
0238       /// Access to the properties of the object
0239       PropertyManager& properties()             {        return m_properties;      }
0240       /// Print the property values
0241       void printProperties() const;
0242       /// Declare property
0243       template <typename T> Geant4Kernel& declareProperty(const std::string& nam, T& val);
0244       /// Declare property
0245       template <typename T> Geant4Kernel& declareProperty(const char* nam, T& val);
0246       /// Check property for existence
0247       bool hasProperty(const std::string& name) const;
0248       /// Access single property
0249       Property& property(const std::string& name);
0250 
0251       /** Output level settings                       */
0252       /// Access the output level
0253       PrintLevel outputLevel() const  {        return (PrintLevel)m_outputLevel;    }
0254       /// Set the global output level of the kernel object; returns previous value
0255       PrintLevel setOutputLevel(PrintLevel new_level);
0256       /// Fill cache with the global output level of a named object. Must be set before instantiation
0257       void setOutputLevel(const std::string object, PrintLevel new_level);
0258       /// Retrieve the global output level of a named object.
0259       PrintLevel getOutputLevel(const std::string object) const;
0260 
0261       /// Register configure callback. Signature:   (function)()
0262       void register_configure(const std::function<void()>& callback);
0263       /// Register initialize callback. Signature:  (function)()
0264       void register_initialize(const std::function<void()>& callback);
0265       /// Register terminate callback. Signature:   (function)()
0266       void register_terminate(const std::function<void()>& callback);
0267 
0268       /// Access interrupt handler. Will be created on the first call
0269       Geant4Interrupts& interruptHandler()  const;
0270       /// Trigger smooth end-of-event-loop with finishing currently processing event
0271       void triggerStop();
0272       /// Check if event processing should be continued
0273       bool processEvents()  const;
0274       /// Install DDG4 default handler for a given signal. If no handler: return false
0275       bool registerInterruptHandler(int sig_num);
0276       /// (Re-)apply registered interrupt handlers to override potentially later registrations by other libraries
0277       /** In this case we overwrite signal handlers applied by Geant4.
0278        */
0279       void applyInterruptHandlers();
0280       
0281       /// Register action by name to be retrieved when setting up and connecting action objects
0282       /** Note: registered actions MUST be unique.
0283        *  However, not all actions need to registered....
0284        *  Only register those, you later need to retrieve by name.
0285        */
0286       Geant4Kernel& registerGlobalAction(Geant4Action* action);
0287       /// Retrieve action from repository
0288       Geant4Action* globalAction(const std::string& action_name, bool throw_if_not_present = true);
0289       /// Register filter by name to be retrieved when setting up and connecting filter objects
0290       /** Note: registered filters MUST be unique.
0291        *  However, not all filters need to registered....
0292        *  Only register those, you later need to retrieve by name.
0293        */
0294       Geant4Kernel& registerGlobalFilter(Geant4Action* filter);
0295       /// Retrieve filter from repository
0296       Geant4Action* globalFilter(const std::string& filter_name, bool throw_if_not_present = true);
0297 
0298       /// Access phase by name
0299       Geant4ActionPhase* getPhase(const std::string& name);
0300 
0301       /// Add a new phase to the phase
0302       virtual Geant4ActionPhase* addSimplePhase(const std::string& name, bool throw_on_exist);
0303 
0304       /// Add a new phase to the phase
0305       virtual Geant4ActionPhase* addPhase(const std::string& name, const std::type_info& arg1, const std::type_info& arg2,
0306                                           const std::type_info& arg3, bool throw_on_exist);
0307       /// Add a new phase to the phase
0308       template <typename A0> Geant4ActionPhase* addPhase(const std::string& name, bool throw_on_exist = true) {
0309         return addPhase(name, typeid(A0), typeid(void), typeid(void), throw_on_exist);
0310       }
0311       /// Add a new phase to the phase
0312       template <typename A0, typename A1>
0313       Geant4ActionPhase* addPhase(const std::string& name, bool throw_on_exist = true) {
0314         return addPhase(name, typeid(A0), typeid(A1), typeid(void), throw_on_exist);
0315       }
0316       /// Add a new phase to the phase
0317       template <typename A0, typename A1, typename A2>
0318       Geant4ActionPhase* addPhase(const std::string& name, bool throw_on_exist = true) {
0319         return addPhase(name, typeid(A0), typeid(A1), typeid(A2), throw_on_exist);
0320       }
0321       /// Remove an existing phase from the phase. If not existing returns false
0322       virtual bool removePhase(const std::string& name);
0323       /// Destroy all phases. To be called only at shutdown.
0324       virtual void destroyPhases();
0325 
0326       /// Execute phase action if it exists
0327       virtual bool executePhase(const std::string& name, const void** args)  const;
0328 
0329       /// Construct detector geometry using description plugin
0330       virtual void loadGeometry(const std::string& compact_file);
0331       /// Load XML file 
0332       virtual void loadXML(const char* fname);
0333       /// Run dd4hep plugin with arguments
0334       virtual long runPlugin(const std::string& plgin, const std::vector<std::string>& args);
0335 
0336       /** Geant4 Multi threading support */
0337       /// Create identified worker instance
0338       virtual Geant4Kernel& createWorker();
0339       /// Access worker instance by its identifier
0340       Geant4Kernel& worker(unsigned long thread_identifier, bool create_if=false);
0341       /// Access number of workers
0342       int numWorkers() const;
0343 
0344       /// Run the simulation: Configure Geant4
0345       virtual int configure();
0346       /// Run the simulation: Initialize Geant4
0347       virtual int initialize();
0348       /// Run the simulation: Simulate the number of events given by the property "NumEvents"
0349       virtual int run();
0350       /// Run the simulation: Simulate the number of events "num_events" and modify the property "NumEvents"
0351       virtual int runEvents(int num_events);
0352       /// Run the simulation: Terminate Geant4
0353       virtual int terminate()  override;
0354     };
0355     /// Declare property
0356     template <typename T> Geant4Kernel& Geant4Kernel::declareProperty(const std::string& nam, T& val) {
0357       m_properties.add(nam, val);
0358       return *this;
0359     }
0360 
0361     /// Declare property
0362     template <typename T> Geant4Kernel& Geant4Kernel::declareProperty(const char* nam, T& val) {
0363       m_properties.add(nam, val);
0364       return *this;
0365     }
0366 
0367     /// Main executor steering the Geant4 execution
0368     class Geant4Exec {
0369     public:
0370       /// Configure the application
0371       static int configure(Geant4Kernel& kernel);
0372       /// Initialize the application
0373       static int initialize(Geant4Kernel& kernel);
0374       /// Run the application and simulate events
0375       static int run(Geant4Kernel& kernel);
0376       /// Terminate the application
0377       static int terminate(Geant4Kernel& kernel);
0378     };
0379 
0380   }    // End namespace sim
0381 }      // End namespace dd4hep
0382 #endif // DDG4_GEANT4KERNEL_H