File indexing completed on 2025-01-18 09:14:20
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031 #include <DDG4/Geant4FastSimShowerModel.inl.h>
0032 #include <DDG4/Geant4FastSimSpot.h>
0033 #include <DDG4/Geant4Random.h>
0034
0035
0036 #include <G4Gamma.hh>
0037 #include <G4SystemOfUnits.hh>
0038
0039
0040
0041
0042
0043 namespace dd4hep {
0044
0045
0046 namespace sim {
0047
0048
0049
0050
0051
0052
0053
0054
0055 class par01_em_model {
0056 public:
0057 G4FastSimHitMaker hitMaker { };
0058 std::string materialName { };
0059 G4Material* material { nullptr };
0060 double criticalEnergyRef { 800*MeV };
0061 double criticalEnergy { 800*MeV };
0062 };
0063
0064
0065 template <>
0066 void Geant4FSShowerModel<par01_em_model>::initialize() {
0067 declareProperty("Material", this->locals.materialName);
0068 declareProperty("CriticalEnergy", this->locals.criticalEnergyRef);
0069 this->m_applicablePartNames.emplace_back("e+");
0070 this->m_applicablePartNames.emplace_back("e-");
0071 }
0072
0073
0074 template <>
0075 void Geant4FSShowerModel<par01_em_model>::constructSensitives(Geant4DetectorConstructionContext* ctxt) {
0076 locals.material = this->getMaterial(this->locals.materialName);
0077 locals.criticalEnergy = this->locals.criticalEnergyRef * (this->locals.material->GetZ() + 1.2);
0078 this->Geant4FastSimShowerModel::constructSensitives(ctxt);
0079 }
0080
0081
0082 template <>
0083 void Geant4FSShowerModel<par01_em_model>::modelShower(const G4FastTrack& track, G4FastStep& step) {
0084 auto* primary = track.GetPrimaryTrack();
0085
0086 this->killParticle(step, primary->GetKineticEnergy(), 0e0);
0087
0088
0089
0090
0091 G4FastHit hit;
0092 Geant4FastSimSpot spot(&hit, &track);
0093
0094
0095 G4double Ec = this->locals.criticalEnergy;
0096 G4double Energy = spot.kineticEnergy();
0097 G4double y = Energy/Ec;
0098
0099 G4double b = 0.5, C = -0.5;
0100 if (spot.trackDefinition() == G4Gamma::GammaDefinition()) C = 0.5;
0101 G4double tmax = 1.0 * (std::log(y) + C);
0102 G4double a = 1.0 + b*tmax;
0103
0104 G4double X0 = this->locals.material->GetRadlen();
0105
0106 G4double Es = 21*MeV;
0107 G4double Rm = X0*Es/Ec;
0108
0109 G4int nSpots = 100;
0110 G4double deposit = Energy/double(nSpots);
0111
0112
0113 G4ThreeVector xShower, yShower, zShower;
0114 zShower = spot.particleLocalDirection();
0115 xShower = zShower.orthogonal();
0116 yShower = zShower.cross(xShower);
0117
0118 Geant4Random* rndm = Geant4Random::instance();
0119 G4ThreeVector sShower = spot.particleLocalPosition();
0120 for (int i = 0; i < nSpots; i++) {
0121
0122 G4double bt = rndm->gamma(a, 1e0);
0123 G4double t = bt/b;
0124 G4double z = t*X0;
0125
0126 G4double xr = rndm->uniform(0e0,1e0);
0127 G4double phi = rndm->uniform(0e0,twopi);
0128 G4double r;
0129 if (xr < 0.9) r = xr/0.9*Rm;
0130 else r = ((xr - 0.9)/0.1*2.5 + 1.0)*Rm;
0131
0132 G4ThreeVector position = sShower + z*zShower + r*std::cos(phi)*xShower + r*std::sin(phi)*yShower;
0133
0134 hit.SetPosition(position);
0135 hit.SetEnergy(deposit);
0136 this->locals.hitMaker.make(hit, track);
0137 }
0138 }
0139
0140
0141
0142
0143
0144
0145
0146
0147 class par01_pion_model {
0148 public:
0149 G4FastSimHitMaker hitMaker { };
0150 };
0151
0152
0153 template <>
0154 void Geant4FSShowerModel<par01_pion_model>::initialize() {
0155 this->m_applicablePartNames.emplace_back("pi+");
0156 this->m_applicablePartNames.emplace_back("pi-");
0157 }
0158
0159
0160 template <>
0161 bool Geant4FSShowerModel<par01_pion_model>::check_trigger(const G4FastTrack& ) {
0162 return true;
0163 }
0164
0165
0166 template <>
0167 void Geant4FSShowerModel<par01_pion_model>::modelShower(const G4FastTrack& track, G4FastStep& step) {
0168 auto* primary = track.GetPrimaryTrack();
0169
0170 this->killParticle(step, primary->GetKineticEnergy(), 0e0);
0171
0172
0173
0174
0175
0176 G4ThreeVector pos = track.GetPrimaryTrackLocalPosition();
0177 G4ThreeVector dir = track.GetPrimaryTrackLocalDirection();
0178 G4double distOut = track.GetEnvelopeSolid()->DistanceToOut(pos, dir);
0179 G4ThreeVector showerCenter = pos + (distOut/2.)*dir;
0180
0181 showerCenter = track.GetInverseAffineTransformation()->TransformPoint(showerCenter);
0182
0183
0184 G4ThreeVector zShower = primary->GetMomentumDirection();
0185 G4ThreeVector xShower = zShower.orthogonal();
0186 G4ThreeVector yShower = zShower.cross(xShower);
0187
0188
0189 G4double Energy = primary->GetKineticEnergy();
0190 G4int nSpot = 50;
0191 G4double deposit = Energy/double(nSpot);
0192 Geant4Random* rndm = Geant4Random::instance();
0193 for (int i = 0; i < nSpot; i++) {
0194 double z = rndm->gauss(0, 20*cm);
0195 double r = rndm->gauss(0, 10*cm);
0196 double phi = rndm->uniform(0e0, twopi);
0197 G4ThreeVector position = showerCenter + z*zShower + r*std::cos(phi)*xShower + r*std::sin(phi)*yShower;
0198
0199 G4FastHit hit(position, deposit);
0200 this->locals.hitMaker.make(hit, track);
0201 }
0202 }
0203
0204 typedef Geant4FSShowerModel<par01_em_model> Geant4Par01EMShowerModel;
0205 typedef Geant4FSShowerModel<par01_pion_model> Geant4Par01PionShowerModel;
0206 }
0207 }
0208
0209 #include <DDG4/Factories.h>
0210 DECLARE_GEANT4ACTION_NS(dd4hep::sim,Geant4Par01EMShowerModel)
0211 DECLARE_GEANT4ACTION_NS(dd4hep::sim,Geant4Par01PionShowerModel)