ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4Scatterer.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file G4Scatterer.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 //
26 //
27 
28 #include <vector>
29 
30 #include "globals.hh"
31 #include "G4PhysicalConstants.hh"
32 #include "G4SystemOfUnits.hh"
33 #include "G4ios.hh"
34 #include "G4Scatterer.hh"
35 #include "G4KineticTrack.hh"
36 #include "G4ThreeVector.hh"
37 #include "G4LorentzRotation.hh"
38 #include "G4LorentzVector.hh"
39 
40 #include "G4CollisionNN.hh"
41 #include "G4CollisionPN.hh"
43 
45 #include "G4HadTmpUtil.hh"
46 #include "G4Pair.hh"
47 #include "G4AutoLock.hh"
48 
49 //Mutex for control of shared resource
50 namespace {
51  G4Mutex collisions_mutex = G4MUTEX_INITIALIZER;
52  G4bool setupDone = false;
53 }
54 
55 // Declare the categories of collisions the Scatterer can handle
56 typedef GROUP2(G4CollisionNN, G4CollisionMesonBaryon) theChannels;
57 
58 G4CollisionVector G4Scatterer::collisions;
59 
60 //----------------------------------------------------------------------------
61 
63 {
64  G4AutoLock l(&collisions_mutex);
65  if ( ! setupDone )
66  {
67  Register aR;
68  G4ForEach<theChannels>::Apply(&aR, &collisions);
69  setupDone = true;
70  }
71 }
72 
73 //----------------------------------------------------------------------------
74 
76 {
77  G4AutoLock l(&collisions_mutex);
78  std::for_each(collisions.begin(), collisions.end(), G4Delete());
79  collisions.clear();
80 }
81 
82 //----------------------------------------------------------------------------
83 
85  const G4KineticTrack& trk2) const
86 {
88  G4double distance_fast;
90 // G4cout << "zcomp=" << std::abs(mom1.vect().unit().z() -1 ) << G4endl;
91  G4double collisionTime;
92 
93  if ( std::abs(mom1.vect().unit().z() -1 ) < 1e-6 )
94  {
96  G4double deltaz=position.z();
97  G4double velocity = mom1.z()/mom1.e() * c_light;
98 
99  collisionTime=deltaz/velocity;
100  distance_fast=position.x()*position.x() + position.y()*position.y();
101  } else {
102 
103  // The nucleons of the nucleus are FROZEN, ie. do not move..
104 
105  G4ThreeVector position = trk2.GetPosition() - trk1.GetPosition();
106 
107  G4ThreeVector velocity = mom1.vect()/mom1.e() * c_light; // mom1.boostVector() will exit on slightly negative mass
108  collisionTime = (position * velocity) / velocity.mag2(); // can't divide by /c_light;
109  position -= velocity * collisionTime;
110  distance_fast=position.mag2();
111 
112 // if ( collisionTime>0 ) G4cout << " dis1/2 square" << dis1 <<" "<< dis2 << G4endl;
113 // collisionTime = GetTimeToClosestApproach(trk1,trk2);
114  }
115  if (collisionTime > 0)
116  {
117  static const G4double maxCrossSection = 500*millibarn;
118  if(0.7*pi*distance_fast>maxCrossSection) return time;
119 
120 
121  G4LorentzVector mom2(0,0,0,trk2.Get4Momentum().mag());
122 
123 // G4ThreeVector momLab = mom1.vect();// frozen Nucleus - mom2.vect();
124 // G4ThreeVector posLab = trk1.GetPosition() - trk2.GetPosition();
125 // G4double disLab=posLab * posLab - (posLab*momLab) * (posLab*momLab) /(momLab.mag2());
126 
127  G4LorentzRotation toCMSFrame((-1)*(mom1 + mom2).boostVector());
128  mom1 = toCMSFrame * mom1;
129  mom2 = toCMSFrame * mom2;
130 
131  G4LorentzVector coordinate1(trk1.GetPosition(), 100.);
132  G4LorentzVector coordinate2(trk2.GetPosition(), 100.);
133  G4ThreeVector pos = ((toCMSFrame * coordinate1).vect() -
134  (toCMSFrame * coordinate2).vect());
135 
136  G4ThreeVector mom = mom1.vect() - mom2.vect();
137 
138  // Calculate the impact parameter
139 
140  G4double distance = pos * pos - (pos*mom) * (pos*mom) / (mom.mag2());
141 
142 // G4cout << " disDiff " << distance-disLab << " " << disLab
143 // << " " << std::abs(distance-disLab)/distance << G4endl
144 // << " mom/Lab " << mom << " " << momLab << G4endl
145 // << " pos/Lab " << pos << " " << posLab
146 // << G4endl;
147 
148  if(pi*distance>maxCrossSection) return time;
149 
150  // charged particles special
151  static const G4double maxChargedCrossSection = 200*millibarn;
152  if(std::abs(trk1.GetDefinition()->GetPDGCharge())>0.1 &&
153  std::abs(trk2.GetDefinition()->GetPDGCharge())>0.1 &&
154  pi*distance>maxChargedCrossSection) return time;
155 
156  G4double sqrtS = (trk1.Get4Momentum() + trk2.Get4Momentum()).mag();
157  // neutrons special pn is largest cross-section, but above 1.91 GeV is less than 200 mb
158  if(( trk1.GetDefinition() == G4Neutron::Neutron() ||
159  trk2.GetDefinition() == G4Neutron::Neutron() ) &&
160  sqrtS>1.91*GeV && pi*distance>maxChargedCrossSection) return time;
161 
162 /*
163  * if(distance <= sqr(1.14*fermi))
164  * {
165  * time = collisionTime;
166  *
167  * *
168  * * G4cout << "Scatter distance/time: " << std::sqrt(distance)/fermi <<
169  * * " / "<< time/ns << G4endl;
170  * * G4ThreeVector pos1=trk1.GetPosition();
171  * * G4ThreeVector pos2=trk2.GetPosition();
172  * * G4LorentzVector xmom1 = trk1.Get4Momentum();
173  * * G4LorentzVector xmom2 = trk2.Get4Momentum();
174  * * G4cout << "position1: " << pos1.x() << " " << pos1.y() << " "
175  * * << pos1.z();
176  * * pos1+=(collisionTime*c_light/xmom1.e())*xmom1.vect();
177  * * G4cout << " straight line trprt: "
178  * * << pos1.x() << " " << pos1.y() << " "
179  * * << pos1.z() << G4endl;
180  * * G4cout << "position2: " << pos2.x() << " " << pos2.y() << " "
181  * * << pos2.z() << G4endl;
182  * * G4cout << "straight line distance 2 fixed:" << (pos1-pos2).mag()/fermi << G4endl;
183  * * pos2+= (collisionTime*c_light/xmom2.e())*xmom2.vect();
184  * * G4cout<< " straight line trprt: "
185  * * << pos2.x() << " " << pos2.y() << " "
186  * * << pos2.z() << G4endl;
187  * * G4cout << "straight line distance :" << (pos1-pos2).mag()/fermi << G4endl;
188  * *
189  * }
190  *
191  * if(1)
192  * return time;
193  */
194 
195  if ((trk1.GetActualMass()+trk2.GetActualMass()) > sqrtS) return time;
196 
197 
198 
199  const G4VCollision* collision = FindCollision(trk1,trk2);
200  G4double totalCrossSection;
201  // The cross section is interpreted geometrically as an area
202  // Two particles are assumed to collide if their distance is < (totalCrossSection/pi)
203 
204  if (collision != 0)
205  {
206  totalCrossSection = collision->CrossSection(trk1,trk2);
207  if ( totalCrossSection > 0 )
208  {
209 /* G4cout << " totalCrossection = "<< totalCrossSection << ", trk1/2, s, e-m: "
210  * << trk1.GetDefinition()->GetParticleName()
211  * << " / "
212  * << trk2.GetDefinition()->GetParticleName()
213  * << ", "
214  * << (trk1.Get4Momentum()+trk2.Get4Momentum()).mag()
215  * << ", "
216  * << (trk1.Get4Momentum()+trk2.Get4Momentum()).mag()-
217  * trk1.Get4Momentum().mag() - trk2.Get4Momentum().mag()
218  * << G4endl;
219  */
220  if (distance <= totalCrossSection / pi)
221  {
222  time = collisionTime;
223  }
224  } else
225  {
226 
227  // For debugging...
228  // G4cout << " totalCrossection = 0, trk1/2, s, e-m: "
229  // << trk1.GetDefinition()->GetParticleName()
230  // << " / "
231  // << trk2.GetDefinition()->GetParticleName()
232  // << ", "
233  // << (trk1.Get4Momentum()+trk2.Get4Momentum()).mag()
234  // << ", "
235  // << (trk1.Get4Momentum()+trk2.Get4Momentum()).mag()-
236  // trk1.Get4Momentum().mag() - trk2.Get4Momentum().mag()
237  // << G4endl;
238 
239  }
240 /*
241  * if(distance <= sqr(5.*fermi))
242  * {
243  * G4cout << " distance,xsect, std::sqrt(xsect/pi) : " << std::sqrt(distance)/fermi
244  * << " " << totalCrossSection/sqr(fermi)
245  * << " " << std::sqrt(totalCrossSection / pi)/fermi << G4endl;
246  * }
247  */
248 
249  }
250  else
251  {
252  time = DBL_MAX;
253 // /*
254  // For debugging
255 //hpw G4cout << "G4Scatterer - collision not found: "
256 //hpw << trk1.GetDefinition()->GetParticleName()
257 //hpw << " - "
258 //hpw << trk2.GetDefinition()->GetParticleName()
259 //hpw << G4endl;
260  // End of debugging
261 // */
262  }
263  }
264 
265  else
266  {
267  /*
268  // For debugging
269  G4cout << "G4Scatterer - negative collisionTime"
270  << ": collisionTime = " << collisionTime
271  << ", position = " << position
272  << ", velocity = " << velocity
273  << G4endl;
274  // End of debugging
275  */
276  }
277 
278  return time;
279 }
280 
281 //----------------------------------------------------------------------------
282 
284  const G4KineticTrack& trk2) const
285 {
286 // G4double sqrtS = (trk1.Get4Momentum() + trk2.Get4Momentum()).mag();
287  G4LorentzVector pInitial=trk1.Get4Momentum() + trk2.Get4Momentum();
288  G4double energyBalance = pInitial.t();
289  G4double pxBalance = pInitial.vect().x();
290  G4double pyBalance = pInitial.vect().y();
291  G4double pzBalance = pInitial.vect().z();
292  G4int chargeBalance = G4lrint(trk1.GetDefinition()->GetPDGCharge()
293  + trk2.GetDefinition()->GetPDGCharge());
294  G4int baryonBalance = trk1.GetDefinition()->GetBaryonNumber()
295  + trk2.GetDefinition()->GetBaryonNumber();
296 
297  const G4VCollision* collision = FindCollision(trk1,trk2);
298  if (collision != 0)
299  {
300  G4double aCrossSection = collision->CrossSection(trk1,trk2);
301  if (aCrossSection > 0.0)
302  {
303 
304 
305  #ifdef debug_G4Scatterer
306  G4cout << "be4 FinalState 1(p,e,m): "
307  << trk1.Get4Momentum() << " "
308  << trk1.Get4Momentum().mag()
309  << ", 2: "
310  << trk2.Get4Momentum()<< " "
311  << trk2.Get4Momentum().mag() << " "
312  << G4endl;
313  #endif
314 
315 
316  G4KineticTrackVector* products = collision->FinalState(trk1,trk2);
317  if(!products || products->size() == 0) return products;
318 
319  #ifdef debug_G4Scatterer
320  G4cout << "size of FS: "<<products->size()<<G4endl;
321  #endif
322 
323  G4KineticTrack *final= products->operator[](0);
324 
325 
326  #ifdef debug_G4Scatterer
327  G4cout << " FinalState 1: "
328  << final->Get4Momentum()<< " "
329  << final->Get4Momentum().mag() ;
330  #endif
331 
332  if(products->size() == 1) return products;
333  final=products->operator[](1);
334  #ifdef debug_G4Scatterer
335  G4cout << ", 2: "
336  << final->Get4Momentum() << " "
337  << final->Get4Momentum().mag() << " " << G4endl;
338  #endif
339 
340  final= products->operator[](0);
341  G4LorentzVector pFinal=final->Get4Momentum();
342  if(products->size()==2)
343  {
344  final=products->operator[](1);
345  pFinal +=final->Get4Momentum();
346  }
347 
348  #ifdef debug_G4Scatterer
349  if ( (pInitial-pFinal).mag() > 0.1*MeV )
350  {
351  G4cout << "G4Scatterer: momentum imbalance, pInitial= " <<pInitial << " pFinal= " <<pFinal<< G4endl;
352  }
353  G4cout << "Scatterer costh= " << trk1.Get4Momentum().vect().unit() *(products->operator[](0))->Get4Momentum().vect().unit()<< G4endl;
354  #endif
355 
356  for(size_t hpw=0; hpw<products->size(); hpw++)
357  {
358  energyBalance-=products->operator[](hpw)->Get4Momentum().t();
359  pxBalance-=products->operator[](hpw)->Get4Momentum().vect().x();
360  pyBalance-=products->operator[](hpw)->Get4Momentum().vect().y();
361  pzBalance-=products->operator[](hpw)->Get4Momentum().vect().z();
362  chargeBalance-=G4lrint(products->operator[](hpw)->GetDefinition()->GetPDGCharge());
363  baryonBalance-=products->operator[](hpw)->GetDefinition()->GetBaryonNumber();
364  }
365  if(std::getenv("ScattererEnergyBalanceCheck"))
366  std::cout << "DEBUGGING energy balance A: "
367  <<energyBalance<<" "
368  <<pxBalance<<" "
369  <<pyBalance<<" "
370  <<pzBalance<<" "
371  <<chargeBalance<<" "
372  <<baryonBalance<<" "
373  <<G4endl;
374  if(chargeBalance !=0 )
375  {
376  G4cout << "track 1"<<trk1.GetDefinition()->GetParticleName()<<G4endl;
377  G4cout << "track 2"<<trk2.GetDefinition()->GetParticleName()<<G4endl;
378  for(size_t hpw=0; hpw<products->size(); hpw++)
379  {
380  G4cout << products->operator[](hpw)->GetDefinition()->GetParticleName()<<G4endl;
381  }
382  G4Exception("G4Scatterer", "im_r_matrix001", FatalException,
383  "Problem in ChargeBalance");
384  }
385  return products;
386  }
387  }
388 
389  return NULL;
390 }
391 
392 //----------------------------------------------------------------------------
393 
395  const G4KineticTrack& trk2) const
396 {
397  G4VCollision* collisionInCharge = 0;
398 
399  size_t i;
400  for (i=0; i<collisions.size(); i++)
401  {
402  G4VCollision* component = collisions[i];
403  if (component->IsInCharge(trk1,trk2))
404  {
405  collisionInCharge = component;
406  break;
407  }
408  }
409 // if(collisionInCharge)
410 // {
411 // G4cout << "found collision : "
412 // << collisionInCharge->GetName()<< " "
413 // << "for "
414 // << trk1.GetDefinition()->GetParticleName()<<" + "
415 // << trk2.GetDefinition()->GetParticleName()<<" "
416 // << G4endl;;
417 // }
418  return collisionInCharge;
419 }
420 
421 //----------------------------------------------------------------------------
422 
424  const G4KineticTrack& trk2) const
425 {
426  const G4VCollision* collision = FindCollision(trk1,trk2);
427  G4double aCrossSection = 0;
428  if (collision != 0)
429  {
430  aCrossSection = collision->CrossSection(trk1,trk2);
431  }
432  return aCrossSection;
433 }
434 
435 //----------------------------------------------------------------------------
436 
437 const std::vector<G4CollisionInitialState *> & G4Scatterer::
439  std::vector<G4KineticTrack *> & someCandidates,
440  G4double aCurrentTime)
441 {
442  theCollisions.clear();
443  std::vector<G4KineticTrack *>::iterator j=someCandidates.begin();
444  for(; j != someCandidates.end(); ++j)
445  {
446  G4double collisionTime = GetTimeToInteraction(*aProjectile, **j);
447  if(collisionTime == DBL_MAX) // no collision
448  {
449  continue;
450  }
451  G4KineticTrackVector aTarget;
452  aTarget.push_back(*j);
453  theCollisions.push_back(
454  new G4CollisionInitialState(collisionTime+aCurrentTime, aProjectile, aTarget, this) );
455 // G4cerr <<" !!!!!! debug collisions "<<collisionTime<<" "<<pkt->GetDefinition()->GetParticleName()<<G4endl;
456  }
457  return theCollisions;
458 }
459 
460 
463  std::vector<G4KineticTrack *> & theTargets)
464 {
465  G4KineticTrack target_reloc(*(theTargets[0]));
466  return Scatter(*aProjectile, target_reloc);
467 }
468 //----------------------------------------------------------------------------