CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
G4ProcessHelper.cc
Go to the documentation of this file.
1 #include"G4ParticleTable.hh"
2 #include "Randomize.hh"
3 
4 #include<iostream>
5 #include<fstream>
6 #include <string>
7 
11 
12 #include"SimG4Core/CustomPhysics/interface/G4ProcessHelper.hh"
15 
16 using namespace CLHEP;
17 
18 G4ProcessHelper::G4ProcessHelper(const edm::ParameterSet & p){
19 
20  particleTable = G4ParticleTable::GetParticleTable();
21 
22  theProton = particleTable->FindParticle("proton");
23  theNeutron = particleTable->FindParticle("neutron");
24 
25  G4String line;
26 
27  edm::FileInPath fp = p.getParameter<edm::FileInPath>("processesDef");
28  std::string processDefFilePath = fp.fullPath();
29  std::ifstream process_stream (processDefFilePath.c_str());
30 
31  resonant = p.getParameter<bool>("resonant");
32  ek_0 = p.getParameter<double>("resonanceEnergy")*GeV;
33  gamma = p.getParameter<double>("gamma")*GeV;
34  amplitude = p.getParameter<double>("amplitude")*millibarn;
35  suppressionfactor = p.getParameter<double>("reggeSuppression");
36  hadronlifetime = p.getParameter<double>("hadronLifeTime");
37  reggemodel = p.getParameter<bool>("reggeModel");
38  mixing = p.getParameter<double>("mixing");
39 
40  edm::LogInfo("CustomPhysics")<<"Read in physics parameters:"<<G4endl;
41  edm::LogInfo("CustomPhysics")<<"Resonant = "<< resonant <<G4endl;
42  edm::LogInfo("CustomPhysics")<<"ResonanceEnergy = "<<ek_0/GeV<<" GeV"<<G4endl;
43  edm::LogInfo("CustomPhysics")<<"Gamma = "<<gamma/GeV<<" GeV"<<G4endl;
44  edm::LogInfo("CustomPhysics")<<"Amplitude = "<<amplitude/millibarn<<" millibarn"<<G4endl;
45  edm::LogInfo("CustomPhysics")<<"ReggeSuppression = "<<100*suppressionfactor<<" %"<<G4endl;
46  edm::LogInfo("CustomPhysics")<<"HadronLifeTime = "<<hadronlifetime<<" s"<<G4endl;
47  edm::LogInfo("CustomPhysics")<<"ReggeModel = "<< reggemodel <<G4endl;
48  edm::LogInfo("CustomPhysics")<<"Mixing = "<< mixing*100 <<" %"<<G4endl;
49 
50 
51  checkfraction = 0;
52  n_22 = 0;
53  n_23 = 0;
54 
55 
56 
57  while(getline(process_stream,line)){
58  std::vector<G4String> tokens;
59  //Getting a line
60  ReadAndParse(line,tokens,"#");
61  //Important info
62  G4String incident = tokens[0];
63 
64  G4ParticleDefinition* incidentDef = particleTable->FindParticle(incident);
65  //particleTable->DumpTable();
66  G4int incidentPDG = incidentDef->GetPDGEncoding();
67  known_particles[incidentDef]=true;
68 
69  G4String target = tokens[1];
70  edm::LogInfo("CustomPhysics")<<"Incident: "<<incident
71  <<" Target: "<<target<<G4endl;
72 
73  // Making a ReactionProduct
74  ReactionProduct prod;
75  for (size_t i = 2; i != tokens.size();i++){
76  G4String part = tokens[i];
77  if (particleTable->contains(part))
78  {
79  prod.push_back(particleTable->FindParticle(part)->GetPDGEncoding());
80  } else {
81  edm::LogInfo("CustomPhysics")<<"Particle: "<<part<<" is unknown."<<G4endl;
82  G4Exception("G4ProcessHelper", "UnkownParticle", FatalException,
83  "Initialization: The reaction product list contained an unknown particle");
84  }
85  }
86  if (target == "proton")
87  {
88  pReactionMap[incidentPDG].push_back(prod);
89  } else if (target == "neutron") {
90  nReactionMap[incidentPDG].push_back(prod);
91  } else {
92  G4Exception("G4ProcessHelper", "IllegalTarget", FatalException,
93  "Initialization: The reaction product list contained an illegal target particle");
94  }
95  }
96 
97  process_stream.close();
98 
99  G4ParticleTable::G4PTblDicIterator* theParticleIterator;
100  theParticleIterator = particleTable->GetIterator();
101 
102  theParticleIterator->reset();
103  while( (*theParticleIterator)() ){
104  CustomParticle* particle = dynamic_cast<CustomParticle*>(theParticleIterator->value());
105  std::string name = theParticleIterator->value()->GetParticleName();
106  G4DecayTable* table = theParticleIterator->value()->GetDecayTable();
107  if(particle!=0&&table!=0&&name.find("cloud")>name.size()&&hadronlifetime > 0)
108  {
109  particle->SetPDGLifeTime(hadronlifetime*s);
110  particle->SetPDGStable(false);
111  edm::LogInfo("CustomPhysics")<<"Lifetime of: "<<name<<" set to: "<<particle->GetPDGLifeTime()/s<<" s."<<G4endl;
112  edm::LogInfo("CustomPhysics")<<"Stable: "<<particle->GetPDGStable()<<G4endl;
113  }
114  }
115  theParticleIterator->reset();
116 
117 
118 }
119 
120 G4bool G4ProcessHelper::ApplicabilityTester(const G4ParticleDefinition& aPart){
121  const G4ParticleDefinition* aP = &aPart;
122  if (known_particles[aP]) return true;
123  return false;
124 }
125 
126 G4double G4ProcessHelper::GetInclusiveCrossSection(const G4DynamicParticle *aParticle,
127  const G4Element *anElement){
128 
129  //We really do need a dedicated class to handle the cross sections. They might not always be constant
130 
131 
132  //Disassemble the PDG-code
133 
134  G4int thePDGCode = aParticle->GetDefinition()->GetPDGEncoding();
135  double boost = (aParticle->GetKineticEnergy()+aParticle->GetMass())/aParticle->GetMass();
136  // G4cout<<"thePDGCode: "<<thePDGCode<<G4endl;
137  G4double theXsec = 0;
138  G4String name = aParticle->GetDefinition()->GetParticleName();
139  if(!reggemodel)
140  {
141  //Flat cross section
142  if(CustomPDGParser::s_isRGlueball(thePDGCode)) {
143  theXsec = 24 * millibarn;
144  } else {
145  std::vector<G4int> nq=CustomPDGParser::s_containedQuarks(thePDGCode);
146  // edm::LogInfo("CustomPhysics")<<"Number of quarks: "<<nq.size()<<G4endl;
147  for (std::vector<G4int>::iterator it = nq.begin();
148  it != nq.end();
149  it++)
150  {
151  // edm::LogInfo("CustomPhysics")<<"Quarkvector: "<<*it<<G4endl;
152  if (*it == 1 || *it == 2) theXsec += 12 * millibarn;
153  if (*it == 3) theXsec += 6 * millibarn;
154  }
155  }
156  }
157  else
158  { //reggemodel
159  double R = Regge(boost);
160  double P = Pom(boost);
161  if(thePDGCode>0)
162  {
163  if(CustomPDGParser::s_isMesonino(thePDGCode)) theXsec=(P+R)*millibarn;
164  if(CustomPDGParser::s_isSbaryon(thePDGCode)) theXsec=2*P*millibarn;
165  if(CustomPDGParser::s_isRMeson(thePDGCode)||CustomPDGParser::s_isRGlueball(thePDGCode)) theXsec=(R+2*P)*millibarn;
166  if(CustomPDGParser::s_isRBaryon(thePDGCode)) theXsec=3*P*millibarn;
167  }
168  else
169  {
170  if(CustomPDGParser::s_isMesonino(thePDGCode)) theXsec=P*millibarn;
171  if(CustomPDGParser::s_isSbaryon(thePDGCode)) theXsec=(2*(P+R)+30/sqrt(boost))*millibarn;
172  if(CustomPDGParser::s_isRMeson(thePDGCode)||CustomPDGParser::s_isRGlueball(thePDGCode)) theXsec=(R+2*P)*millibarn;
173  if(CustomPDGParser::s_isRBaryon(thePDGCode)) theXsec=3*P*millibarn;
174  }
175  }
176 
177 
178 
179  //Adding resonance
180 
181  if(resonant)
182  {
183  double e_0 = ek_0 + aParticle->GetDefinition()->GetPDGMass(); //Now total energy
184 
185  e_0 = sqrt(aParticle->GetDefinition()->GetPDGMass()*aParticle->GetDefinition()->GetPDGMass()
186  + theProton->GetPDGMass()*theProton->GetPDGMass()
187  + 2.*e_0*theProton->GetPDGMass());
188  // edm::LogInfo("CustomPhysics")<<e_0/GeV<<G4endl;
189  // edm::LogInfo("CustomPhysics")<<ek_0/GeV<<" "<<aParticle->GetDefinition()->GetPDGMass()/GeV<<" "<<theProton->GetPDGMass()/GeV<<G4endl;
190  double sqrts=sqrt(aParticle->GetDefinition()->GetPDGMass()*aParticle->GetDefinition()->GetPDGMass()
191  + theProton->GetPDGMass()*theProton->GetPDGMass() + 2*aParticle->GetTotalEnergy()*theProton->GetPDGMass());
192 
193  double res_result = amplitude*(gamma*gamma/4.)/((sqrts-e_0)*(sqrts-e_0)+(gamma*gamma/4.));//Non-relativistic Breit Wigner
194 
195  theXsec += res_result;
196  // if(fabs(aParticle->GetKineticEnergy()/GeV-200)<10) std::cout<<sqrts/GeV<<" "<<theXsec/millibarn<<std::endl;
197  }
198 
199 
200  // std::cout<<"Xsec/nucleon: "<<theXsec/millibarn<<"millibarn, Total Xsec: "<<theXsec * anElement->GetN()/millibarn<<" millibarn"<<std::endl;
201  // return theXsec * anElement->GetN();// * 0.523598775598299;
202  return theXsec * pow(anElement->GetN(),0.7)*1.25;// * 0.523598775598299;
203 
204 }
205 
206 ReactionProduct G4ProcessHelper::GetFinalState(const G4Track& aTrack, G4ParticleDefinition*& aTarget){
207 
208  const G4DynamicParticle* aDynamicParticle = aTrack.GetDynamicParticle();
209 
210  //-----------------------------------------------
211  // Choose n / p as target
212  // and get ReactionProductList pointer
213  //-----------------------------------------------
214 
215  G4Material* aMaterial = aTrack.GetMaterial();
216  const G4ElementVector* theElementVector = aMaterial->GetElementVector() ;
217  const G4double* NbOfAtomsPerVolume = aMaterial->GetVecNbOfAtomsPerVolume();
218 
219  G4double NumberOfProtons=0;
220  G4double NumberOfNucleons=0;
221 
222  for ( size_t elm=0 ; elm < aMaterial->GetNumberOfElements() ; elm++ )
223  {
224  //Summing number of protons per unit volume
225  NumberOfProtons += NbOfAtomsPerVolume[elm]*(*theElementVector)[elm]->GetZ();
226  //Summing nucleons (not neutrons)
227  NumberOfNucleons += NbOfAtomsPerVolume[elm]*(*theElementVector)[elm]->GetN();
228  }
229 
230  if(G4UniformRand()<NumberOfProtons/NumberOfNucleons)
231  {
232  theReactionMap = &pReactionMap;
233  theTarget = theProton;
234  } else {
235  theReactionMap = &nReactionMap;
236  theTarget = theNeutron;
237  }
238  aTarget = theTarget;
239 
240  G4int theIncidentPDG = aDynamicParticle->GetDefinition()->GetPDGEncoding();
241 
242  if(reggemodel
243  &&CustomPDGParser::s_isMesonino(theIncidentPDG)
244  && G4UniformRand()*mixing>0.5
245  &&aDynamicParticle->GetDefinition()->GetPDGCharge()==0.
246  )
247  {
248  // G4cout<<"Oscillating..."<<G4endl;
249  theIncidentPDG *= -1;
250  }
251 
252 
253  bool baryonise=false;
254 
255  if(reggemodel
256  && G4UniformRand()>0.9
257  &&(
258  (CustomPDGParser::s_isMesonino(theIncidentPDG)&&theIncidentPDG>0)
259  ||
260  CustomPDGParser::s_isRMeson(theIncidentPDG)
261  )
262  )
263  baryonise=true;
264 
265  //Making a pointer directly to the ReactionProductList we are looking at. Makes life easier :-)
266  ReactionProductList* aReactionProductList = &((*theReactionMap)[theIncidentPDG]);
267 
268  //-----------------------------------------------
269  // Count processes
270  // kinematic check
271  // compute number of 2 -> 2 and 2 -> 3 processes
272  //-----------------------------------------------
273 
274  G4int N22 = 0; //Number of 2 -> 2 processes
275  G4int N23 = 0; //Number of 2 -> 3 processes. Couldn't think of more informative names
276 
277  //This is the list to be populated
278  ReactionProductList theReactionProductList;
279  std::vector<bool> theChargeChangeList;
280 
281  for (ReactionProductList::iterator prod_it = aReactionProductList->begin();
282  prod_it != aReactionProductList->end();
283  prod_it++){
284  G4int secondaries = prod_it->size();
285  // If the reaction is not possible we will not consider it
286 // if(ReactionIsPossible(*prod_it,aDynamicParticle)){
287  if(ReactionIsPossible(*prod_it,aDynamicParticle)
288  && (!reggemodel ||
289  (baryonise&&ReactionGivesBaryon(*prod_it))
290  ||
291  (!baryonise&&!ReactionGivesBaryon(*prod_it))
292  ||
293  (CustomPDGParser::s_isSbaryon(theIncidentPDG))
294  ||
295  (CustomPDGParser::s_isRBaryon(theIncidentPDG))
296  )
297  )
298  {
299  // The reaction is possible. Let's store and count it
300  theReactionProductList.push_back(*prod_it);
301  if (secondaries == 2){
302  N22++;
303  } else if (secondaries ==3) {
304  N23++;
305  } else {
306  G4cerr << "ReactionProduct has unsupported number of secondaries: "<<secondaries<<G4endl;
307  }
308  } /*else {
309  edm::LogInfo("CustomPhysics")<<"There was an impossible process"<<G4endl;
310  }*/
311  }
312  // edm::LogInfo("CustomPhysics")<<"The size of the ReactionProductList is: "<<theReactionProductList.size()<<G4endl;
313 
314  if (theReactionProductList.size()==0) G4Exception("G4ProcessHelper", "NoProcessPossible", FatalException,
315  "GetFinalState: No process could be selected from the given list.");
316 
317  // For the Regge model no phase space considerations. We pick a process at random
318  if(reggemodel)
319  {
320  int n_rps = theReactionProductList.size();
321  int select = (int)( G4UniformRand()*n_rps);
322  // G4cout<<"Possible: "<<n_rps<<", chosen: "<<select<<G4endl;
323  return theReactionProductList[select];
324  }
325 
326  // Fill a probability map. Remember total probability
327  // 2->2 is 0.15*1/n_22 2->3 uses phase space
328  G4double p22 = 0.15;
329  G4double p23 = 1-p22; // :-)
330 
331  std::vector<G4double> Probabilities;
332  std::vector<G4bool> TwotoThreeFlag;
333 
334  G4double CumulatedProbability = 0;
335 
336  // To each ReactionProduct we assign a cumulated probability and a flag
337  // discerning between 2 -> 2 and 2 -> 3
338  for (unsigned int i = 0; i != theReactionProductList.size(); i++){
339  if (theReactionProductList[i].size() == 2) {
340  CumulatedProbability += p22/N22;
341  TwotoThreeFlag.push_back(false);
342  } else {
343  CumulatedProbability += p23/N23;
344  TwotoThreeFlag.push_back(true);
345  }
346  Probabilities.push_back(CumulatedProbability);
347  // edm::LogInfo("CustomPhysics")<<"Pushing back cumulated probability: "<<CumulatedProbability<<G4endl;
348  }
349 
350  //Renormalising probabilities
351  // edm::LogInfo("CustomPhysics")<<"Probs: ";
352  for (std::vector<G4double>::iterator it = Probabilities.begin();
353  it != Probabilities.end();
354  it++)
355  {
356  *it /= CumulatedProbability;
357  // edm::LogInfo("CustomPhysics")<<*it<<" ";
358  }
359  // edm::LogInfo("CustomPhysics")<<G4endl;
360 
361  // Choosing ReactionProduct
362 
363  G4bool selected = false;
364  G4int tries = 0;
365  // ReactionProductList::iterator prod_it;
366 
367  //Keep looping over the list until we have a choice, or until we have tried 100 times
368  unsigned int i;
369  while(!selected && tries < 100){
370  i=0;
371  G4double dice = G4UniformRand();
372  // edm::LogInfo("CustomPhysics")<<"What's the dice?"<<dice<<G4endl;
373  while(dice>Probabilities[i] && i<theReactionProductList.size()){
374  // edm::LogInfo("CustomPhysics")<<"i: "<<i<<G4endl;
375  i++;
376  }
377 
378  // edm::LogInfo("CustomPhysics")<<"Chosen i: "<<i<<G4endl;
379 
380  if(!TwotoThreeFlag[i]) {
381  // 2 -> 2 processes are chosen immediately
382  selected = true;
383  } else {
384  // 2 -> 3 processes require a phase space lookup
385  if (PhaseSpace(theReactionProductList[i],aDynamicParticle)>G4UniformRand()) selected = true;
386  //selected = true;
387  }
388  // double suppressionfactor=0.5;
389  if(selected&&particleTable->FindParticle(theReactionProductList[i][0])->GetPDGCharge()!=aDynamicParticle->GetDefinition()->GetPDGCharge())
390  {
391  /*
392  edm::LogInfo("CustomPhysics")<<"Incoming particle "<<aDynamicParticle->GetDefinition()->GetParticleName()
393  <<" has charge "<<aDynamicParticle->GetDefinition()->GetPDGCharge()<<G4endl;
394  edm::LogInfo("CustomPhysics")<<"Suggested particle "<<particleTable->FindParticle(theReactionProductList[i][0])->GetParticleName()
395  <<" has charge "<<particleTable->FindParticle(theReactionProductList[i][0])->GetPDGCharge()<<G4endl;
396  */
397  if(G4UniformRand()<suppressionfactor) selected = false;
398  }
399  tries++;
400  // edm::LogInfo("CustomPhysics")<<"Tries: "<<tries<<G4endl;
401  }
402  if(tries>=100) G4cerr<<"Could not select process!!!!"<<G4endl;
403 
404  // edm::LogInfo("CustomPhysics")<<"So far so good"<<G4endl;
405  // edm::LogInfo("CustomPhysics")<<"Sec's: "<<theReactionProductList[i].size()<<G4endl;
406 
407  //Updating checkfraction:
408  if (theReactionProductList[i].size()==2) {
409  n_22++;
410  } else {
411  n_23++;
412  }
413 
414  checkfraction = (1.0*n_22)/(n_22+n_23);
415  // edm::LogInfo("CustomPhysics")<<"n_22: "<<n_22<<" n_23: "<<n_23<<" Checkfraction: "<<checkfraction<<G4endl;
416  // edm::LogInfo("CustomPhysics") <<"Biig number: "<<n_22+n_23<<G4endl;
417  //Return the chosen ReactionProduct
418  return theReactionProductList[i];
419 }
420 
421 G4double G4ProcessHelper::ReactionProductMass(const ReactionProduct& aReaction,const G4DynamicParticle* aDynamicParticle){
422  // Incident energy:
423  G4double E_incident = aDynamicParticle->GetTotalEnergy();
424  //edm::LogInfo("CustomPhysics")<<"Total energy: "<<E_incident<<" Kinetic: "<<aDynamicParticle->GetKineticEnergy()<<G4endl;
425  // sqrt(s)= sqrt(m_1^2 + m_2^2 + 2 E_1 m_2)
426  G4double m_1 = aDynamicParticle->GetDefinition()->GetPDGMass();
427  G4double m_2 = theTarget->GetPDGMass();
428  //edm::LogInfo("CustomPhysics")<<"M_R: "<<m_1/GeV<<" GeV, M_np: "<<m_2/GeV<<" GeV"<<G4endl;
429  G4double sqrts = sqrt(m_1*m_1 + m_2*(m_2 + 2 * E_incident));
430  //edm::LogInfo("CustomPhysics")<<"sqrt(s) = "<<sqrts/GeV<<" GeV"<<G4endl;
431  // Sum of rest masses after reaction:
432  G4double M_after = 0;
433  for (ReactionProduct::const_iterator r_it = aReaction.begin(); r_it !=aReaction.end(); r_it++){
434  //edm::LogInfo("CustomPhysics")<<"Mass contrib: "<<(particleTable->FindParticle(*r_it)->GetPDGMass())/MeV<<" MeV"<<G4endl;
435  M_after += particleTable->FindParticle(*r_it)->GetPDGMass();
436  }
437  //edm::LogInfo("CustomPhysics")<<"Intending to return this ReactionProductMass: "<<(sqrts - M_after)/MeV<<" MeV"<<G4endl;
438  return sqrts - M_after;
439 }
440 
441 G4bool G4ProcessHelper::ReactionIsPossible(const ReactionProduct& aReaction,const G4DynamicParticle* aDynamicParticle){
442  if (ReactionProductMass(aReaction,aDynamicParticle)>0) return true;
443  return false;
444 }
445 
446 G4bool G4ProcessHelper::ReactionGivesBaryon(const ReactionProduct& aReaction){
447  for (ReactionProduct::const_iterator it = aReaction.begin();it!=aReaction.end();it++)
449  return false;
450 }
451 
452 G4double G4ProcessHelper::PhaseSpace(const ReactionProduct& aReaction,const G4DynamicParticle* aDynamicParticle){
453  G4double qValue = ReactionProductMass(aReaction,aDynamicParticle);
454  G4double phi = sqrt(1+qValue/(2*0.139*GeV))*pow(qValue/(1.1*GeV),3./2.);
455  return (phi/(1+phi));
456 }
457 
458 void G4ProcessHelper::ReadAndParse(const G4String& str,
459  std::vector<G4String>& tokens,
460  const G4String& delimiters)
461 {
462  // Skip delimiters at beginning.
463  G4String::size_type lastPos = str.find_first_not_of(delimiters, 0);
464  // Find first "non-delimiter".
465  G4String::size_type pos = str.find_first_of(delimiters, lastPos);
466 
467  while (G4String::npos != pos || G4String::npos != lastPos)
468  {
469  //Skipping leading / trailing whitespaces
470  G4String temp = str.substr(lastPos, pos - lastPos);
471  while(temp.c_str()[0] == ' ') temp.erase(0,1);
472  while(temp[temp.size()-1] == ' ') temp.erase(temp.size()-1,1);
473  // Found a token, add it to the vector.
474  tokens.push_back(temp);
475  // Skip delimiters. Note the "not_of"
476  lastPos = str.find_first_not_of(delimiters, pos);
477  // Find next "non-delimiter"
478  pos = str.find_first_of(delimiters, lastPos);
479  }
480 }
481 
482 double G4ProcessHelper::Regge(const double boost)
483 {
484  double a=2.165635078566177;
485  double b=0.1467453738547229;
486  double c=-0.9607903711871166;
487  return 1.5*exp(a+b/boost+c*log(boost));
488 }
489 
490 
491 double G4ProcessHelper::Pom(const double boost)
492 {
493  double a=4.138224000651535;
494  double b=1.50377557581421;
495  double c=-0.05449742257808247;
496  double d=0.0008221235048211401;
497  return a + b*sqrt(boost) + c*boost + d*pow(boost,1.5);
498 }
499 
T getParameter(std::string const &) const
int i
Definition: DBlmapReader.cc:9
const double GeV
Definition: MathUtil.h:16
static bool s_isRGlueball(int pdg)
static bool s_isSbaryon(int pdg)
#define P
static bool s_isRMeson(int pdg)
uint16_t size_type
tuple d
Definition: ztail.py:151
static bool s_isMesonino(int pdg)
T sqrt(T t)
Definition: SSEVec.h:48
static bool s_isRBaryon(int pdg)
#define table(NAME)
Definition: DbCore.h:49
part
Definition: HCALResponse.h:20
static std::vector< int > s_containedQuarks(int pdg)
double b
Definition: hdecay.h:120
double a
Definition: hdecay.h:121
std::string fullPath() const
Definition: FileInPath.cc:165
tuple size
Write out results.
Power< A, B >::type pow(const A &a, const B &b)
Definition: Power.h:40
tuple log
Definition: cmsBatch.py:347
Definition: DDAxes.h:10