Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-11 08:30:02

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       /// Thread context reference
0141       Geant4Context*     m_threadContext  { nullptr };
0142       /// Interrupt/signal handler: only on master instance
0143       Geant4Interrupts*  m_interrupts     { nullptr };
0144 
0145       bool isMaster() const  { return this == m_master; }
0146       bool isWorker() const  { return this != m_master; }
0147 
0148 #ifndef __CINT__
0149       /// Standard constructor for workers
0150       Geant4Kernel(Geant4Kernel* m, unsigned long identifier);
0151 #endif
0152 
0153     public:
0154       /// Standard constructor for the master instance
0155       Geant4Kernel(Detector& description);
0156 
0157       /// Thread's master context
0158       Geant4Kernel& master()  const  { return *m_master; }
0159 
0160       //bool isMultiThreaded() const { return m_multiThreaded; }
0161       bool isMultiThreaded() const { return m_numThreads > 0; }
0162 
0163       /// Access thread identifier
0164       static unsigned long int thread_self();
0165 
0166     public:
0167 
0168       /// Embedded helper class to facilitate map access to the phases.
0169       /** @class PhaseSelector Geant4Kernel.h DDG4/Geant4Kernel.h
0170        *
0171        * @author  M.Frank
0172        * @version 1.0
0173        */
0174       class PhaseSelector {
0175       public:
0176         /// Reference to embedding object
0177         Geant4Kernel* m_kernel;
0178         /// Standard constructor
0179         PhaseSelector(Geant4Kernel* kernel);
0180         /// Copy constructor
0181         PhaseSelector(const PhaseSelector& c);
0182         /// Assignment operator
0183         PhaseSelector& operator=(const PhaseSelector& c);
0184         /// Phase access to the map
0185         Geant4ActionPhase& operator[](const std::string& name) const;
0186       } phase;
0187 
0188       enum State {
0189         SETTING_UP, INITIALIZED
0190       };
0191       /// Default destructor
0192       virtual ~Geant4Kernel();
0193 
0194 #ifndef __CINT__
0195       /// Instance accessor
0196       static Geant4Kernel& instance(Detector& description);
0197 #endif
0198       /// Access phase phases
0199       const Phases& phases() const              {        return m_phases;          }
0200       /// Access to detector description
0201       Detector& detectorDescription() const     {        return *m_detDesc;        }
0202       /// Access the tracking manager
0203       G4TrackingManager* trackMgr() const       {        return m_trackMgr;        }
0204       /// Access the tracking manager
0205       void setTrackMgr(G4TrackingManager* mgr)  {        m_trackMgr = mgr;         }
0206       /// Access the command directory
0207       const std::string& directoryName() const  {        return m_controlName;     }
0208       /// Access worker identifier
0209       unsigned long id()  const                 {        return m_ident;           }
0210       /// Access to the Geant4 run manager
0211       G4RunManager& runManager();
0212       /// Generic framework access
0213       UserFramework& userFramework()            {        return m_userFramework;   }
0214       /// Set the framework context to the kernel object
0215       template <typename T> void setUserFramework(T* object)   {
0216         m_userFramework = UserFramework(object,&typeid(T));
0217       }
0218       /// Property access: Name of the default factory to create G4VSensitiveDetector instances
0219       const std::string defaultSensitiveDetectorType()  const  {
0220         return m_dfltSensitiveDetectorType;
0221       }
0222       /// Property access: Names with specialized factories to create G4VSensitiveDetector instances
0223       const std::map<std::string, std::string>& sensitiveDetectorTypes()  const   {
0224         return m_sensitiveDetectorTypes;
0225       }
0226       /// Add new sensitive type to factory list
0227       /** This is present mainly for debugging purposes and tests.
0228        * Never necessary in real life!
0229        * For all practical purpose the default type Geant4SensDet is sufficient.
0230        *
0231        */
0232       void defineSensitiveDetectorType(const std::string& type, const std::string& factory);
0233       /// Access to geometry world
0234       G4VPhysicalVolume* world()  const;
0235       /// Set the geometry world
0236       void setWorld(G4VPhysicalVolume* volume);
0237       
0238       /** Property access                            */
0239       /// Access to the properties of the object
0240       PropertyManager& properties()             {        return m_properties;      }
0241       /// Print the property values
0242       void printProperties() const;
0243       /// Declare property
0244       template <typename T> Geant4Kernel& declareProperty(const std::string& nam, T& val);
0245       /// Declare property
0246       template <typename T> Geant4Kernel& declareProperty(const char* nam, T& val);
0247       /// Check property for existence
0248       bool hasProperty(const std::string& name) const;
0249       /// Access single property
0250       Property& property(const std::string& name);
0251 
0252       /** Output level settings                       */
0253       /// Access the output level
0254       PrintLevel outputLevel() const  {        return (PrintLevel)m_outputLevel;    }
0255       /// Set the global output level of the kernel object; returns previous value
0256       PrintLevel setOutputLevel(PrintLevel new_level);
0257       /// Fill cache with the global output level of a named object. Must be set before instantiation
0258       void setOutputLevel(const std::string object, PrintLevel new_level);
0259       /// Retrieve the global output level of a named object.
0260       PrintLevel getOutputLevel(const std::string object) const;
0261 
0262       /// Register configure callback. Signature:   (function)()
0263       void register_configure(const std::function<void()>& callback);
0264       /// Register initialize callback. Signature:  (function)()
0265       void register_initialize(const std::function<void()>& callback);
0266       /// Register terminate callback. Signature:   (function)()
0267       void register_terminate(const std::function<void()>& callback);
0268 
0269       /// Access interrupt handler. Will be created on the first call
0270       Geant4Interrupts& interruptHandler()  const;
0271       /// Trigger smooth end-of-event-loop with finishing currently processing event
0272       void triggerStop();
0273       /// Check if event processing should be continued
0274       bool processEvents()  const;
0275       /// Install DDG4 default handler for a given signal. If no handler: return false
0276       bool registerInterruptHandler(int sig_num);
0277       /// (Re-)apply registered interrupt handlers to override potentially later registrations by other libraries
0278       /** In this case we overwrite signal handlers applied by Geant4.
0279        */
0280       void applyInterruptHandlers();
0281       
0282       /// Register action by name to be retrieved when setting up and connecting action objects
0283       /** Note: registered actions MUST be unique.
0284        *  However, not all actions need to registered....
0285        *  Only register those, you later need to retrieve by name.
0286        */
0287       Geant4Kernel& registerGlobalAction(Geant4Action* action);
0288       /// Retrieve action from repository
0289       Geant4Action* globalAction(const std::string& action_name, bool throw_if_not_present = true);
0290       /// Register filter by name to be retrieved when setting up and connecting filter objects
0291       /** Note: registered filters MUST be unique.
0292        *  However, not all filters need to registered....
0293        *  Only register those, you later need to retrieve by name.
0294        */
0295       Geant4Kernel& registerGlobalFilter(Geant4Action* filter);
0296       /// Retrieve filter from repository
0297       Geant4Action* globalFilter(const std::string& filter_name, bool throw_if_not_present = true);
0298 
0299       /// Access phase by name
0300       Geant4ActionPhase* getPhase(const std::string& name);
0301 
0302       /// Add a new phase to the phase
0303       virtual Geant4ActionPhase* addSimplePhase(const std::string& name, bool throw_on_exist);
0304 
0305       /// Add a new phase to the phase
0306       virtual Geant4ActionPhase* addPhase(const std::string& name, const std::type_info& arg1, const std::type_info& arg2,
0307                                           const std::type_info& arg3, bool throw_on_exist);
0308       /// Add a new phase to the phase
0309       template <typename A0> Geant4ActionPhase* addPhase(const std::string& name, bool throw_on_exist = true) {
0310         return addPhase(name, typeid(A0), typeid(void), typeid(void), throw_on_exist);
0311       }
0312       /// Add a new phase to the phase
0313       template <typename A0, typename A1>
0314       Geant4ActionPhase* addPhase(const std::string& name, bool throw_on_exist = true) {
0315         return addPhase(name, typeid(A0), typeid(A1), typeid(void), throw_on_exist);
0316       }
0317       /// Add a new phase to the phase
0318       template <typename A0, typename A1, typename A2>
0319       Geant4ActionPhase* addPhase(const std::string& name, bool throw_on_exist = true) {
0320         return addPhase(name, typeid(A0), typeid(A1), typeid(A2), throw_on_exist);
0321       }
0322       /// Remove an existing phase from the phase. If not existing returns false
0323       virtual bool removePhase(const std::string& name);
0324       /// Destroy all phases. To be called only at shutdown.
0325       virtual void destroyPhases();
0326 
0327       /// Execute phase action if it exists
0328       virtual bool executePhase(const std::string& name, const void** args)  const;
0329 
0330       /// Construct detector geometry using description plugin
0331       virtual void loadGeometry(const std::string& compact_file);
0332       /// Load XML file 
0333       virtual void loadXML(const char* fname);
0334 
0335       /** Geant4 Multi threading support */
0336       /// Create identified worker instance
0337       virtual Geant4Kernel& createWorker();
0338       /// Access worker instance by its identifier
0339       Geant4Kernel& worker(unsigned long thread_identifier, bool create_if=false);
0340       /// Access number of workers
0341       int numWorkers() const;
0342 
0343       /// Run the simulation: Configure Geant4
0344       virtual int configure();
0345       /// Run the simulation: Initialize Geant4
0346       virtual int initialize();
0347       /// Run the simulation: Simulate the number of events given by the property "NumEvents"
0348       virtual int run();
0349       /// Run the simulation: Simulate the number of events "num_events" and modify the property "NumEvents"
0350       virtual int runEvents(int num_events);
0351       /// Run the simulation: Terminate Geant4
0352       virtual int terminate()  override;
0353     };
0354     /// Declare property
0355     template <typename T> Geant4Kernel& Geant4Kernel::declareProperty(const std::string& nam, T& val) {
0356       m_properties.add(nam, val);
0357       return *this;
0358     }
0359 
0360     /// Declare property
0361     template <typename T> Geant4Kernel& Geant4Kernel::declareProperty(const char* nam, T& val) {
0362       m_properties.add(nam, val);
0363       return *this;
0364     }
0365 
0366     /// Main executor steering the Geant4 execution
0367     class Geant4Exec {
0368     public:
0369       /// Configure the application
0370       static int configure(Geant4Kernel& kernel);
0371       /// Initialize the application
0372       static int initialize(Geant4Kernel& kernel);
0373       /// Run the application and simulate events
0374       static int run(Geant4Kernel& kernel);
0375       /// Terminate the application
0376       static int terminate(Geant4Kernel& kernel);
0377     };
0378 
0379   }    // End namespace sim
0380 }      // End namespace dd4hep
0381 #endif // DDG4_GEANT4KERNEL_H