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