Geant4 11.1.1
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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;
52
53 MassCut = 0.35*GeV;
54
55 SetStrangenessSuppression((1.0 - 0.16)/2.);
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.0002); // According to O.I. Piskunova Yad. Fiz. 56 (1993) 1094; tuned by Uzhi Oct. 2022
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
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 ) {
224 G4cout<<"Split remaining string into 2 final hadrons."<<G4endl;
225 } else {
226 G4cout<<" New attempt to fragment string"<<G4endl;
227 }
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 return sqr( MinimalStringMass + MassCut ) < string->Mass2();
281}
282
283//----------------------------------------------------------------------------------------------------------
284
285G4bool G4QGSMFragmentation::StopFragmenting(const G4FragmentingString * string)
286{
287 SetMinimalStringMass(string);
288 if ( MinimalStringMass < 0.0 ) return true;
289
290 G4double smass = string->Mass();
291 G4double x = (string->IsAFourQuarkString()) ? 0.005*(smass - MinimalStringMass)
292 : 0.66e-6*(smass - MinimalStringMass)*(smass + MinimalStringMass);
293
294 G4bool res = true;
295 if(x > 0.0) {
296 res = (x < 200.) ? (G4UniformRand() < G4Exp(-x)) : false;
297 }
298 return res;
299}
300
301//-----------------------------------------------------------------------------
302
303G4KineticTrack * G4QGSMFragmentation::Splitup( G4FragmentingString *string,
304 G4FragmentingString *&newString )
305{
306 #ifdef debug_QGSMfragmentation
307 G4cout<<G4endl;
308 G4cout<<"Start SplitUP (G4VLongitudinalStringDecay) ========================="<<G4endl;
309 G4cout<<"String partons: " <<string->GetLeftParton()->GetPDGEncoding()<<" "
310 <<string->GetRightParton()->GetPDGEncoding()<<" "
311 <<"Direction " <<string->GetDecayDirection()<<G4endl;
312 #endif
313
314 //... random choice of string end to use for creating the hadron (decay)
315 G4int SideOfDecay = (G4UniformRand() < 0.5)? 1: -1;
316 if (SideOfDecay < 0)
317 {
318 string->SetLeftPartonStable();
319 } else
320 {
321 string->SetRightPartonStable();
322 }
323
324 G4ParticleDefinition *newStringEnd;
325 G4ParticleDefinition * HadronDefinition;
326 if (string->DecayIsQuark())
327 {
328 G4double ProbDqADq = GetDiquarkSuppress();
329
330 G4int NumberOfpossibleBaryons = 2;
331
332 if (string->GetLeftParton()->GetParticleSubType() != "quark") NumberOfpossibleBaryons++;
333 if (string->GetRightParton()->GetParticleSubType() != "quark") NumberOfpossibleBaryons++;
334
335 G4double ActualProb = ProbDqADq ;
336 ActualProb *= (1.0-G4Exp(2.0*(1.0 - string->Mass()/(NumberOfpossibleBaryons*1400.0))));
337
338 SetDiquarkSuppression(ActualProb);
339
340 HadronDefinition= QuarkSplitup(string->GetDecayParton(), newStringEnd);
341
342 SetDiquarkSuppression(ProbDqADq);
343 } else {
344 HadronDefinition= DiQuarkSplitup(string->GetDecayParton(), newStringEnd);
345 }
346
347 if ( HadronDefinition == NULL ) return NULL;
348
349 #ifdef debug_QGSMfragmentation
350 G4cout<<"The parton "<<string->GetDecayParton()->GetPDGEncoding()<<" "
351 <<" produces hadron "<<HadronDefinition->GetParticleName()
352 <<" and is transformed to "<<newStringEnd->GetPDGEncoding()<<G4endl;
353 G4cout<<"The side of the string decay Left/Right (1/-1) "<<SideOfDecay<<G4endl;
354 #endif
355 // create new String from old, ie. keep Left and Right order, but replace decay
356
357 newString=new G4FragmentingString(*string,newStringEnd); // To store possible
358 // quark containt of new string
359
360 #ifdef debug_QGSMfragmentation
361 G4cout<<"An attempt to determine its energy (SplitEandP)"<<G4endl;
362 #endif
363 G4LorentzVector* HadronMomentum=SplitEandP(HadronDefinition, string, newString);
364
365 delete newString; newString=0;
366
367 G4KineticTrack * Hadron =0;
368 if ( HadronMomentum != 0 ) {
369
370 #ifdef debug_QGSMfragmentation
371 G4cout<<"The attempt was successful"<<G4endl;
372 #endif
374 Hadron = new G4KineticTrack(HadronDefinition, 0,Pos, *HadronMomentum);
375
376 newString=new G4FragmentingString(*string,newStringEnd,HadronMomentum);
377
378 delete HadronMomentum;
379 }
380 else
381 {
382 #ifdef debug_QGSMfragmentation
383 G4cout<<"The attempt was not successful !!!"<<G4endl;
384 #endif
385 }
386
387 #ifdef debug_VStringDecay
388 G4cout<<"End SplitUP (G4VLongitudinalStringDecay) ====================="<<G4endl;
389 #endif
390
391 return Hadron;
392}
393
394//-----------------------------------------------------------------------------
395
396G4ParticleDefinition *G4QGSMFragmentation::DiQuarkSplitup( G4ParticleDefinition* decay,
397 G4ParticleDefinition *&created )
398{
399 //... can Diquark break or not?
400 if (G4UniformRand() < DiquarkBreakProb ) //... Diquark break
401 {
402 G4int stableQuarkEncoding = decay->GetPDGEncoding()/1000;
403 G4int decayQuarkEncoding = (decay->GetPDGEncoding()/100)%10;
404
405 if (G4UniformRand() < 0.5)
406 {
407 G4int Swap = stableQuarkEncoding;
408 stableQuarkEncoding = decayQuarkEncoding;
409 decayQuarkEncoding = Swap;
410 }
411
412 G4int IsParticle=(decayQuarkEncoding>0) ? -1 : +1; // if we have a quark, we need antiquark
413
415 SetStrangenessSuppression((1.0 - 0.07)/2.); // Prob qq->K qq' 0.07
416 pDefPair QuarkPair = CreatePartonPair(IsParticle,false); // no diquarks wanted
418
419 //... Build new Diquark
420 G4int QuarkEncoding=QuarkPair.second->GetPDGEncoding();
421 G4int i10 = std::max(std::abs(QuarkEncoding), std::abs(stableQuarkEncoding));
422 G4int i20 = std::min(std::abs(QuarkEncoding), std::abs(stableQuarkEncoding));
423 G4int spin = (i10 != i20 && G4UniformRand() <= 0.5)? 1 : 3;
424 G4int NewDecayEncoding = -1*IsParticle*(i10 * 1000 + i20 * 100 + spin);
425
426 created = FindParticle(NewDecayEncoding);
427 G4ParticleDefinition * decayQuark=FindParticle(decayQuarkEncoding);
428 G4ParticleDefinition * had=hadronizer->Build(QuarkPair.first, decayQuark);
429
430 DecayQuark = decay->GetPDGEncoding();
431 NewQuark = NewDecayEncoding;
432
433 return had;
434
435 } else { //... Diquark does not break
436
437 G4int IsParticle=(decay->GetPDGEncoding()>0) ? +1 : -1; // if we have a diquark, we need quark)
438 G4double StrSup=GetStrangeSuppress(); // for changing s-sbar production
439 SetStrangenessSuppression((1.0 - 0.07)/2.);
440 pDefPair QuarkPair = CreatePartonPair(IsParticle,false); // no diquarks wanted
442
443 created = QuarkPair.second;
444
445 DecayQuark = decay->GetPDGEncoding();
446 NewQuark = created->GetPDGEncoding();
447
448 G4ParticleDefinition * had=hadronizer->Build(QuarkPair.first, decay);
449 return had;
450 }
451}
452
453//-----------------------------------------------------------------------------------------
454
455G4LorentzVector * G4QGSMFragmentation::SplitEandP(G4ParticleDefinition * pHadron,
456 G4FragmentingString * string,
458{
459 G4double HadronMass = pHadron->GetPDGMass();
460
462
463 if ( MinimalStringMass < 0.0 ) return nullptr;
464
465 #ifdef debug_QGSMfragmentation
466 G4cout<<"G4QGSMFragmentation::SplitEandP "<<pHadron->GetParticleName()<<G4endl;
467 G4cout<<"String 4 mom, String M "<<string->Get4Momentum()<<" "<<string->Mass()<<G4endl;
468 G4cout<<"HadM MinimalStringMassLeft StringM hM+sM "<<HadronMass<<" "<<MinimalStringMass<<" "
469 <<string->Mass()<<" "<<HadronMass+MinimalStringMass<<G4endl;
470 #endif
471
472 if (HadronMass + MinimalStringMass > string->Mass())
473 {
474 #ifdef debug_QGSMfragmentation
475 G4cout<<"Mass of the string is not sufficient to produce the hadron!"<<G4endl;
476 #endif
477 return 0;
478 } // have to start all over!
479
480 // calculate and assign hadron transverse momentum component HadronPx andHadronPy
481 G4double StringMT2 = string->MassT2();
482 G4double StringMT = std::sqrt(StringMT2);
483
484 G4LorentzVector String4Momentum = string->Get4Momentum();
485 String4Momentum.setPz(0.);
486 G4ThreeVector StringPt = String4Momentum.vect();
487
488 G4ThreeVector HadronPt , RemSysPt;
489 G4double HadronMassT2, ResidualMassT2;
490
491 // Mt distribution is implemented
492 G4double HadronMt, Pt, Pt2, phi;
493
494 //... sample Pt of the hadron
495 G4int attempt=0;
496 do
497 {
498 attempt++; if (attempt > StringLoopInterrupt) return 0;
499
500 HadronMt = HadronMass - 200.0*G4Log(G4UniformRand()); // 200.0 must be tuned
501 Pt2 = sqr(HadronMt)-sqr(HadronMass); Pt=std::sqrt(Pt2);
502 phi = 2.*pi*G4UniformRand();
503 G4ThreeVector SampleQuarkPtw= G4ThreeVector(Pt*std::cos(phi), Pt*std::sin(phi), 0);
504 HadronPt =SampleQuarkPtw + string->DecayPt();
505 HadronPt.setZ(0);
506 RemSysPt = StringPt - HadronPt;
507
508 HadronMassT2 = sqr(HadronMass) + HadronPt.mag2();
509 ResidualMassT2=sqr(MinimalStringMass) + RemSysPt.mag2();
510
511 } while (std::sqrt(HadronMassT2) + std::sqrt(ResidualMassT2) > StringMT); /* Loop checking, 07.08.2015, A.Ribon */
512
513 //... sample z to define hadron longitudinal momentum and energy
514 //... but first check the available phase space
515
516 G4double Pz2 = (sqr(StringMT2 - HadronMassT2 - ResidualMassT2) -
517 4*HadronMassT2 * ResidualMassT2)/4./StringMT2;
518
519 if ( Pz2 < 0 ) {return 0;} // have to start all over!
520
521 //... then compute allowed z region z_min <= z <= z_max
522
523 G4double Pz = std::sqrt(Pz2);
524 G4double zMin = (std::sqrt(HadronMassT2+Pz2) - Pz)/std::sqrt(StringMT2);
525 G4double zMax = (std::sqrt(HadronMassT2+Pz2) + Pz)/std::sqrt(StringMT2);
526
527 if (zMin >= zMax) return 0; // have to start all over!
528
529 G4double z = GetLightConeZ(zMin, zMax,
530 string->GetDecayParton()->GetPDGEncoding(), pHadron,
531 HadronPt.x(), HadronPt.y());
532
533 //... now compute hadron longitudinal momentum and energy
534 // longitudinal hadron momentum component HadronPz
535
536 HadronPt.setZ( 0.5* string->GetDecayDirection() *
537 (z * string->LightConeDecay() -
538 HadronMassT2/(z * string->LightConeDecay())) );
539 G4double HadronE = 0.5* (z * string->LightConeDecay() +
540 HadronMassT2/(z * string->LightConeDecay()) );
541
542 G4LorentzVector * a4Momentum= new G4LorentzVector(HadronPt,HadronE);
543
544 #ifdef debug_QGSMfragmentation
545 G4cout<<"string->GetDecayDirection() string->LightConeDecay() "
546 <<string->GetDecayDirection()<<" "<<string->LightConeDecay()<<G4endl;
547 G4cout<<"HadronPt,HadronE "<<HadronPt<<" "<<HadronE<<G4endl;
548 G4cout<<"Out of QGSM SplitEandP "<<G4endl;
549 #endif
550
551 return a4Momentum;
552}
553
554//----------------------------------------------------------------------------------------------------------
555
556G4double G4QGSMFragmentation::GetLightConeZ(G4double zmin, G4double zmax, G4int /* PartonEncoding */ ,
557 G4ParticleDefinition* /* pHadron */, G4double ptx , G4double pty)
558{
559 G4double lambda = 2.0*(sqr(ptx)+sqr(pty))/sqr(GeV);
560
561 #ifdef debug_QGSMfragmentation
562 G4cout<<"GetLightConeZ zmin zmax Parton pHadron "<<zmin<<" "<<zmax<<" "/*<< PartonEncoding */
563 <<" "/*<< pHadron->GetParticleName() */ <<G4endl;
564 #endif
565
566 G4double z(0.);
567 G4int DiQold(0), DiQnew(0);
568 G4double d1(-1.0), d2(0.);
569 G4double invD1(0.),invD2(0.), r1(0.),r2(0.),r12(0.);
570
571 G4int absDecayQuarkCode = std::abs( DecayQuark );
572 G4int absNewQuarkCode = std::abs( NewQuark );
573
574 G4int q1(0), q2(0);
575 // q1 = absDecayQuarkCode/1000; q2 = (absDecayQuarkCode % 1000)/100;
576
577 G4int qA(0), qB(0);
578 // qA = absNewQuarkCode/1000; qB = (absNewQuarkCode % 1000)/100;
579
580 if ( (absDecayQuarkCode < 6) && (absNewQuarkCode < 6) ) {
581 d1 = FFq2q[absDecayQuarkCode-1][absNewQuarkCode-1][0]; d2 = FFq2q[absDecayQuarkCode-1][absNewQuarkCode-1][1];
582 }
583
584 if ( (absDecayQuarkCode < 6) && (absNewQuarkCode > 6) ) {
585 qA = absNewQuarkCode/1000; qB = (absNewQuarkCode % 1000)/100; DiQnew = IndexDiQ[qA-1][qB-1];
586 d1 = FFq2qq[absDecayQuarkCode-1][DiQnew][0]; d2 = FFq2q[absDecayQuarkCode-1][DiQnew][1];
587 }
588
589 if ( (absDecayQuarkCode > 6) && (absNewQuarkCode < 6) ) {
590 q1 = absDecayQuarkCode/1000; q2 = (absDecayQuarkCode % 1000)/100; DiQold = IndexDiQ[q1-1][q2-1];
591 d1 = FFqq2q[DiQold][absNewQuarkCode-1][0]; d2 = FFqq2q[DiQold][absNewQuarkCode-1][1];
592 }
593
594 if ( d1 < 0. ) {
595 q1 = absDecayQuarkCode/1000; q2 = (absDecayQuarkCode % 1000)/100; DiQold = IndexDiQ[q1-1][q2-1];
596 qA = absNewQuarkCode/1000; qB = (absNewQuarkCode % 1000)/100; DiQnew = IndexDiQ[qA-1][qB-1];
597 d1 = FFqq2qq[DiQold][DiQnew][0]; d2 = FFqq2qq[DiQold][DiQnew][1];
598 }
599
600 d2 +=lambda;
601 d1+=1.0; d2+=1.0;
602
603 invD1=1./d1; invD2=1./d2;
604
605 const G4int maxNumberOfLoops = 10000;
606 G4int loopCounter = 0;
607 do // Jong's algorithm
608 {
611 r12=r1+r2;
612 z=r1/r12;
613 } while ( ( (r12 > 1.0) || !((zmin <= z)&&(z <= zmax))) &&
614 ++loopCounter < maxNumberOfLoops ); /* Loop checking, 07.08.2015, A.Ribon */
615
616 if ( loopCounter >= maxNumberOfLoops ) {
617 z = 0.5*(zmin + zmax); // Just a value between zmin and zmax, no physics considerations at all!
618 }
619
620 return z;
621}
622
623//-----------------------------------------------------------------------------------------
624
625G4bool G4QGSMFragmentation::SplitLast(G4FragmentingString * string,
626 G4KineticTrackVector * LeftVector,
627 G4KineticTrackVector * RightVector)
628{
629 //... perform last cluster decay
630
631 G4ThreeVector ClusterVel =string->Get4Momentum().boostVector();
632 G4double ResidualMass =string->Mass();
633
634 #ifdef debug_QGSMfragmentation
635 G4cout<<"Split last-----------------------------------------"<<G4endl;
636 G4cout<<"StrMass "<<ResidualMass<<" q's "
637 <<string->GetLeftParton()->GetParticleName()<<" "
638 <<string->GetRightParton()->GetParticleName()<<G4endl;
639 #endif
640
641 G4int cClusterInterrupt = 0;
642 G4ParticleDefinition *LeftHadron = nullptr;
643 G4ParticleDefinition *RightHadron = nullptr;
644 const G4int maxNumberOfLoops = 1000;
645 G4int loopCounter = 0;
646
647 G4double LeftHadronMass(0.); G4double RightHadronMass(0.);
648 do
649 {
650 if (cClusterInterrupt++ >= ClusterLoopInterrupt) return false;
651 LeftHadronMass = -MaxMass; RightHadronMass = -MaxMass;
652
653 G4ParticleDefinition * quark = nullptr;
654 string->SetLeftPartonStable(); // to query quark contents..
655
656 if (string->DecayIsQuark() && string->StableIsQuark() )
657 {
658 //... there are quarks on cluster ends
659
660 G4int IsParticle=(string->GetLeftParton()->GetPDGEncoding()>0) ? -1 : +1;
661 // if we have a quark, we need antiquark or diquark
662
663 pDefPair QuarkPair = CreatePartonPair(IsParticle);
664 quark = QuarkPair.second;
665
666 LeftHadron= hadronizer->Build(QuarkPair.first, string->GetLeftParton());
667 if ( LeftHadron == NULL ) continue;
668 RightHadron = hadronizer->Build(string->GetRightParton(), quark);
669 if ( RightHadron == NULL ) continue;
670 } else if( (!string->DecayIsQuark() && string->StableIsQuark() ) ||
671 ( string->DecayIsQuark() && !string->StableIsQuark() ) ) {
672 //... there is a Diquark on one of cluster ends
673 G4int IsParticle;
674 if ( string->StableIsQuark() ) {
675 IsParticle=(string->GetLeftParton()->GetPDGEncoding()>0) ? -1 : +1;
676 } else {
677 IsParticle=(string->GetLeftParton()->GetPDGEncoding()>0) ? +1 : -1;
678 }
679
680 //G4double ProbSaS = 1.0 - 2.0 * GetStrangeSuppress();
681 //G4double ActualProb = ProbSaS * 1.4;
682 //SetStrangenessSuppression((1.0-ActualProb)/2.0);
683
684 pDefPair QuarkPair = CreatePartonPair(IsParticle,false); // no diquarks wanted
685 //SetStrangenessSuppression((1.0-ProbSaS)/2.0);
686 quark = QuarkPair.second;
687 LeftHadron=hadronizer->Build(QuarkPair.first, string->GetLeftParton());
688 if ( LeftHadron == NULL ) continue;
689 RightHadron = hadronizer->Build(string->GetRightParton(), quark);
690 if ( RightHadron == NULL ) continue;
691 } else { // Diquark and anti-diquark are on the string ends
692 if (cClusterInterrupt++ >= ClusterLoopInterrupt) return false;
693 G4int LeftQuark1= string->GetLeftParton()->GetPDGEncoding()/1000;
694 G4int LeftQuark2=(string->GetLeftParton()->GetPDGEncoding()/100)%10;
695 G4int RightQuark1= string->GetRightParton()->GetPDGEncoding()/1000;
696 G4int RightQuark2=(string->GetRightParton()->GetPDGEncoding()/100)%10;
697 if (G4UniformRand()<0.5) {
698 LeftHadron =hadronizer->Build(FindParticle( LeftQuark1), FindParticle(RightQuark1));
699 RightHadron =hadronizer->Build(FindParticle( LeftQuark2), FindParticle(RightQuark2));
700 } else {
701 LeftHadron =hadronizer->Build(FindParticle( LeftQuark1), FindParticle(RightQuark2));
702 RightHadron =hadronizer->Build(FindParticle( LeftQuark2), FindParticle(RightQuark1));
703 }
704 if ( (LeftHadron == NULL) || (RightHadron == NULL) ) continue;
705 }
706 LeftHadronMass = LeftHadron->GetPDGMass();
707 RightHadronMass = RightHadron->GetPDGMass();
708 //... repeat procedure, if mass of cluster is too low to produce hadrons
709 } while ( ( ResidualMass <= LeftHadronMass + RightHadronMass )
710 && ++loopCounter < maxNumberOfLoops ); /* Loop checking, 07.08.2015, A.Ribon */
711
712 if ( loopCounter >= maxNumberOfLoops ) {
713 return false;
714 }
715
716 //... compute hadron momenta and energies
717 G4LorentzVector LeftMom, RightMom;
719 Sample4Momentum(&LeftMom , LeftHadron->GetPDGMass() ,
720 &RightMom, RightHadron->GetPDGMass(), ResidualMass);
721 LeftMom.boost(ClusterVel);
722 RightMom.boost(ClusterVel);
723
724 #ifdef debug_QGSMfragmentation
725 G4cout<<LeftHadron->GetParticleName()<<" "<<RightHadron->GetParticleName()<<G4endl;
726 G4cout<<"Left Hadrom P M "<<LeftMom<<" "<<LeftMom.mag()<<G4endl;
727 G4cout<<"Right Hadrom P M "<<RightMom<<" "<<RightMom.mag()<<G4endl;
728 #endif
729
730 LeftVector->push_back(new G4KineticTrack(LeftHadron, 0, Pos, LeftMom));
731 RightVector->push_back(new G4KineticTrack(RightHadron, 0, Pos, RightMom));
732
733 return true;
734}
735
736//----------------------------------------------------------------------------------------------------------
737
738void G4QGSMFragmentation::Sample4Momentum(G4LorentzVector* Mom , G4double Mass ,
739 G4LorentzVector* AntiMom, G4double AntiMass, G4double InitialMass)
740{
741 #ifdef debug_QGSMfragmentation
742 G4cout<<"Sample4Momentum Last-----------------------------------------"<<G4endl;
743 G4cout<<" StrMass "<<InitialMass<<" Mass1 "<<Mass<<" Mass2 "<<AntiMass<<G4endl;
744 G4cout<<" SumMass "<<Mass+AntiMass<<G4endl;
745 #endif
746
747 G4double r_val = sqr(InitialMass*InitialMass - Mass*Mass - AntiMass*AntiMass) - sqr(2.*Mass*AntiMass);
748 G4double Pabs = (r_val > 0.)? std::sqrt(r_val)/(2.*InitialMass) : 0;
749
750 //... sample unit vector
751 G4double pz = 1. - 2.*G4UniformRand();
752 G4double st = std::sqrt(1. - pz * pz)*Pabs;
753 G4double phi = 2.*pi*G4UniformRand();
754 G4double px = st*std::cos(phi);
755 G4double py = st*std::sin(phi);
756 pz *= Pabs;
757
758 Mom->setPx(px); Mom->setPy(py); Mom->setPz(pz);
759 Mom->setE(std::sqrt(Pabs*Pabs + Mass*Mass));
760
761 AntiMom->setPx(-px); AntiMom->setPy(-py); AntiMom->setPz(-pz);
762 AntiMom->setE (std::sqrt(Pabs*Pabs + AntiMass*AntiMass));
763}
764
765//----------------------------------------------------------------------------------------------------------
766
767void G4QGSMFragmentation::SetFFq2q() // q-> q' + Meson (q anti q')
768{
769 for (G4int i=0; i < 5; i++) {
770 FFq2q[i][0][0] = 2.0 ; FFq2q[i][0][1] = -arho + alft; // q->d + (q dbar) Pi0, Eta, Eta', Rho0, omega
771 FFq2q[i][1][0] = 2.0 ; FFq2q[i][1][1] = -arho + alft; // q->u + (q ubar) Pi-, Rho-
772 FFq2q[i][2][0] = 1.0 ; FFq2q[i][2][1] = -aphi + alft; // q->s + (q sbar) K0, K*0
773 FFq2q[i][3][0] = 1.0 ; FFq2q[i][3][1] = -aJPs + alft; // q->c + (q+cbar) D-, D*-
774 FFq2q[i][4][0] = 1.0 ; FFq2q[i][4][1] = -aUps + alft; // q->b + (q bbar) EtaB, Upsilon
775 }
776}
777
778//----------------------------------------------------------------------------------------------------------
779
780void G4QGSMFragmentation::SetFFq2qq() // q-> anti (q1'q2') + Baryon (q + q1 + q2)
781{
782 for (G4int i=0; i < 5; i++) {
783 FFq2qq[i][ 0][0] = 0.0 ; FFq2qq[i][ 0][1] = arho - 2.0*an + alft; // q->dd bar + (q dd)
784 FFq2qq[i][ 1][0] = 0.0 ; FFq2qq[i][ 1][1] = arho - 2.0*an + alft; // q->ud bar + (q ud)
785 FFq2qq[i][ 2][0] = 0.0 ; FFq2qq[i][ 2][1] = arho - 2.0*ala + alft; // q->sd bar + (q sd)
786 FFq2qq[i][ 3][0] = 0.0 ; FFq2qq[i][ 3][1] = arho - 2.0*alaC + alft; // q->cd bar + (q cd)
787 FFq2qq[i][ 4][0] = 0.0 ; FFq2qq[i][ 4][1] = arho - 2.0*alaB + alft; // q->bd bar + (q bd)
788 FFq2qq[i][ 5][0] = 0.0 ; FFq2qq[i][ 5][1] = arho - 2.0*an + alft; // q->uu bar + (q uu)
789 FFq2qq[i][ 6][0] = 0.0 ; FFq2qq[i][ 6][1] = arho - 2.0*ala + alft; // q->su bar + (q su)
790 FFq2qq[i][ 7][0] = 0.0 ; FFq2qq[i][ 7][1] = arho - 2.0*alaC + alft; // q->cu bar + (q cu)
791 FFq2qq[i][ 8][0] = 0.0 ; FFq2qq[i][ 8][1] = arho - 2.0*alaB + alft; // q->bu bar + (q bu)
792 FFq2qq[i][ 9][0] = 0.0 ; FFq2qq[i][ 9][1] = arho - 2.0*aXi + alft; // q->ss bar + (q ss)
793 FFq2qq[i][10][0] = 0.0 ; FFq2qq[i][10][1] = arho - 2.0*aXiC + alft; // q->cs bar + (q cs)
794 FFq2qq[i][11][0] = 0.0 ; FFq2qq[i][11][1] = arho - 2.0*aXiB + alft; // q->bs bar + (q bc)
795 FFq2qq[i][12][0] = 0.0 ; FFq2qq[i][12][1] = arho - 2.0*aXiCC + alft; // q->cc bar + (q cc)
796 FFq2qq[i][13][0] = 0.0 ; FFq2qq[i][13][1] = arho - 2.0*aXiCB + alft; // q->bc bar + (q bc)
797 FFq2qq[i][14][0] = 0.0 ; FFq2qq[i][14][1] = arho - 2.0*aXiBB + alft; // q->bb bar + (q bb)
798 }
799}
800
801//----------------------------------------------------------------------------------------------------------
802
803void G4QGSMFragmentation::SetFFqq2q() // q1q2-> anti(q') + Baryon (q1 + q2 + q')
804{
805 for (G4int i=0; i < 15; i++) {
806 FFqq2q[i][0][0] = 2.0*(arho - an); FFqq2q[i][0][1] = -arho + alft;
807 FFqq2q[i][1][0] = 2.0*(arho - an); FFqq2q[i][1][1] = -arho + alft;
808 FFqq2q[i][2][0] = 2.0*(arho - an); FFqq2q[i][2][1] = -aphi + alft;
809 FFqq2q[i][3][0] = 2.0*(arho - an); FFqq2q[i][3][1] = -aJPs + alft;
810 FFqq2q[i][4][0] = 2.0*(arho - an); FFqq2q[i][4][1] = -aUps + alft;
811 }
812}
813
814//----------------------------------------------------------------------------------------------------------
815
816void G4QGSMFragmentation::SetFFqq2qq() // q1(q2)-> q'(q2) + Meson(q1 anti q')
817{
818 for (G4int i=0; i < 15; i++) {
819 FFqq2qq[i][0][0] = 0. ; FFqq2qq[i][0][1] = 2.0*arho - 2.0*an -arho + alft; // dd -> dd + Pi0 (d d bar)
820 FFqq2qq[i][1][0] = 0. ; FFqq2qq[i][1][1] = 2.0*arho - 2.0*an -arho + alft; // dd -> ud + Pi- (d u bar)
821 FFqq2qq[i][2][0] = 0. ; FFqq2qq[i][2][1] = 2.0*arho - 2.0*an -aphi + alft; // dd -> sd + K0 (d s bar)
822 FFqq2qq[i][3][0] = 0. ; FFqq2qq[i][3][1] = 2.0*arho - 2.0*an -aJPs + alft; // dd -> cd + D- (d c bar)
823 FFqq2qq[i][4][0] = 0. ; FFqq2qq[i][4][1] = 2.0*arho - 2.0*an -aUps + alft; // dd -> bd + B0 (d b bar)
824 }
825}
826
G4double G4Exp(G4double initial_x)
Exponential Function double precision.
Definition: G4Exp.hh:180
G4double G4Log(G4double x)
Definition: G4Log.hh:227
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)
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