25#include "HepPDT/ParticleDataTable.hh"
27#include "CLHEP/Random/RandomEngine.h"
33 double r = engine->flat();
34 return ((-ct)*std::log(1.-
r));
40 double r = engine->flat();
96 double e = genpart->momentum().e();
97 double theta = genpart->momentum().theta();
98 double phi = genpart->momentum().phi();
100 double p2 = e*e - newMass*newMass;
102 ATH_MSG_FATAL(
"ParticleDecayer::fillEvt: -- you have generated a tachyon!");
103 return StatusCode::FAILURE;
106 double p = std::sqrt(p2);
107 double px = p*std::sin(
theta)*std::cos(
phi);
108 double py = p*std::sin(
theta)*std::sin(
phi);
109 double pz = p*std::cos(
theta);
111 const CLHEP::HepLorentzVector updatedLV(px,py,pz,e);
112 genpart->set_momentum(HepMC::FourVector(updatedLV.x(),updatedLV.y(),updatedLV.z(),updatedLV.e()));
113 genpart->set_generated_mass(newMass);
114 return StatusCode::SUCCESS;
122 ATH_MSG_FATAL(
"ParticleDecayer::fillEvt: -- no production vertex position found!");
123 return StatusCode::FAILURE;
128 end_vtx->set_position(vtxp->position());
129 end_vtx->add_particle_in(std::move(genpart));
130 event->add_vertex(std::move(end_vtx));
131 return StatusCode::SUCCESS;
135 double gamma = genpart->momentum().e()/genpart->momentum().m();
137 double theta = genpart->momentum().theta();
153 double distanceToEdge = -999.;
165 return StatusCode::FAILURE;
167 double Limit = distanceToEdge / gamma;
172 while ( ctau > Limit )
185 double decayRadius = -999.;
189 double outerRadius = outerLength*std::sin(
theta);
196 double decayLength = decayRadius/std::sin(
theta);
197 ctau = decayLength/gamma;
200 ATH_MSG_FATAL(
"have to pick uniform or exponential decay distance");
201 return StatusCode::FAILURE;
204 double ctg = gamma * ctau;
205 double px = genpart->momentum().px();
206 double py = genpart->momentum().py();
207 double pz = genpart->momentum().pz();
208 double p = std::sqrt(px*px + py*py + pz*pz);
210 const CLHEP::HepLorentzVector posLV(((ctg*px/p)+(vtxp->position().x())), ((ctg*py/p)+(vtxp->position().y())), ((ctg*pz/p)+(vtxp->position().z())), ((ctg)+(vtxp->position().t())));
214 ATH_MSG_DEBUG(
"ParticleDecayer::fillEvt: -- set the decay vertex");
216 end_vtx->set_position(HepMC::FourVector(posLV.x(),posLV.y(),posLV.z(),posLV.t()));
217 end_vtx->add_particle_in(std::move(genpart));
218 event->add_vertex(std::move(end_vtx));
219 return StatusCode::SUCCESS;
262 ATH_MSG_FATAL(
"Cannot configure exponential and uniform decay at the same time.");
263 return StatusCode::FAILURE;
267 if (TOTBR>1.0000001) {
268 ATH_MSG_FATAL(
"ParticleDecayer::genInitialize: -- Branching Ratio sum is larger than 1!! Please check the values in your jobOption.");
272 ATH_MSG_FATAL(
"ParticleDecayer::genInitialize: -- Total Branching Ratio " << TOTBR);
273 return StatusCode::FAILURE;
282 return StatusCode::FAILURE;
286 return StatusCode::SUCCESS;
294 const EventContext& ctx = Gaudi::Hive::currentContext();
295 CLHEP::HepRandomEngine* engine = this->
getRandomEngine(
"ParticleDecayer", ctx);
297 StatusCode status = StatusCode::SUCCESS;
302 ATH_MSG_DEBUG(
"ParticleDecayer::fillEvt: -- Found an McEventCollection for ParticleDecayer");
305 status = StatusCode::FAILURE;
309 event = mcEvtColl->
back();
312 ATH_MSG_FATAL(
"ParticleDecayer::fillEvt: -- McEvent was not successfully created");
313 status = StatusCode::FAILURE;
317 for (
auto genpart : *event) {
324 ATH_MSG_DEBUG(
"ParticleDecayer::fillEvt: -- only one dark photon per LeptonJet");
325 ATH_MSG_DEBUG(
"ParticleDecayer::fillEvt: -- found MC particle with PDG ID = " << genpart->pdg_id());
340 ATH_MSG_DEBUG(
"ParticleDecayer::fillEvt: -- set the new status = 2");
341 genpart->set_status(2);
344 ATH_MSG_DEBUG(
"ParticleDecayer::fillEvt: -- set the new momentum");
356 ATH_MSG_DEBUG(
"ParticleDecayer::fillEvt: -- two dark photons per LeptonJet");
357 ATH_MSG_DEBUG(
"ParticleDecayer::fillEvt: -- found MC particle with PDG ID = " << genpart->pdg_id());
370 ATH_MSG_DEBUG(
"ParticleDecayer::fillEvt: -- set the new status = 2");
371 genpart->set_status(2);
378 ATH_MSG_DEBUG(
"ParticleDecayer::fillEvt: -- allow the two-body decay of the dark scalar to dark photons...");
381 std::vector<CLHEP::HepLorentzVector> darkPhotonLVs;
382 CHECK(
getDecayProducts( engine, CLHEP::HepLorentzVector( genpart->momentum().px(), genpart->momentum().py(), genpart->momentum().pz(), genpart->momentum().e() ),
387 auto v0=darkPhotonLVs.at(0).vect();
390 auto v1=darkPhotonLVs.at(1).vect();
394 int polarizationSwitch = 1;
396 auto pItBegin = genpart->end_vertex()->particles_out().end();
397 auto pItEnd = genpart->end_vertex()->particles_out().end();
399 HepMC::GenVertex::particles_out_const_iterator pItBegin = genpart->end_vertex()->particles_out_const_begin();
400 HepMC::GenVertex::particles_out_const_iterator pItEnd = genpart->end_vertex()->particles_out_const_end();
402 for (
auto pIt=pItBegin ; pIt != pItEnd; ++pIt )
407 ATH_MSG_DEBUG(
"ParticleDecayer::fillEvt: -- Now allow the two-body decay of the dark photons");
411 polarizationSwitch = -polarizationSwitch;
420 return StatusCode::FAILURE;
428 if (event->weights().empty()) {
429 event->weights().push_back(1.);
450 double energy=std::sqrt(std::pow(momentum.x(),2)+std::pow(momentum.y(),2)+std::pow(momentum.z(),2)+mass*mass);
454 prod_vtx->add_particle_out(std::move(aParticle));
460 SmartIF<IPartPropSvc>
partPropSvc(Gaudi::svcLocator()->service(
"PartPropSvc"));
461 if (!
partPropSvc)
throw GaudiException(
"PartPropSvc error",
"I_ParticleDecayer", StatusCode::FAILURE);
464 const HepPDT::ParticleData* particle =
m_particleTable->particle(HepPDT::ParticleID(std::abs(pid)));
465 return particle->mass().value();
473 ATH_MSG_DEBUG(
"ParticleDecayer::fillEvt: -- allow the two-body decay of the dark photon...");
476 CLHEP::HepLorentzVector boostDF( genpart->momentum().px(), genpart->momentum().py(), genpart->momentum().pz(), genpart->momentum().e() );
488 ATH_MSG_DEBUG(
"ParticleDecayer::fillEvt: -- decayMode = " << ModeOfDecay);
496 if(Polarization==0) {
498 }
else if(Polarization==-1 && (ModeOfDecay==11 || ModeOfDecay==13)) {
500 }
else if(Polarization==1 && (ModeOfDecay==11 || ModeOfDecay==13)) {
502 }
else if(Polarization==-1 && ModeOfDecay==211) {
504 }
else if(Polarization==1 && ModeOfDecay==211) {
507 ATH_MSG_FATAL(
"ParticleDecayer::fillEvt: -- wrong polarization value... please check!");
508 return StatusCode::FAILURE;
512 std::vector<CLHEP::HepLorentzVector> daughterLVs;
516 ATH_MSG_DEBUG(
"ParticleDecayer::fillEvt: -- Add the daughters to the pool file");
517 auto end_vtx = genpart->end_vertex();
518 auto v0=daughterLVs.at(0).vect();
519 addParticle(end_vtx, ModeOfDecay, HepMC::FourVector(v0.x(),v0.y(),v0.z(),0.0), 1);
520 auto v1=daughterLVs.at(1).vect();
521 addParticle(std::move(end_vtx), -ModeOfDecay, HepMC::FourVector(v1.x(),v1.y(),v1.z(),0.0), 1);
523 return StatusCode::SUCCESS;
528 double decayPartMass,
529 std::vector<CLHEP::HepLorentzVector>& daughterLVs,
532 double parentMass = parentLV.m();
533 CLHEP::Hep3Vector boostVec = parentLV.boostVector();
535 if( decayPartMass > parentMass/2.)
537 ATH_MSG_FATAL(
"Decay particle has more than half the mass of parent.");
538 return StatusCode::FAILURE;
542 double ct_rf =
cosgen(engine, decayType);
543 double theta_rf = std::acos(ct_rf);
546 double p1_rf = std::sqrt(parentMass*parentMass/4. - decayPartMass*decayPartMass);
547 double px_rf = p1_rf*std::cos(phi_rf)*std::sin(theta_rf);
548 double py_rf = p1_rf*std::sin(phi_rf)*std::sin(theta_rf);
549 double pz_rf = p1_rf*ct_rf;
550 CLHEP::HepLorentzVector hlv1( px_rf, py_rf, pz_rf, parentMass/2.);
551 CLHEP::HepLorentzVector hlv2( -px_rf, -py_rf, -pz_rf, parentMass/2.);
554 hlv1.rotateUz((parentLV.vect()).unit());
555 hlv2.rotateUz((parentLV.vect()).unit());
558 hlv1.boost(boostVec);
559 hlv2.boost(boostVec);
561 daughterLVs.push_back(hlv1);
562 daughterLVs.push_back(hlv2);
564 return StatusCode::SUCCESS;
Scalar phi() const
phi method
Scalar theta() const
theta method
#define CHECK(...)
Evaluate an expression and check for errors.
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
ServiceHandle< StoreGateSvc > & evtStore()
const T * back() const
Access the last element in the collection as an rvalue.
const ServiceHandle< IPartPropSvc > partPropSvc() const
Access the particle property service.
GenModule(const std::string &name, ISvcLocator *pSvcLocator)
Constructor.
CLHEP::HepRandomEngine * getRandomEngine(const std::string &streamName, const EventContext &ctx) const
This defines the McEventCollection, which is really just an ObjectVector of McEvent objectsFile: Gene...
double getParticleMass(int pdgID)
bool m_doExponentialDecay
StatusCode changeMass(HepMC::GenParticlePtr, double)
bool m_expDecayDoVariableLifetime
HepPDT::ParticleDataTable * m_particleTable
StatusCode DFTwoBodyDecay(CLHEP::HepRandomEngine *engine, HepMC::GenParticlePtr, int)
StatusCode getDecayProducts(CLHEP::HepRandomEngine *engine, CLHEP::HepLorentzVector, double, std::vector< CLHEP::HepLorentzVector > &, int decayType=0)
StatusCode setDecayPosition(CLHEP::HepRandomEngine *engine, HepMC::GenParticlePtr, HepMC::GenEvent *, bool doScalarDecay=false)
double rnd_DoubleRange(CLHEP::HepRandomEngine *engine, double a, double b)
std::string m_truthParticleContainerName
void addParticle(HepMC::GenVertexPtr, int pdg, HepMC::FourVector, int statusCode)
ParticleDecayer(const std::string &name, ISvcLocator *pSvcLocator)
double m_particleLifeTime
bool m_oppositePolarization
double m_thetaEndCapBarrel
double cosgen(CLHEP::HepRandomEngine *engine, int itype)
int m_particlePolarization
double m_expDecayFractionToKeep
StatusCode fillEvt(HepMC::GenEvent *)
For filling the HepMC event object.
bool m_expDecayDoTruncateLongDecays
StatusCode genInitialize()
For initializing the generator, if required.
double rnd_ExpLifetime(CLHEP::HepRandomEngine *engine, double ct)
bool contains(const std::string &s, const std::string ®x)
does a string contain the substring
HepMC::GenVertex * GenVertexPtr
GenVertexPtr newGenVertexPtr(const HepMC::FourVector &pos=HepMC::FourVector(0.0, 0.0, 0.0, 0.0), const int i=0)
GenParticlePtr newGenParticlePtr(const HepMC::FourVector &mom=HepMC::FourVector(0.0, 0.0, 0.0, 0.0), int pid=0, int status=0)
GenParticle * GenParticlePtr