File indexing completed on 2025-12-15 09:28:05
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #include <DDG4/Geant4FastSimShowerModel.h>
0016 #include <DDG4/Geant4Mapping.h>
0017 #include <DDG4/Geant4Kernel.h>
0018
0019
0020 #include <G4FastSimulationManager.hh>
0021 #include <G4VFastSimulationModel.hh>
0022 #include <G4TouchableHandle.hh>
0023 #include <G4ParticleTable.hh>
0024 #include <G4FastStep.hh>
0025
0026
0027 #include <sstream>
0028
0029 using namespace dd4hep::sim;
0030
0031
0032 namespace dd4hep {
0033
0034
0035 namespace sim {
0036
0037
0038 class Geant4FastSimShowerModel;
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048 class Geant4ShowerModelWrapper : public G4VFastSimulationModel {
0049
0050 Geant4FastSimShowerModel* m_model { nullptr };
0051
0052 public:
0053
0054 Geant4ShowerModelWrapper(Geant4FastSimShowerModel* model);
0055
0056 virtual ~Geant4ShowerModelWrapper() = default;
0057
0058 virtual G4bool IsApplicable(const G4ParticleDefinition& particle) override;
0059
0060 virtual G4bool ModelTrigger(const G4FastTrack& track) override;
0061
0062 virtual void DoIt(const G4FastTrack& track, G4FastStep& step) override;
0063 };
0064
0065 }
0066 }
0067
0068
0069 Geant4ShowerModelWrapper::Geant4ShowerModelWrapper(Geant4FastSimShowerModel* model)
0070 : G4VFastSimulationModel(model->name()), m_model(model)
0071 {
0072 }
0073
0074
0075 G4bool Geant4ShowerModelWrapper::IsApplicable(const G4ParticleDefinition& particle) {
0076 return this->m_model->check_applicability(particle);
0077 }
0078
0079
0080 G4bool Geant4ShowerModelWrapper::ModelTrigger(const G4FastTrack& track) {
0081 return this->m_model->check_trigger(track);
0082 }
0083
0084
0085 void Geant4ShowerModelWrapper::DoIt(const G4FastTrack& track, G4FastStep& step) {
0086 this->m_model->modelShower(track, step);
0087 }
0088
0089
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
0105 Geant4FastSimShowerModel::~Geant4FastSimShowerModel() {
0106 detail::deletePtr(m_model);
0107 detail::deletePtr(m_wrapper);
0108 }
0109
0110
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
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
0152 void Geant4FastSimShowerModel::addShowerModel(G4Region* region) {
0153 if ( !region ) {
0154 except("Geant4FastSimShowerModel::addShowerModel: Invalid G4Region reference!");
0155 }
0156
0157 G4FastSimulationManager* fastsimManager = region->GetFastSimulationManager();
0158 if ( !fastsimManager ) {
0159 fastsimManager = new G4FastSimulationManager(region, true);
0160 }
0161
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
0171 void Geant4FastSimShowerModel::constructGeo(Geant4DetectorConstructionContext* ) {
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
0180 void Geant4FastSimShowerModel::constructField(Geant4DetectorConstructionContext* ) {
0181 }
0182
0183
0184 void Geant4FastSimShowerModel::constructSensitives(Geant4DetectorConstructionContext* ) {
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) ;
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
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
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
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
0226 void Geant4FastSimShowerModel::modelShower(const G4FastTrack& , G4FastStep& ) {
0227 except("Method %s::modelShower(const G4FastTrack& track, G4FastStep& step) "
0228 "is not implemented. User implementation mandatory.", this->name().c_str());
0229 }