CMS 3D CMS Logo

FullModelHadronicProcess.cc
Go to the documentation of this file.
1 #include "G4ProcessManager.hh"
2 #include "G4ParticleTable.hh"
3 #include "G4HadronicException.hh"
4 
10 
11 using namespace CLHEP;
12 
14  : G4VDiscreteProcess(processName), theHelper(aHelper) {}
15 
17 
18 G4bool FullModelHadronicProcess::IsApplicable(const G4ParticleDefinition& aP) {
19  return theHelper->ApplicabilityTester(aP);
20 }
21 
22 G4double FullModelHadronicProcess::GetMicroscopicCrossSection(const G4DynamicParticle* aParticle,
23  const G4Element* anElement,
24  G4double aTemp) {
25  //Get the cross section for this particle/element combination from the ProcessHelper
26  G4double InclXsec = theHelper->GetInclusiveCrossSection(aParticle, anElement);
27  // G4cout<<"Returned cross section from helper was: "<<InclXsec/millibarn<<" millibarn"<<G4endl;
28  return InclXsec;
29 }
30 
31 G4double FullModelHadronicProcess::GetMeanFreePath(const G4Track& aTrack, G4double, G4ForceCondition*) {
32  G4Material* aMaterial = aTrack.GetMaterial();
33  const G4DynamicParticle* aParticle = aTrack.GetDynamicParticle();
34  G4double sigma = 0.0;
35 
36  G4int nElements = aMaterial->GetNumberOfElements();
37 
38  const G4double* theAtomicNumDensityVector = aMaterial->GetAtomicNumDensityVector();
39  G4double aTemp = aMaterial->GetTemperature();
40 
41  for (G4int i = 0; i < nElements; ++i) {
42  G4double xSection = GetMicroscopicCrossSection(aParticle, (*aMaterial->GetElementVector())[i], aTemp);
43  sigma += theAtomicNumDensityVector[i] * xSection;
44  }
45  G4double res = DBL_MAX;
46  if (sigma > 0.0) {
47  res = 1. / sigma;
48  }
49  return res;
50 }
51 
52 G4VParticleChange* FullModelHadronicProcess::PostStepDoIt(const G4Track& aTrack, const G4Step& aStep) {
53  // G4cout<<"**** Entering FullModelHadronicProcess::PostStepDoIt ******"<<G4endl;
54  const G4TouchableHandle& thisTouchable(aTrack.GetTouchableHandle());
55 
56  // A little setting up
57  aParticleChange.Initialize(aTrack);
58  const G4DynamicParticle* IncidentRhadron = aTrack.GetDynamicParticle();
59  CustomParticle* CustomIncident = static_cast<CustomParticle*>(IncidentRhadron->GetDefinition());
60  const G4ThreeVector& aPosition = aTrack.GetPosition();
61  // G4cout<<"G: "<<aStep.GetStepLength()/cm<<G4endl;
62  const G4int theIncidentPDG = IncidentRhadron->GetDefinition()->GetPDGEncoding();
63  G4ParticleTable* theParticleTable = G4ParticleTable::GetParticleTable();
64  std::vector<G4ParticleDefinition*> theParticleDefinitions;
65  G4bool IncidentSurvives = false;
66  G4bool TargetSurvives = false;
67  G4Nucleus targetNucleus(aTrack.GetMaterial());
68  G4ParticleDefinition* outgoingRhadron = nullptr;
69  G4ParticleDefinition* outgoingCloud = nullptr;
70  G4ParticleDefinition* outgoingTarget = nullptr;
71 
72  G4ThreeVector p_0 = IncidentRhadron->GetMomentum();
73  G4double e_kin_0 = IncidentRhadron->GetKineticEnergy();
74  // G4cout<<e_kin_0/GeV<<G4endl;
75 
76  G4DynamicParticle* cloudParticle = new G4DynamicParticle();
77  /*
78  if(CustomPDGParser::s_isRMeson(theIncidentPDG))
79  G4cout<<"Rmeson"<<G4endl;
80  if(CustomPDGParser::s_isRBaryon(theIncidentPDG))
81  G4cout<<"Rbaryon"<<G4endl;
82  */
83  cloudParticle->SetDefinition(CustomIncident->GetCloud());
84 
85  if (cloudParticle->GetDefinition() == nullptr) {
86  G4cout << "FullModelHadronicProcess::PostStepDoIt Definition of particle cloud not available!!" << G4endl;
87  }
88  /*
89  G4cout<<"Incoming particle was "<<IncidentRhadron->GetDefinition()->GetParticleName()
90  <<". Corresponding cloud is "<<cloudParticle->GetDefinition()->GetParticleName()<<G4endl;
91  G4cout<<"Kinetic energy was: "<<IncidentRhadron->GetKineticEnergy()/GeV<<" GeV"<<G4endl;
92  */
93  double scale = cloudParticle->GetDefinition()->GetPDGMass() / IncidentRhadron->GetDefinition()->GetPDGMass();
94  // G4cout<<"Mass ratio: "<<scale<<G4endl;
95  G4LorentzVector cloudMomentum(IncidentRhadron->GetMomentum() * scale, cloudParticle->GetDefinition()->GetPDGMass());
96  G4LorentzVector gluinoMomentum(IncidentRhadron->GetMomentum() * (1. - scale),
97  CustomIncident->GetSpectator()->GetPDGMass());
98 
99  //These two for getting CMS transforms later (histogramming purposes...)
100  G4LorentzVector FullRhadron4Momentum = IncidentRhadron->Get4Momentum();
101  const G4LorentzVector& Cloud4Momentum = cloudMomentum;
102 
103  cloudParticle->Set4Momentum(cloudMomentum);
104 
105  G4DynamicParticle* OrgPart = cloudParticle;
106 
107  /*
108  G4cout<<"Original momentum: "<<IncidentRhadron->Get4Momentum().v().mag()/GeV
109  <<" GeV, corresponding to gamma: "
110  <<IncidentRhadron->GetTotalEnergy()/IncidentRhadron->GetDefinition()->GetPDGMass()<<G4endl;
111 
112  G4cout<<"Cloud momentum: "<<cloudParticle->Get4Momentum().v().mag()/GeV
113  <<" GeV, corresponding to gamma: "
114  <<cloudParticle->GetTotalEnergy()/cloudParticle->GetDefinition()->GetPDGMass()<<G4endl;
115  */
116 
117  double E_0 = IncidentRhadron->GetKineticEnergy();
118  G4double ek = OrgPart->GetKineticEnergy();
119  G4double amas = OrgPart->GetDefinition()->GetPDGMass();
120  G4ThreeVector dir = (OrgPart->GetMomentum()).unit();
121  G4double tkin = targetNucleus.Cinema(ek);
122  ek += tkin;
123 
124  // calculate black track energies
125  tkin = targetNucleus.EvaporationEffects(ek);
126  ek -= tkin;
127 
128  if (ek + gluinoMomentum.e() - gluinoMomentum.m() <= 0.1 * MeV || ek <= 0.) {
129  //Very rare event...
130  G4cout << "Kinetic energy is sick" << G4endl;
131  G4cout << "Full R-hadron: " << (ek + gluinoMomentum.e() - gluinoMomentum.m()) / MeV << " MeV" << G4endl;
132  G4cout << "Quark system: " << ek / MeV << " MeV" << G4endl;
133  aParticleChange.ProposeTrackStatus(fStopButAlive); // AR_NEWCODE_IMPORT
134  return &aParticleChange;
135  }
136  OrgPart->SetKineticEnergy(ek);
137  G4double p = std::sqrt(ek * (ek + 2 * amas));
138  OrgPart->SetMomentum(dir * p);
139 
140  //Get the final state particles
141  G4ParticleDefinition* aTarget;
142  ReactionProduct rp = theHelper->GetFinalState(aTrack, aTarget);
143  G4bool force2to2 = false;
144  // G4cout<<"Trying to get final state..."<<G4endl;
145  while (rp.size() != 2 && force2to2) {
146  rp = theHelper->GetFinalState(aTrack, aTarget);
147  }
148  G4int NumberOfSecondaries = rp.size();
149  // G4cout<<"Multiplicity of selected final state: "<<rp.size()<<G4endl;
150 
151  //Getting CMS transforms. Boosting is done at histogram filling
152  G4LorentzVector Target4Momentum(0., 0., 0., aTarget->GetPDGMass());
153 
154  G4LorentzVector psum_full = FullRhadron4Momentum + Target4Momentum;
155  G4LorentzVector psum_cloud = Cloud4Momentum + Target4Momentum;
156  G4ThreeVector trafo_full_cms = (-1) * psum_full.boostVector();
157  G4ThreeVector trafo_cloud_cms = (-1) * psum_cloud.boostVector();
158 
159  // OK Let's make some particles :-)
160  // We're not using them for anything yet, I know, but let's make sure the machinery is there
161  for (ReactionProduct::iterator it = rp.begin(); it != rp.end(); ++it) {
162  G4ParticleDefinition* tempDef = theParticleTable->FindParticle(*it);
163  CustomParticle* tempCust = dynamic_cast<CustomParticle*>(tempDef);
164  if (tempDef == aTarget)
165  TargetSurvives = true;
166 
167  // if (tempDef->GetParticleType()=="rhadron")
168  if (tempCust != nullptr) {
169  outgoingRhadron = tempDef;
170  //Setting outgoing cloud definition
171  outgoingCloud = tempCust->GetCloud();
172  if (outgoingCloud == nullptr) {
173  G4cout << "FullModelHadronicProcess::PostStepDoIt Definition of outgoing particle cloud not available!"
174  << G4endl;
175  }
176  /*
177  G4cout<<"Outgoing Rhadron is: "<<outgoingRhadron->GetParticleName()<<G4endl;
178  G4cout<<"Outgoing cloud is: "<<outgoingCloud->GetParticleName()<<G4endl;
179  */
180  }
181 
182  if (tempDef == G4Proton::Proton() || tempDef == G4Neutron::Neutron())
183  outgoingTarget = tempDef;
184  if (tempCust == nullptr && rp.size() == 2)
185  outgoingTarget = tempDef;
186  if (tempDef->GetPDGEncoding() == theIncidentPDG) {
187  IncidentSurvives = true;
188  } else {
189  theParticleDefinitions.push_back(tempDef);
190  }
191  }
192 
193  if (outgoingTarget == nullptr)
194  outgoingTarget = theParticleTable->FindParticle(rp[1]);
195 
196  // A little debug information
197  /*
198  G4cout<<"The particles coming out of this reaction will be: ";
199  for (std::vector<G4DynamicParticle*>::iterator it = theDynamicParticles.begin();
200  it != theDynamicParticles.end();
201  it++){
202  G4cout<< (*it)->GetDefinition()->GetParticleName()<<" ";
203  }
204  G4cout<<G4endl;
205  */
206  // If the incident particle survives it is not a "secondary", although
207  // it would probably be easier to fStopAndKill the track every time.
208  if (IncidentSurvives)
209  NumberOfSecondaries--;
210  aParticleChange.SetNumberOfSecondaries(NumberOfSecondaries);
211 
212  // ADAPTED FROM G4LEPionMinusInelastic::ApplyYourself
213  // It is bloody ugly, but such is the way of cut 'n' paste
214 
215  // Set up the incident
216  // This is where rotation to z-axis is done
217  const G4HadProjectile* originalIncident = new G4HadProjectile(*OrgPart);
218 
219  //Maybe I need to calculate trafo from R-hadron... Bollocks! Labframe does not move. CMS does.
220  G4HadProjectile* org2 = new G4HadProjectile(*OrgPart);
221  G4LorentzRotation trans = org2->GetTrafoToLab();
222  delete org2;
223 
224  // create the target particle
225 
226  G4DynamicParticle* originalTarget = new G4DynamicParticle;
227  originalTarget->SetDefinition(aTarget);
228 
229  G4ReactionProduct targetParticle(aTarget);
230 
231  G4ReactionProduct currentParticle(const_cast<G4ParticleDefinition*>(originalIncident->GetDefinition()));
232  currentParticle.SetMomentum(originalIncident->Get4Momentum().vect());
233  currentParticle.SetKineticEnergy(originalIncident->GetKineticEnergy());
234 
235  /*
236  G4cout<<"After creation:"<<G4endl;
237  G4cout<<"currentParticle: "<<currentParticle.GetMomentum()/GeV<<" GeV vs. "<<OrgPart->Get4Momentum()/GeV<<" GeV"<<G4endl;
238  G4cout<<"targetParticle: "<<targetParticle.GetMomentum()/GeV<<" GeV"<<G4endl;
239  G4cout<<"Fourmomentum from originalIncident: "<<originalIncident->Get4Momentum()<<" vs "<<OrgPart->Get4Momentum()<<G4endl;
240  */
241 
242  G4ReactionProduct modifiedOriginal = currentParticle;
243 
244  currentParticle.SetSide(1); // incident always goes in forward hemisphere
245  targetParticle.SetSide(-1); // target always goes in backward hemisphere
246  G4bool incidentHasChanged = false;
247  if (!IncidentSurvives)
248  incidentHasChanged = true; //I wonder if I am supposed to do this...
249  G4bool targetHasChanged = false;
250  if (!TargetSurvives)
251  targetHasChanged = true; //Ditto here
252  G4bool quasiElastic = false;
253  if (rp.size() == 2)
254  quasiElastic = true; //Oh well...
255  G4FastVector<G4ReactionProduct, MYGHADLISTSIZE> vec; // vec will contain the secondary particles
256  G4int vecLen = 0;
257  vec.Initialize(0);
258 
259  // I hope my understanding of "secondary" is correct here
260  // I think that it entails only what is not a surviving incident of target
261 
262  for (G4int i = 0; i != NumberOfSecondaries; i++) {
263  if (theParticleDefinitions[i] != aTarget && theParticleDefinitions[i] != originalIncident->GetDefinition() &&
264  theParticleDefinitions[i] != outgoingRhadron && theParticleDefinitions[i] != outgoingTarget) {
265  G4ReactionProduct* pa = new G4ReactionProduct;
266  pa->SetDefinition(theParticleDefinitions[i]);
267  (G4UniformRand() < 0.5) ? pa->SetSide(-1) : pa->SetSide(1);
268  vec.SetElement(vecLen++, pa);
269  }
270  }
271 
272  if (incidentHasChanged)
273  currentParticle.SetDefinitionAndUpdateE(outgoingCloud);
274  if (incidentHasChanged)
275  modifiedOriginal.SetDefinition(
276  outgoingCloud); //Is this correct? It solves the "free energy" checking in ReactionDynamics
277  if (targetHasChanged)
278  targetParticle.SetDefinitionAndUpdateE(outgoingTarget);
279 
280  // G4cout<<"Calling CalculateMomenta... "<<G4endl;
281  /*
282  G4cout<<"Current particle starts as: "<<currentParticle.GetDefinition()->GetParticleName()<<G4endl;
283  G4cout<<"with momentum: "<<currentParticle.GetMomentum()/GeV<<" GeV"<<G4endl;
284  G4cout<<"May be killed?: "<<currentParticle.GetMayBeKilled()<<G4endl;
285  */
286 
287  CalculateMomenta(vec,
288  vecLen,
289  originalIncident,
290  originalTarget,
291  modifiedOriginal,
292  targetNucleus,
293  currentParticle,
294  targetParticle,
295  incidentHasChanged,
296  targetHasChanged,
297  quasiElastic);
298 
299  // G4cout <<"Cloud loss: "<<(e_temp-currentParticle.GetKineticEnergy())/GeV<<" GeV"<<G4endl;
300 
301  G4String cPname = currentParticle.GetDefinition()->GetParticleName();
302 
303  // if(cPname!="rhadronmesoncloud"&&cPname!="rhadronbaryoncloud")
304  // {
305  /*
306  G4cout<<"Current particle is now: "<<cPname <<G4endl;
307  G4cout<<"with momentum: "<<currentParticle.GetMomentum()/GeV<<" GeV"<<G4endl;
308  G4cout<<"and kinetic energy: "<<currentParticle.GetKineticEnergy()/GeV<<" GeV"<<G4endl;
309  G4cout<<"May be killed?: "<<currentParticle.GetMayBeKilled()<<G4endl;
310  G4cout<<"Modified original is: "<<modifiedOriginal.GetDefinition()->GetParticleName()<<G4endl;
311  G4cout<<"with momentum: "<<modifiedOriginal.GetMomentum()/GeV<<" GeV"<<G4endl;
312  G4cout<<"and kinetic energy: "<<modifiedOriginal.GetKineticEnergy()/GeV<<" GeV"<<G4endl;
313  G4cout<<"May be killed?: "<<modifiedOriginal.GetMayBeKilled()<<G4endl;
314  G4cout<<"Target particle is: "<<targetParticle.GetDefinition()->GetParticleName()<<G4endl;
315  G4cout<<"with momentum: "<<targetParticle.GetMomentum()/GeV<<" GeV"<<G4endl;
316  G4cout<<"and kinetic energy: "<<targetParticle.GetKineticEnergy()/GeV<<" GeV"<<G4endl;
317  G4cout<<"May be killed?: "<<targetParticle.GetMayBeKilled()<<G4endl;
318  G4cout<<"incidentHasChanged: "<<incidentHasChanged<<G4endl;
319  G4cout<<"targetHasChanged: "<<targetHasChanged<<G4endl;
320  G4cout<<"Particles in vec:"<<G4endl;
321  for(int i=0; i<vecLen; ++i )
322  {
323  G4cout<< vec[i]->GetDefinition()->GetParticleName()<<G4endl;
324  }
325  */
326  // G4cout<<"Done!"<<G4endl;
327 
328  aParticleChange.SetNumberOfSecondaries(vecLen + NumberOfSecondaries);
329  G4double e_kin = 0;
330  G4LorentzVector cloud_p4_new; //Cloud 4-momentum in lab after collision
331  // n++;
332  // G4cout << n << G4endl;
333  /*
334  if(cPname!="rhadronmesoncloud"&&cPname!="rhadronbaryoncloud") {
335  G4cout<<"Cloud deleted!!! AAARRRRGGGHHH!!!"<<G4endl;
336  G4cout<<"Cloud name: "<<cPname<<G4endl;
337  G4cout<<"E_kin_0: "<<e_kin_0/GeV<<" GeV"<<G4endl;
338  // G4cout<<"n: "<<n<<G4endl;
339  // n=0;
340  }
341  */
342  cloud_p4_new.setVectM(currentParticle.GetMomentum(), currentParticle.GetMass());
343  cloud_p4_new *= trans;
344 
345  G4LorentzVector cloud_p4_old_full = Cloud4Momentum; //quark system in CMS BEFORE collision
346  cloud_p4_old_full.boost(trafo_full_cms);
347  G4LorentzVector cloud_p4_old_cloud = Cloud4Momentum; //quark system in cloud CMS BEFORE collision
348  cloud_p4_old_cloud.boost(trafo_cloud_cms);
349  G4LorentzVector cloud_p4_full = cloud_p4_new; //quark system in CMS AFTER collision
350  cloud_p4_full.boost(trafo_full_cms);
351  G4LorentzVector cloud_p4_cloud = cloud_p4_new; //quark system in cloud CMS AFTER collision
352  cloud_p4_cloud.boost(trafo_cloud_cms);
353 
354  G4LorentzVector p_g_cms = gluinoMomentum; //gluino in CMS BEFORE collision
355  p_g_cms.boost(trafo_full_cms);
356 
357  double e = cloud_p4_new.e() + gluinoMomentum.e();
358  if (outgoingRhadron)
359  e += outgoingRhadron->GetPDGMass();
360  G4LorentzVector p4_new(cloud_p4_new.v() + gluinoMomentum.v(), e);
361  // G4cout<<"P4-diff: "<<(p4_new-cloud_p4_new-gluinoMomentum)/GeV<<", magnitude: "
362  // <<(p4_new-cloud_p4_new-gluinoMomentum).m()/MeV<<" MeV" <<G4endl;
363 
364  G4ThreeVector p_new = p4_new.vect();
365 
366  aParticleChange.ProposeLocalEnergyDeposit((p4_new - cloud_p4_new - gluinoMomentum).m());
367 
368  if (incidentHasChanged) {
369  G4DynamicParticle* p0 = new G4DynamicParticle;
370  p0->SetDefinition(outgoingRhadron);
371  p0->SetMomentum(p_new);
372 
373  // May need to run SetDefinitionAndUpdateE here...
374  G4Track* Track0 = new G4Track(p0, aTrack.GetGlobalTime(), aPosition);
375  Track0->SetTouchableHandle(thisTouchable);
376  aParticleChange.AddSecondary(Track0);
377  /*
378  G4cout<<"Adding a particle "<<p0->GetDefinition()->GetParticleName()<<G4endl;
379  G4cout<<"with momentum: "<<p0->GetMomentum()/GeV<<" GeV"<<G4endl;
380  G4cout<<"and kinetic energy: "<<p0->GetKineticEnergy()/GeV<<" GeV"<<G4endl;
381  */
382  if (p0->GetKineticEnergy() > e_kin_0) {
383  G4cout << "ALAAAAARM!!! (incident changed from " << IncidentRhadron->GetDefinition()->GetParticleName() << " to "
384  << p0->GetDefinition()->GetParticleName() << ")" << G4endl;
385  G4cout << "Energy loss: " << (e_kin_0 - p0->GetKineticEnergy()) / GeV << " GeV (should be positive)" << G4endl;
386  //Turns out problem is only in 2 -> 3 (Won't fix 2 -> 2 energy deposition)
387  if (rp.size() != 3)
388  G4cout << "DOUBLE ALAAAAARM!!!" << G4endl;
389  } /*else {
390  G4cout<<"NO ALAAAAARM!!!"<<G4endl;
391  }*/
392  if (std::abs(p0->GetKineticEnergy() - e_kin_0) > 100 * GeV) {
393  G4cout << "Diff. too big" << G4endl;
394  }
395  aParticleChange.ProposeTrackStatus(fStopAndKill);
396  } else {
397  G4double p = p_new.mag();
398  if (p > DBL_MIN)
399  aParticleChange.ProposeMomentumDirection(p_new.x() / p, p_new.y() / p, p_new.z() / p);
400  else
401  aParticleChange.ProposeMomentumDirection(1.0, 0.0, 0.0);
402  }
403 
404  // return G4VDiscreteProcess::PostStepDoIt( aTrack, aStep);
405  if (targetParticle.GetMass() > 0.0) // targetParticle can be eliminated in TwoBody
406  {
407  G4DynamicParticle* p1 = new G4DynamicParticle;
408  p1->SetDefinition(targetParticle.GetDefinition());
409  //G4cout<<"Target secondary: "<<targetParticle.GetDefinition()->GetParticleName()<<G4endl;
410  G4ThreeVector momentum = targetParticle.GetMomentum();
411  momentum = momentum.rotate(cache, what);
412  p1->SetMomentum(momentum);
413  p1->SetMomentum((trans * p1->Get4Momentum()).vect());
414  G4Track* Track1 = new G4Track(p1, aTrack.GetGlobalTime(), aPosition);
415  Track1->SetTouchableHandle(thisTouchable);
416  aParticleChange.AddSecondary(Track1);
417  }
418  G4DynamicParticle* pa;
419  /*
420  G4cout<<"vecLen: "<<vecLen<<G4endl;
421  G4cout<<"#sec's: "<<aParticleChange.GetNumberOfSecondaries()<<G4endl;
422  */
423 
424  for (int i = 0; i < vecLen; ++i) {
425  pa = new G4DynamicParticle();
426  pa->SetDefinition(vec[i]->GetDefinition());
427  pa->SetMomentum(vec[i]->GetMomentum());
428  pa->Set4Momentum(trans * (pa->Get4Momentum()));
429  G4ThreeVector pvec = pa->GetMomentum();
430  G4Track* Trackn = new G4Track(pa, aTrack.GetGlobalTime(), aPosition);
431  Trackn->SetTouchableHandle(thisTouchable);
432  aParticleChange.AddSecondary(Trackn);
433 
434  delete vec[i];
435  }
436 
437  // Histogram filling
438  const G4DynamicParticle* theRhadron = FindRhadron(&aParticleChange);
439 
440  if (theRhadron != nullptr || IncidentSurvives) {
441  double E_new;
442  if (IncidentSurvives) {
443  E_new = e_kin;
444  } else {
445  E_new = theRhadron->GetKineticEnergy();
446  if (CustomPDGParser::s_isRMeson(theRhadron->GetDefinition()->GetPDGEncoding()) !=
447  CustomPDGParser::s_isRMeson(theIncidentPDG) ||
448  CustomPDGParser::s_isMesonino(theRhadron->GetDefinition()->GetPDGEncoding()) !=
449  CustomPDGParser::s_isMesonino(theIncidentPDG)) {
450  G4cout << "Rm: " << CustomPDGParser::s_isRMeson(theRhadron->GetDefinition()->GetPDGEncoding())
451  << " vs: " << CustomPDGParser::s_isRMeson(theIncidentPDG) << G4endl;
452  G4cout << "Sm: " << CustomPDGParser::s_isMesonino(theRhadron->GetDefinition()->GetPDGEncoding())
453  << " vs: " << CustomPDGParser::s_isMesonino(theIncidentPDG) << G4endl;
454  }
455  }
456 
457  //Calculating relevant scattering angles.
458  G4LorentzVector p4_old_full = FullRhadron4Momentum; //R-hadron in CMS BEFORE collision
459  p4_old_full.boost(trafo_full_cms);
460  G4LorentzVector p4_old_cloud = FullRhadron4Momentum; //R-hadron in cloud CMS BEFORE collision
461  p4_old_cloud.boost(trafo_cloud_cms);
462  G4LorentzVector p4_full = p4_new; //R-hadron in CMS AFTER collision
463  // G4cout<<p4_full.v()/GeV<<G4endl;
464  p4_full = p4_full.boost(trafo_full_cms);
465  // G4cout<<p4_full.m()<<" / "<<(cloud_p4_new+gluinoMomentum).boost(trafo_full_cms).m()<<G4endl;
466  G4LorentzVector p4_cloud = p4_new; //R-hadron in cloud CMS AFTER collision
467  p4_cloud.boost(trafo_cloud_cms);
468 
469  G4double AbsDeltaE = E_0 - E_new;
470  // G4cout <<"Energy loss: "<<AbsDeltaE/GeV<<G4endl;
471  if (AbsDeltaE > 10 * GeV) {
472  G4cout << "Energy loss larger than 10 GeV..." << G4endl;
473  G4cout << "E_0: " << E_0 / GeV << " GeV" << G4endl;
474  G4cout << "E_new: " << E_new / GeV << " GeV" << G4endl;
475  G4cout << "Gamma: " << IncidentRhadron->GetTotalEnergy() / IncidentRhadron->GetDefinition()->GetPDGMass()
476  << G4endl;
477  G4cout << "x: " << aPosition.x() / cm << " cm" << G4endl;
478  }
479  }
480  delete originalIncident;
481  delete originalTarget;
482  // aParticleChange.DumpInfo();
483  // G4cout << "Exiting FullModelHadronicProcess::PostStepDoIt"<<G4endl;
484 
485  //clear interaction length
486  ClearNumberOfInteractionLengthLeft();
487 
488  return &aParticleChange;
489 }
490 
492  G4FastVector<G4ReactionProduct, MYGHADLISTSIZE>& vec,
493  G4int& vecLen,
494  const G4HadProjectile* originalIncident, // the original incident particle
495  const G4DynamicParticle* originalTarget,
496  G4ReactionProduct& modifiedOriginal, // Fermi motion and evap. effects included
497  G4Nucleus& targetNucleus,
498  G4ReactionProduct& currentParticle,
499  G4ReactionProduct& targetParticle,
500  G4bool& incidentHasChanged,
501  G4bool& targetHasChanged,
502  G4bool quasiElastic) {
503  FullModelReactionDynamics theReactionDynamics;
504 
505  cache = 0;
506  what = originalIncident->Get4Momentum().vect();
507 
508  if (quasiElastic) {
509  // G4cout<<"We are calling TwoBody..."<<G4endl;
510  theReactionDynamics.TwoBody(
511  vec, vecLen, modifiedOriginal, originalTarget, currentParticle, targetParticle, targetNucleus, targetHasChanged);
512 
513  return;
514  }
515 
516  //If ProduceStrangeParticlePairs is commented out, let's cut this one as well
517  G4ReactionProduct leadingStrangeParticle;
518  G4bool leadFlag = MarkLeadingStrangeParticle(currentParticle, targetParticle, leadingStrangeParticle);
519 
520  //
521  // Note: the number of secondaries can be reduced in GenerateXandPt and TwoCluster
522  //
523  G4bool finishedGenXPt = false;
524  G4bool annihilation = false;
525  if (originalIncident->GetDefinition()->GetPDGEncoding() < 0 && currentParticle.GetMass() == 0.0 &&
526  targetParticle.GetMass() == 0.0) {
527  // original was an anti-particle and annihilation has taken place
528  annihilation = true;
529  G4double ekcor = 1.0;
530  G4double ek = originalIncident->GetKineticEnergy();
531  G4double ekOrg = ek;
532 
533  const G4double tarmas = originalTarget->GetDefinition()->GetPDGMass();
534  if (ek > 1.0 * GeV)
535  ekcor = 1. / (ek / GeV);
536  const G4double atomicWeight = G4double(targetNucleus.GetN_asInt());
537  ek = 2 * tarmas + ek * (1. + ekcor / atomicWeight);
538 
539  G4double tkin = targetNucleus.Cinema(ek);
540  //ek += tkin;
541  ekOrg += tkin;
542  modifiedOriginal.SetKineticEnergy(ekOrg);
543  }
544 
545  const G4double twsup[] = {1.0, 0.7, 0.5, 0.3, 0.2, 0.1};
546  G4double rand1 = G4UniformRand();
547  G4double rand2 = G4UniformRand();
548  if ((annihilation || (vecLen >= 6) || (modifiedOriginal.GetKineticEnergy() / GeV >= 1.0)) &&
549  (((originalIncident->GetDefinition() == G4KaonPlus::KaonPlus()) ||
550  (originalIncident->GetDefinition() == G4KaonMinus::KaonMinus()) ||
551  (originalIncident->GetDefinition() == G4KaonZeroLong::KaonZeroLong()) ||
552  (originalIncident->GetDefinition() == G4KaonZeroShort::KaonZeroShort())) &&
553  ((rand1 < 0.5) || (rand2 > twsup[vecLen]))))
554  finishedGenXPt = theReactionDynamics.GenerateXandPt(vec,
555  vecLen,
556  modifiedOriginal,
557  originalIncident,
558  currentParticle,
559  targetParticle,
560  targetNucleus,
561  incidentHasChanged,
562  targetHasChanged,
563  leadFlag,
564  leadingStrangeParticle);
565  if (finishedGenXPt) {
566  Rotate(vec, vecLen);
567  return;
568  }
569 
570  G4bool finishedTwoClu = false;
571  if (modifiedOriginal.GetTotalMomentum() / MeV < 1.0) {
572  for (G4int i = 0; i < vecLen; i++)
573  delete vec[i];
574  vecLen = 0;
575  } else {
576  theReactionDynamics.SuppressChargedPions(vec,
577  vecLen,
578  modifiedOriginal,
579  currentParticle,
580  targetParticle,
581  targetNucleus,
582  incidentHasChanged,
583  targetHasChanged);
584 
585  try {
586  finishedTwoClu = theReactionDynamics.TwoCluster(vec,
587  vecLen,
588  modifiedOriginal,
589  originalIncident,
590  currentParticle,
591  targetParticle,
592  targetNucleus,
593  incidentHasChanged,
594  targetHasChanged,
595  leadFlag,
596  leadingStrangeParticle);
597  } catch (G4HadronicException& aR) {
598  G4ExceptionDescription ed;
599  aR.Report(ed);
600  G4Exception("FullModelHadronicProcess::CalculateMomenta", "had066", FatalException, ed);
601  }
602  }
603  if (finishedTwoClu) {
604  Rotate(vec, vecLen);
605  return;
606  }
607 
608  //
609  // PNBlackTrackEnergy is the kinetic energy available for
610  // proton/neutron black track particles [was enp(1) in fortran code]
611  // DTABlackTrackEnergy is the kinetic energy available for
612  // deuteron/triton/alpha particles [was enp(3) in fortran code]
613  // the atomic weight of the target nucleus is >= 1.5 AND
614  // neither the incident nor the target particles have changed AND
615  // there is no kinetic energy available for either proton/neutron
616  // or for deuteron/triton/alpha black track particles
617  // For diffraction scattering on heavy nuclei use elastic routines instead
618 
619  theReactionDynamics.TwoBody(
620  vec, vecLen, modifiedOriginal, originalTarget, currentParticle, targetParticle, targetNucleus, targetHasChanged);
621 }
622 
623 G4bool FullModelHadronicProcess::MarkLeadingStrangeParticle(const G4ReactionProduct& currentParticle,
624  const G4ReactionProduct& targetParticle,
625  G4ReactionProduct& leadParticle) {
626  // the following was in GenerateXandPt and TwoCluster
627  // add a parameter to the GenerateXandPt function telling it about the strange particle
628  //
629  // assumes that the original particle was a strange particle
630  //
631  G4bool lead = false;
632  if ((currentParticle.GetMass() >= G4KaonPlus::KaonPlus()->GetPDGMass()) &&
633  (currentParticle.GetDefinition() != G4Proton::Proton()) &&
634  (currentParticle.GetDefinition() != G4Neutron::Neutron())) {
635  lead = true;
636  leadParticle = currentParticle; // set lead to the incident particle
637  } else if ((targetParticle.GetMass() >= G4KaonPlus::KaonPlus()->GetPDGMass()) &&
638  (targetParticle.GetDefinition() != G4Proton::Proton()) &&
639  (targetParticle.GetDefinition() != G4Neutron::Neutron())) {
640  lead = true;
641  leadParticle = targetParticle; // set lead to the target particle
642  }
643  return lead;
644 }
645 
646 void FullModelHadronicProcess::Rotate(G4FastVector<G4ReactionProduct, MYGHADLISTSIZE>& vec, G4int& vecLen) {
647  G4double rotation = 2. * pi * G4UniformRand();
648  cache = rotation;
649  G4int i;
650  for (i = 0; i < vecLen; ++i) {
651  G4ThreeVector momentum = vec[i]->GetMomentum();
652  momentum = momentum.rotate(rotation, what);
653  vec[i]->SetMomentum(momentum);
654  }
655 }
656 
657 const G4DynamicParticle* FullModelHadronicProcess::FindRhadron(G4ParticleChange* aParticleChange) {
658  G4int nsec = aParticleChange->GetNumberOfSecondaries();
659  if (nsec == 0)
660  return nullptr;
661  int i = 0;
662  G4bool found = false;
663  while (i != nsec && !found) {
664  // G4cout<<"Checking "<<aParticleChange->GetSecondary(i)->GetDynamicParticle()->GetDefinition()->GetParticleName()<<G4endl;
665  // if (aParticleChange->GetSecondary(i)->GetDynamicParticle()->GetDefinition()->GetParticleType()=="rhadron") found = true;
666  if (dynamic_cast<CustomParticle*>(aParticleChange->GetSecondary(i)->GetDynamicParticle()->GetDefinition()) !=
667  nullptr)
668  found = true;
669  i++;
670  }
671  i--;
672  if (found)
673  return aParticleChange->GetSecondary(i)->GetDynamicParticle();
674  return nullptr;
675 }
G4bool MarkLeadingStrangeParticle(const G4ReactionProduct &currentParticle, const G4ReactionProduct &targetParticle, G4ReactionProduct &leadParticle)
G4bool ApplicabilityTester(const G4ParticleDefinition &aPart)
void TwoBody(G4FastVector< G4ReactionProduct, MYGHADLISTSIZE > &vec, G4int &vecLen, G4ReactionProduct &modifiedOriginal, const G4DynamicParticle *originalTarget, G4ReactionProduct &currentParticle, G4ReactionProduct &targetParticle, const G4Nucleus &targetNucleus, G4bool &targetHasChanged)
G4ParticleDefinition * GetCloud()
G4VParticleChange * PostStepDoIt(const G4Track &aTrack, const G4Step &aStep) override
static bool s_isRMeson(int pdg)
virtual G4double GetMicroscopicCrossSection(const G4DynamicParticle *aParticle, const G4Element *anElement, G4double aTemp)
Definition: Electron.h:6
std::vector< G4int > ReactionProduct
const Double_t pi
static bool s_isMesonino(int pdg)
G4double GetMeanFreePath(const G4Track &aTrack, G4double, G4ForceCondition *) override
T sqrt(T t)
Definition: SSEVec.h:23
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
ReactionProduct GetFinalState(const G4Track &aTrack, G4ParticleDefinition *&aTarget)
G4bool TwoCluster(G4FastVector< G4ReactionProduct, MYGHADLISTSIZE > &vec, G4int &vecLen, G4ReactionProduct &modifiedOriginal, const G4HadProjectile *originalIncident, G4ReactionProduct &currentParticle, G4ReactionProduct &targetParticle, const G4Nucleus &targetNucleus, G4bool &incidentHasChanged, G4bool &targetHasChanged, G4bool leadFlag, G4ReactionProduct &leadingStrangeParticle)
G4double GetInclusiveCrossSection(const G4DynamicParticle *aParticle, const G4Element *anElement)
G4ParticleDefinition * GetSpectator()
Basic3DVector unit() const
G4bool GenerateXandPt(G4FastVector< G4ReactionProduct, MYGHADLISTSIZE > &vec, G4int &vecLen, G4ReactionProduct &modifiedOriginal, const G4HadProjectile *originalIncident, G4ReactionProduct &currentParticle, G4ReactionProduct &targetParticle, const G4Nucleus &targetNucleus, G4bool &incidentHasChanged, G4bool &targetHasChanged, G4bool leadFlag, G4ReactionProduct &leadingStrangeParticle)
void CalculateMomenta(G4FastVector< G4ReactionProduct, MYGHADLISTSIZE > &vec, G4int &vecLen, const G4HadProjectile *originalIncident, const G4DynamicParticle *originalTarget, G4ReactionProduct &modifiedOriginal, G4Nucleus &targetNucleus, G4ReactionProduct &currentParticle, G4ReactionProduct &targetParticle, G4bool &incidentHasChanged, G4bool &targetHasChanged, G4bool quasiElastic)
FullModelHadronicProcess(G4ProcessHelper *aHelper, const G4String &processName="FullModelHadronicProcess")
void SuppressChargedPions(G4FastVector< G4ReactionProduct, MYGHADLISTSIZE > &vec, G4int &vecLen, const G4ReactionProduct &modifiedOriginal, G4ReactionProduct &currentParticle, G4ReactionProduct &targetParticle, const G4Nucleus &targetNucleus, G4bool &incidentHasChanged, G4bool &targetHasChanged)
void Rotate(G4FastVector< G4ReactionProduct, MYGHADLISTSIZE > &vec, G4int &vecLen)
const G4DynamicParticle * FindRhadron(G4ParticleChange *)
G4bool IsApplicable(const G4ParticleDefinition &aP) override