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