Geant4 9.6.0
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
G4QGSMSplitableHadron.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//
28#include "G4SystemOfUnits.hh"
29#include "G4ParticleTable.hh"
30#include "G4PionPlus.hh"
31#include "G4PionMinus.hh"
32#include "G4Gamma.hh"
33#include "G4PionZero.hh"
34#include "G4KaonPlus.hh"
35#include "G4KaonMinus.hh"
36
37// based on prototype by Maxim Komogorov
38// Splitting into methods, and centralizing of model parameters HPW Feb 1999
39// restructuring HPW Feb 1999
40// fixing bug in the sampling of 'x', HPW Feb 1999
41// fixing bug in sampling pz, HPW Feb 1999.
42// Code now also good for p-nucleus scattering (before only p-p), HPW Feb 1999.
43// Using Parton more directly, HPW Feb 1999.
44// Shortening the algorithm for sampling x, HPW Feb 1999.
45// sampling of x replaced by formula, taking X_min into account in the correlated sampling. HPW, Feb 1999.
46// logic much clearer now. HPW Feb 1999
47// Removed the ordering problem. No Direction needed in selection of valence quark types. HPW Mar'99.
48// Fixing p-t distributions for scattering of nuclei.
49// Separating out parameters.
50
51void G4QGSMSplitableHadron::InitParameters()
52{
53 // changing rapidity distribution for all
54 alpha = -0.5; // Note that this number is still assumed in the algorithm
55 // needs to be generalized.
56 // changing rapidity distribution for projectile like
57 beta = 2.5;// Note that this number is still assumed in the algorithm
58 // needs to be generalized.
59 theMinPz = 0.5*G4PionMinus::PionMinus()->GetPDGMass();
60 // theMinPz = 0.1*G4PionMinus::PionMinus()->GetPDGMass();
61 // theMinPz = G4PionMinus::PionMinus()->GetPDGMass();
62 // as low as possible, otherwise, we have unphysical boundary conditions in the sampling.
63 StrangeSuppress = 0.48;
64 sigmaPt = 0.*GeV; // widens eta slightly, if increased to 1.7,
65 // but Maxim's algorithm breaks energy conservation
66 // to be revised.
67 widthOfPtSquare = 0.01*GeV*GeV;
68 Direction = FALSE;
69 minTransverseMass = 1*keV;
70}
71
73{
74 InitParameters();
75}
76
78:G4VSplitableHadron(aPrimary)
79{
80 InitParameters();
81 Direction = aDirection;
82}
83
84
86: G4VSplitableHadron(aPrimary)
87{
88 InitParameters();
89}
90
92: G4VSplitableHadron(aNucleon)
93{
94 InitParameters();
95}
96
98: G4VSplitableHadron(aNucleon)
99{
100 InitParameters();
101 Direction = aDirection;
102}
103
105
106
107
108//**************************************************************************************************************************
109
111{
112 if (IsSplit()) return;
113 Splitting();
114 if (Color.size()!=0) return;
115 if (GetSoftCollisionCount() == 0)
116 {
117 DiffractiveSplitUp();
118 }
119 else
120 {
121 SoftSplitUp();
122 }
123}
124
125void G4QGSMSplitableHadron::DiffractiveSplitUp()
126{
127 // take the particle definitions and get the partons HPW
128 G4Parton * Left = NULL;
129 G4Parton * Right = NULL;
130 GetValenceQuarkFlavors(GetDefinition(), Left, Right);
131 Left->SetPosition(GetPosition());
132 Right->SetPosition(GetPosition());
133
134 G4LorentzVector HadronMom = Get4Momentum();
135 //std::cout << "DSU 1 - "<<HadronMom<<std::endl;
136
137 // momenta of string ends
138 G4double pt2 = HadronMom.perp2();
139 G4double transverseMass2 = HadronMom.plus()*HadronMom.minus();
140 G4double maxAvailMomentum2 = sqr(std::sqrt(transverseMass2) - std::sqrt(pt2));
141 G4ThreeVector pt(minTransverseMass, minTransverseMass, 0);
142 if(maxAvailMomentum2/widthOfPtSquare>0.01) pt = GaussianPt(widthOfPtSquare, maxAvailMomentum2);
143 //std::cout << "DSU 1.1 - "<< maxAvailMomentum2<< pt <<std::endl;
144
145 G4LorentzVector LeftMom(pt, 0.);
146 G4LorentzVector RightMom;
147 RightMom.setPx(HadronMom.px() - pt.x());
148 RightMom.setPy(HadronMom.py() - pt.y());
149 //std::cout << "DSU 2 - "<<RightMom<<" "<< LeftMom <<std::endl;
150
151 G4double Local1 = HadronMom.minus() + (RightMom.perp2() - LeftMom.perp2())/HadronMom.plus();
152 G4double Local2 = std::sqrt(std::max(0., sqr(Local1) - 4.*RightMom.perp2()*HadronMom.minus()/HadronMom.plus()));
153 //std::cout << "DSU 3 - "<< Local1 <<" "<< Local2 <<std::endl;
154 if (Direction) Local2 = -Local2;
155 G4double RightMinus = 0.5*(Local1 + Local2);
156 G4double LeftMinus = HadronMom.minus() - RightMinus;
157 //std::cout << "DSU 4 - "<< RightMinus <<" "<< LeftMinus << " "<<HadronMom.minus() <<std::endl;
158
159 G4double LeftPlus = LeftMom.perp2()/LeftMinus;
160 G4double RightPlus = HadronMom.plus() - LeftPlus;
161 //std::cout << "DSU 5 - "<< RightPlus <<" "<< LeftPlus <<std::endl;
162 LeftMom.setPz(0.5*(LeftPlus - LeftMinus));
163 LeftMom.setE (0.5*(LeftPlus + LeftMinus));
164 RightMom.setPz(0.5*(RightPlus - RightMinus));
165 RightMom.setE (0.5*(RightPlus + RightMinus));
166 //std::cout << "DSU 6 - "<< LeftMom <<" "<< RightMom <<std::endl;
167 Left->Set4Momentum(LeftMom);
168 Right->Set4Momentum(RightMom);
169 Color.push_back(Left);
170 AntiColor.push_back(Right);
171}
172
173
174void G4QGSMSplitableHadron::SoftSplitUp()
175{
176 //... sample transversal momenta for sea and valence quarks
177 G4double phi, pts;
178 G4double SumPy = 0.;
179 G4double SumPx = 0.;
181 G4int nSeaPair = GetSoftCollisionCount()-1;
182
183 // here the condition,to ensure viability of splitting, also in cases
184 // where difractive excitation occured together with soft scattering.
185 // G4double LightConeMomentum = (Direction)? Get4Momentum().plus() : Get4Momentum().minus();
186 // G4double Xmin = theMinPz/LightConeMomentum;
187 G4double Xmin = theMinPz/( Get4Momentum().e() - GetDefinition()->GetPDGMass() );
188 while(Xmin>=1-(2*nSeaPair+1)*Xmin) Xmin*=0.95;
189
190 G4int aSeaPair;
191 for (aSeaPair = 0; aSeaPair < nSeaPair; aSeaPair++)
192 {
193 // choose quark flavour, d:u:s = 1:1:(1/StrangeSuppress-2)
194
195 G4int aPDGCode = 1 + (G4int)(G4UniformRand()/StrangeSuppress);
196
197 // BuildSeaQuark() determines quark spin, isospin and colour
198 // via parton-constructor G4Parton(aPDGCode)
199
200 G4Parton * aParton = BuildSeaQuark(false, aPDGCode, nSeaPair);
201
202 // G4cerr << "G4QGSMSplitableHadron::SoftSplitUp()" << G4endl;
203
204 // G4cerr << "Parton 1: "
205 // << " PDGcode: " << aPDGCode
206 // << " - Name: " << aParton->GetDefinition()->GetParticleName()
207 // << " - Type: " << aParton->GetDefinition()->GetParticleType()
208 // << " - Spin-3: " << aParton->GetSpinZ()
209 // << " - Colour: " << aParton->GetColour() << G4endl;
210
211 // save colour a spin-3 for anti-quark
212
213 G4int firstPartonColour = aParton->GetColour();
214 G4double firstPartonSpinZ = aParton->GetSpinZ();
215
216 SumPx += aParton->Get4Momentum().px();
217 SumPy += aParton->Get4Momentum().py();
218 Color.push_back(aParton);
219
220 // create anti-quark
221
222 aParton = BuildSeaQuark(true, aPDGCode, nSeaPair);
223 aParton->SetSpinZ(-firstPartonSpinZ);
224 aParton->SetColour(-firstPartonColour);
225
226 // G4cerr << "Parton 2: "
227 // << " PDGcode: " << -aPDGCode
228 // << " - Name: " << aParton->GetDefinition()->GetParticleName()
229 // << " - Type: " << aParton->GetDefinition()->GetParticleType()
230 // << " - Spin-3: " << aParton->GetSpinZ()
231 // << " - Colour: " << aParton->GetColour() << G4endl;
232 // G4cerr << "------------" << G4endl;
233
234 SumPx += aParton->Get4Momentum().px();
235 SumPy += aParton->Get4Momentum().py();
236 AntiColor.push_back(aParton);
237 }
238 // Valence quark
239 G4Parton* pColorParton = NULL;
240 G4Parton* pAntiColorParton = NULL;
241 GetValenceQuarkFlavors(GetDefinition(), pColorParton, pAntiColorParton);
242 G4int ColorEncoding = pColorParton->GetPDGcode();
243
244 pts = sigmaPt*std::sqrt(-std::log(G4UniformRand()));
245 phi = 2.*pi*G4UniformRand();
246 G4double Px = pts*std::cos(phi);
247 G4double Py = pts*std::sin(phi);
248 SumPx += Px;
249 SumPy += Py;
250
251 if (ColorEncoding < 0) // use particle definition
252 {
253 G4LorentzVector ColorMom(-SumPx, -SumPy, 0, 0);
254 pColorParton->Set4Momentum(ColorMom);
255 G4LorentzVector AntiColorMom(Px, Py, 0, 0);
256 pAntiColorParton->Set4Momentum(AntiColorMom);
257 }
258 else
259 {
260 G4LorentzVector ColorMom(Px, Py, 0, 0);
261 pColorParton->Set4Momentum(ColorMom);
262 G4LorentzVector AntiColorMom(-SumPx, -SumPy, 0, 0);
263 pAntiColorParton->Set4Momentum(AntiColorMom);
264 }
265 Color.push_back(pColorParton);
266 AntiColor.push_back(pAntiColorParton);
267
268 // Sample X
269 G4int nAttempt = 0;
270 G4double SumX = 0;
271 G4double aBeta = beta;
272 G4double ColorX, AntiColorX;
273 if (GetDefinition() == G4PionMinus::PionMinusDefinition()) aBeta = 1.;
274 if (GetDefinition() == G4Gamma::GammaDefinition()) aBeta = 1.;
275 if (GetDefinition() == G4PionPlus::PionPlusDefinition()) aBeta = 1.;
276 if (GetDefinition() == G4PionZero::PionZeroDefinition()) aBeta = 1.;
277 if (GetDefinition() == G4KaonPlus::KaonPlusDefinition()) aBeta = 0.;
278 if (GetDefinition() == G4KaonMinus::KaonMinusDefinition()) aBeta = 0.;
279 do
280 {
281 SumX = 0;
282 nAttempt++;
283 G4int NumberOfUnsampledSeaQuarks = 2*nSeaPair;
284 ColorX = SampleX(Xmin, NumberOfUnsampledSeaQuarks, 2*nSeaPair, aBeta);
285 Color.back()->SetX(SumX = ColorX);// this is the valenz quark.
286 for(G4int aPair = 0; aPair < nSeaPair; aPair++)
287 {
288 NumberOfUnsampledSeaQuarks--;
289 ColorX = SampleX(Xmin, NumberOfUnsampledSeaQuarks, 2*nSeaPair, aBeta);
290 Color[aPair]->SetX(ColorX);
291 SumX += ColorX;
292 NumberOfUnsampledSeaQuarks--;
293 AntiColorX = SampleX(Xmin, NumberOfUnsampledSeaQuarks, 2*nSeaPair, aBeta);
294 AntiColor[aPair]->SetX(AntiColorX); // the 'sea' partons
295 SumX += AntiColorX;
296 if (1. - SumX <= Xmin) break;
297 }
298 }
299 while (1. - SumX <= Xmin);
300
301 (*(AntiColor.end()-1))->SetX(1. - SumX); // the di-quark takes the rest, then go to momentum
302 G4double lightCone = ((!Direction) ? Get4Momentum().minus() : Get4Momentum().plus());
303 G4double lightCone2 = ((!Direction) ? Get4Momentum().plus() : Get4Momentum().minus());
304 for(aSeaPair = 0; aSeaPair < nSeaPair+1; aSeaPair++)
305 {
306 G4Parton* aParton = Color[aSeaPair];
307 aParton->DefineMomentumInZ(lightCone, lightCone2, Direction);
308
309 aParton = AntiColor[aSeaPair];
310 aParton->DefineMomentumInZ(lightCone, lightCone2, Direction);
311 }
312 return;
313}
314
315void G4QGSMSplitableHadron::GetValenceQuarkFlavors(const G4ParticleDefinition * aPart, G4Parton *& Parton1, G4Parton *& Parton2)
316{
317 // Note! convention aEnd = q or (qq)bar and bEnd = qbar or qq.
318 G4int aEnd;
319 G4int bEnd;
320 G4int HadronEncoding = aPart->GetPDGEncoding();
321 if (aPart->GetBaryonNumber() == 0)
322 {
323 theMesonSplitter.SplitMeson(HadronEncoding, &aEnd, &bEnd);
324 }
325 else
326 {
327 theBaryonSplitter.SplitBarion(HadronEncoding, &aEnd, &bEnd);
328 }
329
330 Parton1 = new G4Parton(aEnd);
331 Parton1->SetPosition(GetPosition());
332
333 // G4cerr << "G4QGSMSplitableHadron::GetValenceQuarkFlavors()" << G4endl;
334 // G4cerr << "Parton 1: "
335 // << " PDGcode: " << aEnd
336 // << " - Name: " << Parton1->GetDefinition()->GetParticleName()
337 // << " - Type: " << Parton1->GetDefinition()->GetParticleType()
338 // << " - Spin-3: " << Parton1->GetSpinZ()
339 // << " - Colour: " << Parton1->GetColour() << G4endl;
340
341 Parton2 = new G4Parton(bEnd);
342 Parton2->SetPosition(GetPosition());
343
344 // G4cerr << "Parton 2: "
345 // << " PDGcode: " << bEnd
346 // << " - Name: " << Parton2->GetDefinition()->GetParticleName()
347 // << " - Type: " << Parton2->GetDefinition()->GetParticleType()
348 // << " - Spin-3: " << Parton2->GetSpinZ()
349 // << " - Colour: " << Parton2->GetColour() << G4endl;
350 // G4cerr << "... now checking for color and spin conservation - yielding: " << G4endl;
351
352 // colour of parton 1 choosen at random by G4Parton(aEnd)
353 // colour of parton 2 is the opposite:
354
355 Parton2->SetColour(-(Parton1->GetColour()));
356
357 // isospin-3 of both partons is handled by G4Parton(PDGCode)
358
359 // spin-3 of parton 1 and 2 choosen at random by G4Parton(aEnd)
360 // spin-3 of parton 2 may be constrained by spin of original particle:
361
362 if ( std::abs(Parton1->GetSpinZ() + Parton2->GetSpinZ()) > aPart->GetPDGSpin())
363 {
364 Parton2->SetSpinZ(-(Parton2->GetSpinZ()));
365 }
366
367 // G4cerr << "Parton 2: "
368 // << " PDGcode: " << bEnd
369 // << " - Name: " << Parton2->GetDefinition()->GetParticleName()
370 // << " - Type: " << Parton2->GetDefinition()->GetParticleType()
371 // << " - Spin-3: " << Parton2->GetSpinZ()
372 // << " - Colour: " << Parton2->GetColour() << G4endl;
373 // G4cerr << "------------" << G4endl;
374
375}
376
377
378G4ThreeVector G4QGSMSplitableHadron::GaussianPt(G4double widthSquare, G4double maxPtSquare)
379{
380 G4double R;
381 while((R = -widthSquare*std::log(G4UniformRand())) > maxPtSquare) {;}
382 R = std::sqrt(R);
383 G4double phi = twopi*G4UniformRand();
384 return G4ThreeVector (R*std::cos(phi), R*std::sin(phi), 0.);
385}
386
387G4Parton * G4QGSMSplitableHadron::
388BuildSeaQuark(G4bool isAntiQuark, G4int aPDGCode, G4int /* nSeaPair*/)
389{
390 if (isAntiQuark) aPDGCode*=-1;
391 G4Parton* result = new G4Parton(aPDGCode);
392 result->SetPosition(GetPosition());
393 G4ThreeVector aPtVector = GaussianPt(sigmaPt, DBL_MAX);
394 G4LorentzVector a4Momentum(aPtVector, 0);
395 result->Set4Momentum(a4Momentum);
396 return result;
397}
398
399G4double G4QGSMSplitableHadron::
400SampleX(G4double anXmin, G4int nSea, G4int totalSea, G4double aBeta)
401{
402 G4double result;
403 G4double x1, x2;
404 G4double ymax = 0;
405 for(G4int ii=1; ii<100; ii++)
406 {
407 G4double y = std::pow(1./G4double(ii), alpha);
408 y *= std::pow( std::pow(1-anXmin-totalSea*anXmin, alpha+1) - std::pow(anXmin, alpha+1), nSea);
409 y *= std::pow(1-anXmin-totalSea*anXmin, aBeta+1) - std::pow(anXmin, aBeta+1);
410 if(y>ymax) ymax = y;
411 }
412 G4double y;
413 G4double xMax=1-(totalSea+1)*anXmin;
414 if(anXmin > xMax)
415 {
416 G4cout << "anXmin = "<<anXmin<<" nSea = "<<nSea<<" totalSea = "<< totalSea<<G4endl;
417 throw G4HadronicException(__FILE__, __LINE__, "G4QGSMSplitableHadron - Fatal: Cannot sample parton densities under these constraints.");
418 }
419 do
420 {
421 x1 = CLHEP::RandFlat::shoot(anXmin, xMax);
422 y = std::pow(x1, alpha);
423 y *= std::pow( std::pow(1-x1-totalSea*anXmin, alpha+1) - std::pow(anXmin, alpha+1), nSea);
424 y *= std::pow(1-x1-totalSea*anXmin, aBeta+1) - std::pow(anXmin, aBeta+1);
425 x2 = ymax*G4UniformRand();
426 }
427 while(x2>y);
428 result = x1;
429 return result;
430}
CLHEP::Hep3Vector G4ThreeVector
double G4double
Definition: G4Types.hh:64
int G4int
Definition: G4Types.hh:66
bool G4bool
Definition: G4Types.hh:67
#define G4endl
Definition: G4ios.hh:52
G4DLLIMPORT std::ostream G4cout
#define G4UniformRand()
Definition: Randomize.hh:53
double minus() const
double perp2() const
static double shoot()
Definition: RandFlat.cc:59
G4bool SplitBarion(G4int PDGCode, G4int *q_or_qqbar, G4int *qbar_or_qq)
static G4Gamma * GammaDefinition()
Definition: G4Gamma.cc:81
static G4KaonMinus * KaonMinusDefinition()
Definition: G4KaonMinus.cc:108
static G4KaonPlus * KaonPlusDefinition()
Definition: G4KaonPlus.cc:108
G4bool SplitMeson(G4int PDGcode, G4int *aEnd, G4int *bEnd)
void SetSpinZ(G4double aSpinZ)
Definition: G4Parton.hh:94
G4double GetSpinZ()
Definition: G4Parton.hh:95
G4int GetPDGcode() const
Definition: G4Parton.hh:124
void Set4Momentum(const G4LorentzVector &aMomentum)
Definition: G4Parton.hh:145
void DefineMomentumInZ(G4double aLightConeMomentum, G4bool aDirection)
Definition: G4Parton.cc:142
void SetPosition(const G4ThreeVector &aPosition)
Definition: G4Parton.hh:134
G4int GetColour()
Definition: G4Parton.hh:89
void SetColour(G4int aColour)
Definition: G4Parton.hh:88
const G4LorentzVector & Get4Momentum() const
Definition: G4Parton.hh:140
static G4PionMinus * PionMinus()
Definition: G4PionMinus.cc:98
static G4PionMinus * PionMinusDefinition()
Definition: G4PionMinus.cc:93
static G4PionPlus * PionPlusDefinition()
Definition: G4PionPlus.cc:93
static G4PionZero * PionZeroDefinition()
Definition: G4PionZero.cc:99
G4ParticleDefinition * GetDefinition() const
const G4LorentzVector & Get4Momentum() const
const G4ThreeVector & GetPosition() const
ush Pos
Definition: deflate.h:82
#define FALSE
Definition: globals.hh:52
const G4double pi
T sqr(const T &x)
Definition: templates.hh:145
#define DBL_MAX
Definition: templates.hh:83