Geant4 11.1.1
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4MesonAbsorption.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#include "G4MesonAbsorption.hh"
29#include "G4SystemOfUnits.hh"
30#include "G4LorentzRotation.hh"
31#include "G4LorentzVector.hh"
32#include "Randomize.hh"
35#include <cmath>
36#include "G4PionPlus.hh"
37#include "G4PionMinus.hh"
39#include "G4HadTmpUtil.hh"
40
41// first prototype
42
43const std::vector<G4CollisionInitialState *> & G4MesonAbsorption::
44GetCollisions(G4KineticTrack * aProjectile,
45 std::vector<G4KineticTrack *> & someCandidates,
46 G4double aCurrentTime)
47{
48 theCollisions.clear();
49 if(someCandidates.size() >1)
50 {
51 std::vector<G4KineticTrack *>::iterator j=someCandidates.begin();
52 for(; j != someCandidates.end(); ++j)
53 {
54 G4double collisionTime = GetTimeToAbsorption(*aProjectile, **j);
55 if(collisionTime == DBL_MAX)
56 {
57 continue;
58 }
60 aTarget.push_back(*j);
61 FindAndFillCluster(aTarget, aProjectile, someCandidates);
62 if(aTarget.size()>=2)
63 {
64 theCollisions.push_back(
65 new G4CollisionInitialState(collisionTime+aCurrentTime, aProjectile, aTarget, this) );
66 }
67 }
68 }
69 return theCollisions;
70}
71
72
73void G4MesonAbsorption::
74FindAndFillCluster(G4KineticTrackVector & result,
75 G4KineticTrack * aProjectile, std::vector<G4KineticTrack *> & someCandidates)
76{
77 std::vector<G4KineticTrack *>::iterator j=someCandidates.begin();
78 G4KineticTrack * aTarget = result[0];
79 G4int chargeSum = G4lrint(aTarget->GetDefinition()->GetPDGCharge());
80 chargeSum+=G4lrint(aProjectile->GetDefinition()->GetPDGCharge());
81 G4ThreeVector firstBase = aTarget->GetPosition();
82 G4double min = DBL_MAX;
83 G4KineticTrack * partner = 0;
84 for(; j != someCandidates.end(); ++j)
85 {
86 if(*j == aTarget) continue;
87 G4int cCharge = G4lrint((*j)->GetDefinition()->GetPDGCharge());
88 if (chargeSum+cCharge > 2) continue;
89 if (chargeSum+cCharge < 0) continue;
90 // get the one with the smallest distance.
91 G4ThreeVector secodeBase = (*j)->GetPosition();
92 if((firstBase+secodeBase).mag()<min)
93 {
94 min=(firstBase+secodeBase).mag();
95 partner = *j;
96 }
97 }
98 if(partner) result.push_back(partner);
99 else result.clear();
100}
101
102
104GetFinalState(G4KineticTrack * projectile,
105 std::vector<G4KineticTrack *> & targets)
106{
107 // G4cout << "We have an absorption !!!!!!!!!!!!!!!!!!!!!!"<<G4endl;
108 // Only 2-body absorption for the time being.
109 // If insufficient, use 2-body absorption and clusterization to emulate 3-,4-,etc body absorption.
110 G4LorentzVector thePro = projectile->Get4Momentum();
111 G4LorentzVector theT1 = targets[0]->Get4Momentum();
112 G4LorentzVector theT2 = targets[1]->Get4Momentum();
113 G4LorentzVector incoming = thePro + theT1 + theT2;
114 G4double energyBalance = incoming.t();
115 G4int chargeBalance = G4lrint(projectile->GetDefinition()->GetPDGCharge()
116 + targets[0]->GetDefinition()->GetPDGCharge()
117 + targets[1]->GetDefinition()->GetPDGCharge());
118
119 G4int baryonBalance = projectile->GetDefinition()->GetBaryonNumber()
120 + targets[0]->GetDefinition()->GetBaryonNumber()
121 + targets[1]->GetDefinition()->GetBaryonNumber();
122
123
124 // boost all to MMS
125 G4LorentzRotation toSPS((-1)*(thePro + theT1 + theT2).boostVector());
126 theT1 = toSPS * theT1;
127 theT2 = toSPS * theT2;
128 thePro = toSPS * thePro;
129 G4LorentzRotation fromSPS(toSPS.inverse());
130
131 // rotate to z
133 G4LorentzVector Ptmp=projectile->Get4Momentum();
134 toZ.rotateZ(-1*Ptmp.phi());
135 toZ.rotateY(-1*Ptmp.theta());
136 theT1 = toZ * theT1;
137 theT2 = toZ * theT2;
138 thePro = toZ * thePro;
139 G4LorentzRotation toLab(toZ.inverse());
140
141 // Get definitions
142 const G4ParticleDefinition * d1 = targets[0]->GetDefinition();
143 const G4ParticleDefinition * d2 = targets[1]->GetDefinition();
144 if(0.5>G4UniformRand())
145 {
146 const G4ParticleDefinition * temp;
147 temp=d1;d1=d2;d2=temp;
148 }
149 const G4ParticleDefinition * dp = projectile->GetDefinition();
150 if(dp->GetPDGCharge()<-.5)
151 {
152 if(d1->GetPDGCharge()>.5)
153 {
154 if(d2->GetPDGCharge()>.5 && 0.5>G4UniformRand())
155 {
157 }
158 else
159 {
161 }
162 }
163 else if(d2->GetPDGCharge()>.5)
164 {
166 }
167 }
168 else if(dp->GetPDGCharge()>.5)
169 {
170 if(d1->GetPDGCharge()<.5)
171 {
172 if(d2->GetPDGCharge()<.5 && 0.5>G4UniformRand())
173 {
175 }
176 else
177 {
179 }
180 }
181 else if(d2->GetPDGCharge()<.5)
182 {
184 }
185 }
186
187 // calculate the momenta.
188 G4double M_sq = (thePro+theT1+theT2).mag2();
189 G4double m1_sq = sqr(d1->GetPDGMass());
190 G4double m2_sq = sqr(d2->GetPDGMass());
191 G4double m_sq = M_sq-m1_sq-m2_sq;
192 G4double p = std::sqrt((m_sq*m_sq - 4.*m1_sq * m2_sq)/(4.*M_sq));
193 G4double costh = 2.*G4UniformRand()-1.;
194 G4double phi = 2.*pi*G4UniformRand();
195 G4ThreeVector pFinal(p*std::sin(std::acos(costh))*std::cos(phi), p*std::sin(std::acos(costh))*std::sin(phi), p*costh);
196
197 // G4cout << "testing p "<<p-pFinal.mag()<<G4endl;
198 // construct the final state particles lorentz momentum.
199 G4double eFinal1 = std::sqrt(m1_sq+pFinal.mag2());
200 G4LorentzVector final1(pFinal, eFinal1);
201 G4double eFinal2 = std::sqrt(m2_sq+pFinal.mag2());
202 G4LorentzVector final2(-1.*pFinal, eFinal2);
203
204 // rotate back.
205 final1 = toLab * final1;
206 final2 = toLab * final2;
207
208 // boost back to LAB
209 final1 = fromSPS * final1;
210 final2 = fromSPS * final2;
211
212 // make the final state
213 G4KineticTrack * f1 =
214 new G4KineticTrack(d1, 0., targets[0]->GetPosition(), final1);
215 G4KineticTrack * f2 =
216 new G4KineticTrack(d2, 0., targets[1]->GetPosition(), final2);
218 result->push_back(f1);
219 result->push_back(f2);
220
221 for(size_t hpw=0; hpw<result->size(); hpw++)
222 {
223 energyBalance-=result->operator[](hpw)->Get4Momentum().t();
224 chargeBalance-=G4lrint(result->operator[](hpw)->GetDefinition()->GetPDGCharge());
225 baryonBalance-=result->operator[](hpw)->GetDefinition()->GetBaryonNumber();
226 }
227 if(std::getenv("AbsorptionEnergyBalanceCheck"))
228 std::cout << "DEBUGGING energy balance B: "
229 <<energyBalance<<" "
230 <<chargeBalance<<" "
231 <<baryonBalance<<" "
232 <<G4endl;
233 return result;
234}
235
236
237G4double G4MesonAbsorption::
238GetTimeToAbsorption(const G4KineticTrack& trk1, const G4KineticTrack& trk2)
239{
244 {
245 return DBL_MAX;
246 }
247 G4double time = DBL_MAX;
248 G4double sqrtS = (trk1.Get4Momentum() + trk2.Get4Momentum()).mag();
249
250 // Check whether there is enough energy for elastic scattering
251 // (to put the particles on to mass shell
252
253 if (trk1.GetActualMass() + trk2.GetActualMass() < sqrtS)
254 {
257 if ( mom1.mag2() < -1.*eV )
258 {
259 G4cout << "G4MesonAbsorption::GetTimeToInteraction(): negative m2:" << mom1.mag2() << G4endl;
260 }
261 G4ThreeVector velocity = mom1.vect()/mom1.e() * c_light;
262 G4double collisionTime = - (position * velocity) / (velocity * velocity);
263
264 if (collisionTime > 0)
265 {
266 G4LorentzVector mom2(0,0,0,trk2.Get4Momentum().mag());
267 G4LorentzRotation toCMSFrame((-1)*(mom1 + mom2).boostVector());
268 mom1 = toCMSFrame * mom1;
269 mom2 = toCMSFrame * mom2;
270
271 G4LorentzVector coordinate1(trk1.GetPosition(), 100.);
272 G4LorentzVector coordinate2(trk2.GetPosition(), 100.);
273 G4ThreeVector pos = ((toCMSFrame * coordinate1).vect() -
274 (toCMSFrame * coordinate2).vect());
275 G4ThreeVector mom = mom1.vect() - mom2.vect();
276
277 G4double distance = pos * pos - (pos*mom) * (pos*mom) / (mom*mom);
278
279 // global optimization
280 static const G4double maxCrossSection = 500*millibarn;
281 if(pi*distance>maxCrossSection) return time;
282 // charged particles special optimization
283 static const G4double maxChargedCrossSection = 200*millibarn;
284 if(std::abs(trk1.GetDefinition()->GetPDGCharge())>0.1 &&
285 std::abs(trk2.GetDefinition()->GetPDGCharge())>0.1 &&
286 pi*distance>maxChargedCrossSection) return time;
287 // neutrons special optimization
288 if(( trk1.GetDefinition() == G4Neutron::Neutron() ||
289 trk2.GetDefinition() == G4Neutron::Neutron() ) &&
290 sqrtS>1.91*GeV && pi*distance>maxChargedCrossSection) return time;
291
292 G4double totalCrossSection = AbsorptionCrossSection(trk1,trk2);
293 if ( totalCrossSection > 0 )
294 {
295 if (distance <= totalCrossSection / pi)
296 {
297 time = collisionTime;
298 }
299 }
300 }
301 }
302 return time;
303}
304
305G4double G4MesonAbsorption::
306AbsorptionCrossSection(const G4KineticTrack & aT, const G4KineticTrack & bT)
307{
308 G4double t = 0;
311 {
312 t = aT.Get4Momentum().t()-aT.Get4Momentum().mag()/MeV;
313 }
316 {
317 t = bT.Get4Momentum().t()-bT.Get4Momentum().mag()/MeV;
318 }
319
320 static const G4double it [26] =
321 {0,4,50,5.5,75,8,95,10,120,11.5,140,12,160,11.5,180,10,190,8,210,6,235,4,260,3,300,2};
322
323 G4double aCross(0);
324 if(t<=it[24])
325 {
326 G4int count = 0;
327 while(t>it[count])count+=2; /* Loop checking, 30-Oct-2015, G.Folger */
328
329 G4double x1 = it[count-2];
330 G4double x2 = it[count];
331 G4double y1 = it[count-1];
332 G4double y2 = it[count+1];
333 aCross = y1+(y2-y1)/(x2-x1)*(t-x1);
334 // G4cout << "Printing the absorption crosssection "
335 // <<x1<< " "<<x2<<" "<<t<<" "<<y1<<" "<<y2<<" "<<0.5*aCross<<G4endl;
336 }
337 return .5*aCross*millibarn;
338}
double G4double
Definition: G4Types.hh:83
int G4int
Definition: G4Types.hh:85
#define G4endl
Definition: G4ios.hh:57
G4GLOB_DLL std::ostream G4cout
#define G4UniformRand()
Definition: Randomize.hh:52
double mag2() const
HepLorentzRotation & rotateY(double delta)
HepLorentzRotation & rotateZ(double delta)
HepLorentzRotation inverse() const
double theta() const
Hep3Vector vect() const
const G4ThreeVector & GetPosition() const
const G4ParticleDefinition * GetDefinition() const
const G4LorentzVector & GetTrackingMomentum() const
const G4LorentzVector & Get4Momentum() const
G4double GetActualMass() const
virtual const std::vector< G4CollisionInitialState * > & GetCollisions(G4KineticTrack *aProjectile, std::vector< G4KineticTrack * > &someCandidates, G4double aCurrentTime)
virtual G4KineticTrackVector * GetFinalState(G4KineticTrack *aProjectile, std::vector< G4KineticTrack * > &theTargets)
static G4Neutron * NeutronDefinition()
Definition: G4Neutron.cc:98
static G4Neutron * Neutron()
Definition: G4Neutron.cc:103
G4double GetPDGCharge() const
static G4PionMinus * PionMinusDefinition()
Definition: G4PionMinus.cc:92
static G4PionPlus * PionPlusDefinition()
Definition: G4PionPlus.cc:92
static G4Proton * ProtonDefinition()
Definition: G4Proton.cc:87
int G4lrint(double ad)
Definition: templates.hh:134
T sqr(const T &x)
Definition: templates.hh:128
#define DBL_MAX
Definition: templates.hh:62