ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4LightTargetCollider.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file G4LightTargetCollider.cc
1 //
2 // ********************************************************************
3 // * License and Disclaimer *
4 // * *
5 // * The Geant4 software is copyright of the Copyright Holders of *
6 // * the Geant4 Collaboration. It is provided under the terms and *
7 // * conditions of the Geant4 Software License, included in the file *
8 // * LICENSE and available at http://cern.ch/geant4/license . These *
9 // * include a list of copyright holders. *
10 // * *
11 // * Neither the authors of this software system, nor their employing *
12 // * institutes,nor the agencies providing financial support for this *
13 // * work make any representation or warranty, express or implied, *
14 // * regarding this software system or assume any liability for its *
15 // * use. Please see the license in the file LICENSE and URL above *
16 // * for the full disclaimer and the limitation of liability. *
17 // * *
18 // * This code implementation is the result of the scientific and *
19 // * technical work of the GEANT4 collaboration. *
20 // * By using, copying, modifying or distributing the software (or *
21 // * any work based on the software) you agree to acknowledge its *
22 // * use in resulting scientific publications, and indicate your *
23 // * acceptance of all terms of the Geant4 Software license. *
24 // ********************************************************************
25 //
27 // //
28 // File: G4LightTargetCollider.cc //
29 // Date: 30 September 2019 //
30 // Author: Dennis Wright (SLAC) //
31 // //
32 // Description: model for collision of elementary particles with light //
33 // targets (H, D, T, 3He) //
34 // //
36 
37 #include "G4LightTargetCollider.hh"
38 #include "G4CascadeChannel.hh"
40 #include "G4CascadeCheckBalance.hh"
41 #include "G4CollisionOutput.hh"
44 #include "G4InuclNuclei.hh"
45 #include "G4NucleiModel.hh"
46 #include "G4LorentzConvertor.hh"
47 #include "G4Deuteron.hh"
48 #include "G4Gamma.hh"
49 #include "G4PionZero.hh"
50 #include "G4PionPlus.hh"
51 #include "G4PionMinus.hh"
52 #include "G4RandomDirection.hh"
53 
54 
56  : G4CascadeColliderBase("G4LightTargetCollider"),
57  theElementaryParticleCollider(new G4ElementaryParticleCollider)
58 {
62  pFermiD = 0.045; // Fermi momentum of nucleon in deuteron Hulthen potential
63 }
64 
67 }
68 
69 
70 // Set verbosity and pass on to member objects
75 }
76 
77 
80  G4CollisionOutput& globalOutput)
81 {
82  if (verboseLevel) {
83  G4cout << " >>> G4LightTargetCollider::collide" << G4endl;
84  G4cout << " Projectile: " << bullet->getDefinition()->GetParticleName() << G4endl;
85  G4cout << " Target: " << target->getDefinition()->GetParticleName() << G4endl;
86  }
87 
88  // Particle-on-particle collision
89  // No nucleus involved, just a proton in this case
90  if (useEPCollider(bullet,target)) {
91  if (verboseLevel > 2)
92  G4cout << " InuclCollider -> particle on particle collision" << G4endl;
93 
94  theElementaryParticleCollider->collide(bullet, target, globalOutput);
95  return;
96  }
97 
98  G4double ke = bullet->getKineticEnergy();
99  if (target->getDefinition() == G4Deuteron::Deuteron()) {
100 
101  if (ke < mP + mN - mD) {
102  // Should not happen as long as inelastic cross section is zero
103  G4Exception("G4LightTargetCollider::collide()","HAD_BERT_201",
104  JustWarning, "Projectile energy below reaction threshold");
105  globalOutput.trivialise(bullet, target);
106 
107  } else {
108  // Get p, n and deuteron cross sections; use lab energy to access
111  G4double gammaDXS = GammaDCrossSection(ke);
112 
113  G4double probP = 0.0;
114  G4double probN = 0.0;
115  // Highest threshold is 0.152 (for gamma p -> n pi+)
116  // Because of Fermi momentum in deuteron, raise this to 0.159
117  if (ke > 0.159) {
118  G4double totalDXS = gammaPXS + gammaNXS + gammaDXS;
119  probP = gammaPXS/totalDXS;
120  probN = (gammaPXS+gammaNXS)/totalDXS;
121  }
122 
123  G4double rndm = G4UniformRand();
124  if (rndm < probP) {
125  // Generate Fermi momenta of bullet and target
126  G4ThreeVector fermiMomentum = pFermiD*G4RandomDirection();
127  G4LorentzVector protonMomentum(fermiMomentum, std::sqrt(mP*mP + pFermiD*pFermiD) );
128  G4LorentzVector neutronMomentum(-fermiMomentum, std::sqrt(mN*mN + pFermiD*pFermiD) );
129 
130  G4LorentzVector bulletMomentum = bullet->getMomentum();
131  G4ThreeVector betacm = bulletMomentum.findBoostToCM(protonMomentum);
132 
133  // First boost bullet and target so that target is at rest
134  G4ThreeVector toProtonRest = -protonMomentum.boostVector();
135  protonMomentum.boost(toProtonRest);
136  bulletMomentum.boost(toProtonRest);
137 
138  G4InuclElementaryParticle projectile(bulletMomentum, bullet->getDefinition() );
139  G4InuclElementaryParticle targetNucleon(protonMomentum, G4Proton::Proton() );
140  G4InuclElementaryParticle spectatorNucleon(neutronMomentum, G4Neutron::Neutron() );
141  ScatteringProducts products = SingleNucleonScattering(projectile, targetNucleon);
142 
143  // Particles from SingleNucleonScattering are in CM frame of projectile
144  // and moving proton. Transform back to lab frame with -betacm, then
145  // add them to outgoing list.
146  globalOutput.reset();
147  G4LorentzVector temp;
148  for (G4int i = 0; i < G4int(products.size()); i++) {
149  temp = products[i].getMomentum();
150  temp.boost(-betacm);
151  products[i].setMomentum(temp);
152  globalOutput.addOutgoingParticle(products[i]);
153  }
154 
155  // Add the recoil nucleon unmodified
156  globalOutput.addOutgoingParticle(spectatorNucleon);
157 
158  } else if (rndm < probN) {
159  G4ThreeVector fermiMomentum = pFermiD*G4RandomDirection();
160  G4LorentzVector protonMomentum(fermiMomentum, std::sqrt(mP*mP + pFermiD*pFermiD) );
161  G4LorentzVector neutronMomentum(-fermiMomentum, std::sqrt(mN*mN + pFermiD*pFermiD) );
162 
163  G4LorentzVector bulletMomentum = bullet->getMomentum();
164  G4ThreeVector betacm = bulletMomentum.findBoostToCM(neutronMomentum);
165 
166  // First boost bullet and target so that target is at rest
167  G4ThreeVector toNeutronRest = -neutronMomentum.boostVector();
168  neutronMomentum.boost(toNeutronRest);
169  bulletMomentum.boost(toNeutronRest);
170 
171  G4InuclElementaryParticle projectile(bulletMomentum, bullet->getDefinition() );
172  G4InuclElementaryParticle targetNucleon(neutronMomentum, G4Neutron::Neutron() );
173  G4InuclElementaryParticle spectatorNucleon(protonMomentum, G4Proton::Proton() );
174 
175  ScatteringProducts products = SingleNucleonScattering(projectile, targetNucleon);
176 
177  // Particles from SingleNucleonScattering are in CM frame of projectile
178  // and moving neutron. Transform back to lab frame with -betacm, then add
179  // them to outgoing list
180  globalOutput.reset();
181  G4LorentzVector temp;
182  for (G4int i = 0; i < G4int(products.size()); i++) {
183  temp = products[i].getMomentum();
184  temp.boost(-betacm);
185  products[i].setMomentum(temp);
186  globalOutput.addOutgoingParticle(products[i]);
187  }
188 
189  // Add the recoil nucleon unmodified
190  globalOutput.addOutgoingParticle(spectatorNucleon);
191 
192  } else {
193  NucleonPair products = AbsorptionOnDeuteron(bullet);
194  globalOutput.reset();
195  globalOutput.addOutgoingParticle(products.first);
196  globalOutput.addOutgoingParticle(products.second);
197  }
198  } // Energy above threshold ?
199 
200  // Test code
201  // G4int numPart = globalOutput.numberOfOutgoingParticles();
202  // std::vector<G4InuclElementaryParticle> testList = globalOutput.getOutgoingParticles();
203  // G4LorentzVector sumP;
204  // G4cout << " Global output " << G4endl;
205  // for (G4int i = 0; i < numPart; i++) {
206  // sumP += testList[i].getMomentum();
207  // G4cout << testList[i] << G4endl;
208  // }
209  // G4cout << " Global 4-momentum sum = " << sumP << G4endl;
210  // G4cout << " Initial lab energy = " << mD + bullet->getEnergy() << G4endl;
211 
212  } else {
213  G4Exception("G4LightTargetCollider::collide()","HAD_BERT_203",
214  FatalException, "Scattering from this target not implemented");
215  }
216 
217  return;
218 }
219 
220 
222 {
223  // Gamma deuteron cross section in mb parameterized from JLab data
224  // No parameterization needed below pi0 threshold where cross section
225  // is 100% disintegration
226  G4double sigma = 1000.0;
227  G4double term = 0.;
228  if (gammaEnergy > 0.144 && gammaEnergy < 0.42) {
229  term = (gammaEnergy - 0.24)/0.155;
230  sigma = 0.065*std::exp(-term*term);
231  } else if (gammaEnergy >= 0.42) {
232  sigma = 0.000526/gammaEnergy/gammaEnergy/gammaEnergy/gammaEnergy;
233  }
234 
235  return sigma;
236 }
237 
238 
240 {
241  // Do break-up in center of mass, convert to lab frame before returning
242  // particles
243 
244  G4double bulletMass = bullet->getMass();
245  G4double bulletE = bullet->getEnergy();
246 
247  G4double S = bulletMass*bulletMass + mD*mD + 2.*mD*bulletE;
248 
249  G4double qcm = 0.;
250  G4int outType1 = 0;
251  G4int outType2 = 0;
252  G4LorentzVector Mom1;
253  G4LorentzVector Mom2;
254 
255  // Set up outgoing particle types
256  if (bullet->getDefinition() == G4Gamma::Gamma() ||
257  bullet->getDefinition() == G4PionZero::PionZero() ) {
258  qcm = std::sqrt( (S - (mP + mN)*(mP + mN)) * (S - (mP - mN)*(mP - mN))/S/4.);
259  Mom1.setE(std::sqrt(mP*mP + qcm*qcm) );
260  outType1 = G4InuclParticleNames::proton;
261  Mom2.setE(std::sqrt(mN*mN + qcm*qcm) );
263 
264  } else if (bullet->getDefinition() == G4PionPlus::PionPlus() ) {
265  qcm = std::sqrt( (S - 4.*mP*mP)/4.);
266  Mom1.setE(std::sqrt(mP*mP + qcm*qcm) );
267  outType1 = G4InuclParticleNames::proton;
268  Mom2.setE(std::sqrt(mP*mP + qcm*qcm) );
269  outType2 = G4InuclParticleNames::proton;
270 
271  } else if (bullet->getDefinition() == G4PionMinus::PionMinus() ) {
272  qcm = std::sqrt( (S - 4.*mN*mN)/4.);
273  Mom1.setE(std::sqrt(mN*mN + qcm*qcm) );
275  Mom2.setE(std::sqrt(mN*mN + qcm*qcm) );
277 
278  } else {
279  G4Exception("G4LightTargetCollider::collide()","HAD_BERT_204",
280  FatalException, "Illegal bullet type");
281  }
282 
283  // Sample angular distribution, assuming 100% S wave (no D-wave)
284  G4ThreeVector qVect = qcm*G4RandomDirection();
285  Mom1.setVect(qVect);
286  Mom2.setVect(-qVect);
287 
288  // Boost to lab frame
289  G4ThreeVector betacm(0., 0., bullet->getMomModule()/(bulletE + mD) );
290  Mom1.boost(betacm);
291  Mom2.boost(betacm);
292 
293  G4InuclElementaryParticle particle1(Mom1, outType1);
294  G4InuclElementaryParticle particle2(Mom2, outType2);
295  NucleonPair nucleon_pair(particle1, particle2);
296 
297  // if pion, use parameterization of B.G. Ritchie, PRC 44, 533 (1991)
298  // Total cross section: 1/E + Lorentzian
299 
300  return nucleon_pair;
301 }
302 
303 
307 {
308  // At this point projectile and nucleon momenta are in nucleon rest frame
309  G4int reactionIndex = G4InuclElementaryParticle::type(projectile.getDefinition() )
311 
312  const G4CascadeChannel* xsecTable = G4CascadeChannelTables::GetTable(reactionIndex);
313  G4double ke = projectile.getKineticEnergy();
314  G4int mult = xsecTable->getMultiplicity(ke);
315 
316  std::vector<G4double> masses;
317  G4double mass = 0.0;
318  G4LorentzVector totalMom = projectile.getMomentum() + nucleon.getMomentum();
319  G4double Ecm = totalMom.mag();
320 
321  std::vector<G4LorentzVector> cmMomenta;
322  std::vector<G4int> particle_kinds;
323  G4int itry = 0;
324  G4int itry_max = 200;
325  G4bool generate = true;
326 
327  while (mult > 1) {
328  itry = 0;
329  generate = true;
330  while (generate && itry < itry_max) {
331  particle_kinds.clear();
332  xsecTable->getOutgoingParticleTypes(particle_kinds, mult, ke);
333  masses.clear();
334  for (G4int i = 0; i < mult; i++) {
335  mass = G4InuclElementaryParticle::getParticleMass(particle_kinds[i]);
336  masses.push_back(mass);
337  }
338 
339  fsGen.Configure(const_cast<G4InuclElementaryParticle*>(&projectile),
340  const_cast<G4InuclElementaryParticle*>(&nucleon),
341  particle_kinds);
342  // Generate final state in CM of projectile and at-rest nucleon
343  cmMomenta.clear();
344  generate = !fsGen.Generate(Ecm, masses, cmMomenta);
345  itry++;
346  } // while
347 
348  if (itry == itry_max) mult--;
349  else break;
350 
351  } // while mult
352 
353  ScatteringProducts finalState;
354  if (mult < 2) {
355  G4Exception("G4LightTargetCollider::SingleNucleonScattering()","HAD_BERT_202",
356  JustWarning, "Failed to generate final state");
357  // Final state particles not in CM - just using them as dummies
358  finalState.push_back(projectile);
359  finalState.push_back(nucleon);
360 
361  } else {
362  for (G4int i = 0; i < mult; i++) {
363  G4InuclElementaryParticle fsPart(cmMomenta[i], particle_kinds[i]);
364  finalState.push_back(fsPart);
365  }
366  }
367 
368  return finalState;
369 }