Geant4-11
G4QuarkExchange.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// GEANT 4 class implemetation file
29//
30// ---------------- G4QuarkExchange --------------
31// by V. Uzhinsky, October 2016.
32// QuarkExchange is used by strings models.
33// Take a projectile and a target.
34//Simulate Q exchange with excitation of projectile or target.
35// ------------------------------------------------------------
36
37#include "G4QuarkExchange.hh"
38#include "globals.hh"
40#include "G4SystemOfUnits.hh"
41#include "Randomize.hh"
42#include "G4LorentzRotation.hh"
43#include "G4ThreeVector.hh"
45#include "G4VSplitableHadron.hh"
46#include "G4ExcitedString.hh"
47
48#include "G4ParticleTable.hh" // Uzhi June 2020
49
50#include "G4Log.hh"
51#include "G4Pow.hh"
52
53//#define debugQuarkExchange
54
56{
57 StrangeSuppress = (1.0-0.04)/2.0; // Uzhi June 2020 : suppression of strange quark pair prodution,
58 // i.e. u:d:s=1:1:0.04 . Need to be tuned!
59}
60
62
65{
66 #ifdef debugQuarkExchange
67 G4cout<<G4endl<<"G4QuarkExchange::ExciteParticipants"<<G4endl;
68 #endif
69
70 G4LorentzVector Pprojectile = projectile->Get4Momentum();
71 G4double Mprojectile = projectile->GetDefinition()->GetPDGMass();
72 G4double Mprojectile2 = sqr(Mprojectile);
73
74 G4LorentzVector Ptarget = target->Get4Momentum();
75 G4double Mtarget = target->GetDefinition()->GetPDGMass();
76 G4double Mtarget2 = sqr(Mtarget);
77
78 #ifdef debugQuarkExchange
79 G4cout<<"Proj Targ "<<projectile->GetDefinition()->GetPDGEncoding()<<" "<<target->GetDefinition()->GetPDGEncoding()<<G4endl;
80 G4cout<<"Proj. 4-Mom "<<Pprojectile<<" "<<Pprojectile.mag()<<G4endl
81 <<"Targ. 4-Mom "<<Ptarget <<" "<<Ptarget.mag() <<G4endl;
82 #endif
83
84 G4LorentzVector Psum=Pprojectile+Ptarget;
85 G4double SqrtS=Psum.mag();
86 G4double S =Psum.mag2();
87
88 #ifdef debugQuarkExchange
89 G4cout<<"SS Mpr Mtr SqrtS-Mprojectile-Mtarget "<<SqrtS<<" "<<Mprojectile<<" "<<Mtarget
90 <<" "<<SqrtS-Mprojectile-Mtarget<<G4endl;
91 #endif
92 if (SqrtS-Mprojectile-Mtarget <= 250.0*MeV) {
93 #ifdef debugQuarkExchange
94 G4cerr<<"Energy is too small for quark exchange!"<<G4endl;
95 G4cerr<<"Projectile: "<<projectile->GetDefinition()->GetPDGEncoding()<<" "
96 <<Pprojectile<<" "<<Pprojectile.mag()<<G4endl;
97 G4cerr<<"Target: "<<target->GetDefinition()->GetPDGEncoding()<<" "
98 <<Ptarget<<" "<<Ptarget.mag()<<G4endl;
99 G4cerr<<"sqrt(S) = "<<SqrtS<<" Mp + Mt = "<<Pprojectile.mag()+Ptarget.mag()<<G4endl;
100 #endif
101 return true;
102 }
103
104 G4LorentzRotation toCms(-1*Psum.boostVector());
105
106 G4LorentzVector Ptmp=toCms*Pprojectile;
107
108 if ( Ptmp.pz() <= 0. )
109 {
110 // "String" moving backwards in CMS, abort collision !!
111 // G4cout << " abort Collision!! " << G4endl;
112 return false;
113 }
114
115 toCms.rotateZ(-1*Ptmp.phi());
116 toCms.rotateY(-1*Ptmp.theta());
117
118 G4LorentzRotation toLab(toCms.inverse());
119
120 Pprojectile.transform(toCms);
121 Ptarget.transform(toCms);
122
123 #ifdef debugQuarkExchange
124 G4cout << "Pprojectile in CMS " << Pprojectile << G4endl;
125 G4cout << "Ptarget in CMS " << Ptarget << G4endl;
126 #endif
127 G4double maxPtSquare=sqr(Ptarget.pz());
128
129 G4double ProjectileMinDiffrMass = Pprojectile.mag()/GeV;
130 G4double TargetMinDiffrMass = Ptarget.mag()/GeV;
131
132 G4double AveragePt2(0.);
133
134 G4int PDGcode=projectile->GetDefinition()->GetPDGEncoding();
135 G4int absPDGcode=std::abs(PDGcode);
136
137 G4bool ProjectileDiffraction = true;
138
139 // Also for heavy hadrons, assume 50% probability of projectile diffraction.
140 if ( absPDGcode > 1000 ) { ProjectileDiffraction = G4UniformRand() <= 0.5; }
141 if ( (absPDGcode == 211) || (absPDGcode == 111) ) { ProjectileDiffraction = G4UniformRand() <= 0.66; }
142 if ( (absPDGcode == 321) || (absPDGcode == 311) ||
143 ( PDGcode == 130) || ( PDGcode == 310) ) { ProjectileDiffraction = G4UniformRand() <= 0.5; }
144 if ( absPDGcode > 400 && absPDGcode < 600 ) { ProjectileDiffraction = G4UniformRand() <= 0.5; }
145
146 //G4cout<<"ProjectileDiffr "<<ProjectileDiffraction<<G4endl;
147
148 if ( ProjectileDiffraction ) {
149 if ( absPDGcode > 1000 ) //------Projectile is baryon --------
150 {
151 if ( absPDGcode > 4000 && absPDGcode < 6000 ) // Projectile is a charm or bottom baryon
152 {
153 ProjectileMinDiffrMass = projectile->GetDefinition()->GetPDGMass()/CLHEP::GeV + 0.25; // GeV
154 AveragePt2 = 0.3; // GeV^2
155 }
156 else
157 {
158 ProjectileMinDiffrMass = 1.16; // GeV
159 AveragePt2 = 0.3; // GeV^2
160 }
161 }
162 else if( absPDGcode == 211 || absPDGcode == 111) //------Projectile is Pion -----------
163 {
164 ProjectileMinDiffrMass = 1.0; // GeV
165 AveragePt2 = 0.3; // GeV^2
166 }
167 else if( absPDGcode == 321 || absPDGcode == 130 || absPDGcode == 310) //Projectile is Kaon
168 {
169 ProjectileMinDiffrMass = 1.1; // GeV
170 AveragePt2 = 0.3; // GeV^2
171 }
172 else if( absPDGcode == 22) //------Projectile is Gamma -----------
173 {
174 ProjectileMinDiffrMass = 0.25; // GeV
175 AveragePt2 = 0.36; // GeV^2
176 }
177 else if( absPDGcode > 400 && absPDGcode < 600) // Projectile is a charm or bottom meson
178 {
179 ProjectileMinDiffrMass = projectile->GetDefinition()->GetPDGMass()/CLHEP::GeV + 0.25; // GeV
180 AveragePt2 = 0.3; // GeV^2
181 }
182 else //------Projectile is undefined, Nucleon assumed
183 {
184 ProjectileMinDiffrMass = 1.1; // GeV
185 AveragePt2 = 0.3; // GeV^2
186 };
187
188 ProjectileMinDiffrMass = ProjectileMinDiffrMass * GeV;
189 Mprojectile2=sqr(ProjectileMinDiffrMass);
190
191 if (G4UniformRand() <= 0.5) TargetMinDiffrMass += 0.22;
192 TargetMinDiffrMass *= GeV;
193 Mtarget2 = sqr( TargetMinDiffrMass) ;
194 }
195 else
196 {
197 if (G4UniformRand() <= 0.5) ProjectileMinDiffrMass += 0.22;
198 ProjectileMinDiffrMass *=GeV;
199 Mprojectile2=sqr(ProjectileMinDiffrMass);
200
201 TargetMinDiffrMass = 1.16*GeV; // For target nucleon
202 Mtarget2 = sqr( TargetMinDiffrMass) ;
203 AveragePt2 = 0.3; // GeV^2
204 } // end of if ( ProjectileDiffraction )
205
206 AveragePt2 = AveragePt2 * GeV*GeV;
207
208 if ( SqrtS - (ProjectileMinDiffrMass+TargetMinDiffrMass) < 220.0*MeV ) return false;
209
210 //-----------------------
211 G4double Pt2, PZcms, PZcms2;
212 G4double ProjMassT2, ProjMassT;
213 G4double TargMassT2, TargMassT;
214 G4double PMinusMin, PMinusMax, sqrtPMinusMin, sqrtPMinusMax;
215 G4double TPlusMin, TPlusMax, sqrtTPlusMin, sqrtTPlusMax;
216 G4double PMinusNew, PPlusNew, TPlusNew(0.), TMinusNew;
217
218 G4LorentzVector Qmomentum;
219 G4double Qminus, Qplus;
220
221 G4double x(0.), y(0.);
222 G4int whilecount=0;
223 do {
224 whilecount++;
225
226 if (whilecount > 1000 )
227 {
228 Qmomentum=G4LorentzVector(0.,0.,0.,0.);
229 return false; // Ignore this interaction
230 }
231
232 // Generate pt
233 Qmomentum=G4LorentzVector(GaussianPt(AveragePt2,maxPtSquare),0);
234
235 Pt2 = G4ThreeVector( Qmomentum.vect() ).mag2();
236 ProjMassT2 = Mprojectile2 + Pt2;
237 ProjMassT = std::sqrt( ProjMassT2 );
238 TargMassT2 = Mtarget2 + Pt2;
239 TargMassT = std::sqrt( TargMassT2 );
240
241 #ifdef debugQuarkExchange
242 G4cout<<"whilecount Pt2 ProjMassT TargMassT SqrtS S ProjectileDiffraction"<<G4endl;
243 G4cout<<whilecount<<" "<<Pt2<<" "<<ProjMassT<<" "<<TargMassT<<" "<<SqrtS<<" "<<S<<" "<<ProjectileDiffraction<<G4endl;
244 #endif
245
246 if ( SqrtS < ProjMassT + TargMassT + 220.0*MeV ) continue;
247
248 PZcms2 = ( S*S + ProjMassT2*ProjMassT2 + TargMassT2*TargMassT2
249 - 2.0*S*ProjMassT2 - 2.0*S*TargMassT2 - 2.0*ProjMassT2*TargMassT2 ) / 4.0 / S;
250
251 if ( PZcms2 < 0 ) continue;
252
253 PZcms = std::sqrt( PZcms2 );
254
255 if ( ProjectileDiffraction )
256 { // The projectile will fragment, the target will saved.
257 PMinusMin = std::sqrt( ProjMassT2 + PZcms2 ) - PZcms;
258 PMinusMax = SqrtS - TargMassT;
259 sqrtPMinusMin = std::sqrt(PMinusMin); sqrtPMinusMax = std::sqrt(PMinusMax);
260
261 if ( absPDGcode > 1000 )
262 {
263 PMinusNew = PMinusMax * (1.0 - (1.0 - PMinusMin/PMinusMax)
264 * G4Pow::GetInstance()->powA(G4UniformRand(),0.3333) );
265 }
266 else if ( (absPDGcode == 211) || (absPDGcode == 111) )
267 {
268 while (true)
269 {
270 x=sqrtPMinusMax-(sqrtPMinusMax-sqrtPMinusMin)*G4UniformRand();
271 y=G4UniformRand();
272 if ( y < 1.0-0.7 * x/sqrtPMinusMax ) break;
273 }
274 PMinusNew = sqr(x);
275 }
276 else if ( (absPDGcode == 321) || (absPDGcode == 311) ||
277 ( PDGcode == 130) || ( PDGcode == 310) )
278 { // For K-mesons it must be found !!! Uzhi
279 while (true)
280 {
281 x=sqrtPMinusMax-(sqrtPMinusMax-sqrtPMinusMin)*G4UniformRand();
282 y=G4UniformRand();
283 if ( y < 1.0-0.7 * x/sqrtPMinusMax ) break;
284 }
285 PMinusNew = sqr(x);
286 }
287 else
288 {
289 PMinusNew = PMinusMax * (1.0 - (1.0 - PMinusMin/PMinusMax)
290 * G4Pow::GetInstance()->powA(G4UniformRand(),0.3333) );
291 };
292
293 TMinusNew = SqrtS - PMinusNew;
294
295 Qminus = Ptarget.minus() - TMinusNew;
296 TPlusNew = TargMassT2 / TMinusNew;
297 Qplus = Ptarget.plus() - TPlusNew;
298
299 }
300 else
301 { // The target will fragment, the projectile will saved.
302 TPlusMin = std::sqrt( TargMassT2 + PZcms2 ) - PZcms;
303 TPlusMax = SqrtS - ProjMassT;
304 sqrtTPlusMin = std::sqrt(TPlusMin); sqrtTPlusMax = std::sqrt(TPlusMax);
305
306 if ( absPDGcode > 1000 )
307 {
308 TPlusNew = TPlusMax * (1.0 - (1.0 - TPlusMin/TPlusMax)
309 * G4Pow::GetInstance()->powA(G4UniformRand(),0.3333) );
310 }
311 else if ( (absPDGcode == 211) || (absPDGcode == 111) )
312 {
313 while (true)
314 {
315 x=sqrtTPlusMax-(sqrtTPlusMax-sqrtTPlusMin)*G4UniformRand();
316 y=G4UniformRand();
317 if ( y < 1.0-0.7 * x/sqrtTPlusMax ) break;
318 }
319 TPlusNew = sqr(x);
320 }
321 else if ( (absPDGcode == 321) || (absPDGcode == 311) ||
322 ( PDGcode == 130) || ( PDGcode == 310) )
323 { // For K-mesons it must be found !!! Uzhi
324 while (true)
325 {
326 x=sqrtTPlusMax-(sqrtTPlusMax-sqrtTPlusMin)*G4UniformRand();
327 y=G4UniformRand();
328 if ( y < 1.0-0.7 * x/sqrtTPlusMax ) break;
329 }
330 }
331 else
332 {
333 TPlusNew = TPlusMax * (1.0 - (1.0 - TPlusMin/TPlusMax)
334 * G4Pow::GetInstance()->powA(G4UniformRand(),0.3333) );
335 };
336
337 PPlusNew = SqrtS - TPlusNew;
338
339 Qplus = PPlusNew - Pprojectile.plus();
340 PMinusNew = ProjMassT2 / PPlusNew;
341 Qminus = PMinusNew - Pprojectile.minus();
342 }
343
344 Qmomentum.setPz( (Qplus - Qminus)/2 );
345 Qmomentum.setE( (Qplus + Qminus)/2 );
346
347 #ifdef debugQuarkExchange
348 G4cout<<"ProjectileDiffraction (Pprojectile + Qmomentum).mag2() Mprojectile2"<<G4endl;
349 G4cout<<ProjectileDiffraction<<" "<<( Pprojectile + Qmomentum ).mag2()<<" "<< Mprojectile2<<G4endl;
350 G4cout<<"TargetDiffraction (Ptarget - Qmomentum).mag2() Mtarget2"<<G4endl;
351 G4cout<<!ProjectileDiffraction<<" "<<( Ptarget - Qmomentum ).mag2()<<" "<< Mtarget2<<G4endl;
352 #endif
353
354 } while ( ( ProjectileDiffraction&&( Pprojectile + Qmomentum ).mag2() < Mprojectile2 ) ||
355 (!ProjectileDiffraction&&( Ptarget - Qmomentum ).mag2() < Mtarget2 ) );
356 // Repeat the sampling because there was not any excitation
357
358 Pprojectile += Qmomentum;
359
360 Ptarget -= Qmomentum;
361
362 // Transform back and update SplitableHadron Participant.
363 Pprojectile.transform(toLab);
364 Ptarget.transform(toLab);
365
366 #ifdef debugQuarkExchange
367 G4cout << "Pprojectile in Lab. " << Pprojectile << G4endl;
368 G4cout << "Ptarget in Lab. " << Ptarget << G4endl;
369 G4cout << "G4QuarkExchange: Projectile mass " << Pprojectile.mag() << G4endl;
370 G4cout << "G4QuarkExchange: Target mass " << Ptarget.mag() << G4endl;
371 #endif
372
373 target->Set4Momentum(Ptarget);
374 projectile->Set4Momentum(Pprojectile);
375
376 //=================================== Quark exchange ================================
377 projectile->SplitUp();
378 target->SplitUp();
379
380 G4Parton* PrQuark = nullptr;
381 G4Parton* TrQuark = nullptr;
382
383 if( projectile->GetDefinition()->GetBaryonNumber() >= 0 ) { // Uzhi June 2020
384 // Quark exchange ----
385 PrQuark = projectile->GetNextParton();
386 TrQuark = target->GetNextParton();
387 G4ParticleDefinition * Tmp = PrQuark->GetDefinition();
388 PrQuark->SetDefinition(TrQuark->GetDefinition());
389 TrQuark->SetDefinition(Tmp);
390 return true;
391 }
392
393 // Quark exchage for projectile anti-baryon (annihilation and new Q pair creation ---
394 // This part added by Uzhi June 2020
395 PrQuark = projectile->GetNextAntiParton();
396 TrQuark = target->GetNextParton();
397 if( -PrQuark->GetDefinition()->GetPDGEncoding() == TrQuark->GetDefinition()->GetPDGEncoding() ){
398 G4int QuarkCode = 1 + (int)(G4UniformRand()/StrangeSuppress);
401 if( (AQpr != nullptr) && (Qtr != nullptr) ) {
402 PrQuark->SetDefinition(AQpr);
403 TrQuark->SetDefinition( Qtr);
404 }
405 }
406
407 return true;
408}
409
410
411// --------- private methods ----------------------
412
414{ // @@ this method is used in FTFModel as well. Should go somewhere common!
415
416 G4double pt2;
417
418 const G4int maxNumberOfLoops = 1000;
419 G4int loopCounter = 0;
420 do {
421 pt2=-widthSquare * G4Log( G4UniformRand() );
422 } while ( ( pt2 > maxPtSquare) && ++loopCounter < maxNumberOfLoops ); /* Loop checking, 07.08.2015, A.Ribon */
423 if ( loopCounter >= maxNumberOfLoops ) {
424 pt2 = 0.99*maxPtSquare; // Just an acceptable value, without any physics consideration.
425 }
426
427 pt2=std::sqrt(pt2);
428
430
431 return G4ThreeVector (pt2*std::cos(phi), pt2*std::sin(phi), 0.);
432}
433
G4double S(G4double temp)
G4double G4Log(G4double x)
Definition: G4Log.hh:226
CLHEP::HepLorentzVector G4LorentzVector
static constexpr double twopi
Definition: G4SIunits.hh:56
static constexpr double GeV
Definition: G4SIunits.hh:203
static constexpr double MeV
Definition: G4SIunits.hh:200
CLHEP::Hep3Vector G4ThreeVector
double G4double
Definition: G4Types.hh:83
bool G4bool
Definition: G4Types.hh:86
int G4int
Definition: G4Types.hh:85
G4GLOB_DLL std::ostream G4cerr
#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 boostVector() const
Hep3Vector vect() const
double minus() const
HepLorentzVector & transform(const HepRotation &)
G4ParticleDefinition * FindParticle(G4int PDGEncoding)
static G4ParticleTable * GetParticleTable()
G4ParticleDefinition * GetDefinition()
Definition: G4Parton.hh:161
void SetDefinition(G4ParticleDefinition *aDefinition)
Definition: G4Parton.hh:166
static G4Pow * GetInstance()
Definition: G4Pow.cc:41
G4double powA(G4double A, G4double y) const
Definition: G4Pow.hh:230
G4double StrangeSuppress
G4bool ExciteParticipants(G4VSplitableHadron *aPartner, G4VSplitableHadron *bPartner) const
G4ThreeVector GaussianPt(G4double widthSquare, G4double maxPtSquare) const
virtual void SplitUp()=0
const G4ParticleDefinition * GetDefinition() const
void Set4Momentum(const G4LorentzVector &a4Momentum)
virtual G4Parton * GetNextParton()=0
virtual G4Parton * GetNextAntiParton()=0
const G4LorentzVector & Get4Momentum() const
static constexpr double GeV
T sqr(const T &x)
Definition: templates.hh:128