CMS 3D CMS Logo

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