Geant4 11.1.1
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4Scatterer.cc
Go to the documentation of this file.
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"
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
50namespace {
51 G4Mutex collisions_mutex = G4MUTEX_INITIALIZER;
52 G4bool setupDone = false;
53}
54
55// Declare the categories of collisions the Scatterer can handle
57
58G4CollisionVector 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{
87 G4double time = DBL_MAX;
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
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
394const G4VCollision* G4Scatterer::FindCollision(const G4KineticTrack& trk1,
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
437const std::vector<G4CollisionInitialState *> & G4Scatterer::
438GetCollisions(G4KineticTrack * aProjectile,
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
462GetFinalState(G4KineticTrack * aProjectile,
463 std::vector<G4KineticTrack *> & theTargets)
464{
465 G4KineticTrack target_reloc(*(theTargets[0]));
466 return Scatter(*aProjectile, target_reloc);
467}
468//----------------------------------------------------------------------------
std::vector< G4VCollision * > G4CollisionVector
@ FatalException
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.cc:59
#define GROUP2(t1, t2)
Definition: G4Pair.hh:42
#define G4MUTEX_INITIALIZER
Definition: G4Threading.hh:85
std::mutex G4Mutex
Definition: G4Threading.hh:81
double G4double
Definition: G4Types.hh:83
bool G4bool
Definition: G4Types.hh:86
int G4int
Definition: G4Types.hh:85
#define G4endl
Definition: G4ios.hh:57
G4GLOB_DLL std::ostream G4cout
double z() const
Hep3Vector unit() const
double x() const
double mag2() const
double y() const
Hep3Vector vect() const
static void Apply()
Definition: G4Pair.hh:179
const G4ThreeVector & GetPosition() const
const G4ParticleDefinition * GetDefinition() const
const G4LorentzVector & GetTrackingMomentum() const
const G4LorentzVector & Get4Momentum() const
G4double GetActualMass() const
static G4Neutron * Neutron()
Definition: G4Neutron.cc:103
G4double GetPDGCharge() const
const G4String & GetParticleName() const
G4double GetCrossSection(const G4KineticTrack &trk1, const G4KineticTrack &trk2) const
Definition: G4Scatterer.cc:423
virtual const std::vector< G4CollisionInitialState * > & GetCollisions(G4KineticTrack *aProjectile, std::vector< G4KineticTrack * > &someCandidates, G4double aCurrentTime)
Definition: G4Scatterer.cc:438
virtual G4double GetTimeToInteraction(const G4KineticTrack &trk1, const G4KineticTrack &trk2) const
Definition: G4Scatterer.cc:84
virtual G4KineticTrackVector * GetFinalState(G4KineticTrack *aProjectile, std::vector< G4KineticTrack * > &theTargets)
Definition: G4Scatterer.cc:462
virtual G4KineticTrackVector * Scatter(const G4KineticTrack &trk1, const G4KineticTrack &trk2) const
Definition: G4Scatterer.cc:283
virtual ~G4Scatterer()
Definition: G4Scatterer.cc:75
virtual G4double CrossSection(const G4KineticTrack &trk1, const G4KineticTrack &trk2) const
Definition: G4VCollision.cc:54
virtual G4KineticTrackVector * FinalState(const G4KineticTrack &trk1, const G4KineticTrack &trk2) const =0
virtual G4bool IsInCharge(const G4KineticTrack &trk1, const G4KineticTrack &trk2) const =0
int G4lrint(double ad)
Definition: templates.hh:134
#define DBL_MAX
Definition: templates.hh:62