Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-15 09:28: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 
0014 // Framework include files
0015 #include <DDG4/Geant4FastSimShowerModel.h>
0016 #include <DDG4/Geant4Mapping.h>
0017 #include <DDG4/Geant4Kernel.h>
0018 
0019 // Geant4 include files
0020 #include <G4FastSimulationManager.hh>
0021 #include <G4VFastSimulationModel.hh>
0022 #include <G4TouchableHandle.hh>
0023 #include <G4ParticleTable.hh>
0024 #include <G4FastStep.hh>
0025 
0026 // C/C++ include files
0027 #include <sstream>
0028 
0029 using namespace dd4hep::sim;
0030 
0031 /// Namespace for the AIDA detector description toolkit
0032 namespace dd4hep  {
0033 
0034   /// Namespace for the Geant4 based simulation part of the AIDA detector description toolkit
0035   namespace sim  {
0036 
0037     /// Forward declaratons
0038     class Geant4FastSimShowerModel;
0039     
0040     /// Geant4 wrapper for the Geant4 fast simulation shower model
0041     /**
0042      *  Geant4 wrapper for the Geant4 fast simulation shower model
0043      *
0044      *  \author  M.Frank
0045      *  \version 1.0
0046      *  \ingroup DD4HEP_SIMULATION
0047      */
0048     class Geant4ShowerModelWrapper : public G4VFastSimulationModel  {
0049       /// Reference to the model wrapper
0050       Geant4FastSimShowerModel* m_model { nullptr };
0051 
0052     public:
0053       /// Initializing constructor
0054       Geant4ShowerModelWrapper(Geant4FastSimShowerModel* model);
0055       /// Default destructor
0056       virtual ~Geant4ShowerModelWrapper() = default;
0057       /// User callback to determine if the model is applicable for the particle type
0058       virtual G4bool IsApplicable(const G4ParticleDefinition& particle)  override;
0059       /// User callback to determine if the shower creation should be triggered
0060       virtual G4bool ModelTrigger(const G4FastTrack& track)  override;
0061       /// User callback to model the particle/energy shower
0062       virtual void DoIt(const G4FastTrack& track, G4FastStep& step)  override;
0063     };
0064     
0065   }
0066 }
0067 
0068 /// Initializing constructor
0069 Geant4ShowerModelWrapper::Geant4ShowerModelWrapper(Geant4FastSimShowerModel* model)
0070   : G4VFastSimulationModel(model->name()), m_model(model)
0071 {
0072 }
0073 
0074 /// User callback to determine if the model is applicable for the particle type
0075 G4bool Geant4ShowerModelWrapper::IsApplicable(const G4ParticleDefinition& particle)    {
0076   return this->m_model->check_applicability(particle);
0077 }
0078 
0079 /// User callback to determine if the shower creation should be triggered
0080 G4bool Geant4ShowerModelWrapper::ModelTrigger(const G4FastTrack& track)   {
0081   return this->m_model->check_trigger(track);
0082 }
0083 
0084 /// User callback to model the particle/energy shower
0085 void Geant4ShowerModelWrapper::DoIt(const G4FastTrack& track, G4FastStep& step)   {
0086   this->m_model->modelShower(track, step);
0087 }
0088 
0089 /// Standard constructor
0090 Geant4FastSimShowerModel::Geant4FastSimShowerModel(Geant4Context* ctxt, const std::string& nam)
0091   : Geant4DetectorConstruction(ctxt, nam)
0092 {
0093   this->declareProperty("RegionName",          this->m_regionName);
0094   this->declareProperty("ApplicableParticles", this->m_applicablePartNames);
0095   this->declareProperty("Enable",              this->m_enable);
0096   this->declareProperty("StepLength",          this->m_stepX0);
0097   this->declareProperty("Emin",                this->m_eMin);
0098   this->declareProperty("Emax",                this->m_eMax);
0099   this->declareProperty("Ekill",               this->m_eKill);
0100   this->declareProperty("Etrigger",            this->m_eTriggerNames);
0101   this->m_wrapper= new Geant4ShowerModelWrapper(this);
0102 }
0103 
0104 /// Default destructor
0105 Geant4FastSimShowerModel::~Geant4FastSimShowerModel()    {
0106   detail::deletePtr(m_model);
0107   detail::deletePtr(m_wrapper);
0108 }
0109 
0110 /// Access particle definition from string
0111 G4ParticleDefinition* Geant4FastSimShowerModel::getParticleDefinition(const std::string& particle)  const  {
0112   G4ParticleTable* pt = G4ParticleTable::GetParticleTable();
0113   G4ParticleDefinition* def = pt->FindParticle(particle);
0114   if ( def ) return def;
0115   except("Failed to access Geant4 particle definition: %s", particle.c_str());
0116   return nullptr;
0117 }
0118 
0119 G4Material* Geant4FastSimShowerModel::getMaterial(const std::string& mat_name)   const   {
0120   auto& kernel = this->context()->kernel();
0121   Geant4GeometryInfo& mapping = Geant4Mapping::instance().data();
0122   Material material = kernel.detectorDescription().material(mat_name);
0123   if ( material.isValid() )   {
0124     auto mat_iter = mapping.g4Materials.find(material);
0125     if ( mat_iter != mapping.g4Materials.end() )   {
0126       return (*mat_iter).second;
0127     }
0128   }
0129   except("Failed to access shower parametrization material: %s", mat_name.c_str());
0130   return nullptr;
0131 }
0132 
0133 /// Access the region from the detector description by name
0134 G4Region* Geant4FastSimShowerModel::getRegion(const std::string& nam)   const   {
0135   auto& kernel = this->context()->kernel();
0136   Geant4GeometryInfo& mapping = Geant4Mapping::instance().data();
0137   Region rg = kernel.detectorDescription().region(nam);
0138   if ( !rg.isValid() )   {
0139     except("Failed to access the region %s from the detector description.", nam.c_str());
0140   }
0141   auto region_iter = mapping.g4Regions.find(rg);
0142   if ( region_iter == mapping.g4Regions.end() )    {
0143     except("Failed to locate G4Region: %s from the Geant4 mapping.", nam.c_str());
0144   }
0145   G4Region* region = (*region_iter).second;
0146   if ( region )   {
0147   }
0148   return region;
0149 }
0150 
0151 /// Add shower model to region's fast simulation manager
0152 void Geant4FastSimShowerModel::addShowerModel(G4Region* region)     {
0153   if ( !region )     {
0154     except("Geant4FastSimShowerModel::addShowerModel: Invalid G4Region reference!");
0155   }
0156   // Retrieves the Fast Simulation Manage and add the model
0157   G4FastSimulationManager* fastsimManager = region->GetFastSimulationManager();
0158   if ( !fastsimManager )   {
0159     fastsimManager = new G4FastSimulationManager(region, true);
0160   }
0161   // add this model to the Fast Simulation Manager.
0162   if ( m_model )
0163     fastsimManager->AddFastSimulationModel(m_model);
0164   else if ( m_wrapper )
0165     fastsimManager->AddFastSimulationModel(m_wrapper);
0166   else
0167     except("Geant4FastSimShowerModel::addShowerModel: Invalid shower model reference!");
0168 }
0169 
0170 /// Geometry construction callback. Called at "Construct()"
0171 void Geant4FastSimShowerModel::constructGeo(Geant4DetectorConstructionContext* /* ctxt */)    {
0172   this->m_applicableParticles.clear();
0173   for(const std::string& p : m_applicablePartNames)   {
0174     G4ParticleDefinition* def = (p=="*") ? nullptr : this->getParticleDefinition(p);
0175     this->m_applicableParticles.emplace(def);
0176   }
0177 }
0178 
0179 /// Electromagnetic field construction callback. Called at "ConstructSDandField()"
0180 void Geant4FastSimShowerModel::constructField(Geant4DetectorConstructionContext* /* ctxt */)   {
0181 }
0182 
0183 /// Sensitive detector construction callback. Called at "ConstructSDandField()"
0184 void Geant4FastSimShowerModel::constructSensitives(Geant4DetectorConstructionContext* /* ctxt */)    {
0185   G4Region* region = this->getRegion(this->m_regionName);
0186   for(const auto& prop : this->m_eTriggerNames)    {
0187     G4ParticleDefinition* def = this->getParticleDefinition(prop.first);
0188     double val = dd4hep::_toDouble(prop.second) ; // allready in G4units
0189     this->m_eTriggerCut.emplace(def, val);
0190     this->info("Set Energy(ModelTrigger) [%-16s] = %8.4f GeV", prop.first.c_str(), val);
0191   }
0192   this->m_model = nullptr;
0193   this->addShowerModel(region);
0194 }
0195 
0196 /// Kill primary particle when creating the shower
0197 void Geant4FastSimShowerModel::killParticle(G4FastStep& step, double deposit, double step_length)   {
0198   step.KillPrimaryTrack();
0199   step.ProposePrimaryTrackPathLength(step_length);
0200   step.ProposeTotalEnergyDeposited(deposit);
0201 }
0202 
0203 /// User callback to determine if the model is applicable for the particle type
0204 bool Geant4FastSimShowerModel::check_applicability(const G4ParticleDefinition& particle)   {
0205   return
0206     this->m_enable && 
0207     this->m_applicableParticles.find(&particle) != this->m_applicableParticles.end();
0208 }
0209 
0210 /// User callback to determine if the shower creation should be triggered
0211 bool Geant4FastSimShowerModel::check_trigger(const G4FastTrack& track)    {
0212   auto* prim = track.GetPrimaryTrack();
0213   auto* def  = prim->GetParticleDefinition();
0214   auto  iter = this->m_eTriggerCut.find(def);
0215   if ( iter != this->m_eTriggerCut.end() )  {
0216     return (*iter).second < prim->GetKineticEnergy();
0217   }
0218   iter = this->m_eTriggerCut.find(nullptr);
0219   if ( iter != this->m_eTriggerCut.end() )  {
0220     return (*iter).second < prim->GetKineticEnergy();
0221   }
0222   return false;
0223 }
0224 
0225 /// User callback to model the particle/energy shower
0226 void Geant4FastSimShowerModel::modelShower(const G4FastTrack& /* track */, G4FastStep& /* step */)    {
0227   except("Method %s::modelShower(const G4FastTrack& track, G4FastStep& step) "
0228      "is not implemented. User implementation mandatory.", this->name().c_str());
0229 }