Geant4 10.7.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4QGSMFragmentation.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// -----------------------------------------------------------------------------
29// GEANT 4 class implementation file
30//
31// History: first implementation, Maxim Komogorov, 10-Jul-1998
32// -----------------------------------------------------------------------------
35#include "G4SystemOfUnits.hh"
36#include "Randomize.hh"
37#include "G4ios.hh"
39#include "G4DiQuarks.hh"
40#include "G4Quarks.hh"
42#include "G4Pow.hh"
43
44//#define debug_QGSMfragmentation
45
46// Class G4QGSMFragmentation
47//****************************************************************************************
48
50{
51 SigmaQT = 0.45 * GeV; // Uzhi June 2020
52
53 MassCut = 0.35*GeV;
54
55 SetStrangenessSuppression((1.0 - 0.12)/2.); // Uzhi June 2020 0.16 -> 0.12
56
57 // Check if charmed and bottom hadrons are enabled: if this is the case, then
58 // set the non-zero probabilities for c-cbar and b-bbar creation from the vacuum,
59 // else set them to 0.0. If these probabilities are/aren't zero then charmed or bottom
60 // hadrons can't/can be created during the string fragmentation of ordinary
61 // (i.e. not heavy) projectile hadron nuclear reactions.
62 if ( G4HadronicParameters::Instance()->EnableBCParticles() ) {
63 SetProbCCbar(0.005); // According to O.I. Piskunova Yad. Fiz. 56 (1993) 1094
64 SetProbBBbar(5.0e-5); // According to O.I. Piskunova Yad. Fiz. 56 (1993) 1094
65 } else {
66 SetProbCCbar(0.0);
67 SetProbBBbar(0.0);
68 }
69
70 SetDiquarkSuppression(0.195); // Uzhi June 2020 0.32 -> 0.195
71 SetDiquarkBreakProbability(0.0); // Uzhi June 2020 0.7 -> 0.0
72
74
75 arho = 0.5; // alpha_rho0
76 aphi = 0.0; // alpha_fi
77 aJPs =-2.2; // alpha_J/Psi
78 aUps =-8.0; // alpha_Y ??? O. Piskunova Yad. Phys. 56 (1993) 1094.
79
80 aksi =-1.0;
81 alft = 0.5; // 2 * alpha'_R *<Pt^2>
82
83 an = -0.5 ;
84 ala = -0.75; // an - arho/2 + aphi/2
85 alaC = an - arho/2.0 + aJPs/2.0;
86 alaB = an - arho/2.0 + aUps/2.0;
87 aXi = 0.0; // ??
88 aXiC = 0.0; // ??
89 aXiB = 0.0; // ??
90 aXiCC = 0.0; // ??
91 aXiCB = 0.0; // ??
92 aXiBB = 0.0; // ??
93
94 SetFFq2q();
95 SetFFq2qq();
96 SetFFqq2q();
97 SetFFqq2qq();
98 // d u s c b
99 G4int Index[5][5] = { { 0, 1, 2, 3, 4 }, // d
100 { 1, 5, 6, 7, 8 }, // u
101 { 2, 6, 9, 10, 11 }, // s
102 { 3, 7, 10, 12, 13 }, // c
103 { 4, 8, 11, 13, 14 } }; // b
104 for (G4int i = 0; i < 5; i++ ) {
105 for ( G4int j = 0; j < 5; j++ ) {
106 IndexDiQ[i][j] = Index[i][j];
107 }
108 };
109}
110
112{}
113
114//----------------------------------------------------------------------------------------------------------
115
117{
118
119 G4FragmentingString aString(theString);
120 SetMinimalStringMass(&aString);
121
122 #ifdef debug_QGSMfragmentation
123 G4cout<<G4endl<<"QGSM StringFragm: String Mass "
124 <<theString.Get4Momentum().mag()<<" Pz "
125 <<theString.Get4Momentum().pz()
126 <<"------------------------------------"<<G4endl;
127 G4cout<<"String ends Direct "<<theString.GetLeftParton()->GetPDGcode()<<" "
128 <<theString.GetRightParton()->GetPDGcode()<<" "
129 <<theString.GetDirection()<< G4endl;
130 G4cout<<"Left mom "<<theString.GetLeftParton()->Get4Momentum()<<G4endl;
131 G4cout<<"Right mom "<<theString.GetRightParton()->Get4Momentum()<<G4endl;
132 G4cout<<"Check for Fragmentation "<<G4endl;
133 #endif
134
135 // Can no longer modify Parameters for Fragmentation.
136 PastInitPhase=true;
137
138 // Check if string has enough mass to fragment...
139 G4KineticTrackVector * LeftVector=NULL;
140
141 if ( !IsItFragmentable(&aString) ) {
142 LeftVector=ProduceOneHadron(&theString);
143
144 #ifdef debug_QGSMfragmentation
145 if ( LeftVector != 0 ) G4cout<<"Non fragmentable - the string is converted to one hadron "<<G4endl;
146 #endif
147
148 if ( LeftVector == nullptr ) LeftVector = new G4KineticTrackVector;
149 return LeftVector;
150 }
151
152 #ifdef debug_QGSMfragmentation
153 G4cout<<"The string will be fragmented. "<<G4endl;
154 #endif
155
156 LeftVector = new G4KineticTrackVector;
158
159 G4ExcitedString *theStringInCMS=CopyExcited(theString);
160 G4LorentzRotation toCms=theStringInCMS->TransformToAlignedCms();
161
162 G4bool success=false, inner_sucess=true;
163 G4int attempt=0;
164 while ( !success && attempt++ < StringLoopInterrupt ) /* Loop checking, 07.08.2015, A.Ribon */
165 {
166 #ifdef debug_QGSMfragmentation
167 G4cout<<"Loop_toFrag "<<theStringInCMS->GetLeftParton()->GetPDGcode()<<" "
168 <<theStringInCMS->GetRightParton()->GetPDGcode()<<" "
169 <<theStringInCMS->GetDirection()<< G4endl;
170 #endif
171
172 G4FragmentingString *currentString=new G4FragmentingString(*theStringInCMS);
173
174 std::for_each(LeftVector->begin(), LeftVector->end(), DeleteKineticTrack());
175 LeftVector->clear();
176 std::for_each(RightVector->begin(), RightVector->end(), DeleteKineticTrack());
177 RightVector->clear();
178
179 inner_sucess=true; // set false on failure..
180 const G4int maxNumberOfLoops = 1000;
181 G4int loopCounter = -1;
182 while (! StopFragmenting(currentString) && ++loopCounter < maxNumberOfLoops ) /* Loop checking, 07.08.2015, A.Ribon */
183 { // Split current string into hadron + new string
184
185 #ifdef debug_QGSMfragmentation
186 G4cout<<"The string can fragment. "<<G4endl;;
187 #endif
188 G4FragmentingString *newString=0; // used as output from SplitUp...
189 G4KineticTrack * Hadron=Splitup(currentString,newString);
190
191 if ( Hadron != 0 )
192 {
193 #ifdef debug_QGSMfragmentation
194 G4cout<<"Hadron prod at fragm. "<<Hadron->GetDefinition()->GetParticleName()<<G4endl;
195 #endif
196 // To close the production of hadrons at fragmentation stage
197 if ( currentString->GetDecayDirection() > 0 )
198 LeftVector->push_back(Hadron);
199 else
200 RightVector->push_back(Hadron);
201
202 delete currentString;
203 currentString=newString;
204
205 } else {
206
207 #ifdef debug_QGSMfragmentation
208 G4cout<<"abandon ... start from the beginning ---------------"<<G4endl;
209 #endif
210
211 // Abandon ... start from the beginning
212 if (newString) delete newString;
213 inner_sucess=false;
214 break;
215 }
216 }
217 if ( loopCounter >= maxNumberOfLoops ) {
218 inner_sucess=false;
219 }
220
221 // Split current string into 2 final Hadrons
222 #ifdef debug_QGSMfragmentation
223 if( inner_sucess ) { // Uzhi June 2020
224 G4cout<<"Split remaining string into 2 final hadrons."<<G4endl;
225 } else {
226 G4cout<<" New attempt to fragment string"<<G4endl;
227 } // Uzhi June 2020
228 #endif
229 // To the close production of hadrons at last string decay
230 if ( inner_sucess &&
231 SplitLast(currentString,LeftVector, RightVector) )
232 {
233 success=true;
234 }
235 delete currentString;
236 }
237
238 delete theStringInCMS;
239
240 if ( ! success )
241 {
242 std::for_each(LeftVector->begin(), LeftVector->end(), DeleteKineticTrack());
243 LeftVector->clear();
244 std::for_each(RightVector->begin(), RightVector->end(), DeleteKineticTrack());
245 delete RightVector;
246 return LeftVector;
247 }
248
249 // Join Left- and RightVector into LeftVector in correct order.
250 while(!RightVector->empty()) /* Loop checking, 07.08.2015, A.Ribon */
251 {
252 LeftVector->push_back(RightVector->back());
253 RightVector->erase(RightVector->end()-1);
254 }
255 delete RightVector;
256
257 CalculateHadronTimePosition(theString.Get4Momentum().mag(), LeftVector);
258
259 G4LorentzRotation toObserverFrame(toCms.inverse());
260
261 for (size_t C1 = 0; C1 < LeftVector->size(); C1++)
262 {
263 G4KineticTrack* Hadron = LeftVector->operator[](C1);
264 G4LorentzVector Momentum = Hadron->Get4Momentum();
265 Momentum = toObserverFrame*Momentum;
266 Hadron->Set4Momentum(Momentum);
267 G4LorentzVector Coordinate(Hadron->GetPosition(), Hadron->GetFormationTime());
268 Momentum = toObserverFrame*Coordinate;
269 Hadron->SetFormationTime(Momentum.e());
270 G4ThreeVector aPosition(Momentum.vect());
271 Hadron->SetPosition(theString.GetPosition()+aPosition);
272 }
273 return LeftVector;
274}
275
276//----------------------------------------------------------------------------------------------------------
277
278G4bool G4QGSMFragmentation::IsItFragmentable(const G4FragmentingString * string)
279{
280 //Uzhi June 2020 return sqr( PossibleHadronMass(string) + MassCut ) < string->Mass2();
281 return sqr( MinimalStringMass + MassCut ) < string->Mass2(); // Uzhi June 2020
282}
283
284//----------------------------------------------------------------------------------------------------------
285
286G4bool G4QGSMFragmentation::StopFragmenting(const G4FragmentingString * string)
287{
288 SetMinimalStringMass(string);
289 if ( MinimalStringMass < 0.0 ) return true;
290
291 G4double smass = string->Mass();
292 G4double x = (string->IsAFourQuarkString()) ? 0.005*(smass - MinimalStringMass)
293 : 0.66e-6*(smass - MinimalStringMass)*(smass + MinimalStringMass);
294
295 G4bool res = true;
296 if(x > 0.0) {
297 res = (x < 200.) ? (G4UniformRand() < G4Exp(-x)) : false;
298 }
299 return res;
300}
301
302//-----------------------------------------------------------------------------
303
304G4KineticTrack * G4QGSMFragmentation::Splitup( G4FragmentingString *string,
305 G4FragmentingString *&newString )
306{
307 #ifdef debug_QGSMfragmentation
308 G4cout<<G4endl;
309 G4cout<<"Start SplitUP (G4VLongitudinalStringDecay) ========================="<<G4endl;
310 G4cout<<"String partons: " <<string->GetLeftParton()->GetPDGEncoding()<<" "
311 <<string->GetRightParton()->GetPDGEncoding()<<" "
312 <<"Direction " <<string->GetDecayDirection()<<G4endl;
313 #endif
314
315 //... random choice of string end to use for creating the hadron (decay)
316 G4int SideOfDecay = (G4UniformRand() < 0.5)? 1: -1;
317 if (SideOfDecay < 0)
318 {
319 string->SetLeftPartonStable();
320 } else
321 {
322 string->SetRightPartonStable();
323 }
324
325 G4ParticleDefinition *newStringEnd;
326 G4ParticleDefinition * HadronDefinition;
327 if (string->DecayIsQuark())
328 {
329 G4double ProbDqADq = GetDiquarkSuppress();
330
331 G4int NumberOfpossibleBaryons = 2;
332
333 if (string->GetLeftParton()->GetParticleSubType() != "quark") NumberOfpossibleBaryons++;
334 if (string->GetRightParton()->GetParticleSubType() != "quark") NumberOfpossibleBaryons++;
335
336 G4double ActualProb = ProbDqADq ;
337 ActualProb *= (1.0-G4Exp(2.0*(1.0 - string->Mass()/(NumberOfpossibleBaryons*1400.0))));
338
339 SetDiquarkSuppression(ActualProb);
340
341 HadronDefinition= QuarkSplitup(string->GetDecayParton(), newStringEnd);
342
343 SetDiquarkSuppression(ProbDqADq);
344 } else {
345 HadronDefinition= DiQuarkSplitup(string->GetDecayParton(), newStringEnd);
346 }
347
348 if ( HadronDefinition == NULL ) return NULL;
349
350 #ifdef debug_QGSMfragmentation
351 G4cout<<"The parton "<<string->GetDecayParton()->GetPDGEncoding()<<" "
352 <<" produces hadron "<<HadronDefinition->GetParticleName()
353 <<" and is transformed to "<<newStringEnd->GetPDGEncoding()<<G4endl;
354 G4cout<<"The side of the string decay Left/Right (1/-1) "<<SideOfDecay<<G4endl;
355 #endif
356 // create new String from old, ie. keep Left and Right order, but replace decay
357
358 newString=new G4FragmentingString(*string,newStringEnd); // To store possible
359 // quark containt of new string
360
361 #ifdef debug_QGSMfragmentation
362 G4cout<<"An attempt to determine its energy (SplitEandP)"<<G4endl;
363 #endif
364 G4LorentzVector* HadronMomentum=SplitEandP(HadronDefinition, string, newString);
365
366 delete newString; newString=0;
367
368 G4KineticTrack * Hadron =0;
369 if ( HadronMomentum != 0 ) {
370
371 #ifdef debug_QGSMfragmentation
372 G4cout<<"The attempt was successful"<<G4endl;
373 #endif
375 Hadron = new G4KineticTrack(HadronDefinition, 0,Pos, *HadronMomentum);
376
377 newString=new G4FragmentingString(*string,newStringEnd,HadronMomentum);
378
379 delete HadronMomentum;
380 }
381 else
382 {
383 #ifdef debug_QGSMfragmentation
384 G4cout<<"The attempt was not successful !!!"<<G4endl;
385 #endif
386 }
387
388 #ifdef debug_VStringDecay
389 G4cout<<"End SplitUP (G4VLongitudinalStringDecay) ====================="<<G4endl;
390 #endif
391
392 return Hadron;
393}
394
395//-----------------------------------------------------------------------------
396
397G4ParticleDefinition *G4QGSMFragmentation::DiQuarkSplitup( G4ParticleDefinition* decay,
398 G4ParticleDefinition *&created )
399{
400 //... can Diquark break or not?
401 if (G4UniformRand() < DiquarkBreakProb ) //... Diquark break
402 {
403 G4int stableQuarkEncoding = decay->GetPDGEncoding()/1000;
404 G4int decayQuarkEncoding = (decay->GetPDGEncoding()/100)%10;
405
406 if (G4UniformRand() < 0.5)
407 {
408 G4int Swap = stableQuarkEncoding;
409 stableQuarkEncoding = decayQuarkEncoding;
410 decayQuarkEncoding = Swap;
411 }
412
413 G4int IsParticle=(decayQuarkEncoding>0) ? -1 : +1; // if we have a quark, we need antiquark
414
416 SetStrangenessSuppression((1.0 - 0.07)/2.); // Prob qq->K qq' 0.07
417 pDefPair QuarkPair = CreatePartonPair(IsParticle,false); // no diquarks wanted
419
420 //... Build new Diquark
421 G4int QuarkEncoding=QuarkPair.second->GetPDGEncoding();
422 G4int i10 = std::max(std::abs(QuarkEncoding), std::abs(stableQuarkEncoding));
423 G4int i20 = std::min(std::abs(QuarkEncoding), std::abs(stableQuarkEncoding));
424 G4int spin = (i10 != i20 && G4UniformRand() <= 0.5)? 1 : 3;
425 G4int NewDecayEncoding = -1*IsParticle*(i10 * 1000 + i20 * 100 + spin);
426
427 created = FindParticle(NewDecayEncoding);
428 G4ParticleDefinition * decayQuark=FindParticle(decayQuarkEncoding);
429 G4ParticleDefinition * had=hadronizer->Build(QuarkPair.first, decayQuark);
430
431 DecayQuark = decay->GetPDGEncoding(); //Uzhi June 2020 decayQuarkEncoding;
432 NewQuark = NewDecayEncoding; //Uzhi June 2020 QuarkPair.first->GetPDGEncoding();
433
434 return had;
435
436 } else { //... Diquark does not break
437
438 G4int IsParticle=(decay->GetPDGEncoding()>0) ? +1 : -1; // if we have a diquark, we need quark)
439 G4double StrSup=GetStrangeSuppress(); // for changing s-sbar production
440 SetStrangenessSuppression((1.0 - 0.07)/2.);
441 pDefPair QuarkPair = CreatePartonPair(IsParticle,false); // no diquarks wanted
443
444 created = QuarkPair.second;
445
446 DecayQuark = decay->GetPDGEncoding();
447 NewQuark = created->GetPDGEncoding();
448
449 G4ParticleDefinition * had=hadronizer->Build(QuarkPair.first, decay);
450 return had;
451 }
452}
453
454//-----------------------------------------------------------------------------------------
455
456G4LorentzVector * G4QGSMFragmentation::SplitEandP(G4ParticleDefinition * pHadron,
457 G4FragmentingString * string,
459{
460 G4double HadronMass = pHadron->GetPDGMass();
461
463
464 if ( MinimalStringMass < 0.0 ) return nullptr;
465
466 #ifdef debug_QGSMfragmentation
467 G4cout<<"G4QGSMFragmentation::SplitEandP "<<pHadron->GetParticleName()<<G4endl;
468 G4cout<<"String 4 mom, String M "<<string->Get4Momentum()<<" "<<string->Mass()<<G4endl;
469 G4cout<<"HadM MinimalStringMassLeft StringM hM+sM "<<HadronMass<<" "<<MinimalStringMass<<" "
470 <<string->Mass()<<" "<<HadronMass+MinimalStringMass<<G4endl;
471 #endif
472
473 if (HadronMass + MinimalStringMass > string->Mass())
474 {
475 #ifdef debug_QGSMfragmentation
476 G4cout<<"Mass of the string is not sufficient to produce the hadron!"<<G4endl;
477 #endif
478 return 0;
479 } // have to start all over!
480
481 // calculate and assign hadron transverse momentum component HadronPx andHadronPy
482 G4double StringMT2 = string->MassT2();
483 G4double StringMT = std::sqrt(StringMT2);
484
485 G4LorentzVector String4Momentum = string->Get4Momentum();
486 String4Momentum.setPz(0.);
487 G4ThreeVector StringPt = String4Momentum.vect();
488
489 G4ThreeVector HadronPt , RemSysPt;
490 G4double HadronMassT2, ResidualMassT2;
491
492 //Uzhi June 2020 Mt distribution is implemented
493 G4double HadronMt, Pt, Pt2, phi; // Uzhi June 2020
494
495 //... sample Pt of the hadron
496 G4int attempt=0;
497 do
498 {
499 attempt++; if (attempt > StringLoopInterrupt) return 0;
500
501 HadronMt = HadronMass - 200.0*G4Log(G4UniformRand()); // Uzhi June 2020, 200.0 must be tuned
502 Pt2 = sqr(HadronMt)-sqr(HadronMass); Pt=std::sqrt(Pt2); // Uzhi June 2020
503 phi = 2.*pi*G4UniformRand();
504 G4ThreeVector SampleQuarkPtw= G4ThreeVector(Pt*std::cos(phi), Pt*std::sin(phi), 0);
505 HadronPt =SampleQuarkPtw + string->DecayPt(); // Uzhi June 2020
506 //Uzhi June 2020 HadronPt =SampleQuarkPt() + string->DecayPt(); // Save this for possible return
507 HadronPt.setZ(0);
508 RemSysPt = StringPt - HadronPt;
509
510 HadronMassT2 = sqr(HadronMass) + HadronPt.mag2();
511 ResidualMassT2=sqr(MinimalStringMass) + RemSysPt.mag2();
512
513 } while (std::sqrt(HadronMassT2) + std::sqrt(ResidualMassT2) > StringMT); /* Loop checking, 07.08.2015, A.Ribon */
514
515 //... sample z to define hadron longitudinal momentum and energy
516 //... but first check the available phase space
517
518 G4double Pz2 = (sqr(StringMT2 - HadronMassT2 - ResidualMassT2) -
519 4*HadronMassT2 * ResidualMassT2)/4./StringMT2;
520
521 if ( Pz2 < 0 ) {return 0;} // have to start all over!
522
523 //... then compute allowed z region z_min <= z <= z_max
524
525 G4double Pz = std::sqrt(Pz2);
526 G4double zMin = (std::sqrt(HadronMassT2+Pz2) - Pz)/std::sqrt(StringMT2);
527 G4double zMax = (std::sqrt(HadronMassT2+Pz2) + Pz)/std::sqrt(StringMT2);
528
529 if (zMin >= zMax) return 0; // have to start all over!
530
531 G4double z = GetLightConeZ(zMin, zMax,
532 string->GetDecayParton()->GetPDGEncoding(), pHadron,
533 HadronPt.x(), HadronPt.y());
534
535 //... now compute hadron longitudinal momentum and energy
536 // longitudinal hadron momentum component HadronPz
537
538 HadronPt.setZ( 0.5* string->GetDecayDirection() *
539 (z * string->LightConeDecay() -
540 HadronMassT2/(z * string->LightConeDecay())) );
541 G4double HadronE = 0.5* (z * string->LightConeDecay() +
542 HadronMassT2/(z * string->LightConeDecay()) );
543
544 G4LorentzVector * a4Momentum= new G4LorentzVector(HadronPt,HadronE);
545
546 #ifdef debug_QGSMfragmentation
547 G4cout<<"string->GetDecayDirection() string->LightConeDecay() "
548 <<string->GetDecayDirection()<<" "<<string->LightConeDecay()<<G4endl;
549 G4cout<<"HadronPt,HadronE "<<HadronPt<<" "<<HadronE<<G4endl;
550 G4cout<<"Out of QGSM SplitEandP "<<G4endl;
551 #endif
552
553 return a4Momentum;
554}
555
556//----------------------------------------------------------------------------------------------------------
557
558G4double G4QGSMFragmentation::GetLightConeZ(G4double zmin, G4double zmax, G4int /* PartonEncoding */ ,
559 G4ParticleDefinition* /* pHadron */, G4double ptx , G4double pty)
560{
561 G4double lambda = 2.0*(sqr(ptx)+sqr(pty))/sqr(GeV); // Uzhi June 2020
562
563 #ifdef debug_QGSMfragmentation
564 G4cout<<"GetLightConeZ zmin zmax Parton pHadron "<<zmin<<" "<<zmax<<" "/*<< PartonEncoding */
565 <<" "/*<< pHadron->GetParticleName() */ <<G4endl;
566 #endif
567
568 G4double z(0.);
569 G4int DiQold(0), DiQnew(0);
570 G4double d1(-1.0), d2(0.);
571 G4double invD1(0.),invD2(0.), r1(0.),r2(0.),r12(0.);
572
573 G4int absDecayQuarkCode = std::abs( DecayQuark );
574 G4int absNewQuarkCode = std::abs( NewQuark );
575
576 G4int q1(0), q2(0);
577 // q1 = absDecayQuarkCode/1000; q2 = (absDecayQuarkCode % 1000)/100;
578
579 G4int qA(0), qB(0);
580 // qA = absNewQuarkCode/1000; qB = (absNewQuarkCode % 1000)/100;
581
582 if ( (absDecayQuarkCode < 6) && (absNewQuarkCode < 6) ) {
583 d1 = FFq2q[absDecayQuarkCode-1][absNewQuarkCode-1][0]; d2 = FFq2q[absDecayQuarkCode-1][absNewQuarkCode-1][1];
584 }
585
586 if ( (absDecayQuarkCode < 6) && (absNewQuarkCode > 6) ) {
587 qA = absNewQuarkCode/1000; qB = (absNewQuarkCode % 1000)/100; DiQnew = IndexDiQ[qA-1][qB-1];
588 d1 = FFq2qq[absDecayQuarkCode-1][DiQnew][0]; d2 = FFq2q[absDecayQuarkCode-1][DiQnew][1];
589 }
590
591 if ( (absDecayQuarkCode > 6) && (absNewQuarkCode < 6) ) {
592 q1 = absDecayQuarkCode/1000; q2 = (absDecayQuarkCode % 1000)/100; DiQold = IndexDiQ[q1-1][q2-1];
593 d1 = FFqq2q[DiQold][absNewQuarkCode-1][0]; d2 = FFqq2q[DiQold][absNewQuarkCode-1][1];
594 }
595
596 if ( d1 < 0. ) {
597 q1 = absDecayQuarkCode/1000; q2 = (absDecayQuarkCode % 1000)/100; DiQold = IndexDiQ[q1-1][q2-1];
598 d1 = FFqq2qq[DiQold][absNewQuarkCode-1][0]; d2 = FFqq2qq[DiQold][absNewQuarkCode-1][1];
599 }
600
601 d2 +=lambda; // Uzhi June 2020
602 d1+=1.0; d2+=1.0;
603
604 invD1=1./d1; invD2=1./d2;
605
606 const G4int maxNumberOfLoops = 10000;
607 G4int loopCounter = 0;
608 do // Jong's algorithm
609 {
612 r12=r1+r2;
613 z=r1/r12;
614 } while ( ( (r12 > 1.0) || !((zmin <= z)&&(z <= zmax))) &&
615 ++loopCounter < maxNumberOfLoops ); /* Loop checking, 07.08.2015, A.Ribon */
616
617 if ( loopCounter >= maxNumberOfLoops ) {
618 z = 0.5*(zmin + zmax); // Just a value between zmin and zmax, no physics considerations at all!
619 }
620
621 return z;
622}
623
624//-----------------------------------------------------------------------------------------
625
626G4bool G4QGSMFragmentation::SplitLast(G4FragmentingString * string,
627 G4KineticTrackVector * LeftVector,
628 G4KineticTrackVector * RightVector)
629{
630 //... perform last cluster decay
631
632 G4ThreeVector ClusterVel =string->Get4Momentum().boostVector();
633 G4double ResidualMass =string->Mass();
634
635 #ifdef debug_QGSMfragmentation
636 G4cout<<"Split last-----------------------------------------"<<G4endl;
637 G4cout<<"StrMass "<<ResidualMass<<" q's "
638 <<string->GetLeftParton()->GetParticleName()<<" "
639 <<string->GetRightParton()->GetParticleName()<<G4endl;
640 #endif
641
642 G4int cClusterInterrupt = 0;
643 G4ParticleDefinition *LeftHadron = nullptr;
644 G4ParticleDefinition *RightHadron = nullptr;
645 const G4int maxNumberOfLoops = 1000;
646 G4int loopCounter = 0;
647
648 G4double LeftHadronMass(0.); G4double RightHadronMass(0.);
649 do
650 {
651 if (cClusterInterrupt++ >= ClusterLoopInterrupt) return false; // Uzhi June 2020
652 LeftHadronMass = -MaxMass; RightHadronMass = -MaxMass;
653
654 G4ParticleDefinition * quark = nullptr;
655 string->SetLeftPartonStable(); // to query quark contents..
656
657 if (string->DecayIsQuark() && string->StableIsQuark() )
658 {
659 //... there are quarks on cluster ends
660
661 G4int IsParticle=(string->GetLeftParton()->GetPDGEncoding()>0) ? -1 : +1;
662 // if we have a quark, we need antiquark or diquark
663
664 pDefPair QuarkPair = CreatePartonPair(IsParticle);
665 quark = QuarkPair.second;
666
667 LeftHadron= hadronizer->BuildLowSpin(QuarkPair.first, string->GetLeftParton());
668 if ( LeftHadron == NULL ) continue; // Uzhi June 2020
669 RightHadron = hadronizer->BuildLowSpin(string->GetRightParton(), quark); // Uzhi June 2020
670 if ( RightHadron == NULL ) continue; // Uzhi June 2020
671 } else if( (!string->DecayIsQuark() && string->StableIsQuark() ) || // Uzhi June 2020
672 ( string->DecayIsQuark() && !string->StableIsQuark() ) ) { // Uzhi June 2020
673 //... there is a Diquark on one of cluster ends
674 G4int IsParticle;
675 if ( string->StableIsQuark() ) {
676 IsParticle=(string->GetLeftParton()->GetPDGEncoding()>0) ? -1 : +1;
677 } else {
678 IsParticle=(string->GetLeftParton()->GetPDGEncoding()>0) ? +1 : -1;
679 }
680
681 //G4double ProbSaS = 1.0 - 2.0 * GetStrangeSuppress();
682 //G4double ActualProb = ProbSaS * 1.4;
683 //SetStrangenessSuppression((1.0-ActualProb)/2.0);
684
685 pDefPair QuarkPair = CreatePartonPair(IsParticle,false); // no diquarks wanted
686 //SetStrangenessSuppression((1.0-ProbSaS)/2.0);
687 quark = QuarkPair.second;
688 LeftHadron=hadronizer->BuildLowSpin(QuarkPair.first, string->GetLeftParton());
689 if ( LeftHadron == NULL ) continue; // Uzhi June 2020
690 RightHadron = hadronizer->BuildLowSpin(string->GetRightParton(), quark); // Uzhi June 2020
691 if ( RightHadron == NULL ) continue; // Uzhi June 2020
692 } else { // Diquark and anti-diquark are on the string ends // Uzhi June 2020
693 //+++++++++++++++++++++++++++++++ Inserted from FTF // Uzhi June 2020
694 // Uzhi G4double StringMass = string->Mass();
695 if (cClusterInterrupt++ >= ClusterLoopInterrupt) return false;
696 G4int LeftQuark1= string->GetLeftParton()->GetPDGEncoding()/1000;
697 G4int LeftQuark2=(string->GetLeftParton()->GetPDGEncoding()/100)%10;
698 G4int RightQuark1= string->GetRightParton()->GetPDGEncoding()/1000;
699 G4int RightQuark2=(string->GetRightParton()->GetPDGEncoding()/100)%10;
700 if (G4UniformRand()<0.5) {
701 LeftHadron =hadronizer->Build(FindParticle( LeftQuark1), FindParticle(RightQuark1));
702 RightHadron =hadronizer->Build(FindParticle( LeftQuark2), FindParticle(RightQuark2));
703 } else {
704 LeftHadron =hadronizer->Build(FindParticle( LeftQuark1), FindParticle(RightQuark2));
705 RightHadron =hadronizer->Build(FindParticle( LeftQuark2), FindParticle(RightQuark1));
706 }
707 if ( (LeftHadron == NULL) || (RightHadron == NULL) ) continue;
708 // End of inserting from FTF Uzhi June 2020
709 }
710 LeftHadronMass = LeftHadron->GetPDGMass();
711 RightHadronMass = RightHadron->GetPDGMass();
712 //... repeat procedure, if mass of cluster is too low to produce hadrons
713 } while ( ( ResidualMass <= LeftHadronMass + RightHadronMass )
714 && ++loopCounter < maxNumberOfLoops ); /* Loop checking, 07.08.2015, A.Ribon */
715
716 if ( loopCounter >= maxNumberOfLoops ) {
717 return false;
718 }
719
720 //... compute hadron momenta and energies
721 G4LorentzVector LeftMom, RightMom;
723 Sample4Momentum(&LeftMom , LeftHadron->GetPDGMass() ,
724 &RightMom, RightHadron->GetPDGMass(), ResidualMass);
725 LeftMom.boost(ClusterVel);
726 RightMom.boost(ClusterVel);
727
728 #ifdef debug_QGSMfragmentation
729 G4cout<<LeftHadron->GetParticleName()<<" "<<RightHadron->GetParticleName()<<G4endl;
730 G4cout<<"Left Hadrom P M "<<LeftMom<<" "<<LeftMom.mag()<<G4endl;
731 G4cout<<"Right Hadrom P M "<<RightMom<<" "<<RightMom.mag()<<G4endl;
732 #endif
733
734 LeftVector->push_back(new G4KineticTrack(LeftHadron, 0, Pos, LeftMom));
735 RightVector->push_back(new G4KineticTrack(RightHadron, 0, Pos, RightMom));
736
737 return true;
738}
739
740//----------------------------------------------------------------------------------------------------------
741
742void G4QGSMFragmentation::Sample4Momentum(G4LorentzVector* Mom , G4double Mass ,
743 G4LorentzVector* AntiMom, G4double AntiMass, G4double InitialMass)
744{
745 #ifdef debug_QGSMfragmentation // Uzhi June 2020
746 G4cout<<"Sample4Momentum Last-----------------------------------------"<<G4endl;
747 G4cout<<" StrMass "<<InitialMass<<" Mass1 "<<Mass<<" Mass2 "<<AntiMass<<G4endl;
748 G4cout<<" SumMass "<<Mass+AntiMass<<G4endl;
749 #endif
750
751 G4double r_val = sqr(InitialMass*InitialMass - Mass*Mass - AntiMass*AntiMass) - sqr(2.*Mass*AntiMass);
752 G4double Pabs = (r_val > 0.)? std::sqrt(r_val)/(2.*InitialMass) : 0;
753
754 //... sample unit vector
755 G4double pz = 1. - 2.*G4UniformRand();
756 G4double st = std::sqrt(1. - pz * pz)*Pabs;
757 G4double phi = 2.*pi*G4UniformRand();
758 G4double px = st*std::cos(phi);
759 G4double py = st*std::sin(phi);
760 pz *= Pabs;
761
762 Mom->setPx(px); Mom->setPy(py); Mom->setPz(pz);
763 Mom->setE(std::sqrt(Pabs*Pabs + Mass*Mass));
764
765 AntiMom->setPx(-px); AntiMom->setPy(-py); AntiMom->setPz(-pz);
766 AntiMom->setE (std::sqrt(Pabs*Pabs + AntiMass*AntiMass));
767}
768
769//----------------------------------------------------------------------------------------------------------
770
771void G4QGSMFragmentation::SetFFq2q() // q-> q' + Meson (q anti q')
772{
773 for (G4int i=0; i < 5; i++) {
774 FFq2q[i][0][0] = 2.0 ; FFq2q[i][0][1] = -arho + alft; // q->d + (q dbar) Pi0, Eta, Eta', Rho0, omega
775 FFq2q[i][1][0] = 2.0 ; FFq2q[i][1][1] = -arho + alft; // q->u + (q ubar) Pi-, Rho-
776 FFq2q[i][2][0] = 1.0 ; FFq2q[i][2][1] = -aphi + alft; // q->s + (q sbar) K0, K*0
777 FFq2q[i][3][0] = 1.0 ; FFq2q[i][3][1] = -aJPs + alft; // q->c + (q+cbar) D-, D*-
778 FFq2q[i][4][0] = 1.0 ; FFq2q[i][4][1] = -aUps + alft; // q->b + (q bbar) EtaB, Upsilon
779 }
780}
781
782//----------------------------------------------------------------------------------------------------------
783
784void G4QGSMFragmentation::SetFFq2qq() // q-> anti (q1'q2') + Baryon (q + q1 + q2)
785{
786 for (G4int i=0; i < 5; i++) {
787 FFq2qq[i][ 0][0] = 0.0 ; FFq2qq[i][ 0][1] = arho - 2.0*an + alft; // q->dd bar + (q dd)
788 FFq2qq[i][ 1][0] = 0.0 ; FFq2qq[i][ 1][1] = arho - 2.0*an + alft; // q->ud bar + (q ud)
789 FFq2qq[i][ 2][0] = 0.0 ; FFq2qq[i][ 2][1] = arho - 2.0*ala + alft; // q->sd bar + (q sd)
790 FFq2qq[i][ 3][0] = 0.0 ; FFq2qq[i][ 3][1] = arho - 2.0*alaC + alft; // q->cd bar + (q cd)
791 FFq2qq[i][ 4][0] = 0.0 ; FFq2qq[i][ 4][1] = arho - 2.0*alaB + alft; // q->bd bar + (q bd)
792 FFq2qq[i][ 5][0] = 0.0 ; FFq2qq[i][ 5][1] = arho - 2.0*an + alft; // q->uu bar + (q uu)
793 FFq2qq[i][ 6][0] = 0.0 ; FFq2qq[i][ 6][1] = arho - 2.0*ala + alft; // q->su bar + (q su)
794 FFq2qq[i][ 7][0] = 0.0 ; FFq2qq[i][ 7][1] = arho - 2.0*alaC + alft; // q->cu bar + (q cu)
795 FFq2qq[i][ 8][0] = 0.0 ; FFq2qq[i][ 8][1] = arho - 2.0*alaB + alft; // q->bu bar + (q bu)
796 FFq2qq[i][ 9][0] = 0.0 ; FFq2qq[i][ 9][1] = arho - 2.0*aXi + alft; // q->ss bar + (q ss)
797 FFq2qq[i][10][0] = 0.0 ; FFq2qq[i][10][1] = arho - 2.0*aXiC + alft; // q->cs bar + (q cs)
798 FFq2qq[i][11][0] = 0.0 ; FFq2qq[i][11][1] = arho - 2.0*aXiB + alft; // q->bs bar + (q bc)
799 FFq2qq[i][12][0] = 0.0 ; FFq2qq[i][12][1] = arho - 2.0*aXiCC + alft; // q->cc bar + (q cc)
800 FFq2qq[i][13][0] = 0.0 ; FFq2qq[i][13][1] = arho - 2.0*aXiCB + alft; // q->bc bar + (q bc)
801 FFq2qq[i][14][0] = 0.0 ; FFq2qq[i][14][1] = arho - 2.0*aXiBB + alft; // q->bb bar + (q bb)
802 }
803}
804
805//----------------------------------------------------------------------------------------------------------
806
807void G4QGSMFragmentation::SetFFqq2q() // q1q2-> anti(q') + Baryon (q1 + q2 + q')
808{
809 for (G4int i=0; i < 15; i++) {
810 FFqq2q[i][0][0] = 2.0*(arho - an); FFqq2q[i][0][1] = -arho + alft;
811 FFqq2q[i][1][0] = 2.0*(arho - an); FFqq2q[i][1][1] = -arho + alft;
812 FFqq2q[i][2][0] = 2.0*(arho - an); FFqq2q[i][2][1] = -aphi + alft;
813 FFqq2q[i][3][0] = 2.0*(arho - an); FFqq2q[i][3][1] = -aJPs + alft;
814 FFqq2q[i][4][0] = 2.0*(arho - an); FFqq2q[i][4][1] = -aUps + alft;
815 }
816}
817
818//----------------------------------------------------------------------------------------------------------
819
820void G4QGSMFragmentation::SetFFqq2qq() // q1(q2)-> q'(q2) + Meson(q1 anti q')
821{
822 for (G4int i=0; i < 15; i++) {
823 FFqq2qq[i][0][0] = 0. ; FFqq2qq[i][0][1] = 2.0*arho - 2.0*an -arho + alft; // dd -> dd + Pi0 (d d bar)
824 FFqq2qq[i][1][0] = 0. ; FFqq2qq[i][1][1] = 2.0*arho - 2.0*an -arho + alft; // dd -> ud + Pi- (d u bar)
825 FFqq2qq[i][2][0] = 0. ; FFqq2qq[i][2][1] = 2.0*arho - 2.0*an -aphi + alft; // dd -> sd + K0 (d s bar)
826 FFqq2qq[i][3][0] = 0. ; FFqq2qq[i][3][1] = 2.0*arho - 2.0*an -aJPs + alft; // dd -> cd + D- (d c bar)
827 FFqq2qq[i][4][0] = 0. ; FFqq2qq[i][4][1] = 2.0*arho - 2.0*an -aUps + alft; // dd -> bd + B0 (d b bar)
828 }
829}
830
G4double G4Exp(G4double initial_x)
Exponential Function double precision.
Definition: G4Exp.hh:179
G4double G4Log(G4double x)
Definition: G4Log.hh:226
CLHEP::HepLorentzVector G4LorentzVector
CLHEP::Hep3Vector G4ThreeVector
double G4double
Definition: G4Types.hh:83
bool G4bool
Definition: G4Types.hh:86
int G4int
Definition: G4Types.hh:85
#define NewString(str)
#define G4endl
Definition: G4ios.hh:57
G4GLOB_DLL std::ostream G4cout
#define C1
#define G4UniformRand()
Definition: Randomize.hh:52
double mag2() const
void setZ(double)
HepLorentzRotation inverse() const
HepLorentzVector & boost(double, double, double)
Hep3Vector vect() const
const G4ThreeVector & GetPosition() const
G4int GetDirection(void) const
G4LorentzRotation TransformToAlignedCms()
G4Parton * GetRightParton(void) const
G4Parton * GetLeftParton(void) const
G4LorentzVector Get4Momentum() const
G4ParticleDefinition * GetLeftParton(void) const
G4ParticleDefinition * GetRightParton(void) const
G4ParticleDefinition * GetDecayParton() const
G4int GetDecayDirection() const
G4ParticleDefinition * Build(G4ParticleDefinition *black, G4ParticleDefinition *white)
G4ParticleDefinition * BuildLowSpin(G4ParticleDefinition *black, G4ParticleDefinition *white)
static G4HadronicParameters * Instance()
G4double GetFormationTime() const
void SetPosition(const G4ThreeVector aPosition)
void Set4Momentum(const G4LorentzVector &a4Momentum)
const G4ThreeVector & GetPosition() const
const G4ParticleDefinition * GetDefinition() const
void SetFormationTime(G4double aFormationTime)
const G4LorentzVector & Get4Momentum() const
const G4String & GetParticleName() const
const G4String & GetParticleSubType() const
G4int GetPDGcode() const
Definition: G4Parton.hh:127
const G4LorentzVector & Get4Momentum() const
Definition: G4Parton.hh:143
static G4Pow * GetInstance()
Definition: G4Pow.cc:41
G4double powA(G4double A, G4double y) const
Definition: G4Pow.hh:230
virtual G4KineticTrackVector * FragmentString(const G4ExcitedString &theString)
std::pair< G4ParticleDefinition *, G4ParticleDefinition * > pDefPair
G4ParticleDefinition * FindParticle(G4int Encoding)
G4KineticTrackVector * ProduceOneHadron(const G4ExcitedString *const theString)
virtual G4ParticleDefinition * QuarkSplitup(G4ParticleDefinition *decay, G4ParticleDefinition *&created)
void SetDiquarkSuppression(G4double aValue)
void SetStrangenessSuppression(G4double aValue)
void SetDiquarkBreakProbability(G4double aValue)
pDefPair CreatePartonPair(G4int NeedParticle, G4bool AllowDiquarks=true)
void CalculateHadronTimePosition(G4double theInitialStringMass, G4KineticTrackVector *)
void SetMinimalStringMass(const G4FragmentingString *const string)
G4ExcitedString * CopyExcited(const G4ExcitedString &string)
ush Pos
Definition: deflate.h:91
ParticleList decay(Cluster *const c)
Carries out a cluster decay.
const G4double pi
T sqr(const T &x)
Definition: templates.hh:128