Geant4 11.1.1
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4LundStringFragmentation.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"
38#include "G4DiQuarks.hh"
39#include "G4Quarks.hh"
41#include "G4Exp.hh"
42#include "G4Pow.hh"
43
44//#define debug_LUNDfragmentation
45
46// Class G4LundStringFragmentation
47//*************************************************************************************
48
50 : G4VLongitudinalStringDecay("LundStringFragmentation")
51{
52 SetMassCut(210.*MeV); // Mpi + Delta
53 // For ProduceOneHadron it is required
54 // that no one pi-meson can be produced.
55 SigmaQT = 0.435 * GeV;
56 Tmt = 190.0 * MeV;
57
58 SetStringTensionParameter(1.*GeV/fermi);
60
61 SetStrangenessSuppression((1.0 - 0.12)/2.0);
63
64 // Check if charmed and bottom hadrons are enabled: if this is the case, then
65 // set the non-zero probabilities for c-cbar and b-bbar creation from the vacuum,
66 // else set them to 0.0. If these probabilities are/aren't zero then charmed or bottom
67 // hadrons can't/can be created during the string fragmentation of ordinary
68 // (i.e. not heavy) projectile hadron nuclear reactions.
69 if ( G4HadronicParameters::Instance()->EnableBCParticles() ) {
70 SetProbCCbar(0.0002); // According to O.I. Piskunova Yad. Fiz. 56 (1993) 1094; tuned by Uzhi Oct. 2022
71 SetProbBBbar(5.0e-5); // According to O.I. Piskunova Yad. Fiz. 56 (1993) 1094
72 } else {
73 SetProbCCbar(0.0);
74 SetProbBBbar(0.0);
75 }
76
77 SetMinMasses(); // For treating of small string decays
78}
79
80//--------------------------------------------------------------------------------------
81
83{
84 // Can no longer modify Parameters for Fragmentation.
85
86 PastInitPhase=true;
87
88 G4FragmentingString aString(theString);
89 SetMinimalStringMass(&aString);
90
91 #ifdef debug_LUNDfragmentation
92 G4cout<<G4endl<<"LUND StringFragmentation ------------------------------------"<<G4endl;
93 G4cout<<G4endl<<"LUND StringFragm: String Mass "
94 <<theString.Get4Momentum().mag()<<G4endl
95 <<"4Mom "<<theString.Get4Momentum()<<G4endl
96 <<"------------------------------------"<<G4endl;
97 G4cout<<"String ends Direct "<<theString.GetLeftParton()->GetPDGcode()<<" "
98 <<theString.GetRightParton()->GetPDGcode()<<" "
99 <<theString.GetDirection()<< G4endl;
100 G4cout<<"Left mom "<<theString.GetLeftParton()->Get4Momentum()<<G4endl;
101 G4cout<<"Right mom "<<theString.GetRightParton()->Get4Momentum()<<G4endl<<G4endl;
102 G4cout<<"Check for Fragmentation "<<G4endl;
103 #endif
104
105 G4KineticTrackVector * LeftVector(0);
106
107 if (!aString.IsAFourQuarkString() && !IsItFragmentable(&aString))
108 {
109 #ifdef debug_LUNDfragmentation
110 G4cout<<"Non fragmentable - the string is converted to one hadron "<<G4endl;
111 #endif
112 // SetMassCut(210.*MeV); // For ProduceOneHadron it is required
113 // that no one pi-meson can be produced.
114
115 G4double Mcut = GetMassCut();
116 SetMassCut(10000.*MeV);
117 LeftVector=ProduceOneHadron(&theString);
118 SetMassCut(Mcut);
119
120 if ( LeftVector )
121 {
122 if ( LeftVector->size() > 0)
123 {
124 LeftVector->operator[](0)->SetFormationTime(theString.GetTimeOfCreation());
125 LeftVector->operator[](0)->SetPosition(theString.GetPosition());
126 }
127 if (LeftVector->size() > 1)
128 {
129 // 2 hadrons created from qq-qqbar are stored
130 LeftVector->operator[](1)->SetFormationTime(theString.GetTimeOfCreation());
131 LeftVector->operator[](1)->SetPosition(theString.GetPosition());
132 }
133 }
134 return LeftVector;
135 }
136
137 #ifdef debug_LUNDfragmentation
138 G4cout<<"The string will be fragmented. "<<G4endl;
139 #endif
140
141 // The string can fragment. At least two particles can be produced.
142 LeftVector =new G4KineticTrackVector;
144
145 G4bool success = Loop_toFragmentString(theString, LeftVector, RightVector);
146
147 if ( ! success )
148 {
149 std::for_each(LeftVector->begin(), LeftVector->end(), DeleteKineticTrack());
150 LeftVector->clear();
151 std::for_each(RightVector->begin(), RightVector->end(), DeleteKineticTrack());
152 delete RightVector;
153 return LeftVector;
154 }
155
156 // Join Left- and RightVector into LeftVector in correct order.
157 while (!RightVector->empty())
158 {
159 LeftVector->push_back(RightVector->back());
160 RightVector->erase(RightVector->end()-1);
161 }
162 delete RightVector;
163
164 return LeftVector;
165}
166
167//----------------------------------------------------------------------------------
168
169G4bool G4LundStringFragmentation::IsItFragmentable(const G4FragmentingString * const string)
170{
171 SetMinimalStringMass(string);
172 //G4cout<<"MinM StrM "<<MinimalStringMass<<" "<< string->Get4Momentum().mag()<<G4endl;
173
174 return std::abs(MinimalStringMass) < string->Get4Momentum().mag();
175
176 //MinimalStringMass is negative and large for a string with unknown particles in a final 2-particle decay.
177}
178
179//----------------------------------------------------------------------------------------
180
181G4bool G4LundStringFragmentation::Loop_toFragmentString( const G4ExcitedString &theString,
182 G4KineticTrackVector * & LeftVector,
183 G4KineticTrackVector * & RightVector )
184{
185 #ifdef debug_LUNDfragmentation
186 G4cout<<"Loop_toFrag "<<theString.GetLeftParton()->GetPDGcode()<<" "
187 <<theString.GetLeftParton()->Get4Momentum()<<G4endl
188 <<" "<<theString.GetRightParton()->GetPDGcode()<<" "
189 <<theString.GetRightParton()->Get4Momentum()<<G4endl
190 <<"Direction "<<theString.GetDirection()<< G4endl;
191 #endif
192
193 G4LorentzRotation toCmsI, toObserverFrameI;
194
195 G4bool final_success=false;
196 G4bool inner_success=true;
197
198 G4int attempt=0;
199
200 while ( ! final_success && attempt++ < StringLoopInterrupt )
201 { // If the string fragmentation does not be happend,
202 // repeat the fragmentation.
203
204 G4FragmentingString *currentString = new G4FragmentingString(theString);
205 toCmsI = currentString->TransformToAlignedCms();
206 toObserverFrameI = toCmsI.inverse();
207
208 G4LorentzRotation toCms, toObserverFrame;
209
210 //G4cout<<"Main loop start whilecounter "<<attempt<<G4endl;
211
212 // Cleaning up the previously produced hadrons
213 std::for_each(LeftVector->begin(), LeftVector->end(), DeleteKineticTrack());
214 LeftVector->clear();
215 std::for_each(RightVector->begin(), RightVector->end(), DeleteKineticTrack());
216 RightVector->clear();
217
218 // Main fragmentation loop until the string will not be able to fragment
219 inner_success=true; // set false on failure.
220 const G4int maxNumberOfLoops = 1000;
221 G4int loopCounter = -1;
222
223 while ( (! StopFragmenting(currentString)) && ++loopCounter < maxNumberOfLoops )
224 { // Split current string into hadron + new string
225 #ifdef debug_LUNDfragmentation
226 G4cout<<"The string will fragment. "<<G4endl;;
227 //G4cout<<"1 "<<currentString->GetDecayDirection()<<G4endl;
228 #endif
229 G4FragmentingString *newString=0; // used as output from SplitUp.
230
231 toCms=currentString->TransformToAlignedCms();
232 toObserverFrame= toCms.inverse();
233
234 #ifdef debug_LUNDfragmentation
235 //G4cout<<"CMS Left mom "<<currentString->GetPleft()<<G4endl;
236 //G4cout<<"CMS Right mom "<<currentString->GetPright()<<G4endl;
237 //G4cout<<"CMS String M "<<currentString->GetPstring()<<G4endl;
238 #endif
239
240 G4KineticTrack * Hadron=Splitup(currentString,newString);
241
242 if ( Hadron != 0 ) // Store the hadron
243 {
244 #ifdef debug_LUNDfragmentation
245 G4cout<<"Hadron prod at fragm. "<<Hadron->GetDefinition()->GetParticleName()<<G4endl;
246 //G4cout<<"2 "<<currentString->GetDecayDirection()<<G4endl;
247 #endif
248
249 Hadron->Set4Momentum(toObserverFrame*Hadron->Get4Momentum());
250
251 G4double TimeOftheStringCreation=theString.GetTimeOfCreation();
252 G4ThreeVector PositionOftheStringCreation(theString.GetPosition());
253
254 G4LorentzVector Coordinate(Hadron->GetPosition(), Hadron->GetFormationTime());
255 G4LorentzVector Momentum = toObserverFrame*Coordinate;
256 Hadron->SetFormationTime(TimeOftheStringCreation + Momentum.e() - fermi/c_light);
257 G4ThreeVector aPosition(Momentum.vect());
258 Hadron->SetPosition(PositionOftheStringCreation+aPosition);
259
260 // Open to protect hadron production at fragmentation
261 if ( currentString->GetDecayDirection() > 0 )
262 {
263 LeftVector->push_back(Hadron);
264 } else
265 {
266 RightVector->push_back(Hadron);
267 }
268 delete currentString;
269 currentString=newString;
270 } else {
271 if ( newString ) delete newString;
272 }
273
274 currentString->LorentzRotate(toObserverFrame);
275 };
276
277 if ( loopCounter >= maxNumberOfLoops ) {
278 inner_success=false;
279 }
280
281 // Split remaining string into 2 final hadrons.
282 #ifdef debug_LUNDfragmentation
283 if (inner_success) G4cout<<"Split remaining string into 2 final hadrons."<<G4endl;
284 #endif
285
286 if ( inner_success && SplitLast(currentString, LeftVector, RightVector) ) // Close to protect Last Str. Decay
287 {
288 final_success = true;
289 }
290
291 delete currentString;
292 } // End of the loop where we try to fragment the string.
293
294 G4int sign = +1;
295 if ( theString.GetDirection() < 0 ) sign = -1;
296 for ( unsigned int hadronI = 0; hadronI < LeftVector->size(); ++hadronI ) {
297 G4LorentzVector Tmp = LeftVector->operator[](hadronI)->Get4Momentum();
298 Tmp.setZ(sign*Tmp.getZ());
299 Tmp *= toObserverFrameI;
300 LeftVector->operator[](hadronI)->Set4Momentum(Tmp);
301 }
302 for ( unsigned int hadronI = 0; hadronI < RightVector->size(); ++hadronI ) {
303 G4LorentzVector Tmp = RightVector->operator[](hadronI)->Get4Momentum();
304 Tmp.setZ(sign*Tmp.getZ());
305 Tmp *= toObserverFrameI;
306 RightVector->operator[](hadronI)->Set4Momentum(Tmp);
307 }
308
309 return final_success;
310}
311
312//----------------------------------------------------------------------------------------
313
314G4bool G4LundStringFragmentation::StopFragmenting(const G4FragmentingString * const string)
315{
316 SetMinimalStringMass(string);
317
318 if ( MinimalStringMass < 0.) return true;
319
320 if (string->IsAFourQuarkString())
321 {
322 return G4UniformRand() < G4Exp(-0.0005*(string->Mass() - MinimalStringMass));
323 } else {
324
325 if (MinimalStringMass < 0.0 ) return false; // For a string with di-quark having c or b quarks and s, c, b quarks
326
327 G4bool Result = G4UniformRand() <
328 G4Exp(-0.66e-6*(string->Mass()*string->Mass() - MinimalStringMass*MinimalStringMass));
329 // G4bool Result = string->Mass() < MinimalStringMass + 150.*MeV*G4UniformRand(); // a'la LUND
330
331 #ifdef debug_LUNDfragmentation
332 G4cout<<"StopFragmenting MinimalStringMass string->Mass() "<<MinimalStringMass
333 <<" "<<string->Mass()<<G4endl;
334 G4cout<<"StopFragmenting - Yes/No "<<Result<<G4endl;
335 #endif
336 return Result;
337 }
338}
339
340//-----------------------------------------------------------------------------
341
342G4KineticTrack * G4LundStringFragmentation::Splitup(G4FragmentingString *string,
343 G4FragmentingString *&newString)
344{
345 #ifdef debug_LUNDfragmentation
346 G4cout<<G4endl;
347 G4cout<<"Start SplitUP ========================="<<G4endl;
348 G4cout<<"String partons: " <<string->GetLeftParton()->GetPDGEncoding()<<" "
349 <<string->GetRightParton()->GetPDGEncoding()<<" "
350 <<"Direction " <<string->GetDecayDirection()<<G4endl;
351 #endif
352
353 //... random choice of string end to use for creating the hadron (decay)
354 G4int SideOfDecay = (G4UniformRand() < 0.5)? 1: -1;
355 if (SideOfDecay < 0)
356 {
357 string->SetLeftPartonStable();
358 } else
359 {
360 string->SetRightPartonStable();
361 }
362
363 G4ParticleDefinition *newStringEnd;
364 G4ParticleDefinition * HadronDefinition;
365
366 G4double StringMass=string->Mass();
367
368 G4double ProbDqADq = GetDiquarkSuppress();
369 G4double ProbSaS = 1.0 - 2.0 * GetStrangeSuppress();
370
371 #ifdef debug_LUNDfragmentation
372 G4cout<<"StrMass DiquarkSuppression "<<StringMass<<" "<<GetDiquarkSuppress()<<G4endl;
373 #endif
374
375 G4int NumberOfpossibleBaryons = 2;
376
377 if (string->GetLeftParton()->GetParticleSubType() != "quark") NumberOfpossibleBaryons++;
378 if (string->GetRightParton()->GetParticleSubType() != "quark") NumberOfpossibleBaryons++;
379
380 G4double ActualProb = ProbDqADq ;
381 ActualProb *= (1.0-G4Pow::GetInstance()->powA(NumberOfpossibleBaryons*1400.0/StringMass, 8.0));
382 if(ActualProb <0.0) ActualProb = 0.;
383
384 SetDiquarkSuppression(ActualProb);
385
386 G4double Mth = 1250.0; // 2 Mk + Mpi
387 if ( NumberOfpossibleBaryons == 3 ){Mth = 2520.0;} // Mlambda/Msigma + Mk + Mpi
388 else if ( NumberOfpossibleBaryons == 4 ){Mth = 2380.0;} // 2 Mlambda/Msigma + Mk + Mpi
389 else {}
390
391 ActualProb = ProbSaS;
392 ActualProb *= (1.0 - G4Pow::GetInstance()->powA( Mth/StringMass, 2.5 ));
393 if ( ActualProb < 0.0 ) ActualProb = 0.0;
394 SetStrangenessSuppression((1.0-ActualProb)/2.0);
395
396 #ifdef debug_LUNDfragmentation
397 G4cout<<"StrMass DiquarkSuppression corrected "<<StringMass<<" "<<GetDiquarkSuppress()<<G4endl;
398 #endif
399
400 if (string->DecayIsQuark())
401 {
402 HadronDefinition= QuarkSplitup(string->GetDecayParton(), newStringEnd);
403 } else {
404 HadronDefinition= DiQuarkSplitup(string->GetDecayParton(), newStringEnd);
405 }
406
407 SetDiquarkSuppression(ProbDqADq);
408 SetStrangenessSuppression((1.0-ProbSaS)/2.0);
409
410 if ( HadronDefinition == NULL ) { G4KineticTrack * Hadron =0; return Hadron; }
411
412 #ifdef debug_LUNDfragmentation
413 G4cout<<"The parton "<<string->GetDecayParton()->GetPDGEncoding()<<" "
414 <<" produces hadron "<<HadronDefinition->GetParticleName()
415 <<" and is transformed to "<<newStringEnd->GetPDGEncoding()<<G4endl;
416 G4cout<<"The side of the string decay Left/Right (1/-1) "<<SideOfDecay<<G4endl;
417 #endif
418 // create new String from old, ie. keep Left and Right order, but replace decay
419
420 if ( newString ) delete newString;
421
422 newString=new G4FragmentingString(*string,newStringEnd); // To store possible quark containt of new string
423
424 #ifdef debug_LUNDfragmentation
425 G4cout<<"An attempt to determine its energy (SplitEandP)"<<G4endl;
426 #endif
427 G4LorentzVector* HadronMomentum=SplitEandP(HadronDefinition, string, newString);
428
429 delete newString; newString=0;
430
431 G4KineticTrack * Hadron =0;
432 if ( HadronMomentum != 0 ) {
433
434 #ifdef debug_LUNDfragmentation
435 G4cout<<"The attempt was successful"<<G4endl;
436 #endif
438 Hadron = new G4KineticTrack(HadronDefinition, 0,Pos, *HadronMomentum);
439
440 if ( newString ) delete newString;
441
442 newString=new G4FragmentingString(*string,newStringEnd,
443 HadronMomentum);
444 delete HadronMomentum;
445 }
446 else
447 {
448 #ifdef debug_LUNDfragmentation
449 G4cout<<"The attempt was not successful !!!"<<G4endl;
450 #endif
451 }
452
453 #ifdef debug_LUNDfragmentation
454 G4cout<<"End SplitUP (G4VLongitudinalStringDecay) ====================="<<G4endl;
455 #endif
456
457 return Hadron;
458}
459
460//-----------------------------------------------------------------------------
461
462G4ParticleDefinition * G4LundStringFragmentation::DiQuarkSplitup(G4ParticleDefinition* decay,
463 G4ParticleDefinition *&created)
464{
466 G4double ProbQQbar = (1.0 - 2.0*StrSup)*1.25;
467
468 //... can Diquark break or not?
470
471 //... Diquark break
472 G4int stableQuarkEncoding = decay->GetPDGEncoding()/1000;
473 G4int decayQuarkEncoding = (decay->GetPDGEncoding()/100)%10;
474 if (G4UniformRand() < 0.5)
475 {
476 G4int Swap = stableQuarkEncoding;
477 stableQuarkEncoding = decayQuarkEncoding;
478 decayQuarkEncoding = Swap;
479 }
480
481 G4int IsParticle=(decayQuarkEncoding>0) ? -1 : +1; // if we have a quark, we need antiquark
482
483 SetStrangenessSuppression((1.0-ProbQQbar)/2.0);
484 pDefPair QuarkPair = CreatePartonPair(IsParticle,false); // no diquarks wanted
485 SetStrangenessSuppression((1.0-StrSup)/2.0);
486
487 //... Build new Diquark
488 G4int QuarkEncoding=QuarkPair.second->GetPDGEncoding();
489 G4int i10 = std::max(std::abs(QuarkEncoding), std::abs(stableQuarkEncoding));
490 G4int i20 = std::min(std::abs(QuarkEncoding), std::abs(stableQuarkEncoding));
491 G4int spin = (i10 != i20 && G4UniformRand() <= 0.5)? 1 : 3;
492 G4int NewDecayEncoding = -1*IsParticle*(i10 * 1000 + i20 * 100 + spin);
493 created = FindParticle(NewDecayEncoding);
494 G4ParticleDefinition * decayQuark=FindParticle(decayQuarkEncoding);
495 G4ParticleDefinition * had=hadronizer->Build(QuarkPair.first, decayQuark);
496 StrangeSuppress=StrSup;
497
498 return had;
499
500 } else {
501 //... Diquark does not break
502
503 G4int IsParticle=(decay->GetPDGEncoding()>0) ? +1 : -1; // if we have a diquark, we need quark
504
505 StrangeSuppress=(1.0 - ProbQQbar)/2.0;
506 pDefPair QuarkPair = CreatePartonPair(IsParticle,false); // no diquarks wanted
507
508 created = QuarkPair.second;
509
510 G4ParticleDefinition * had=hadronizer->Build(QuarkPair.first, decay);
511 StrangeSuppress=StrSup;
512
513 return had;
514 }
515}
516
517//-----------------------------------------------------------------------------
518
519G4LorentzVector * G4LundStringFragmentation::SplitEandP(G4ParticleDefinition * pHadron,
520 G4FragmentingString * string,
521 G4FragmentingString * newString)
522{
523 G4LorentzVector String4Momentum=string->Get4Momentum();
524 G4double StringMT2=string->MassT2();
525 G4double StringMT =std::sqrt(StringMT2);
526
527 G4double HadronMass = pHadron->GetPDGMass();
528 SetMinimalStringMass(newString);
529
530 if ( MinimalStringMass < 0.0 ) return nullptr;
531
532 #ifdef debug_LUNDfragmentation
533 G4cout<<G4endl<<"Start LUND SplitEandP "<<G4endl;
534 G4cout<<"String 4 mom, String M and Mt "<<String4Momentum<<" "<<String4Momentum.mag()
535 <<" "<<std::sqrt(StringMT2)<<G4endl;
536 G4cout<<"Hadron "<<pHadron->GetParticleName()<<G4endl;
537 G4cout<<"HadM MinimalStringMassLeft StringM hM+sM "<<HadronMass<<" "<<MinimalStringMass<<" "
538 <<String4Momentum.mag()<<" "<<HadronMass+MinimalStringMass<<G4endl;
539 #endif
540
541 if ((HadronMass + MinimalStringMass > string->Mass()) || MinimalStringMass < 0.)
542 {
543 #ifdef debug_LUNDfragmentation
544 G4cout<<"Mass of the string is not sufficient to produce the hadron!"<<G4endl;
545 #endif
546 return 0;
547 } // have to start all over!
548
549 String4Momentum.setPz(0.);
550 G4ThreeVector StringPt=String4Momentum.vect();
551 StringPt.setZ(0.);
552
553 // calculate and assign hadron transverse momentum component HadronPx and HadronPy
554 G4ThreeVector HadronPt , RemSysPt;
555 G4double HadronMassT2, ResidualMassT2;
556 G4double HadronMt, Pt, Pt2, phi;
557
558 G4double TmtCur = Tmt;
559
560 if ( (string->GetDecayParton()->GetParticleSubType()== "quark") &&
561 (pHadron->GetBaryonNumber() != 0) ) {
562 TmtCur = Tmt*0.37; // q->B
563 } else if ( (string->GetDecayParton()->GetParticleSubType()== "quark") &&
564 (pHadron->GetBaryonNumber() == 0) ) {
565 //TmtCur = Tmt; // q->M
566 } else if ( (string->GetDecayParton()->GetParticleSubType()== "di_quark") &&
567 (pHadron->GetBaryonNumber() == 0) ) {
568 //TmtCur = Tmt*0.89; // qq -> M
569 } else if ( (string->GetDecayParton()->GetParticleSubType()== "di_quark") &&
570 (pHadron->GetBaryonNumber() != 0) ) {
571 TmtCur = Tmt*1.35; // qq -> B
572 }
573
574 //... sample Pt of the hadron
575 G4int attempt=0;
576 do
577 {
578 attempt++; if (attempt > StringLoopInterrupt) {return 0;}
579
580 HadronMt = HadronMass - TmtCur*G4Log(G4UniformRand());
581 Pt2 = sqr(HadronMt)-sqr(HadronMass); Pt=std::sqrt(Pt2);
582 phi = 2.*pi*G4UniformRand();
583 HadronPt = G4ThreeVector( Pt*std::cos(phi), Pt*std::sin(phi), 0. );
584 RemSysPt = StringPt - HadronPt;
585 HadronMassT2 = sqr(HadronMass) + HadronPt.mag2();
586 ResidualMassT2=sqr(MinimalStringMass) + RemSysPt.mag2();
587
588 } while (std::sqrt(HadronMassT2) + std::sqrt(ResidualMassT2) > StringMT);
589
590 //... sample z to define hadron longitudinal momentum and energy
591 //... but first check the available phase space
592
593 G4double Pz2 = (sqr(StringMT2 - HadronMassT2 - ResidualMassT2) -
594 4*HadronMassT2 * ResidualMassT2)/4./StringMT2;
595
596 if (Pz2 < 0 ) {return 0;} // have to start all over!
597
598 //... then compute allowed z region z_min <= z <= z_max
599
600 G4double Pz = std::sqrt(Pz2);
601 G4double zMin = (std::sqrt(HadronMassT2+Pz2) - Pz)/std::sqrt(StringMT2);
602 // G4double zMin = (std::sqrt(HadronMassT2+Pz2) - 0.)/std::sqrt(StringMT2); // For testing purposes
603 G4double zMax = (std::sqrt(HadronMassT2+Pz2) + Pz)/std::sqrt(StringMT2);
604
605 if (zMin >= zMax) return 0; // have to start all over!
606
607 G4double z = GetLightConeZ(zMin, zMax,
608 string->GetDecayParton()->GetPDGEncoding(), pHadron,
609 HadronPt.x(), HadronPt.y());
610
611 //... now compute hadron longitudinal momentum and energy
612 // longitudinal hadron momentum component HadronPz
613
614 HadronPt.setZ(0.5* string->GetDecayDirection() *
615 (z * string->LightConeDecay() -
616 HadronMassT2/(z * string->LightConeDecay())));
617 G4double HadronE = 0.5* (z * string->LightConeDecay() +
618 HadronMassT2/(z * string->LightConeDecay()));
619
620 G4LorentzVector * a4Momentum= new G4LorentzVector(HadronPt,HadronE);
621
622 #ifdef debug_LUNDfragmentation
623 G4cout<<G4endl<<" string->GetDecayDirection() "<<string->GetDecayDirection()<<G4endl<<G4endl;
624 G4cout<<"string->LightConeDecay() "<<string->LightConeDecay()<<G4endl;
625 G4cout<<"HadronPt,HadronE "<<HadronPt<<" "<<HadronE<<G4endl;
626 G4cout<<"String4Momentum "<<String4Momentum<<G4endl;
627 G4cout<<"Out of LUND SplitEandP "<<G4endl<<G4endl;
628 #endif
629
630 return a4Momentum;
631}
632
633//-----------------------------------------------------------------------------------------
634
635G4double G4LundStringFragmentation::GetLightConeZ(G4double zmin, G4double zmax,
636 G4int PDGEncodingOfDecayParton,
637 G4ParticleDefinition* pHadron,
638 G4double Px, G4double Py)
639{
640 G4double Mass = pHadron->GetPDGMass();
641 G4int HadronEncoding=std::abs(pHadron->GetPDGEncoding());
642
643 G4double Mt2 = Px*Px + Py*Py + Mass*Mass;
644
645 G4double Alund, Blund;
646 G4double zOfMaxyf(0.), maxYf(1.), z(0.), yf(1.);
647
648 if (!((std::abs(PDGEncodingOfDecayParton) > 1000) && (HadronEncoding > 1000)) )
649 { // ---------------- Quark fragmentation and qq-> meson ----------------------
650 Alund=1.;
651 Blund=0.7/GeV/GeV;
652
653 G4double BMt2 = Blund*Mt2;
654 if (Alund == 1.0) {
655 zOfMaxyf=BMt2/(Blund*Mt2 + 1.);}
656 else {
657 zOfMaxyf = ((1.0+BMt2) - std::sqrt(sqr(1.0-BMt2) + 4.0*BMt2*Alund))/2.0/(1.-Alund);
658 }
659
660 if (zOfMaxyf < zmin) {zOfMaxyf=zmin;}
661 if (zOfMaxyf > zmax) {zOfMaxyf=zmax;}
662 maxYf=(1-zOfMaxyf)/zOfMaxyf * G4Exp(-Blund*Mt2/zOfMaxyf);
663
664 const G4int maxNumberOfLoops = 1000;
665 G4int loopCounter = 0;
666 do
667 {
668 z = zmin + G4UniformRand()*(zmax-zmin);
669 //yf = (1-z)/z * G4Exp(-Blund*Mt2/z);
670 yf = G4Pow::GetInstance()->powA(1.0-z,Alund)/z*G4Exp(-BMt2/z);
671 }
672 while ( (G4UniformRand()*maxYf > yf) && ++loopCounter < maxNumberOfLoops );
673 if ( loopCounter >= maxNumberOfLoops ) {
674 z = 0.5*(zmin + zmax); // Just a value between zmin and zmax, no physics considerations at all!
675 }
676 return z;
677 }
678
679 if (std::abs(PDGEncodingOfDecayParton) > 1000)
680 {
681 G4double an = 2.5;
682 an +=(sqr(Px)+sqr(Py))/sqr(GeV)-0.5;
683 z=zmin + (zmax-zmin)*G4Pow::GetInstance()->powA(G4UniformRand(),1./an);
684 if( PDGEncodingOfDecayParton > 3000 ) z=zmin+zmax-z;
685 }
686
687 return z;
688}
689
690//----------------------------------------------------------------------------------------------------------
691
692G4bool G4LundStringFragmentation::SplitLast(G4FragmentingString * string,
693 G4KineticTrackVector * LeftVector,
694 G4KineticTrackVector * RightVector)
695{
696 //... perform last cluster decay
697 SetMinimalStringMass( string);
698 if ( MinimalStringMass < 0.) return false;
699 #ifdef debug_LUNDfragmentation
700 G4cout<<G4endl<<"Split last-----------------------------------------"<<G4endl;
701 G4cout<<"MinimalStringMass "<<MinimalStringMass<<G4endl;
702 G4cout<<"Left "<<string->GetLeftParton()->GetPDGEncoding()<<" "<<string->GetPleft()<<G4endl;
703 G4cout<<"Right "<<string->GetRightParton()->GetPDGEncoding()<<" "<<string->GetPright()<<G4endl;
704 G4cout<<"String4mom "<<string->GetPstring()<<" "<<string->GetPstring().mag()<<G4endl;
705 #endif
706
707 G4LorentzVector Str4Mom=string->Get4Momentum();
708 G4LorentzRotation toCms(-1*Str4Mom.boostVector());
709 G4LorentzVector Pleft = toCms * string->GetPleft();
710 toCms.rotateZ(-1*Pleft.phi());
711 toCms.rotateY(-1*Pleft.theta());
712
713 G4LorentzRotation toObserverFrame= toCms.inverse();
714
715 G4double StringMass=string->Mass();
716
717 G4ParticleDefinition * LeftHadron(0), * RightHadron(0);
718
719 NumberOf_FS=0;
720 for (G4int i=0; i<350; i++) {FS_Weight[i]=0.;}
721
722 G4int sampledState = 0;
723
724 #ifdef debug_LUNDfragmentation
725 G4cout<<"StrMass "<<StringMass<<" q's "
726 <<string->GetLeftParton()->GetParticleName()<<" "
727 <<string->GetRightParton()->GetParticleName()<<G4endl;
728 #endif
729
730 string->SetLeftPartonStable(); // to query quark contents..
731
732 if (string->IsAFourQuarkString() )
733 {
734 G4int IDleft =std::abs(string->GetLeftParton()->GetPDGEncoding());
735 G4int IDright=std::abs(string->GetRightParton()->GetPDGEncoding());
736
737 if ( (IDleft > 3000) || (IDright > 3000) ) {
738 if ( ! Diquark_AntiDiquark_belowThreshold_lastSplitting(string, LeftHadron, RightHadron) )
739 {
740 return false;
741 }
742 } else {
743 // The string is qq-qqbar type. Diquarks are on the string ends
744 if (StringMass-MinimalStringMass < 0.)
745 {
746 if (! Diquark_AntiDiquark_belowThreshold_lastSplitting(string, LeftHadron, RightHadron) )
747 {
748 return false;
749 }
750 } else
751 {
752 Diquark_AntiDiquark_aboveThreshold_lastSplitting(string, LeftHadron, RightHadron);
753
754 if (NumberOf_FS == 0) return false;
755
756 sampledState = SampleState();
757 if (string->GetLeftParton()->GetPDGEncoding() < 0)
758 {
759 LeftHadron =FS_LeftHadron[sampledState];
760 RightHadron=FS_RightHadron[sampledState];
761 } else
762 {
763 LeftHadron =FS_RightHadron[sampledState];
764 RightHadron=FS_LeftHadron[sampledState];
765 }
766 }
767 } // ID > 3300
768 } else {
769 if (string->DecayIsQuark() && string->StableIsQuark() )
770 { //... there are quarks on cluster ends
771 #ifdef debug_LUNDfragmentation
772 G4cout<<"Q Q string LastSplit"<<G4endl;
773 #endif
774
775 Quark_AntiQuark_lastSplitting(string, LeftHadron, RightHadron);
776
777 if (NumberOf_FS == 0) return false;
778 sampledState = SampleState();
779 if (string->GetLeftParton()->GetPDGEncoding() < 0)
780 {
781 LeftHadron =FS_RightHadron[sampledState];
782 RightHadron=FS_LeftHadron[sampledState];
783 } else
784 {
785 LeftHadron =FS_LeftHadron[sampledState];
786 RightHadron=FS_RightHadron[sampledState];
787 }
788 } else
789 { //... there is a Diquark on one of the cluster ends
790 #ifdef debug_LUNDfragmentation
791 G4cout<<"DiQ Q string Last Split"<<G4endl;
792 #endif
793
794 Quark_Diquark_lastSplitting(string, LeftHadron, RightHadron);
795
796 if (NumberOf_FS == 0) return false;
797 sampledState = SampleState();
798
799 if (string->GetLeftParton()->GetParticleSubType() == "quark")
800 {
801 LeftHadron =FS_LeftHadron[sampledState];
802 RightHadron=FS_RightHadron[sampledState];
803 } else
804 {
805 LeftHadron =FS_RightHadron[sampledState];
806 RightHadron=FS_LeftHadron[sampledState];
807 }
808 }
809
810 }
811
812 #ifdef debug_LUNDfragmentation
813 G4cout<<"Sampled hadrons: "<<LeftHadron->GetParticleName()<<" "<<RightHadron->GetParticleName()<<G4endl;
814 #endif
815
816 G4LorentzVector P_left =string->GetPleft(), P_right = string->GetPright();
817
818 G4LorentzVector LeftMom, RightMom;
820
821 Sample4Momentum(&LeftMom, LeftHadron->GetPDGMass(),
822 &RightMom, RightHadron->GetPDGMass(),
823 StringMass);
824
825 // Sample4Momentum ascribes LeftMom.pz() along positive Z axis for baryons in many cases.
826 // It must be negative in case when the system is moving against Z axis.
827
828 if (!(string->DecayIsQuark() && string->StableIsQuark() ))
829 { // Only for qq - q, q - qq, and qq - qqbar -------------------
830
831 if ( G4UniformRand() <= 0.5 )
832 {
833 if (P_left.z() <= 0.) {G4LorentzVector tmp = LeftMom; LeftMom=RightMom; RightMom=tmp;}
834 }
835 else
836 {
837 if (P_right.z() >= 0.) {G4LorentzVector tmp = LeftMom; LeftMom=RightMom; RightMom=tmp;}
838 }
839 }
840
841 LeftMom *=toObserverFrame;
842 RightMom*=toObserverFrame;
843
844 LeftVector->push_back(new G4KineticTrack(LeftHadron, 0, Pos, LeftMom));
845 RightVector->push_back(new G4KineticTrack(RightHadron, 0, Pos, RightMom));
846
847 string->LorentzRotate(toObserverFrame);
848 return true;
849}
850
851//----------------------------------------------------------------------------------------
852
853G4bool G4LundStringFragmentation::
854Diquark_AntiDiquark_belowThreshold_lastSplitting(G4FragmentingString * & string,
855 G4ParticleDefinition * & LeftHadron,
856 G4ParticleDefinition * & RightHadron)
857{
858 G4double StringMass = string->Mass();
859
860 G4int cClusterInterrupt = 0;
861 G4bool isOK = false;
862 do
863 {
864 G4int LeftQuark1= string->GetLeftParton()->GetPDGEncoding()/1000;
865 G4int LeftQuark2=(string->GetLeftParton()->GetPDGEncoding()/100)%10;
866
867 G4int RightQuark1= string->GetRightParton()->GetPDGEncoding()/1000;
868 G4int RightQuark2=(string->GetRightParton()->GetPDGEncoding()/100)%10;
869
870 if (G4UniformRand()<0.5)
871 {
872 LeftHadron =hadronizer->Build(FindParticle( LeftQuark1),
873 FindParticle(RightQuark1));
874 RightHadron= (LeftHadron == nullptr) ? nullptr :
875 hadronizer->Build(FindParticle( LeftQuark2),
876 FindParticle(RightQuark2));
877 } else
878 {
879 LeftHadron =hadronizer->Build(FindParticle( LeftQuark1),
880 FindParticle(RightQuark2));
881 RightHadron=(LeftHadron == nullptr) ? nullptr :
882 hadronizer->Build(FindParticle( LeftQuark2),
883 FindParticle(RightQuark1));
884 }
885
886 isOK = (LeftHadron != nullptr) && (RightHadron != nullptr);
887
888 if(isOK) { isOK = (StringMass > LeftHadron->GetPDGMass() + RightHadron->GetPDGMass()); }
889 ++cClusterInterrupt;
890 //... repeat procedure, if mass of cluster is too low to produce hadrons
891 //... ClusterMassCut = 0.15*GeV model parameter
892 }
893 while (isOK == false && cClusterInterrupt < ClusterLoopInterrupt);
894 /* Loop checking, 07.08.2015, A.Ribon */
895 return isOK;
896}
897
898//----------------------------------------------------------------------------------------
899
900G4bool G4LundStringFragmentation::
901Diquark_AntiDiquark_aboveThreshold_lastSplitting(G4FragmentingString * & string,
902 G4ParticleDefinition * & LeftHadron,
903 G4ParticleDefinition * & RightHadron)
904{
905 // StringMass-MinimalStringMass > 0. Creation of 2 baryons is possible ----
906
907 G4double StringMass = string->Mass();
908 G4double StringMassSqr= sqr(StringMass);
909 G4ParticleDefinition * Di_Quark;
910 G4ParticleDefinition * Anti_Di_Quark;
911
912 if (string->GetLeftParton()->GetPDGEncoding() < 0)
913 {
914 Anti_Di_Quark =string->GetLeftParton();
915 Di_Quark=string->GetRightParton();
916 } else
917 {
918 Anti_Di_Quark =string->GetRightParton();
919 Di_Quark=string->GetLeftParton();
920 }
921
922 G4int IDAnti_di_quark =Anti_Di_Quark->GetPDGEncoding();
923 G4int AbsIDAnti_di_quark =std::abs(IDAnti_di_quark);
924 G4int IDdi_quark =Di_Quark->GetPDGEncoding();
925 G4int AbsIDdi_quark =std::abs(IDdi_quark);
926
927 G4int ADi_q1=AbsIDAnti_di_quark/1000;
928 G4int ADi_q2=(AbsIDAnti_di_quark-ADi_q1*1000)/100;
929
930 G4int Di_q1=AbsIDdi_quark/1000;
931 G4int Di_q2=(AbsIDdi_quark-Di_q1*1000)/100;
932
933 NumberOf_FS=0;
934 for (G4int ProdQ=1; ProdQ < 6; ProdQ++)
935 {
936 G4int StateADiQ=0;
937 const G4int maxNumberOfLoops = 1000;
938 G4int loopCounter = 0;
939 do // while(Meson[AbsIDquark-1][ProdQ-1][StateQ]<>0);
940 {
942 -Baryon[ADi_q1-1][ADi_q2-1][ProdQ-1][StateADiQ]);
943
944 if (LeftHadron == NULL) continue;
945 G4double LeftHadronMass=LeftHadron->GetPDGMass();
946
947 G4int StateDiQ=0;
948 const G4int maxNumberOfInternalLoops = 1000;
949 G4int internalLoopCounter = 0;
950 do // while(Baryon[Di_q1-1][Di_q2-1][ProdQ-1][StateDiQ]<>0);
951 {
953 +Baryon[Di_q1-1][Di_q2-1][ProdQ-1][StateDiQ]);
954
955 if (RightHadron == NULL) continue;
956 G4double RightHadronMass=RightHadron->GetPDGMass();
957
958 if (StringMass > LeftHadronMass + RightHadronMass)
959 {
960 if ( NumberOf_FS > 349 ) {
962 ed << " NumberOf_FS exceeds its limit: NumberOf_FS=" << NumberOf_FS << G4endl;
963 G4Exception( "G4LundStringFragmentation::Diquark_AntiDiquark_aboveThreshold_lastSplitting ",
964 "HAD_LUND_001", JustWarning, ed );
965 NumberOf_FS = 349;
966 }
967
968 G4double FS_Psqr=lambda(StringMassSqr,sqr(LeftHadronMass),
969 sqr(RightHadronMass));
970 //FS_Psqr=1.;
971 FS_Weight[NumberOf_FS]=std::sqrt(FS_Psqr)*FS_Psqr*
972 BaryonWeight[ADi_q1-1][ADi_q2-1][ProdQ-1][StateADiQ]*
973 BaryonWeight[Di_q1-1][Di_q2-1][ProdQ-1][StateDiQ]*
974 Prob_QQbar[ProdQ-1];
975
976 FS_LeftHadron[NumberOf_FS] = LeftHadron;
977 FS_RightHadron[NumberOf_FS]= RightHadron;
978 NumberOf_FS++;
979 } // End of if (StringMass > LeftHadronMass + RightHadronMass)
980
981 StateDiQ++;
982
983 } while( (Baryon[Di_q1-1][Di_q2-1][ProdQ-1][StateDiQ]!=0) &&
984 ++internalLoopCounter < maxNumberOfInternalLoops );
985 if ( internalLoopCounter >= maxNumberOfInternalLoops ) {
986 return false;
987 }
988
989 StateADiQ++;
990 } while( (Baryon[ADi_q1-1][ADi_q2-1][ProdQ-1][StateADiQ]!=0) &&
991 ++loopCounter < maxNumberOfLoops );
992 if ( loopCounter >= maxNumberOfLoops ) {
993 return false;
994 }
995 } // End of for (G4int ProdQ=1; ProdQ < 4; ProdQ++)
996
997 return true;
998}
999
1000//----------------------------------------------------------------------------------------
1001
1002G4bool G4LundStringFragmentation::Quark_Diquark_lastSplitting(G4FragmentingString * & string,
1003 G4ParticleDefinition * & LeftHadron,
1004 G4ParticleDefinition * & RightHadron)
1005{
1006 G4double StringMass = string->Mass();
1007 G4double StringMassSqr= sqr(StringMass);
1008
1009 G4ParticleDefinition * Di_Quark;
1010 G4ParticleDefinition * Quark;
1011
1012 if (string->GetLeftParton()->GetParticleSubType()== "quark")
1013 {
1014 Quark =string->GetLeftParton();
1015 Di_Quark=string->GetRightParton();
1016 } else
1017 {
1018 Quark =string->GetRightParton();
1019 Di_Quark=string->GetLeftParton();
1020 }
1021
1022 G4int IDquark =Quark->GetPDGEncoding();
1023 G4int AbsIDquark =std::abs(IDquark);
1024 G4int IDdi_quark =Di_Quark->GetPDGEncoding();
1025 G4int AbsIDdi_quark=std::abs(IDdi_quark);
1026 G4int Di_q1=AbsIDdi_quark/1000;
1027 G4int Di_q2=(AbsIDdi_quark-Di_q1*1000)/100;
1028 G4int SignDiQ= 1;
1029 if (IDdi_quark < 0) SignDiQ=-1;
1030
1031 NumberOf_FS=0;
1032 for (G4int ProdQ=1; ProdQ < 4; ProdQ++) // Loop over quark-antiquark cases: u-ubar, d-dbar, s-sbar
1033 { // (as last splitting, do not consider c-cbar and b-bbar cases)
1034 G4int SignQ;
1035 if (IDquark > 0)
1036 {
1037 SignQ=-1;
1038 if (IDquark == 2) SignQ= 1;
1039 if ((IDquark == 1) && (ProdQ == 3)) SignQ= 1; // K0
1040 if ((IDquark == 3) && (ProdQ == 1)) SignQ=-1; // K0bar
1041 if (IDquark == 4) SignQ= 1; // D+, D0, Ds+
1042 if (IDquark == 5) SignQ=-1; // B-, anti_B0, anti_Bs0
1043 } else
1044 {
1045 SignQ= 1;
1046 if (IDquark == -2) SignQ=-1;
1047 if ((IDquark ==-1) && (ProdQ == 3)) SignQ=-1; // K0bar
1048 if ((IDquark ==-3) && (ProdQ == 1)) SignQ= 1; // K0
1049 if (IDquark == -4) SignQ=-1; // D-, anti_D0, anti_Ds+
1050 if (IDquark == -5) SignQ= 1; // B+, B0, Bs0
1051 }
1052
1053 if (AbsIDquark == ProdQ) SignQ= 1;
1054
1055 G4int StateQ=0;
1056 const G4int maxNumberOfLoops = 1000;
1057 G4int loopCounter = 0;
1058 do // while(Meson[AbsIDquark-1][ProdQ-1][StateQ]<>0);
1059 {
1061 Meson[AbsIDquark-1][ProdQ-1][StateQ]);
1062 if (LeftHadron == NULL) continue;
1063 G4double LeftHadronMass=LeftHadron->GetPDGMass();
1064
1065 G4int StateDiQ=0;
1066 const G4int maxNumberOfInternalLoops = 1000;
1067 G4int internalLoopCounter = 0;
1068 do // while(Baryon[Di_q1-1][Di_q2-1][ProdQ-1][StateDiQ]<>0);
1069 {
1070 RightHadron=G4ParticleTable::GetParticleTable()->FindParticle(SignDiQ*
1071 Baryon[Di_q1-1][Di_q2-1][ProdQ-1][StateDiQ]);
1072 if (RightHadron == NULL) continue;
1073 G4double RightHadronMass=RightHadron->GetPDGMass();
1074
1075 if (StringMass > LeftHadronMass + RightHadronMass)
1076 {
1077 if ( NumberOf_FS > 349 ) {
1079 ed << " NumberOf_FS exceeds its limit: NumberOf_FS=" << NumberOf_FS << G4endl;
1080 G4Exception( "G4LundStringFragmentation::Quark_Diquark_lastSplitting ",
1081 "HAD_LUND_002", JustWarning, ed );
1082 NumberOf_FS = 349;
1083 }
1084
1085 G4double FS_Psqr=lambda(StringMassSqr,sqr(LeftHadronMass),
1086 sqr(RightHadronMass));
1087 FS_Weight[NumberOf_FS]=std::sqrt(FS_Psqr)*
1088 MesonWeight[AbsIDquark-1][ProdQ-1][StateQ]*
1089 BaryonWeight[Di_q1-1][Di_q2-1][ProdQ-1][StateDiQ]*
1090 Prob_QQbar[ProdQ-1];
1091
1092 FS_LeftHadron[NumberOf_FS] = LeftHadron;
1093 FS_RightHadron[NumberOf_FS]= RightHadron;
1094
1095 NumberOf_FS++;
1096 } // End of if (StringMass > LeftHadronMass + RightHadronMass)
1097
1098 StateDiQ++;
1099
1100 } while( (Baryon[Di_q1-1][Di_q2-1][ProdQ-1][StateDiQ]!=0) &&
1101 ++internalLoopCounter < maxNumberOfInternalLoops );
1102 if ( internalLoopCounter >= maxNumberOfInternalLoops ) {
1103 return false;
1104 }
1105
1106 StateQ++;
1107 } while( (Meson[AbsIDquark-1][ProdQ-1][StateQ]!=0) &&
1108 ++loopCounter < maxNumberOfLoops ); /* Loop checking, 07.08.2015, A.Ribon */
1109
1110 if ( loopCounter >= maxNumberOfLoops ) {
1111 return false;
1112 }
1113 }
1114
1115 return true;
1116}
1117
1118//----------------------------------------------------------------------------------------
1119
1120G4bool G4LundStringFragmentation::Quark_AntiQuark_lastSplitting(G4FragmentingString * & string,
1121 G4ParticleDefinition * & LeftHadron,
1122 G4ParticleDefinition * & RightHadron)
1123{
1124 G4double StringMass = string->Mass();
1125 G4double StringMassSqr= sqr(StringMass);
1126
1127 G4ParticleDefinition * Quark;
1128 G4ParticleDefinition * Anti_Quark;
1129
1130 if (string->GetLeftParton()->GetPDGEncoding()>0)
1131 {
1132 Quark =string->GetLeftParton();
1133 Anti_Quark=string->GetRightParton();
1134 } else
1135 {
1136 Quark =string->GetRightParton();
1137 Anti_Quark=string->GetLeftParton();
1138 }
1139
1140 G4int IDquark =Quark->GetPDGEncoding();
1141 G4int AbsIDquark =std::abs(IDquark);
1142 G4int QuarkCharge =Qcharge[IDquark-1];
1143
1144 G4int IDanti_quark =Anti_Quark->GetPDGEncoding();
1145 G4int AbsIDanti_quark =std::abs(IDanti_quark);
1146 G4int AntiQuarkCharge =-Qcharge[AbsIDanti_quark-1];
1147
1148 G4int LeftHadronCharge(0), RightHadronCharge(0);
1149
1150 //G4cout<<"Q Qbar "<<IDquark<<" "<<IDanti_quark<<G4endl;
1151
1152 NumberOf_FS=0;
1153 for (G4int ProdQ=1; ProdQ < 4; ProdQ++) // Loop over quark-antiquark cases: u-ubar, d-dbar, s-sbar
1154 { // (as last splitting, do not consider c-cbar and b-bbar cases)
1155 //G4cout<<"NumberOf_FS ProdQ "<<NumberOf_FS<<" "<<ProdQ<<G4endl;
1156 LeftHadronCharge = QuarkCharge - Qcharge[ProdQ-1];
1157 G4int SignQ = LeftHadronCharge/3; if (SignQ == 0) SignQ = 1;
1158
1159 if ((IDquark == 1) && (ProdQ == 3)) SignQ= 1; // K0 (d,sbar)
1160 if ((IDquark == 3) && (ProdQ == 1)) SignQ=-1; // K0bar (s,dbar)
1161 if ((IDquark == 4) && (ProdQ == 2)) SignQ= 1; // D0 (c,ubar)
1162 if ((IDquark == 5) && (ProdQ == 1)) SignQ=-1; // anti_B0 (b,dbar)
1163 if ((IDquark == 5) && (ProdQ == 3)) SignQ=-1; // anti_Bs0 (b,sbar)
1164
1165 RightHadronCharge = AntiQuarkCharge + Qcharge[ProdQ-1];
1166 G4int SignAQ = RightHadronCharge/3; if (SignAQ == 0) SignAQ = 1;
1167
1168 if ((IDanti_quark ==-1) && (ProdQ == 3)) SignAQ=-1; // K0bar (dbar,s)
1169 if ((IDanti_quark ==-3) && (ProdQ == 1)) SignAQ= 1; // K0 (sbar,d)
1170 if ((IDanti_quark ==-4) && (ProdQ == 2)) SignAQ=-1; // anti_D0 (cbar,u)
1171 if ((IDanti_quark ==-5) && (ProdQ == 1)) SignAQ= 1; // B0 (bbar,d)
1172 if ((IDanti_quark ==-5) && (ProdQ == 3)) SignAQ= 1; // Bs0 (bbar,s)
1173
1174 //G4cout<<"ProQ signs "<<ProdQ<<" "<<SignQ<<" "<<SignAQ<<G4endl;
1175
1176 G4int StateQ=0;
1177 const G4int maxNumberOfLoops = 1000;
1178 G4int loopCounter = 0;
1179 do
1180 {
1181 //G4cout<<"[AbsIDquark-1][ProdQ-1][StateQ "<<AbsIDquark-1<<" "
1182 //<<ProdQ-1<<" "<<StateQ<<" "<<SignQ*Meson[AbsIDquark-1][ProdQ-1][StateQ]<<G4endl;
1184 Meson[AbsIDquark-1][ProdQ-1][StateQ]);
1185 //G4cout<<"LeftHadron "<<LeftHadron<<G4endl;
1186 if (LeftHadron == NULL) { StateQ++; continue; }
1187 //G4cout<<"LeftHadron "<<LeftHadron->GetParticleName()<<G4endl;
1188 G4double LeftHadronMass=LeftHadron->GetPDGMass();
1189
1190 G4int StateAQ=0;
1191 const G4int maxNumberOfInternalLoops = 1000;
1192 G4int internalLoopCounter = 0;
1193 do
1194 {
1195 //G4cout<<" [AbsIDanti_quark-1][ProdQ-1][StateAQ] "<<AbsIDanti_quark-1<<" "
1196 // <<ProdQ-1<<" "<<StateAQ<<" "<<SignAQ*Meson[AbsIDanti_quark-1][ProdQ-1][StateAQ]<<G4endl;
1197 RightHadron=G4ParticleTable::GetParticleTable()->FindParticle(SignAQ*
1198 Meson[AbsIDanti_quark-1][ProdQ-1][StateAQ]);
1199 //G4cout<<"RightHadron "<<RightHadron<<G4endl;
1200 if(RightHadron == NULL) { StateAQ++; continue; }
1201 //G4cout<<"RightHadron "<<RightHadron->GetParticleName()<<G4endl;
1202 G4double RightHadronMass=RightHadron->GetPDGMass();
1203
1204 if (StringMass > LeftHadronMass + RightHadronMass)
1205 {
1206 if ( NumberOf_FS > 349 ) {
1208 ed << " NumberOf_FS exceeds its limit: NumberOf_FS=" << NumberOf_FS << G4endl;
1209 G4Exception( "G4LundStringFragmentation::Quark_AntiQuark_lastSplitting ",
1210 "HAD_LUND_003", JustWarning, ed );
1211 NumberOf_FS = 349;
1212 }
1213
1214 G4double FS_Psqr=lambda(StringMassSqr,sqr(LeftHadronMass),
1215 sqr(RightHadronMass));
1216 //FS_Psqr=1.;
1217 FS_Weight[NumberOf_FS]=std::sqrt(FS_Psqr)*
1218 MesonWeight[AbsIDquark-1][ProdQ-1][StateQ]*
1219 MesonWeight[AbsIDanti_quark-1][ProdQ-1][StateAQ]*
1220 Prob_QQbar[ProdQ-1];
1221 if (string->GetLeftParton()->GetPDGEncoding()>0)
1222 {
1223 FS_LeftHadron[NumberOf_FS] = RightHadron;
1224 FS_RightHadron[NumberOf_FS]= LeftHadron;
1225 } else
1226 {
1227 FS_LeftHadron[NumberOf_FS] = LeftHadron;
1228 FS_RightHadron[NumberOf_FS]= RightHadron;
1229 }
1230
1231 NumberOf_FS++;
1232
1233 }
1234
1235 StateAQ++;
1236 //G4cout<<" StateAQ Meson[AbsIDanti_quark-1][ProdQ-1][StateAQ] "<<StateAQ<<" "
1237 // <<Meson[AbsIDanti_quark-1][ProdQ-1][StateAQ]<<" "<<internalLoopCounter<<G4endl;
1238 } while ( (Meson[AbsIDanti_quark-1][ProdQ-1][StateAQ]!=0) &&
1239 ++internalLoopCounter < maxNumberOfInternalLoops );
1240 if ( internalLoopCounter >= maxNumberOfInternalLoops ) {
1241 return false;
1242 }
1243
1244 StateQ++;
1245 //G4cout<<"StateQ Meson[AbsIDquark-1][ProdQ-1][StateQ] "<<StateQ<<" "
1246 // <<Meson[AbsIDquark-1][ProdQ-1][StateQ]<<" "<<loopCounter<<G4endl;
1247
1248 } while ( (Meson[AbsIDquark-1][ProdQ-1][StateQ]!=0) &&
1249 ++loopCounter < maxNumberOfLoops );
1250 if ( loopCounter >= maxNumberOfLoops ) {
1251 return false;
1252 }
1253 } // End of for (G4int ProdQ=1; ProdQ < 4; ProdQ++)
1254
1255 return true;
1256}
1257
1258//----------------------------------------------------------------------------------------------------------
1259
1260G4int G4LundStringFragmentation::SampleState(void)
1261{
1262 if ( NumberOf_FS > 349 ) {
1264 ed << " NumberOf_FS exceeds its limit: NumberOf_FS=" << NumberOf_FS << G4endl;
1265 G4Exception( "G4LundStringFragmentation::SampleState ", "HAD_LUND_004", JustWarning, ed );
1266 NumberOf_FS = 349;
1267 }
1268
1269 G4double SumWeights=0.;
1270 for (G4int i=0; i<NumberOf_FS; i++) {SumWeights+=FS_Weight[i];}
1271
1272 G4double ksi=G4UniformRand();
1273 G4double Sum=0.;
1274 G4int indexPosition = 0;
1275
1276 for (G4int i=0; i<NumberOf_FS; i++)
1277 {
1278 Sum+=(FS_Weight[i]/SumWeights);
1279 indexPosition=i;
1280 if (Sum >= ksi) break;
1281 }
1282 return indexPosition;
1283}
1284
1285//----------------------------------------------------------------------------------------------------------
1286
1287void G4LundStringFragmentation::Sample4Momentum(G4LorentzVector* Mom, G4double Mass,
1288 G4LorentzVector* AntiMom, G4double AntiMass,
1289 G4double InitialMass)
1290{
1291 // ------ Sampling of momenta of 2 last produced hadrons --------------------
1292 G4ThreeVector Pt;
1293 G4double MassMt, AntiMassMt;
1294 G4double AvailablePz, AvailablePz2;
1295 #ifdef debug_LUNDfragmentation
1296 G4cout<<"Sampling of momenta of 2 last produced hadrons ----------------"<<G4endl;
1297 G4cout<<"Init Mass "<<InitialMass<<" FirstM "<<Mass<<" SecondM "<<AntiMass<<" ProbIsotropy "<<G4endl;
1298 #endif
1299
1300 G4double r_val = sqr(InitialMass*InitialMass - Mass*Mass - AntiMass*AntiMass) -
1301 sqr(2.*Mass*AntiMass);
1302 G4double Pabs = (r_val > 0.)? std::sqrt(r_val)/(2.*InitialMass) : 0;
1303
1304 const G4int maxNumberOfLoops = 1000;
1305 G4double SigmaQTw = SigmaQT;
1306 if ( Mass > 930. || AntiMass > 930. ) {
1307 SigmaQT *= ( 1.0 - 0.55*sqr( (Mass+AntiMass)/InitialMass ) );
1308 }
1309 if ( Mass < 930. && AntiMass < 930. ) {} // q-qbar string
1310 if ( ( Mass < 930. && AntiMass > 930. ) ||
1311 ( Mass > 930. && AntiMass < 930. ) ) { // q-di_q string
1312 //SigmaQT = -1.; // isotropical decay
1313 }
1314 if ( Mass > 930. && AntiMass > 930. ) { // qq-qqbar string
1315 SigmaQT *= ( 1.0 - 0.55*sqr( (Mass+AntiMass)/InitialMass ) );
1316 }
1317
1318 G4int loopCounter = 0;
1319 do
1320 {
1321 Pt=SampleQuarkPt(Pabs); Pt.setZ(0); G4double Pt2=Pt.mag2();
1322 MassMt = std::sqrt( Mass * Mass + Pt2);
1323 AntiMassMt= std::sqrt(AntiMass * AntiMass + Pt2);
1324 }
1325 while ( (InitialMass < MassMt + AntiMassMt) && ++loopCounter < maxNumberOfLoops );
1326
1327 SigmaQT = SigmaQTw;
1328
1329 if ( loopCounter >= maxNumberOfLoops ) {
1330 AvailablePz2 = 0.0;
1331 }
1332
1333 AvailablePz2= sqr(InitialMass*InitialMass - sqr(MassMt) - sqr(AntiMassMt)) -
1334 4.*sqr(MassMt*AntiMassMt);
1335
1336 AvailablePz2 /=(4.*InitialMass*InitialMass);
1337 AvailablePz = std::sqrt(AvailablePz2);
1338
1339 G4double Px=Pt.getX();
1340 G4double Py=Pt.getY();
1341
1342 Mom->setPx(Px); Mom->setPy(Py); Mom->setPz(AvailablePz);
1343 Mom->setE(std::sqrt(sqr(MassMt)+AvailablePz2));
1344
1345 AntiMom->setPx(-Px); AntiMom->setPy(-Py); AntiMom->setPz(-AvailablePz);
1346 AntiMom->setE (std::sqrt(sqr(AntiMassMt)+AvailablePz2));
1347
1348 #ifdef debug_LUNDfragmentation
1349 G4cout<<"Fmass Mom "<<Mom->getX()<<" "<<Mom->getY()<<" "<<Mom->getZ()<<" "<<Mom->getT()<<G4endl;
1350 G4cout<<"Smass Mom "<<AntiMom->getX()<<" "<<AntiMom->getY()<<" "<<AntiMom->getZ()
1351 <<" "<<AntiMom->getT()<<G4endl;
1352 #endif
1353}
1354
1355//------------------------------------------------------------------------
1356
1357G4double G4LundStringFragmentation::lambda(G4double S, G4double m1_Sqr, G4double m2_Sqr)
1358{
1359 G4double lam = sqr(S - m1_Sqr - m2_Sqr) - 4.*m1_Sqr*m2_Sqr;
1360 return lam;
1361}
1362
1363// --------------------------------------------------------------
1365{}
1366
G4double S(G4double temp)
@ JustWarning
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.cc:59
std::ostringstream G4ExceptionDescription
Definition: G4Exception.hh:40
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 G4endl
Definition: G4ios.hh:57
G4GLOB_DLL std::ostream G4cout
#define G4UniformRand()
Definition: Randomize.hh:52
double mag2() const
void setZ(double)
double getX() const
double getY() const
HepLorentzRotation & rotateY(double delta)
HepLorentzRotation & rotateZ(double delta)
HepLorentzRotation inverse() const
double theta() const
Hep3Vector boostVector() const
Hep3Vector vect() const
G4double GetTimeOfCreation() const
const G4ThreeVector & GetPosition() const
G4int GetDirection(void) const
G4Parton * GetRightParton(void) const
G4Parton * GetLeftParton(void) const
G4LorentzVector Get4Momentum() const
G4bool IsAFourQuarkString(void) const
G4ParticleDefinition * GetLeftParton(void) const
G4ParticleDefinition * GetRightParton(void) const
void LorentzRotate(const G4LorentzRotation &rotation)
G4LorentzRotation TransformToAlignedCms()
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
virtual G4KineticTrackVector * FragmentString(const G4ExcitedString &theString)
const G4String & GetParticleName() const
const G4String & GetParticleSubType() const
G4ParticleDefinition * FindParticle(G4int PDGEncoding)
static G4ParticleTable * GetParticleTable()
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
G4ThreeVector SampleQuarkPt(G4double ptMax=-1.)
std::pair< G4ParticleDefinition *, G4ParticleDefinition * > pDefPair
G4ParticleDefinition * FindParticle(G4int Encoding)
G4KineticTrackVector * ProduceOneHadron(const G4ExcitedString *const theString)
virtual G4ParticleDefinition * QuarkSplitup(G4ParticleDefinition *decay, G4ParticleDefinition *&created)
G4ParticleDefinition * FS_RightHadron[350]
virtual void SetMassCut(G4double aValue)
void SetDiquarkSuppression(G4double aValue)
void SetStrangenessSuppression(G4double aValue)
G4ParticleDefinition * FS_LeftHadron[350]
void SetDiquarkBreakProbability(G4double aValue)
pDefPair CreatePartonPair(G4int NeedParticle, G4bool AllowDiquarks=true)
void SetStringTensionParameter(G4double aValue)
void SetMinimalStringMass(const G4FragmentingString *const string)
ush Pos
Definition: deflate.h:91
ParticleList decay(Cluster *const c)
Carries out a cluster decay.
const G4double pi
G4int sign(const T t)
T sqr(const T &x)
Definition: templates.hh:128