CMS 3D CMS Logo

CustomParticleFactory.cc
Go to the documentation of this file.
4 
7 
8 #include "G4ParticleTable.hh"
9 #include "G4DecayTable.hh"
10 #include "G4PhaseSpaceDecayChannel.hh"
11 #include "G4ProcessManager.hh"
12 #include "G4ParticleDefinition.hh"
13 #include "G4SystemOfUnits.hh"
14 
15 #include <iomanip>
16 #include <iostream>
17 #include <sstream>
18 
20 std::vector<G4ParticleDefinition *> CustomParticleFactory::m_particles;
21 
22 #ifdef G4MULTITHREADED
23 G4Mutex CustomParticleFactory::customParticleFactoryMutex = G4MUTEX_INITIALIZER;
24 #endif
25 
27 {}
28 
30 {}
31 
33 
34  if(loaded) { return; }
35 #ifdef G4MULTITHREADED
36  G4MUTEXLOCK(&customParticleFactoryMutex);
37  if(loaded) { return; }
38 #endif
39 
40  // loading once
41  loaded = true;
42  std::ifstream configFile(filePath.c_str());
43 
45  edm::LogInfo("SimG4CoreCustomPhysics")
46  <<"CustomParticleFactory: Reading Custom Particle and G4DecayTable from \n"
47  << filePath;
48  // This should be compatible IMO to SLHA
49  G4ParticleTable* theParticleTable = G4ParticleTable::GetParticleTable();
50  while(getline(configFile, line)){
51  line.erase(0, line.find_first_not_of(" \t")); // Remove leading whitespace.
52  if (line.length()==0 || line.at(0) == '#') { continue; } // Skip blank lines and comments.
53  // The mass table begins with a line containing "BLOCK MASS"
54  if (ToLower(line).find("block") < line.npos &&
55  ToLower(line).find("mass") < line.npos) {
56  edm::LogInfo("SimG4CoreCustomPhysics") <<"CustomParticleFactory: Retrieving mass table.";
57  getMassTable(&configFile);
58  }
59  if(line.find("DECAY")<line.npos) {
60  int pdgId;
61  double width;
62  std::string tmpString;
63  std::stringstream lineStream(line);
64  lineStream >> tmpString >> pdgId >> width;
65  // assume SLHA format, e.g.: DECAY 1000021 5.50675438E+00 # gluino decays
66  edm::LogInfo("SimG4CoreCustomPhysics")
67  <<"CustomParticleFactory: entry to G4DecayTable: pdgID, width "
68  << pdgId << ", " << width;
69  G4DecayTable* aDecayTable = getDecayTable(&configFile, pdgId);
70  G4ParticleDefinition *aParticle = theParticleTable->FindParticle(pdgId);
71  G4ParticleDefinition *aAntiParticle = theParticleTable->FindAntiParticle(pdgId);
72  if (!aParticle) { continue; }
73  aParticle->SetDecayTable(aDecayTable);
74  aParticle->SetPDGStable(false);
75  aParticle->SetPDGLifeTime(1.0/(width*CLHEP::GeV)*6.582122e-22*CLHEP::MeV*CLHEP::s);
76  if(aAntiParticle && aAntiParticle->GetPDGEncoding() != pdgId){
77  aAntiParticle->SetDecayTable(getAntiDecayTable(pdgId,aDecayTable));
78  aAntiParticle->SetPDGStable(false);
79  aAntiParticle->SetPDGLifeTime(1.0/(width*CLHEP::GeV)*6.582122e-22*CLHEP::MeV*CLHEP::s);
80  }
81  }
82  }
83 #ifdef G4MULTITHREADED
84  G4MUTEXUNLOCK(&customParticleFactoryMutex);
85 #endif
86 }
87 
89  const std::string & name){
90 
91  if(std::abs(pdgCode)%100 <14 && std::abs(pdgCode)/1000000 == 0){
92  edm::LogError("CustomParticleFactory::addCustomParticle")
93  << "Pdg code too low " << pdgCode << " "<<std::abs(pdgCode)/1000000;
94  return;
95  }
96 
98  G4String pType="custom";
99  G4String pSubType="";
100  G4double spectatormass = 0.0;
101  G4ParticleDefinition* spectator = nullptr;
103  if(CustomPDGParser::s_isRHadron(pdgCode)) { pType = "rhadron"; }
104  if(CustomPDGParser::s_isSLepton(pdgCode)) { pType = "sLepton"; }
105  if(CustomPDGParser::s_isMesonino(pdgCode)){ pType = "mesonino"; }
106  if(CustomPDGParser::s_isSbaryon(pdgCode)) { pType = "sbaryon"; }
107 
108  double massGeV = mass*CLHEP::GeV;
109  double width = 0.0;
110  double charge = CLHEP::eplus* CustomPDGParser::s_charge(pdgCode);
111  if (name.compare(0,4,"~HIP") == 0)
112  {
113  if ((name.compare(0,7,"~HIPbar") == 0)) {
114  std::string str = name.substr(7);
115  charge=CLHEP::eplus*atoi(str.c_str())/3.;
116  } else {
117  std::string str = name.substr(4);
118  charge=-CLHEP::eplus*atoi(str.c_str())/3.;
119  }
120  }
121  if (name.compare(0,9,"anti_~HIP") == 0)
122  {
123  if ((name.compare(0,12,"anti_~HIPbar") == 0)) {
124  std::string str = name.substr (12);
125  charge=-CLHEP::eplus*atoi(str.c_str())/3.;
126  } else {
127  std::string str = name.substr (9);
128  charge=CLHEP::eplus*atoi(str.c_str())/3.;
129  }
130  }
131  int spin = (int)CustomPDGParser::s_spin(pdgCode)-1;
132  int parity = +1;
133  int conjugation = 0;
134  int isospin = 0;
135  int isospinZ = 0;
136  int gParity = 0;
137  int lepton = 0; //FIXME:
138  int baryon = 1; //FIXME:
139  bool stable = true;
140  double lifetime = -1;
141 
142  if(CustomPDGParser::s_isDphoton(pdgCode)){
143  pType = "darkpho";
144  spin = 2;
145  parity = -1;
146  conjugation = -1;
147  isospin = 0;
148  isospinZ = 0;
149  gParity = 0;
150  lepton = 0;
151  baryon =0;
152  stable = true;
153  lifetime = -1;
154  }
155 
156  G4DecayTable *decaytable = nullptr;
157  G4ParticleTable* theParticleTable = G4ParticleTable::GetParticleTable();
158 
159  CustomParticle *particle = new CustomParticle(name, massGeV, width, charge, spin,
160  parity, conjugation, isospin, isospinZ,
161  gParity, pType, lepton, baryon, pdgCode,
162  stable, lifetime, decaytable);
163 
164  if(pType == "rhadron" && name!="~g"){
165  G4String cloudname = name+"cloud";
166  G4String cloudtype = pType+"cloud";
167  spectator = theParticleTable->FindParticle(1000021);
168  spectatormass = spectator->GetPDGMass();
169  G4double cloudmass = massGeV - spectatormass;
170  CustomParticle *tmpParticle = new CustomParticle(
171  cloudname, cloudmass, 0.0, 0,
172  0, +1, 0,
173  0, 0, 0,
174  cloudtype, 0, +1, 0,
175  true, -1.0, nullptr );
176  particle->SetCloud(tmpParticle);
177  particle->SetSpectator(spectator);
178 
179  edm::LogInfo("SimG4CoreCustomPhysics")
180  <<"CustomParticleFactory: " <<name<<" being assigned spectator"
181  << spectator->GetParticleName() << " and cloud " <<cloudname << "\n"
182  <<" Masses: "<<mass<<" Gev, "
183  <<spectatormass/CLHEP::GeV<<" GeV and "<<cloudmass/CLHEP::GeV<<" GeV.";
184  } else if(pType == "mesonino" || pType == "sbaryon") {
185  int sign=1;
186  if(pdgCode < 0 ) sign=-1;
187 
188  G4String cloudname = name+"cloud";
189  G4String cloudtype = pType+"cloud";
190  if(CustomPDGParser::s_isstopHadron(pdgCode)) {
191  spectator = theParticleTable->FindParticle(1000006*sign);
192  }
193  else {
194  if (CustomPDGParser::s_issbottomHadron(pdgCode)) {
195  spectator = theParticleTable->FindParticle(1000005*sign);
196  } else {
197  spectator = nullptr;
198  edm::LogError("SimG4CoreCustomPhysics")<< "CustomParticleFactory: Cannot find spectator parton";
199  }
200  }
201  if(spectator) { spectatormass = spectator->GetPDGMass(); }
202  G4double cloudmass = massGeV - spectatormass;
203  CustomParticle *tmpParticle = new CustomParticle(
204  cloudname, cloudmass, 0.0, 0 ,
205  0, +1, 0,
206  0, 0, 0,
207  cloudtype, 0, +1, 0,
208  true, -1.0, nullptr);
209  particle->SetCloud(tmpParticle);
210  particle->SetSpectator(spectator);
211 
212  edm::LogInfo("SimG4CoreCustomPhysics")
213  <<"CustomParticleFactory: " <<name<<" being assigned spectator"
214  << spectator->GetParticleName() << " and cloud " <<cloudname << "\n"
215  <<" Masses: "<<mass<<" Gev, "
216  <<spectatormass/CLHEP::GeV<<" GeV and "<<cloudmass/CLHEP::GeV<<" GeV.";
217  }
218  else{
219  particle->SetCloud(nullptr);
220  particle->SetSpectator(nullptr);
221  }
222  m_particles.push_back(particle);
223 }
224 
225 void CustomParticleFactory::getMassTable(std::ifstream *configFile) {
226 
227  int pdgId;
228  double mass;
231  // This should be compatible IMO to SLHA
232  while (getline(*configFile,line)) {
233  line.erase(0, line.find_first_not_of(" \t")); // remove leading whitespace
234  if (line.length()==0 || line.at(0) == '#') continue; // skip blank lines and comments
235  if (ToLower(line).find("block") < line.npos) {
236  edm::LogInfo("SimG4CoreCustomPhysics")
237  <<"CustomParticleFactory: Finished the Mass Table ";
238  break;
239  }
240  std::stringstream sstr(line);
241  sstr >> pdgId >> mass >> tmp >> name; // Assume SLHA format, e.g.: 1000001 5.68441109E+02 # ~d_L
242 
243  mass = std::max(mass, 0.0);
244 
245  edm::LogInfo("SimG4CoreCustomPhysics")
246  <<"CustomParticleFactory: Calling addCustomParticle for pdgId: " << pdgId
247  << ", mass " << mass << " GeV, name " << name;
248  addCustomParticle(pdgId, mass, name);
250  int pdgIdPartner = pdgId%100;
251  G4ParticleTable* theParticleTable = G4ParticleTable::GetParticleTable();
252  G4ParticleDefinition *aParticle = theParticleTable->FindParticle(pdgIdPartner);
253  //Add antiparticles for SUSY particles only, not for rHadrons.
254  edm::LogInfo("SimG4CoreCustomPhysics")
255  <<"CustomParticleFactory: Found aParticle = " << aParticle
256  << ", pdgId = " << pdgId
257  << ", pdgIdPartner = " << pdgIdPartner
258  << ", CustomPDGParser::s_isRHadron(pdgId) = " << CustomPDGParser::s_isRHadron(pdgId)
259  << ", CustomPDGParser::s_isstopHadron(pdgId) = " << CustomPDGParser::s_isstopHadron(pdgId);
260 
261  if (aParticle &&
262  !CustomPDGParser::s_isRHadron(pdgId) &&
263  !CustomPDGParser::s_isstopHadron(pdgId) &&
264  pdgId!=1000006 &&
265  pdgId!=-1000006 &&
266  pdgId!=25 &&
267  pdgId!=35 &&
268  pdgId!=36 &&
269  pdgId!=37){
270  int sign = aParticle->GetAntiPDGEncoding()/pdgIdPartner;
271  edm::LogInfo("SimG4CoreCustomPhysics")
272  <<"CustomParticleFactory: Found sign = " << sign
273  << ", aParticle->GetAntiPDGEncoding() " << aParticle->GetAntiPDGEncoding()
274  << ", pdgIdPartner = " << pdgIdPartner;
275  if(std::abs(sign)!=1) {
276  edm::LogInfo("SimG4CoreCustomPhysics")
277  <<"CustomParticleFactory: sgn= "<<sign<<" a "
278  <<aParticle->GetAntiPDGEncoding()<<" b "<<pdgIdPartner;
279  aParticle->DumpTable();
280  }
281  if(sign==-1 && pdgId!=25 && pdgId!=35 && pdgId!=36 && pdgId!=37 && pdgId!=1000039){
282  tmp = "anti_"+name;
283  edm::LogInfo("SimG4CoreCustomPhysics")
284  <<"CustomParticleFactory: Calling addCustomParticle for antiparticle with pdgId: "
285  << -pdgId << ", mass " << mass << " GeV, name " << tmp;
286  addCustomParticle(-pdgId, mass, tmp);
287  theParticleTable->FindParticle(pdgId)->SetAntiPDGEncoding(-pdgId);
288  }
289  else theParticleTable->FindParticle(pdgId)->SetAntiPDGEncoding(pdgId);
290  }
291 
292  if(pdgId==1000039) theParticleTable->FindParticle(pdgId)->SetAntiPDGEncoding(pdgId); // gravitino
293  if(pdgId==1000024 || pdgId==1000037 || pdgId==37) {
294  tmp = "anti_"+name;
295  edm::LogInfo("SimG4CoreCustomPhysics")
296  <<"CustomParticleFactory: Calling addCustomParticle for antiparticle (2) with pdgId: "
297  << -pdgId << ", mass " << mass << " GeV, name " << tmp;
298  addCustomParticle(-pdgId, mass, tmp);
299  theParticleTable->FindParticle(pdgId)->SetAntiPDGEncoding(-pdgId);
300  }
301  }
302 }
303 
304 G4DecayTable* CustomParticleFactory::getDecayTable(std::ifstream *configFile, int pdgId) {
305 
306  double br;
307  int nDaughters;
308  std::vector<int> pdg(4);
310  std::vector<std::string> name(4);
311 
312  G4ParticleTable* theParticleTable = G4ParticleTable::GetParticleTable();
313 
314  std::string parentName = theParticleTable->FindParticle(pdgId)->GetParticleName();
315  G4DecayTable *decaytable= new G4DecayTable();
316 
317  while(getline(*configFile,line)) {
318 
319  line.erase(0, line.find_first_not_of(" \t")); // remove leading whitespace
320  if (line.length()==0) continue; // skip blank lines
321  if (line.at(0) == '#' &&
322  ToLower(line).find("br") < line.npos &&
323  ToLower(line).find("nda") < line.npos) continue; // skip a comment of the form: # BR NDA ID1 ID2
324  if (line.at(0) == '#') { // other comments signal the end of the decay block
325  edm::LogInfo("SimG4CoreCustomPhysics") <<"CustomParticleFactory: Finished the Decay Table ";
326  break;
327  }
328 
329  pdg.clear();
330  name.clear();
331 
332  std::stringstream sstr(line);
333  sstr >> br >> nDaughters; // assume SLHA format, e.g.: 1.49435135E-01 2 -15 16 # BR(H+ -> tau+ nu_tau)
334  edm::LogInfo("SimG4CoreCustomPhysics")
335  <<"CustomParticleFactory: Branching Ratio: " << br << ", Number of Daughters: " << nDaughters;
336  if (nDaughters > 4) {
337  edm::LogError("SimG4CoreCustomPhysics")
338  <<"CustomParticleFactory: Number of daughters is too large (max = 4): " << nDaughters
339  << " for pdgId: " << pdgId;
340  break;
341  }
342  for(int i=0; i<nDaughters; i++) {
343  sstr >> pdg[i];
344  edm::LogInfo("SimG4CoreCustomPhysics") <<"CustomParticleFactory: Daughter ID " << pdg[i];
345  const G4ParticleDefinition* part = theParticleTable->FindParticle(pdg[i]);
346  if (!part) {
347  edm::LogWarning("SimG4CoreCustomPhysics")
348  <<"CustomParticleFactory: particle with PDG code"<<pdg[i] <<" not found!";
349  continue;
350  }
351  name[i] = part->GetParticleName();
352  }
354  G4PhaseSpaceDecayChannel *aDecayChannel = new G4PhaseSpaceDecayChannel(parentName, br, nDaughters,
355  name[0],name[1],name[2],name[3]);
356  decaytable->Insert(aDecayChannel);
357  }
358  return decaytable;
359 }
360 
361 G4DecayTable* CustomParticleFactory::getAntiDecayTable(int pdgId, G4DecayTable *theDecayTable) {
362 
363  std::vector<std::string> name(4);
364  G4ParticleTable* theParticleTable = G4ParticleTable::GetParticleTable();
365 
366  std::string parentName = theParticleTable->FindParticle(-pdgId)->GetParticleName();
367  G4DecayTable *decaytable= new G4DecayTable();
368 
369  for(int i=0;i<theDecayTable->entries();i++){
370  G4VDecayChannel *theDecayChannel = theDecayTable->GetDecayChannel(i);
371  int nd = std::min(4, theDecayChannel->GetNumberOfDaughters());
372  for(int j=0; j<nd; ++j){
373  int id = theDecayChannel->GetDaughter(j)->GetAntiPDGEncoding();
374  const G4ParticleDefinition* part = theParticleTable->FindParticle(id);
375  if (!part) {
376  edm::LogWarning("SimG4CoreCustomPhysics")
377  <<"CustomParticleFactory: antiparticle with PDG code"<<id <<" not found!";
378  continue;
379  }
380  name[j] = part->GetParticleName();
381  }
382  G4PhaseSpaceDecayChannel *aDecayChannel =
383  new G4PhaseSpaceDecayChannel(parentName,
384  theDecayChannel->GetBR(), nd,
385  name[0],name[1],name[2],name[3]);
386  decaytable->Insert(aDecayChannel);
387  }
388  return decaytable;
389 }
390 
392  std::locale loc;
393  for (std::string::size_type i=0; i<str.length(); ++i)
394  str.at(i) = std::tolower(str.at(i),loc);
395  return str;
396 }
397 
398 const std::vector<G4ParticleDefinition *>& CustomParticleFactory::GetCustomParticles()
399 {
400  return m_particles;
401 }
const double GeV
Definition: MathUtil.h:16
static bool s_isDphoton(int pdg)
static double s_charge(int pdg)
static const int stable
Definition: TopGenEvent.h:11
static bool s_isSbaryon(int pdg)
void SetCloud(G4ParticleDefinition *theCloud)
uint16_t size_type
void loadCustomParticles(const std::string &filePath)
static std::vector< G4ParticleDefinition * > m_particles
const double MeV
static bool s_isMesonino(int pdg)
static bool s_isSLepton(int pdg)
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
std::string ToLower(std::string str)
void SetSpectator(G4ParticleDefinition *theSpectator)
T min(T a, T b)
Definition: MathUtil.h:58
static double s_spin(int pdg)
void getMassTable(std::ifstream *configFile)
G4DecayTable * getDecayTable(std::ifstream *configFile, int pdgId)
void addCustomParticle(int pdgCode, double mass, const std::string &name)
part
Definition: HCALResponse.h:20
G4DecayTable * getAntiDecayTable(int pdgId, G4DecayTable *theDecayTable)
static bool s_isRHadron(int pdg)
std::vector< std::vector< double > > tmp
Definition: MVATrainer.cc:100
const std::vector< G4ParticleDefinition * > & GetCustomParticles()
static bool s_issbottomHadron(int pdg)
static bool s_isstopHadron(int pdg)
float spin(float ph)