File indexing completed on 2026-06-12 07:51:40
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #include <DD4hep/Printout.h>
0016 #include <DD4hep/InstanceCount.h>
0017 #include <DDG4/Geant4Context.h>
0018 #include <DDG4/Geant4Primary.h>
0019 #include <DDG4/Geant4ParticleGenerator.h>
0020 #include <DDG4/Geant4Random.h>
0021 #include <CLHEP/Units/PhysicalConstants.h>
0022 #include <CLHEP/Units/SystemOfUnits.h>
0023
0024
0025 #include <G4ParticleTable.hh>
0026 #include <G4ParticleDefinition.hh>
0027
0028
0029 #include <stdexcept>
0030 #include <cmath>
0031
0032 using namespace dd4hep::sim;
0033
0034
0035 Geant4ParticleGenerator::Geant4ParticleGenerator(Geant4Context* ctxt, const std::string& nam)
0036 : Geant4GeneratorAction(ctxt, nam), m_direction(0,1,0), m_position(0,0,0), m_particle(0)
0037 {
0038 InstanceCount::increment(this);
0039 m_needsControl = true;
0040 declareProperty("Particle", m_particleName = "e-");
0041 declareProperty("Energy", m_energy = -1);
0042 declareProperty("energy", m_energy = -1);
0043 declareProperty("MomentumMin", m_momentumMin = 0.0);
0044 declareProperty("MomentumMax", m_momentumMax = 50 * CLHEP::MeV);
0045 declareProperty("Multiplicity", m_multiplicity = 1);
0046 declareProperty("Mask", m_mask = 0);
0047 declareProperty("Position", m_position = ROOT::Math::XYZVector(0.,0.,0.));
0048 declareProperty("Direction", m_direction = ROOT::Math::XYZVector(1.,1.,1.));
0049 }
0050
0051
0052 Geant4ParticleGenerator::~Geant4ParticleGenerator() {
0053 InstanceCount::decrement(this);
0054 }
0055
0056
0057 void Geant4ParticleGenerator::getParticleDirection(int , ROOT::Math::XYZVector& , double& momentum) const {
0058 getParticleMomentumUniform(momentum);
0059 }
0060
0061
0062 void Geant4ParticleGenerator::getParticleMomentumUniform(double& momentum) const {
0063 if (m_energy != -1) {
0064 momentum = m_energy;
0065 return;
0066 }
0067 Geant4Event& evt = context()->event();
0068 Geant4Random& rnd = evt.random();
0069 if (m_momentumMax < m_momentumMin)
0070
0071 momentum = m_momentumMin+(momentum-m_momentumMin)*rnd.rndm();
0072 else
0073 momentum = m_momentumMin+(m_momentumMax-m_momentumMin)*rnd.rndm();
0074 }
0075
0076
0077 void Geant4ParticleGenerator::getParticleMultiplicity(int& ) const {
0078 }
0079
0080
0081 void Geant4ParticleGenerator::getVertexPosition(ROOT::Math::XYZVector& ) const {
0082 }
0083
0084
0085 void Geant4ParticleGenerator::printInteraction(int mask) const {
0086 Geant4PrimaryEvent* prim = context()->event().extension<Geant4PrimaryEvent>();
0087 if ( !prim ) {
0088 warning("printInteraction: Bad primary event [NULL-Pointer].");
0089 return;
0090 }
0091 Geant4PrimaryInteraction* inter = prim->get(mask);
0092 if ( !inter ) {
0093 warning("printInteraction: Bad interaction identifier 0x%08X [Unknown Mask].",mask);
0094 return;
0095 }
0096 printInteraction(inter);
0097 }
0098
0099
0100 void Geant4ParticleGenerator::printInteraction(Geant4PrimaryInteraction* inter) const {
0101 int count = 0;
0102 if ( !inter ) {
0103 warning("printInteraction: Invalid interaction pointer [NULL-Pointer].");
0104 return;
0105 }
0106 for(const auto& iv : inter->vertices ) {
0107 for( Geant4Vertex* v : iv.second ){
0108 print("+-> Interaction [%d] [%.3f , %.3f] GeV %s pos:(%.3f %.3f %.3f)[mm]",
0109 count, m_momentumMin/CLHEP::GeV, m_momentumMax/CLHEP::GeV, m_particleName.c_str(),
0110 v->x/CLHEP::mm, v->y/CLHEP::mm, v->z/CLHEP::mm);
0111 ++count;
0112 for ( int i : v->out ) {
0113 Geant4ParticleHandle p = inter->particles[i];
0114 p.dumpWithVertex(outputLevel(),name()," +->");
0115 }
0116 }
0117 }
0118 }
0119
0120
0121 void Geant4ParticleGenerator::operator()(G4Event*) {
0122 typedef Geant4Particle Particle;
0123
0124 if (0 == m_particle || m_particle->GetParticleName() != m_particleName.c_str()) {
0125 G4ParticleTable* particleTable = G4ParticleTable::GetParticleTable();
0126 m_particle = particleTable->FindParticle(m_particleName);
0127 if (0 == m_particle) {
0128 except("Geant4ParticleGenerator: Bad particle type: %s!", m_particleName.c_str());
0129 }
0130 }
0131 Geant4Event& evt = context()->event();
0132 Geant4PrimaryEvent* prim = evt.extension<Geant4PrimaryEvent>();
0133 Geant4PrimaryInteraction* inter = new Geant4PrimaryInteraction();
0134 prim->add(m_mask, inter);
0135
0136 Geant4Vertex* vtx = new Geant4Vertex();
0137 int multiplicity = m_multiplicity;
0138 ROOT::Math::XYZVector unit_direction, position = m_position;
0139 getVertexPosition(position);
0140 getParticleMultiplicity(multiplicity);
0141 vtx->mask = m_mask;
0142 vtx->x = position.X();
0143 vtx->y = position.Y();
0144 vtx->z = position.Z();
0145 inter->vertices[m_mask].emplace_back( vtx );
0146 for(int i=0; i<m_multiplicity; ++i) {
0147 double momentum = 0.0;
0148 ROOT::Math::XYZVector direction = m_direction;
0149 Particle* p = new Particle();
0150 getParticleDirection(i, direction, momentum);
0151 unit_direction = direction.unit();
0152 p->id = inter->nextPID();
0153 p->status |= G4PARTICLE_GEN_STABLE;
0154 p->mask = m_mask;
0155 p->pdgID = m_particle->GetPDGEncoding();
0156
0157 p->psx = unit_direction.X()*momentum;
0158 p->psy = unit_direction.Y()*momentum;
0159 p->psz = unit_direction.Z()*momentum;
0160 p->mass = m_particle->GetPDGMass();
0161 p->charge = 3 * m_particle->GetPDGCharge();
0162
0163
0164 if ( m_particle->GetParticleName() == "opticalphoton" ) {
0165 if ( momentum == 0.0 ) {
0166 except("Geant4ParticleGenerator: Cannot assign polarization to optical photon with zero momentum!");
0167 }
0168
0169 ROOT::Math::XYZVector e1, e2;
0170 if ( std::fabs(unit_direction.X()) < 0.9 )
0171 e1 = ROOT::Math::XYZVector(1, 0, 0);
0172 else
0173 e1 = ROOT::Math::XYZVector(0, 1, 0);
0174 e2 = unit_direction.Cross(e1).unit();
0175 e1 = e2.Cross(unit_direction).unit();
0176 Geant4Random& rnd = evt.random();
0177 double angle = CLHEP::twopi * rnd.rndm();
0178 ROOT::Math::XYZVector pol = (std::cos(angle)*e1 + std::sin(angle)*e2).unit();
0179 p->spin[0] = pol.X();
0180 p->spin[1] = pol.Y();
0181 p->spin[2] = pol.Z();
0182 }
0183 else {
0184 p->spin[0] = 0;
0185 p->spin[1] = 0;
0186 p->spin[2] = 0;
0187 }
0188 p->colorFlow[0] = 0;
0189 p->colorFlow[1] = 0;
0190 p->vsx = vtx->x;
0191 p->vsy = vtx->y;
0192 p->vsz = vtx->z;
0193
0194
0195
0196
0197 inter->particles.emplace(p->id,p);
0198 vtx->out.insert(p->id);
0199 printout(INFO,name(),"Particle [%d] %-12s Mom:%.3f GeV vertex:(%6.3f %6.3f %6.3f)[mm] direction:(%6.3f %6.3f %6.3f)",
0200 p->id, m_particleName.c_str(), momentum/CLHEP::GeV,
0201 vtx->x/CLHEP::mm, vtx->y/CLHEP::mm, vtx->z/CLHEP::mm,
0202 direction.X(), direction.Y(), direction.Z());
0203 }
0204 }