Geant4 9.6.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4QString.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// $Id$
28//
29// ------------------------------------------------------------
30// GEANT 4 class implementation file
31//
32// ---------------- G4QString ----------------
33// by Mikhail Kossov Oct, 2006
34// class for excited string used by Parton String Models
35// For comparison mirror member functions are taken from G4 classes:
36// G4FragmentingString
37// G4ExcitedStringDecay
38// ---------------------------------------------------------------------
39// Short description: If partons from the G4QPartonPair are close in
40// rapidity, they create Quasmons, but if they are far in the rapidity
41// space, they can not interact directly. Say the bottom parton (quark)
42// has rapidity 0, and the top parton (antiquark) has rapidity 8, then
43// the top quark splits in two by radiating gluon, and each part has
44// rapidity 4, then the gluon splits in quark-antiquark pair (rapidity
45// 2 each), and then the quark gadiates anothe gluon and reachs rapidity
46// 1. Now it can interact with the bottom antiquark, creating a Quasmon
47// or a hadron. The intermediate partons is the string ladder.
48// ---------------------------------------------------------------------
49
50//#define debug
51//#define pdebug
52//#define edebug
53
54#include <algorithm>
55
56#include "G4QString.hh"
58#include "G4SystemOfUnits.hh"
59
60// Static parameters definition
61G4double G4QString::MassCut=350.*MeV; // minimum mass cut for the string
62G4double G4QString::SigmaQT=0.5*GeV; // quarkTransverseMomentum distribution parameter
63G4double G4QString::DiquarkSuppress=0.1; // is Diquark suppression parameter
64G4double G4QString::DiquarkBreakProb=0.1; // is Diquark breaking probability
65G4double G4QString::SmoothParam=0.9; // QGS model parameter
66G4double G4QString::StrangeSuppress=0.435;// Strangeness suppression (u:d:s=1:1:0.3 ?M.K.)
67G4double G4QString::widthOfPtSquare=-0.72*GeV*GeV; // pt -width2 forStringExcitation
68
69G4QString::G4QString() : theDirection(0), thePosition(G4ThreeVector(0.,0.,0.)),
70 theStableParton(0), theDecayParton(0){}
71
72G4QString::G4QString(G4QParton* Color, G4QParton* AntiColor, G4int Direction)
73 : SideOfDecay(0)
74{
75#ifdef debug
76 G4cout<<"G4QString::PPD-Constructor: Direction="<<Direction<<G4endl;
77#endif
78 ExciteString(Color, AntiColor, Direction);
79#ifdef debug
80 G4cout<<"G4QString::PPD-Constructor: ------>> String is excited"<<G4endl;
81#endif
82}
83
85{
86#ifdef debug
87 G4cout<<"G4QString::PartonPair-Constructor: Is CALLED"<<G4endl;
88#endif
89 ExciteString(CAC->GetParton1(), CAC->GetParton2(), CAC->GetDirection());
90#ifdef debug
91 G4cout<<"G4QString::PartonPair-Constructor: ------>> String is excited"<<G4endl;
92#endif
93}
94
95G4QString::G4QString(G4QParton* QCol,G4QParton* Gluon,G4QParton* QAntiCol,G4int Direction)
96 : theDirection(Direction), thePosition(QCol->GetPosition()), SideOfDecay(0)
97{
98 thePartons.push_back(QCol);
99 G4LorentzVector sum=QCol->Get4Momentum();
100 thePartons.push_back(Gluon);
101 sum+=Gluon->Get4Momentum();
102 thePartons.push_back(QAntiCol);
103 sum+=QAntiCol->Get4Momentum();
104 Pplus =sum.e() + sum.pz();
105 Pminus=sum.e() - sum.pz();
106 decaying=None;
107}
108
109G4QString::G4QString(const G4QString &right) : theDirection(right.GetDirection()),
110 thePosition(right.GetPosition()), SideOfDecay(0)
111{
112 //LeftParton=right.LeftParton;
113 //RightParton=right.RightParton;
114 Ptleft=right.Ptleft;
115 Ptright=right.Ptright;
116 Pplus=right.Pplus;
117 Pminus=right.Pminus;
118 decaying=right.decaying;
119}
120
122{if(thePartons.size()) std::for_each(thePartons.begin(),thePartons.end(),DeleteQParton());}
123
125{
126 G4LorentzVector momentum(0.,0.,0.,0.);
127 for(unsigned i=0; i<thePartons.size(); i++) momentum += thePartons[i]->Get4Momentum();
128 return momentum;
129}
130
132{
133 for(unsigned i=0; i<thePartons.size(); i++)
134 thePartons[i]->Set4Momentum(rotation*thePartons[i]->Get4Momentum());
135}
136
137//void G4QString::InsertParton(G4QParton* aParton, const G4QParton* addafter)
138//{
139// G4QPartonVector::iterator insert_index; // Begin by default (? M.K.)
140// if(addafter != NULL)
141// {
142// insert_index=std::find(thePartons.begin(), thePartons.end(), addafter);
143// if (insert_index == thePartons.end()) // No object addafter in thePartons
144// {
145// G4cerr<<"***G4QString::InsertParton: Addressed Parton is not found"<<G4endl;
146// G4Exception("G4QString::InsertParton:","72",FatalException,"NoAddressParton");
147// }
148// }
149// thePartons.insert(insert_index+1, aParton);
150//}
151
153{
154 for(unsigned cParton=0; cParton<thePartons.size(); cParton++)
155 {
156 G4LorentzVector Mom = thePartons[cParton]->Get4Momentum();
157 Mom.boost(Velocity);
158 thePartons[cParton]->Set4Momentum(Mom);
159 }
160}
161
162//G4QParton* G4QString::GetColorParton(void) const
163//{
164// G4QParton* start = *(thePartons.begin());
165// G4QParton* end = *(thePartons.end()-1);
166// G4int Encoding = start->GetPDGCode();
167// if (Encoding<-1000 || (Encoding < 1000 && Encoding > 0)) return start;
168// return end;
169//}
170
171//G4QParton* G4QString::GetAntiColorParton(void) const
172//{
173// G4QParton* start = *(thePartons.begin());
174// G4QParton* end = *(thePartons.end()-1);
175// G4int Encoding = start->GetPDGCode();
176// if (Encoding < -1000 || (Encoding < 1000 && Encoding > 0)) return end;
177// return start;
178//}
179
180// Fill parameters
182 G4double smPar, G4double SSup, G4double SigPt)
183{
184 MassCut = mCut; // minimum mass cut for the string
185 SigmaQT = sigQT; // quark transverse momentum distribution parameter
186 DiquarkSuppress = DQSup; // is Diquark suppression parameter
187 DiquarkBreakProb= DQBU; // is Diquark breaking probability
188 SmoothParam = smPar; // QGS model parameter
189 StrangeSuppress = SSup; // Strangeness suppression parameter
190 widthOfPtSquare = -2*SigPt*SigPt; // width^2 of pt for string excitation
191}
192
193// Pt distribution @@ one can use 1/(1+A*Pt^2)^B
194G4ThreeVector G4QString::GaussianPt(G4double widthSquare, G4double maxPtSquare) const
195{
196 G4double pt2; do{pt2=widthSquare*std::log(G4UniformRand());} while (pt2>maxPtSquare);
197 pt2=std::sqrt(pt2);
198 G4double phi=G4UniformRand()*twopi;
199 return G4ThreeVector(pt2*std::cos(phi),pt2*std::sin(phi),0.);
200} // End of GaussianPt
201
202// Diffractively excite the string
203//void G4QString::DiffString(G4QHadron* hadron, G4bool isProjectile)
204//{
205// hadron->SplitUp();
206// G4QParton* start = hadron->GetNextParton();
207// if( start==NULL)
208// {
209// G4cerr<<"***G4QString::DiffString: No start parton found, nothing is done"<<G4endl;
210// return;
211// }
212// G4QParton* end = hadron->GetNextParton();
213// if( end==NULL)
214// {
215// G4cerr<<"***G4QString::DiffString: No end parton found, nothing is done"<<G4endl;
216// return;
217// }
218// if(isProjectile) ExciteString(end, start, 1); // 1 = Projectile
219// else ExciteString(start, end,-1); // -1 = Target
220// SetPosition(hadron->GetPosition());
221// // momenta of string ends
222// G4double ptSquared= hadron->Get4Momentum().perp2();
223// G4double hmins=hadron->Get4Momentum().minus();
224// G4double hplus=hadron->Get4Momentum().plus();
225// G4double transMassSquared=hplus*hmins;
226// G4double maxMomentum = std::sqrt(transMassSquared) - std::sqrt(ptSquared);
227// G4double maxAvailMomentumSquared = maxMomentum * maxMomentum;
228// G4ThreeVector pt=GaussianPt(widthOfPtSquare,maxAvailMomentumSquared);
229// G4LorentzVector Pstart(G4LorentzVector(pt,0.));
230// G4LorentzVector Pend(hadron->Get4Momentum().px(), hadron->Get4Momentum().py(), 0.);
231// Pend-=Pstart;
232// G4double tm1=hmins+(Pend.perp2()-Pstart.perp2())/hplus;
233// G4double tm2=std::sqrt( std::max(0., tm1*tm1-4*Pend.perp2()*hmins/hplus ) );
234// G4int Sign= isProjectile ? TARGET : PROJECTILE;
235// G4double endMinus = 0.5 * (tm1 + Sign*tm2);
236// G4double startMinus= hmins - endMinus;
237// G4double startPlus = Pstart.perp2() / startMinus;
238// G4double endPlus = hplus - startPlus;
239// Pstart.setPz(0.5*(startPlus - startMinus));
240// Pstart.setE (0.5*(startPlus + startMinus));
241// Pend.setPz (0.5*(endPlus - endMinus));
242// Pend.setE (0.5*(endPlus + endMinus));
243// start->Set4Momentum(Pstart);
244// end->Set4Momentum(Pend);
245//#ifdef debug
246// G4cout<<"G4QString::DiffString: StartQ="<<start->GetPDGCode()<<start->Get4Momentum()<<"("
247// <<start->Get4Momentum().mag()<<"), EndQ="<<end->GetPDGCode()<<end ->Get4Momentum()
248// <<"("<<end->Get4Momentum().mag()<<"), sumOfEnds="<<Pstart+Pend<<", H4M(original)="
249// <<hadron->Get4Momentum()<<G4endl;
250//#endif
251//} // End of DiffString (The string is excited diffractively)
252
253// Excite the string by two partons
254void G4QString::ExciteString(G4QParton* Color, G4QParton* AntiColor, G4int Direction)
255{
256#ifdef debug
257 G4cout<<"G4QString::ExciteString: **Called**, direction="<<Direction<<G4endl;
258#endif
259 if(thePartons.size()) std::for_each(thePartons.begin(),thePartons.end(),DeleteQParton());
260 thePartons.clear();
261 theDirection = Direction;
262 thePosition = Color->GetPosition();
263#ifdef debug
264 G4cout<<"G4QString::ExciteString: ColourPosition = "<<thePosition<<", beg="<<Color->GetPDGCode()
265 <<",end="<<AntiColor->GetPDGCode()<<G4endl;
266#endif
267 thePartons.push_back(Color);
268 G4LorentzVector sum=Color->Get4Momentum();
269 thePartons.push_back(AntiColor); // @@ Complain of Valgrind
270 sum+=AntiColor->Get4Momentum();
271 Pplus =sum.e() + sum.pz();
272 Pminus=sum.e() - sum.pz();
273 decaying=None;
274#ifdef debug
275 G4cout<<"G4QString::ExciteString: ***Done***, beg="<<(*thePartons.begin())->GetPDGCode()
276 <<",end="<<(*(thePartons.end()-1))->GetPDGCode()<<G4endl;
277#endif
278} // End of ExciteString
279
280// LUND Longitudinal fragmentation
281G4double G4QString::GetLundLightConeZ(G4double zmin, G4double zmax, G4int , // @@ ? M.K.
282 G4QHadron* pHadron, G4double Px, G4double Py)
283{
284 static const G4double alund = 0.7/GeV/GeV;
285 // If blund get restored, you MUST adapt the calculation of zOfMaxyf.
286 //static const G4double blund = 1;
287 G4double z, yf;
288 G4double Mt2 = Px*Px + Py*Py + pHadron->GetMass2();
289 G4double zOfMaxyf=alund*Mt2/(alund*Mt2+1.);
290 G4double maxYf=(1.-zOfMaxyf)/zOfMaxyf * std::exp(-alund*Mt2/zOfMaxyf);
291 do
292 {
293 z = zmin + G4UniformRand()*(zmax-zmin);
294 // yf = std::pow(1. - z, blund)/z*std::exp(-alund*Mt2/z);
295 yf = (1-z)/z * std::exp(-alund*Mt2/z);
296 } while (G4UniformRand()*maxYf>yf);
297 return z;
298} // End of GetLundLightConeZ
299
300
301// QGSM Longitudinal fragmentation
302G4double G4QString::GetQGSMLightConeZ(G4double zmin, G4double zmax, G4int PartonEncoding,
303 G4QHadron* , G4double, G4double) // @@ M.K.
304{
305 static const G4double arho=0.5;
306 static const G4double aphi=0.;
307 static const G4double an=-0.5;
308 static const G4double ala=-0.75;
309 static const G4double aksi=-1.;
310 static const G4double alft=0.5;
311 G4double z;
312 G4double theA(0), d2, yf;
313 G4int absCode = std::abs(PartonEncoding);
314 // @@ Crazy algorithm is used for simple power low...
315 if (absCode < 10) // Quarks (@@ 9 can be a gluon)
316 {
317 if(absCode == 1 || absCode == 2) theA = arho;
318 else if(absCode == 3) theA = aphi;
319 else
320 {
321 G4cerr<<"***G4QString::GetQGSMLightConeZ: CHIPS is SU(3), quakCode="<<absCode<<G4endl;
322 G4Exception("G4QString::GetQGSMLightConeZ:","72",FatalException,"WrongQuark");
323 }
324 do
325 {
326 z = zmin + G4UniformRand()*(zmax - zmin);
327 d2 = alft - theA;
328 yf = std::pow( 1.-z, d2);
329 }
330 while (G4UniformRand()>yf);
331 }
332 else // Di-quarks (@@ Crazy codes are not checked)
333 {
334 if (absCode==3101||absCode==3103||absCode==3201||absCode==3203) d2=alft-ala-ala+arho;
335 else if(absCode==1103||absCode==2101||absCode==2203||absCode==2103) d2=alft-an-an+arho;
336 else d2=alft-aksi-aksi+arho;
337 do
338 {
339 z = zmin + G4UniformRand()*(zmax - zmin);
340 yf = std::pow(1.-z, d2);
341 }
342 while (G4UniformRand()>yf);
343 }
344 return z;
345} // End of GetQGSMLightConeZ
346
347// Diffractively excite the string (QL=true - QGS Light Cone, =false - Lund Light Cone)
349{
350 // Can no longer modify Parameters for Fragmentation.
351#ifdef edebug
352 G4LorentzVector string4M=Get4Momentum(); // Just for Energy-Momentum ConservCheck
353#endif
354#ifdef debug
355 G4cout<<"G4QString::FragmentString:-->Called,QL="<<QL<<", M="<<Get4Momentum().m()<<", L="
357#endif
358 // check if string has enough mass to fragment. If not, convert to one or two hadrons
360 if(LeftVector)
361 {
362#ifdef edebug
363 G4LorentzVector sL=string4M;
364 for(unsigned L = 0; L < LeftVector->size(); L++)
365 {
366 G4QHadron* LH = (*LeftVector)[L];
368 sL-=L4M;
369 G4cout<<"-EMC-G4QStr::FragStr:L#"<<L<<",PDG="<<LH->GetPDGCode()<<",4M="<<L4M<<G4endl;
370 }
371 G4cout<<"-EMC-G4QString::FragmentString:---LightFragmentation---> Res4M="<<sL<<G4endl;
372#endif
373 return LeftVector; //@@ Just decay in 2 or 1 (?) hadron, if below theCut
374 }
375#ifdef debug
376 G4cout<<"G4QString::FragmentString:OUTPUT is not yet defined, define Left/Right"<<G4endl;
377#endif
378 LeftVector = new G4QHadronVector; // Valgrind complain to LeftVector
379 G4QHadronVector* RightVector = new G4QHadronVector;
380 // Remember 4-momenta of the string ends (@@ only for the two-parton string, no gluons)
381 G4LorentzVector left4M=GetLeftParton()->Get4Momentum(); // For recovery when failed
383#ifdef debug
384 G4cout<<"G4QString::FragmString: ***Remember*** L4M="<<left4M<<", R4M="<<right4M<<G4endl;
385#endif
386 G4int leftPDG=GetLeftParton()->GetPDGCode();
387 G4int rightPDG=GetRightParton()->GetPDGCode();
388 // Transform string to CMS
389 G4LorentzVector momentum=Get4Momentum();
390 G4LorentzRotation toCms(-(momentum.boostVector()));
391 momentum= toCms * thePartons[0]->Get4Momentum();
392 toCms.rotateZ(-1*momentum.phi());
393 toCms.rotateY(-1*momentum.theta());
394 for(unsigned index=0; index<thePartons.size(); index++)
395 {
396 momentum = toCms * thePartons[index]->Get4Momentum(); // @@ reuse of the momentum
397 thePartons[index]->Set4Momentum(momentum);
398 }
399 // Copy the string for independent attempts
400 G4QParton* LeftParton = new G4QParton(GetLeftParton());
401 G4QParton* RightParton= new G4QParton(GetRightParton());
402 G4QString* theStringInCMS = new G4QString(LeftParton,RightParton,GetDirection());
403#ifdef debug
404 G4cout<<"G4QString::FragmentString: Copy with nP="<<theStringInCMS->thePartons.size()
405 <<", beg="<<(*(theStringInCMS->thePartons.begin()))->GetPDGCode()
406 <<", end="<<(*(theStringInCMS->thePartons.end()-1))->GetPDGCode()<<G4endl;
407#endif
408 G4bool success=false;
409 G4bool inner_sucess=true;
410 G4int attempt=0;
411 G4int StringLoopInterrupt=27; // String fragmentation LOOP limit
412#ifdef debug
413 G4cout<<"G4QString::FragmentString: BeforeWhileLOOP, max = "<<StringLoopInterrupt
414 <<", nP="<<thePartons.size()<<", beg="<<(*thePartons.begin())->GetPDGCode()
415 <<",end="<<(*(thePartons.end()-1))->GetPDGCode()<<G4endl;
416#endif
417#ifdef edebug
418 G4LorentzVector cmS4M=theStringInCMS->Get4Momentum();
419 G4cout<<"-EMC-G4QString::FragmString: c4M="<<cmS4M<<",Max="<<StringLoopInterrupt<<G4endl;
420#endif
421 while (!success && attempt++ < StringLoopInterrupt) // Try fragment String till success
422 {
423 // Recover the CMS String
424 LeftParton = new G4QParton(theStringInCMS->GetLeftParton());
425 RightParton= new G4QParton(theStringInCMS->GetRightParton());
426 ExciteString(LeftParton, RightParton, theStringInCMS->GetDirection());
427#ifdef edebug
428 G4LorentzVector cm4M=cmS4M; // Copy the full momentum for the reduction and check
429 G4cout<<"-EMC-.G4QString::FragmentString: CHEK "<<cm4M<<" ?= "<<Get4Momentum()<<G4endl;
430#endif
431#ifdef debug
432 G4cout<<"G4QString::FragmentString:===>LOOP, attempt = "<<attempt<<", nP="
433 <<thePartons.size()<<", beg="<<(*thePartons.begin())->GetPDGCode()
434 <<",end="<<(*(thePartons.end()-1))->GetPDGCode()<<G4endl;
435#endif
436 // Now clean up all hadrons in the Left and Right vectors for the new attempt
437 if(LeftVector->size())
438 {
439 std::for_each(LeftVector->begin(), LeftVector->end(), DeleteQHadron());
440 LeftVector->clear();
441 }
442 //delete LeftVector; // @@ Valgrind ?
443 if(RightVector->size())
444 {
445 std::for_each(RightVector->begin(), RightVector->end(), DeleteQHadron());
446 RightVector->clear();
447 }
448 //delete RightVector; // @@ Valgrind ?
449 inner_sucess=true; // set false on failure
450 while (!StopFragmentation()) // LOOP with break
451 { // Split current string into hadron + new string state
452#ifdef debug
453 G4cout<<"G4QString::FragmentString:-->Begin LOOP/LOOP, decaying="<<decaying<<G4endl;
454#endif
455 G4QHadron* Hadron=Splitup(QL); // MAIN: where the hadron is split from the string
456#ifdef edebug
457 cm4M-=Hadron->Get4Momentum();
458 G4cout<<"-EMC-G4QString::FragmentString:LOOP/LOOP,d4M="<<cm4M-Get4Momentum()<<G4endl;
459#endif
460 G4bool canBeFrag=IsFragmentable();
461#ifdef debug
462 G4cout<<"G4QString::FragmentString: LOOP/LOOP, canBeFrag="<<canBeFrag<<", decay="
463 <<decaying<<", H="<<Hadron<<", newStringMass="<<Get4Momentum().m()<<G4endl;
464#endif
465 if(Hadron && canBeFrag)
466 {
467#ifdef debug
468 G4cout<<">>G4QString::FragmentString: LOOP/LOOP-NO FRAGM-, dec="<<decaying<<G4endl;
469#endif
470 if(GetDecayDirection()>0) LeftVector->push_back(Hadron);
471 else RightVector->push_back(Hadron);
472 }
473 else
474 {
475 // @@ Try to convert to the resonance and decay, abandon if M<mGS+mPI0
476 // abandon ... start from the beginning
477#ifdef debug
478 G4cout<<"G4QString::FragmentString: LOOP/LOOP, Start from scratch"<<G4endl;
479#endif
480 if (Hadron) delete Hadron;
481 inner_sucess=false;
482 break;
483 }
484#ifdef debug
485 G4cout<<"G4QString::FragmentString: LOOP/LOOP End, nP="
486 <<thePartons.size()<<", beg="<<(*thePartons.begin())->GetPDGCode()
487 <<",end="<<(*(thePartons.end()-1))->GetPDGCode()<<G4endl;
488#endif
489 }
490#ifdef edebug
491 G4LorentzVector fLR=cmS4M-Get4Momentum();
492 for(unsigned L = 0; L < LeftVector->size(); L++)
493 {
494 G4QHadron* LH = (*LeftVector)[L];
496 fLR-=L4M;
497 G4cout<<"-EMC-G4QStr::FrStr:L#"<<L<<",PDG="<<LH->GetPDGCode()<<",4M="<<L4M<<G4endl;
498 }
499 for(unsigned R = 0; R < RightVector->size(); R++)
500 {
501 G4QHadron* RH = (*RightVector)[R];
503 fLR-=R4M;
504 G4cout<<"-EMC-G4QStr::FrStr:R#"<<R<<",PDG="<<RH->GetPDGCode()<<",4M="<<R4M<<G4endl;
505 }
506 G4cout<<"-EMC-G4QString::FragmentString:L/R_BeforLast->r4M/M2="<<fLR<<fLR.m2()<<G4endl;
507#endif
508 // Split current string into 2 final Hadrons
509#ifdef debug
510 G4cout<<"G4QString::FragmentString: inner_success = "<<inner_sucess<<G4endl;
511#endif
512 if(inner_sucess)
513 {
514 success=true; // Default prototype
515 //... perform last cluster decay
517 G4double totM = tot4M.m();
518#ifdef debug
519 G4cout<<"G4QString::FragmString: string4M="<<tot4M<<totM<<G4endl;
520#endif
521 G4QHadron* LeftHadron;
522 G4QHadron* RightHadron;
523 G4QParton* RQuark = 0;
524 SetLeftPartonStable(); // to query quark contents
525 if(DecayIsQuark() && StableIsQuark()) // There're quarks on clusterEnds
526 {
527#ifdef debug
528 G4cout<<"G4QString::FragmentString: LOOP Quark Algorithm"<<G4endl;
529#endif
530 LeftHadron= QuarkSplitup(GetLeftParton(), RQuark);
531 }
532 else
533 {
534#ifdef debug
535 G4cout<<"G4QString::FragmentString: LOOP Di-Quark Algorithm"<<G4endl;
536#endif
537 //... there is a Diquark on cluster ends
538 G4int IsParticle;
539 if(StableIsQuark()) IsParticle=(GetLeftParton()->GetPDGCode()>0)?-1:1;
540 else IsParticle=(GetLeftParton()->GetPDGCode()>0)?1:-1;
541 G4QPartonPair QuarkPair = CreatePartonPair(IsParticle,false); // no diquarks
542 RQuark = QuarkPair.GetParton2();
543 G4QParton* LQuark = QuarkPair.GetParton1();
544 LeftHadron = CreateHadron(LQuark, GetLeftParton()); // Create Left Hadron
545 delete LQuark; // Delete the temporaryParton
546 }
547 RightHadron = CreateHadron(GetRightParton(), RQuark); // Create Right Hadron
548 delete RQuark; // Delete the temporaryParton
549 //... repeat procedure, if mass of cluster is too low to produce hadrons
550 G4double LhM=LeftHadron->GetMass();
551 G4double RhM=RightHadron->GetMass();
552#ifdef debug
553 G4cout<<"G4QStr::FrSt:L="<<LeftHadron->GetPDGCode()<<",R="<<RightHadron->GetPDGCode()
554 <<",ML="<<LhM<<",MR="<<RhM<<",SumM="<<LhM+RhM<<",tM="<<totM<<G4endl;
555#endif
556 if(totM < LhM + RhM) success=false;
557 //... compute hadron momenta and energies
558 if(success)
559 {
561 G4LorentzVector Lh4M(0.,0.,0.,LhM);
562 G4LorentzVector Rh4M(0.,0.,0.,RhM);
563 if(G4QHadron(tot4M).DecayIn2(Lh4M,Rh4M))
564 {
565 LeftVector->push_back(new G4QHadron(LeftHadron, 0, Pos, Lh4M));
566 delete LeftHadron;
567 RightVector->push_back(new G4QHadron(RightHadron, 0, Pos, Rh4M));
568 delete RightHadron;
569 }
570#ifdef debug
571 G4cout<<"->>G4QStr::FragString:HFilled (L) PDG="<<LeftHadron->GetPDGCode()<<", 4M="
572 <<Lh4M<<", (R) PDG="<<RightHadron->GetPDGCode()<<", 4M="<<Rh4M<<G4endl;
573#endif
574#ifdef edebug
575 G4cout<<"-EMC-G4QString::FragmentString: Residual4M="<<tot4M-Lh4M-Rh4M<<G4endl;
576#endif
577 }
578 else
579 {
580 if(LeftHadron) delete LeftHadron;
581 if(RightHadron) delete RightHadron;
582 }
583 } // End of inner success
584 } // End of while
585 delete theStringInCMS;
586#ifdef debug
587 G4cout<<"G4QString::FragmentString: LOOP/LOOP, success="<<success<<G4endl;
588#endif
589 if (!success)
590 {
591 if(RightVector->size())
592 {
593 std::for_each(RightVector->begin(), RightVector->end(), DeleteQHadron());
594 RightVector->clear();
595 }
596 delete RightVector;
597 if(LeftVector->size())
598 {
599 std::for_each(LeftVector->begin(), LeftVector->end(), DeleteQHadron());
600 LeftVector->clear();
601 }
602 delete LeftVector;
603#ifdef debug
604 G4cout<<"G4QString::FragmString:StringNotFragm,L4M="<<left4M<<",R4M="<<right4M<<G4endl;
605#endif
606 // Recover the Left/Right partons 4-moms of the String in ZLS
607 GetLeftParton()->SetPDGCode(leftPDG);
608 GetRightParton()->SetPDGCode(rightPDG);
609 GetLeftParton()->Set4Momentum(left4M);
610 GetRightParton()->Set4Momentum(right4M);
611 return 0; // The string can not be fragmented
612 }
613 // @@@@@ Print collected Left and Right Hadrons (decay resonances!)
614#ifdef edebug
615 G4LorentzVector sLR=cmS4M;
616 for(unsigned L = 0; L < LeftVector->size(); L++)
617 {
618 G4QHadron* LH = (*LeftVector)[L];
620 sLR-=L4M;
621 G4cout<<"-EMC-G4QStr::FragmStri:L#"<<L<<",PDG="<<LH->GetPDGCode()<<",4M="<<L4M<<G4endl;
622 }
623 for(unsigned R = 0; R < RightVector->size(); R++)
624 {
625 G4QHadron* RH = (*RightVector)[R];
627 sLR-=R4M;
628 G4cout<<"-EMC-G4QStr::FragmStri:R#"<<R<<",PDG="<<RH->GetPDGCode()<<",4M="<<R4M<<G4endl;
629 }
630 G4cout<<"-EMC-G4QString::FragmentString:---L/R_BeforeMerge---> Res4M="<<sLR<<G4endl;
631#endif
632 // Join Left and Right Vectors into LeftVector in correct order.
633 while(!RightVector->empty())
634 {
635 LeftVector->push_back(RightVector->back());
636 RightVector->erase(RightVector->end()-1);
637 }
638 delete RightVector;
639 // @@ A trick, the real bug should be found !!
640 G4QHadronVector::iterator ilv; // @@
641 for(ilv = LeftVector->begin(); ilv < LeftVector->end(); ilv++) // @@
642 {
643 G4ThreeVector CV=(*ilv)->Get4Momentum().vect(); // @@
644 if(CV.x()==0. && CV.y()==0. && CV.z()==0.) LeftVector->erase(ilv); // @@
645 }
646 // Calculate time and position of hadrons with @@ very rough formation time
647 G4double StringMass=Get4Momentum().mag();
648 static const G4double dkappa = 2.0 * GeV/fermi; // @@ 2*kappa kappa=1 GeV/fermi (?)
649 for(unsigned c1 = 0; c1 < LeftVector->size(); c1++)
650 {
651 G4double SumPz = 0;
652 G4double SumE = 0;
653 for(unsigned c2 = 0; c2 < c1; c2++)
654 {
655 G4LorentzVector hc2M=(*LeftVector)[c2]->Get4Momentum();
656 SumPz += hc2M.pz();
657 SumE += hc2M.e();
658 }
659 G4QHadron* hc1=(*LeftVector)[c1];
660 G4LorentzVector hc1M=hc1->Get4Momentum();
661 G4double HadronE = hc1M.e();
662 G4double HadronPz= hc1M.pz();
663 hc1->SetFormationTime((StringMass-SumPz-SumPz+HadronE-HadronPz)/dkappa);
664 hc1->SetPosition(G4ThreeVector(0,0,(StringMass-SumE-SumE-HadronE+HadronPz)/dkappa));
665 }
666 G4LorentzRotation toObserverFrame(toCms.inverse());
667#ifdef debug
668 G4cout<<"G4QString::FragmentString: beforeLoop LVsize = "<<LeftVector->size()<<G4endl;
669#endif
670 for(unsigned C1 = 0; C1 < LeftVector->size(); C1++)
671 {
672 G4QHadron* Hadron = (*LeftVector)[C1];
673 G4LorentzVector Momentum = Hadron->Get4Momentum();
674 Momentum = toObserverFrame*Momentum;
675 Hadron->Set4Momentum(Momentum);
676 G4LorentzVector Coordinate(Hadron->GetPosition(), Hadron->GetFormationTime());
677 Momentum = toObserverFrame*Coordinate;
678 Hadron->SetFormationTime(Momentum.e());
679 Hadron->SetPosition(GetPosition()+Momentum.vect());
680 }
681#ifdef edebug
682 G4LorentzVector sLA=string4M;
683 for(unsigned L = 0; L < LeftVector->size(); L++)
684 {
685 G4QHadron* LH = (*LeftVector)[L];
687 sLA-=L4M;
688 G4cout<<"-EMC-G4QStr::FragmStri:L#"<<L<<",PDG="<<LH->GetPDGCode()<<",4M="<<L4M<<G4endl;
689 }
690 G4cout<<"-EMC-G4QString::FragmentString:---LSAfterMerge&Conv---> Res4M="<<sLA<<G4endl;
691#endif
692#ifdef debug
693 G4cout<<"G4QString::FragmentString: *** Done *** "<<G4endl;
694#endif
695 return LeftVector; // Should be deleted by user (@@ Valgrind complain ?)
696} // End of FragmentString
697
698// Simple decay of the string if the excitation mass is too small for HE fragmentation
699// !! If the mass is below the single hadron threshold, make warning (improve) and convert
700// the string to the single S-hadron breaking energy conservation (temporary) and improve,
701// taking the threshold into account on the level of the String creation (merge strings) !!
703{
704 // Check string decay threshold
706#ifdef debug
707 G4cout<<"G4QString::LightFragmentationTest: ***Called***, string4M="<<tot4M<<G4endl;
708#endif
709 G4QHadronVector* result=0; // return 0 when string exceeds the mass cut or below mh1+mh2
710
711 G4QHadronPair hadrons((G4QHadron*)0, (G4QHadron*)0); // pair of hadrons for output of FrM
712 G4double fragMass = FragmentationMass(0,&hadrons); // Minimum mass to decay the string
713#ifdef debug
714 G4cout<<"G4QString::LightFragTest: before check nP="<<thePartons.size()<<", MS2="
715 <<Mass2()<<", MCut="<<MassCut<<", beg="<<(*thePartons.begin())->GetPDGCode()
716 <<",end="<<(*(thePartons.end()-1))->GetPDGCode()<<", fM="<<fragMass<<G4endl;
717#endif
718 if(Mass2() > sqr(fragMass+MassCut))// Big enough to fragment in a lader (avoid the decay)
719 {
720 if(hadrons.first) delete hadrons.first;
721 if(hadrons.second) delete hadrons.second;
722#ifdef debug
723 G4cout<<"G4QString::LightFragTest:NO,M2="<<Mass2()<<">"<<sqr(fragMass+MassCut)<<G4endl;
724#endif
725 return result; // =0. Depends on the parameter of the Mass Cut
726 }
727 G4double totM= tot4M.m();
728 G4QHadron* h1=hadrons.first;
729 G4QHadron* h2=hadrons.second;
730 if(h1 && h2)
731 {
732 G4double h1M = h1->GetMass();
733 G4double h2M = h2->GetMass();
734#ifdef debug
735 G4cout<<"G4QString::LightFragTest:tM="<<totM<<","<<h1M<<"+"<<h2M<<"+"<<h1M+h2M<<G4endl;
736#endif
737 if(h1M + h2M <= totM) // The string can decay in these two hadrons
738 {
739 // Create two stable hadrons
740 G4LorentzVector h4M1(0.,0.,0.,h1M);
741 G4LorentzVector h4M2(0.,0.,0.,h2M);
742 if(G4QHadron(tot4M).DecayIn2(h4M1,h4M2))
743 {
744 result = new G4QHadronVector;
745 result->push_back(new G4QHadron(hadrons.first, 0, GetPosition(), h4M1));
746 result->push_back(new G4QHadron(hadrons.second,0, GetPosition(), h4M2));
747 }
748#ifdef edebug
749 G4int L=result->size(); if(L) for(G4int i=0; i<L; i++)
750 {
751 tot4M-=(*result)[i]->Get4Momentum();
752 G4cout<<"-EMC-G4QString::LightFragTest: i="<<i<<", residual4M="<<tot4M<<G4endl;
753 }
754#endif
755 }
756#ifdef debug
757 else G4cout<<"-Warning-G4QString::LightFragTest: TooBigHadronMasses to decay"<<G4endl;
758#endif
759 }
760#ifdef debug
761 else G4cout<<"-Warning-G4QString::LightFragTest: No Hadrons have been proposed"<<G4endl;
762#endif
763 delete hadrons.first;
764 delete hadrons.second;
765 return result;
766} // End of LightFragmentationTest
767
768// Calculate Fragmentation Mass (if pdefs # 0, returns two hadrons)
770{
771 G4double mass=0.;
772#ifdef debug
773 G4cout<<"G4QString::FragmMass: ***Called***, s4M="<<Get4Momentum()<<G4endl;
774#endif
775 // Example how to use an interface to different member functions
776 G4QHadron* Hadron1 = 0;
777 G4QHadron* Hadron2 = 0;
778#ifdef debug
779 G4cout<<"G4QString::FragmentationMass: Create spin-0 or spin-1/2 hadron: nP="
780 <<thePartons.size()<<", beg="<<(*thePartons.begin())->GetPDGCode()
781 <<",end="<<(*(thePartons.end()-1))->GetPDGCode()<<G4endl;
782#endif
783 G4int iflc = (G4UniformRand() < 0.5) ? 1 : 2; // Create additional Q-antiQ pair @@ No S
784 G4int LPDG= GetLeftParton()->GetPDGCode();
786 if ( (LPDG > 0 && LT == 1) || (LPDG < 0 && LT == 2) ) iflc = -iflc; // anti-quark
787 G4QParton* piflc = new G4QParton( iflc);
788 G4QParton* miflc = new G4QParton(-iflc);
789 if(HighSpin)
790 {
791 Hadron1 = CreateHighSpinHadron(GetLeftParton(),piflc);
792 Hadron2 = CreateHighSpinHadron(GetRightParton(),miflc);
793#ifdef debug
794 G4cout<<"G4QString::FragmentationMass: High, PDG1="<<Hadron1->GetPDGCode()
795 <<", PDG2="<<Hadron2->GetPDGCode()<<G4endl;
796#endif
797 }
798 else
799 {
800 Hadron1 = CreateLowSpinHadron(GetLeftParton(),piflc);
801 Hadron2 = CreateLowSpinHadron(GetRightParton(),miflc);
802#ifdef debug
803 G4cout<<"G4QString::FragmentationMass: Low, PDG1="<<Hadron1->GetPDGCode()
804 <<", PDG2="<<Hadron2->GetPDGCode()<<G4endl;
805#endif
806 }
807 mass = Hadron1->GetMass() + Hadron2->GetMass();
808 if(pdefs) // need to return hadrons as well as the mass estimate
809 {
810 pdefs->first = Hadron1; // To be deleted by the calling program if not zero
811 pdefs->second = Hadron2; // To be deleted by the calling program if not zero
812 }
813 else // Forget about the hadrons
814 {
815 if(Hadron1) delete Hadron1;
816 if(Hadron2) delete Hadron2;
817 }
818 delete piflc;
819 delete miflc;
820#ifdef debug
821 G4cout<<"G4QString::FragmentationMass: ***Done*** mass="<<mass<<G4endl;
822#endif
823 return mass;
824} // End of FragmentationMass
825
827{
828 theStableParton=GetLeftParton();
829 theDecayParton=GetRightParton();
830 decaying=Right;
831}
832
834{
835 theStableParton=GetRightParton();
836 theDecayParton=GetLeftParton();
837 decaying=Left;
838}
839
841{
842 if (decaying == Left ) return +1;
843 else if (decaying == Right) return -1;
844 else
845 {
846 G4cerr<<"***G4QString::GetDecayDirection: wrong DecayDirection="<<decaying<<G4endl;
847 G4Exception("G4QString::GetDecayDirection:","72",FatalException,"WrongDecayDirection");
848 }
849 return 0;
850}
851
852//G4ThreeVector G4QString::StablePt()
853//{
854// if (decaying == Left ) return Ptright;
855// else if (decaying == Right ) return Ptleft;
856// else
857// {
858// G4cerr<<"***G4QString::StablePt: wrong DecayDirection="<<decaying<<G4endl;
859// G4Exception("G4QString::StablePt:","72",FatalException,"WrongDecayDirection");
860// }
861// return G4ThreeVector();
862//}
863
865{
866 if (decaying == Left ) return Ptleft;
867 else if (decaying == Right ) return Ptright;
868 else
869 {
870 G4cerr<<"***G4QString::DecayPt: wrong DecayDirection="<<decaying<<G4endl;
871 G4Exception("G4QString::DecayPt:","72",FatalException,"WrongDecayDirection");
872 }
873 return G4ThreeVector();
874}
875
876// Random choice of string end to use it for creating the hadron (decay)
878{
879 SideOfDecay = (G4UniformRand() < 0.5) ? 1: -1;
880#ifdef debug
881 G4cout<<"G4QString::Splitup:**Called**,s="<<SideOfDecay<<",s4M="<<Get4Momentum()<<G4endl;
882#endif
883 if(SideOfDecay<0) SetLeftPartonStable(); // Decay Right parton
884 else SetRightPartonStable(); // Decay Left parton
885 G4QParton* newStringEnd;
886 G4QHadron* Hadron;
887 if(DecayIsQuark()) Hadron= QuarkSplitup(theDecayParton, newStringEnd); // Split Quark
888 else Hadron= DiQuarkSplitup(theDecayParton, newStringEnd); // Split DiQuark
889#ifdef debug
890 G4cout<<"G4QString::Splitup: newStringEndPDG="<<newStringEnd->GetPDGCode()<<", nP="
891 <<thePartons.size()<<", beg="<<(*thePartons.begin())->GetPDGCode()
892 <<",end="<<(*(thePartons.end()-1))->GetPDGCode()<<G4endl;
893#endif
894 // create new String from the old one: keep Left and Right order, but replace decay
895 G4LorentzVector* HadronMomentum=SplitEandP(Hadron, QL);//The decayed parton isn't changed
896#ifdef debug
897 G4cout<<"G4QString::Splitup: HM="<<HadronMomentum<<", nP="
898 <<thePartons.size()<<", beg="<<(*thePartons.begin())->GetPDGCode()
899 <<",end="<<(*(thePartons.end()-1))->GetPDGCode()<<G4endl;
900#endif
901 if(HadronMomentum) // The decay succeeded, now the new 4-mon can be set to NewStringEnd
902 {
903#ifdef pdebug
904 G4cout<<"---->>G4QString::Splitup: HFilled 4M="<<*HadronMomentum<<",PDG="
905 <<Hadron->GetPDGCode()<<",s4M-h4M="<<Get4Momentum()-*HadronMomentum<<G4endl;
906#endif
907 newStringEnd->Set4Momentum(theDecayParton->Get4Momentum()-*HadronMomentum);
908 Hadron->Set4Momentum(*HadronMomentum);
909 Hadron->SetPosition(GetPosition());
910 if(decaying == Left)
911 {
912 G4QParton* theFirst = thePartons[0]; // Substitute for the First Parton
913 delete theFirst; // The OldParton instance is deleted
914 thePartons[0] = newStringEnd; // Delete equivalent for newStringEnd
915#ifdef debug
916 G4cout<<"G4QString::Splitup: theFirstPDG="<<theFirst->GetPDGCode()<<G4endl;
917#endif
918 Ptleft -= HadronMomentum->vect();
919 Ptleft.setZ(0.); // @@ (Z is anyway ignored) M.K. (?)
920 }
921 else if (decaying == Right)
922 {
923 G4QParton* theLast = thePartons[thePartons.size()-1]; // Substitute for theLastParton
924 delete theLast; // The OldParton instance is deleted
925 thePartons[thePartons.size()-1] = newStringEnd; // Delete equivalent for newStringEnd
926#ifdef debug
927 G4cout<<"G4QString::Splitup: theLastPDG="<<theLast->GetPDGCode()<<", nP="
928 <<thePartons.size()<<", beg="<<thePartons[0]->GetPDGCode()<<",end="
929 <<thePartons[thePartons.size()-1]->GetPDGCode()<<",P="<<theLast
930 <<"="<<thePartons[thePartons.size()-1]<<G4endl;
931#endif
932 Ptright -= HadronMomentum->vect();
933 Ptright.setZ(0.); // @@ (Z is anyway ignored) M.K. (?)
934 }
935 else
936 {
937 G4cerr<<"***G4QString::Splitup: wrong oldDecay="<<decaying<<G4endl;
938 G4Exception("G4QString::Splitup","72",FatalException,"WrongDecayDirection");
939 }
940 Pplus -= HadronMomentum->e() + HadronMomentum->pz();// Reduce Pplus ofTheString (Left)
941 Pminus -= HadronMomentum->e() - HadronMomentum->pz();// Reduce Pminus ofTheString(Rite)
942#ifdef debug
943 G4cout<<"G4QString::Splitup: P+="<<Pplus<<",P-="<<Pminus<<", nP="
944 <<thePartons.size()<<", beg="<<(*thePartons.begin())->GetPDGCode()
945 <<",end="<<(*(thePartons.end()-1))->GetPDGCode()<<G4endl;
946 G4cout<<">...>G4QString::Splitup: NewString4M="<<Get4Momentum()<<G4endl;
947#endif
948 delete HadronMomentum;
949 }
950#ifdef debug
951 G4cout<<"G4QString::Splitup: ***Done*** H4M="<<Hadron->Get4Momentum()<<", nP="
952 <<thePartons.size()<<", beg="<<(*thePartons.begin())->GetPDGCode()
953 <<",end="<<(*(thePartons.end()-1))->GetPDGCode()<<G4endl;
954#endif
955 return Hadron;
956} // End of Splitup
957
958// QL=true for QGSM and QL=false for Lund fragmentation
960{
961 G4double HadronMass = pHadron->GetMass();
962#ifdef debug
963 G4cout<<"G4QString::SplitEandP: ***Called*** HMass="<<HadronMass<<G4endl;
964#endif
965 // calculate and assign hadron transverse momentum component HadronPx andHadronPy
966 G4ThreeVector HadronPt = SampleQuarkPt() + DecayPt(); // @@ SampleQuarkPt & DecayPt once
967 HadronPt.setZ(0.);
968 //... sample z to define hadron longitudinal momentum and energy
969 //... but first check the available phase space
970 G4double HadronMass2T = HadronMass*HadronMass + HadronPt.mag2();
971 if (HadronMass2T >= SmoothParam*Mass2() ) return 0; // restart!
972 //... then compute allowed z region z_min <= z <= z_max
973 G4double zMin = HadronMass2T/Mass2();
974 G4double zMax = 1.;
975#ifdef debug
976 G4cout<<"G4QString::SplitEandP: zMin="<<zMin<<", zMax"<<zMax<<G4endl;
977#endif
978 if (zMin >= zMax) return 0; // have to start all over!
979 G4double z=0;
980 if(QL) z = GetQGSMLightConeZ(zMin, zMax, theDecayParton->GetPDGCode(), pHadron,
981 HadronPt.x(), HadronPt.y());
982 else z = GetLundLightConeZ(zMin, zMax, theDecayParton->GetPDGCode(), pHadron,
983 HadronPt.x(), HadronPt.y());
984 //... now compute hadron longitudinal momentum and energy
985 // longitudinal hadron momentum component HadronPz
986 G4double zl= z;
987 if (decaying == Left ) zl*=Pplus;
988 else if (decaying == Right ) zl*=Pminus;
989 else // @@ Is that possible?
990 {
991 G4cerr<<"***G4QString::SplitEandP: wrong DecayDirection="<<decaying<<G4endl;
992 G4Exception("G4QString::SplitEandP:","72",FatalException,"WrongDecayDirection");
993 }
994 G4double HadronE = (zl + HadronMass2T/zl)/2;
995 HadronPt.setZ( GetDecayDirection() * (zl - HadronE) );
996 G4LorentzVector* a4Momentum= new G4LorentzVector(HadronPt,HadronE);
997 return a4Momentum;
998}
999
1001{
1002 G4double Pt = SigmaQT * std::sqrt( -std::log(G4UniformRand()));
1003 G4double phi = twopi*G4UniformRand();
1004 return G4ThreeVector(Pt * std::cos(phi),Pt * std::sin(phi),0);
1005}
1006
1007G4QHadron* G4QString::QuarkSplitup(G4QParton* decay, G4QParton* &created)// VGComplTo decay
1008{
1009 G4int IsParticle=(decay->GetPDGCode()>0) ? -1 : +1; // a quark needs antiquark or diquark
1010 G4QPartonPair QuarkPair = CreatePartonPair(IsParticle);
1011 created = QuarkPair.GetParton2(); // New Parton after splitting
1012#ifdef debug
1013 G4cout<<"G4QString::QuarkSplitup: ***Called*** crP="<<created->GetPDGCode()<<G4endl;
1014#endif
1015 G4QParton* P1=QuarkPair.GetParton1();
1016 G4QHadron* result=CreateHadron(P1, decay); // New Hadron after splitting
1017 delete P1; // Clean up the temporary parton
1018 return result;
1019} // End of QuarkSplitup
1020
1021//
1023{
1024 //... can Diquark break or not?
1025 if (G4UniformRand() < DiquarkBreakProb )
1026 {
1027 //... Diquark break
1028 G4int stableQuarkEncoding = decay->GetPDGCode()/1000;
1029 G4int decayQuarkEncoding = (decay->GetPDGCode()/100)%10;
1030 if (G4UniformRand() < 0.5)
1031 {
1032 G4int Swap = stableQuarkEncoding;
1033 stableQuarkEncoding = decayQuarkEncoding;
1034 decayQuarkEncoding = Swap;
1035 }
1036 G4int IsParticle=(decayQuarkEncoding>0) ? -1 : +1;// Diquark is equivalent to antiquark
1037 G4QPartonPair QuarkPair = CreatePartonPair(IsParticle,false); // no diquarks wanted
1038 G4QParton* P2=QuarkPair.GetParton2();
1039 G4int QuarkEncoding=P2->GetPDGCode();
1040 delete P2;
1041 G4int i10 = std::max(std::abs(QuarkEncoding), std::abs(stableQuarkEncoding));
1042 G4int i20 = std::min(std::abs(QuarkEncoding), std::abs(stableQuarkEncoding));
1043 G4int spin = (i10 != i20 && G4UniformRand() <= 0.5) ? 1 : 3;
1044 G4int NewDecayEncoding = -1*IsParticle*(i10 * 1000 + i20 * 100 + spin);
1045 created = new G4QParton(NewDecayEncoding);
1046#ifdef debug
1047 G4cout<<"G4QString::DiQuarkSplitup: inside, crP="<<created->GetPDGCode()<<G4endl;
1048#endif
1049 G4QParton* decayQuark= new G4QParton(decayQuarkEncoding);
1050 G4QParton* P1=QuarkPair.GetParton1();
1051 G4QHadron* newH=CreateHadron(P1, decayQuark);
1052 delete P1;
1053 delete decayQuark;
1054 return newH;
1055 }
1056 else
1057 {
1058 //... Diquark does not break
1059 G4int IsParticle=(decay->GetPDGCode()>0) ? +1 : -1;
1060 G4QPartonPair QuarkPair = CreatePartonPair(IsParticle,false); // no diquarks wanted
1061 created = QuarkPair.GetParton2();
1062#ifdef debug
1063 G4cout<<"G4QString::DiQuarkSplitup: diQ not break, crP="<<created->GetPDGCode()<<G4endl;
1064#endif
1065 G4QParton* P1=QuarkPair.GetParton1();
1066 G4QHadron* newH=CreateHadron(P1, decay);
1067 delete P1;
1068 return newH;
1069 }
1070} // End of DiQuarkSplitup
1071
1073{
1074#ifdef debug
1075 G4cout<<"G4QString::CreatePartonPair: ***Called***, P="<<NeedParticle<<", ALLOWdQ="
1076 <<AllowDiquarks<<G4endl;
1077#endif
1078 // NeedParticle = {+1 for Particle, -1 for AntiParticle}
1079 if(AllowDiquarks && G4UniformRand() < DiquarkSuppress)
1080 {
1081 // Create a Diquark - AntiDiquark pair , first in pair is anti to IsParticle
1082 G4int q1 = SampleQuarkFlavor();
1083 G4int q2 = SampleQuarkFlavor();
1084 G4int spin = (q1 != q2 && G4UniformRand() <= 0.5) ? 1 : 3; // @@ 0.5 M.K.?
1085 // Convention: quark with higher PDG number is first
1086 G4int PDGcode = (std::max(q1,q2) * 1000 + std::min(q1,q2) * 100 + spin) * NeedParticle;
1087#ifdef debug
1088 G4cout<<"G4QString::CreatePartonPair: Created dQ-AdQ, PDG="<<PDGcode<<G4endl;
1089#endif
1090 return G4QPartonPair(new G4QParton(-PDGcode), new G4QParton(PDGcode));
1091 }
1092 else
1093 {
1094 // Create a Quark - AntiQuark pair, first in pair is a Particle
1095 G4int PDGcode=SampleQuarkFlavor()*NeedParticle;
1096#ifdef debug
1097 G4cout<<"G4QString::CreatePartonPair: Created Q-aQ, PDG="<<PDGcode<<G4endl;
1098#endif
1099 return G4QPartonPair(new G4QParton(PDGcode), new G4QParton(-PDGcode));
1100 }
1101} // End of CreatePartonPair
1102
1103// Creation of the Meson out of two partons (q, anti-q)
1104G4QHadron* G4QString::CreateMeson(G4QParton* black, G4QParton* white, Spin theSpin)
1105{
1106 static G4double scalarMesonMixings[6]={0.5, 0.25, 0.5, 0.25, 1.0, 0.5};
1107 static G4double vectorMesonMixings[6]={0.5, 0.0, 0.5, 0.0, 1.0, 1.0};
1108 G4int id1= black->GetPDGCode();
1109 G4int id2= white->GetPDGCode();
1110#ifdef debug
1111 G4cout<<"G4QString::CreateMeson: bT="<<black->GetType()<<"("<<id1<<"), wT="
1112 <<white->GetType()<<"("<<id2<<")"<<G4endl;
1113#endif
1114 if (std::abs(id1) < std::abs(id2)) // exchange black and white
1115 {
1116 G4int xchg = id1;
1117 id1 = id2;
1118 id2 = xchg;
1119 }
1120 if(std::abs(id1)>3)
1121 {
1122 G4cerr<<"***G4QString::CreateMeson: q1="<<id1<<", q2="<<id2
1123 <<" while CHIPS is only SU(3)"<<G4endl;
1124 G4Exception("G4QString::CreateMeson:","72",FatalException,"HeavyQuarkFound");
1125 }
1126 G4int PDGEncoding=0;
1127 if(!(id1+id2)) // annihilation case (neutral)
1128 {
1129 G4double rmix = G4UniformRand();
1130 G4int imix = 2*std::abs(id1) - 1;
1131 if(theSpin == SpinZero)
1132 PDGEncoding = 110*(1 + G4int(rmix + scalarMesonMixings[imix - 1])
1133 + G4int(rmix + scalarMesonMixings[imix] ) ) + theSpin;
1134 else
1135 PDGEncoding = 110*(1 + G4int(rmix + vectorMesonMixings[imix - 1])
1136 + G4int(rmix + vectorMesonMixings[imix] ) ) + theSpin;
1137 }
1138 else
1139 {
1140 PDGEncoding = 100 * std::abs(id1) + 10 * std::abs(id2) + theSpin;
1141 G4bool IsUp = (std::abs(id1)&1) == 0; // quark 1 is up type quark (u or c?)
1142 G4bool IsAnti = id1 < 0; // quark 1 is an antiquark?
1143 if( (IsUp && IsAnti) || (!IsUp && !IsAnti) ) PDGEncoding = - PDGEncoding;
1144 // Correction for the true neutral mesons
1145 if( PDGEncoding == -111 || PDGEncoding == -113 || PDGEncoding == -223 ||
1146 PDGEncoding == -221 || PDGEncoding == -331 || PDGEncoding == -333 )
1147 PDGEncoding = - PDGEncoding;
1148 }
1149 G4QHadron* Meson= new G4QHadron(PDGEncoding);
1150#ifdef debug
1151 G4cout<<"G4QString::CreateBaryon: Meson is created with PDG="<<PDGEncoding<<G4endl;
1152#endif
1153 //delete black; // It is better to delete here and consider
1154 //delete white; // the hadron creation as a delete equivalent
1155 return Meson;
1156}
1157
1158// Creation of the Baryon out of two partons (q, di-q), (anti-q, anti-di-q)
1159G4QHadron* G4QString::CreateBaryon(G4QParton* black, G4QParton* white, Spin theSpin)
1160{
1161 G4int id1= black->GetPDGCode();
1162 G4int id2= white->GetPDGCode();
1163#ifdef debug
1164 G4cout<<"G4QString::CreateBaryon: bT="<<black->GetType()<<"("<<id1<<"), wT="
1165 <<white->GetType()<<"("<<id2<<")"<<G4endl;
1166#endif
1167 if(std::abs(id1) < std::abs(id2))
1168 {
1169 G4int xchg = id1;
1170 id1 = id2;
1171 id2 = xchg;
1172 }
1173 if(std::abs(id1)<1000 || std::abs(id2)> 3)
1174 {
1175 G4cerr<<"***G4QString::CreateBaryon: q1="<<id1<<", q2="<<id2
1176 <<" can't create a Baryon"<<G4endl;
1177 G4Exception("G4QString::CreateBaryon:","72",FatalException,"WrongQdQSequence");
1178 }
1179 G4int ifl1= std::abs(id1)/1000;
1180 G4int ifl2 = (std::abs(id1) - ifl1 * 1000)/100;
1181 G4int diquarkSpin = std::abs(id1)%10;
1182 G4int ifl3 = id2;
1183 if (id1 < 0) {ifl1 = - ifl1; ifl2 = - ifl2;}
1184 //... Construct baryon, distinguish Lambda and Sigma baryons.
1185 G4int kfla = std::abs(ifl1);
1186 G4int kflb = std::abs(ifl2);
1187 G4int kflc = std::abs(ifl3);
1188 G4int kfld = std::max(kfla,kflb);
1189 kfld = std::max(kfld,kflc);
1190 G4int kflf = std::min(kfla,kflb);
1191 kflf = std::min(kflf,kflc);
1192 G4int kfle = kfla + kflb + kflc - kfld - kflf;
1193 //... baryon with content uuu or ddd or sss has always spin = 3/2
1194 if(kfla==kflb && kflb==kflc) theSpin=SpinThreeHalf;
1195
1196 G4int kfll = 0;
1197 if(theSpin == SpinHalf && kfld > kfle && kfle > kflf)
1198 {
1199 // Spin J=1/2 and all three quarks different
1200 // Two states exist: (uds -> lambda or sigma0)
1201 // - lambda: s(ud)0 s : 3122; ie. reverse the two lighter quarks
1202 // - sigma0: s(ud)1 s : 3212
1203 if(diquarkSpin == 1 )
1204 {
1205 if ( kfla == kfld) kfll = 1; // heaviest quark in diquark
1206 else kfll = G4int(0.25 + G4UniformRand());
1207 }
1208 if(diquarkSpin==3 && kfla!=kfld) kfll = G4int(0.75+G4UniformRand());
1209 }
1210 G4int PDGEncoding=0;
1211 if (kfll == 1) PDGEncoding = 1000 * kfld + 100 * kflf + 10 * kfle + theSpin;
1212 else PDGEncoding = 1000 * kfld + 100 * kfle + 10 * kflf + theSpin;
1213 if (id1 < 0) PDGEncoding = -PDGEncoding;
1214 G4QHadron* Baryon= new G4QHadron(PDGEncoding);
1215#ifdef debug
1216 G4cout<<"G4QString::CreateBaryon: Baryon is created with PDG="<<PDGEncoding<<G4endl;
1217#endif
1218 //delete black; // It is better to delete here and consider
1219 //delete white; // the hadron creation as a delete equivalent
1220 return Baryon;
1221} // End of CreateBaryon
1222
1224{
1225 //static G4double mesonLowSpin = 0.25; // probability to create scalar meson (2s+1)
1226 //static G4double baryonLowSpin= 1./3.; // probability to create 1/2 baryon (2s+1)
1227 static G4double mesonLowSpin = 0.5; // probability to create scalar meson (spFlip)
1228 static G4double baryonLowSpin= 0.5; // probability to create 1/2 baryon (spinFlip)
1229 G4int bT=black->GetType();
1230 G4int wT=white->GetType();
1231#ifdef debug
1232 G4cout<<"G4QString::CreateHadron: bT="<<bT<<"("<<black->GetPDGCode()<<"), wT="<<wT<<"("
1233 <<white->GetPDGCode()<<")"<<G4endl;
1234#endif
1235 if(bT==2 || wT==2)
1236 {
1237 // Baryon consists of quark and at least one di-quark
1238 Spin spin = (G4UniformRand() < baryonLowSpin) ? SpinHalf : SpinThreeHalf;
1239#ifdef debug
1240 G4cout<<"G4QString::CreateHadron: ----> Baryon is under creation"<<G4endl;
1241#endif
1242 return CreateBaryon(black, white, spin);
1243 }
1244 else
1245 {
1246 // Meson consists of quark and abnti-quark
1247 Spin spin = (G4UniformRand() < mesonLowSpin) ? SpinZero : SpinOne;
1248#ifdef debug
1249 G4cout<<"G4QString::CreateHadron: ----> Meson is under creation"<<G4endl;
1250#endif
1251 return CreateMeson(black, white, spin);
1252 }
1253} // End of Create Hadron
1254
1255// Creation of only High Spin (2,3/2) hadrons
1257{
1258 G4int bT=black->GetType();
1259 G4int wT=white->GetType();
1260#ifdef debug
1261 G4cout<<"G4QString::CreateLowSpinHadron: ***Called***, bT="<<bT<<"("<<black->GetPDGCode()
1262 <<"), wT="<<wT<<"("<<white->GetPDGCode()<<")"<<G4endl;
1263#endif
1264 if(bT == 1 && wT == 1)
1265 {
1266#ifdef debug
1267 G4cout<<"G4QString::CreateLowSpinHadron: ----> Meson is under creation"<<G4endl;
1268#endif
1269 return CreateMeson(black, white, SpinZero);
1270 }
1271 else // returns a SpinThreeHalf Baryon if all quarks are the same
1272 {
1273#ifdef debug
1274 G4cout<<"G4QString::CreateLowSpinHadron: ----> Baryon is under creation"<<G4endl;
1275#endif
1276 return CreateBaryon(black, white, SpinHalf);
1277 }
1278} // End of CreateLowSpinHadron
1279
1280// Creation of only High Spin (2,3/2) hadrons
1282{
1283 G4int bT=black->GetType();
1284 G4int wT=white->GetType();
1285#ifdef debug
1286 G4cout<<"G4QString::CreateHighSpinHadron:***Called***, bT="<<bT<<"("<<black->GetPDGCode()
1287 <<"), wT="<<wT<<"("<<white->GetPDGCode()<<")"<<G4endl;
1288#endif
1289 if(bT == 1 && wT == 1)
1290 {
1291#ifdef debug
1292 G4cout<<"G4QString::CreateHighSpinHadron: ----> Meson is created"<<G4endl;
1293#endif
1294 return CreateMeson(black,white, SpinOne);
1295 }
1296 else
1297 {
1298#ifdef debug
1299 G4cout<<"G4QString::CreateHighSpinHadron: ----> Baryon is created"<<G4endl;
1300#endif
1301 return CreateBaryon(black,white,SpinThreeHalf);
1302 }
1303} // End of CreateHighSpinHadron
@ LT
Definition: Evaluator.cc:66
@ FatalException
CLHEP::HepLorentzVector G4LorentzVector
std::vector< G4QHadron * > G4QHadronVector
std::pair< G4QHadron *, G4QHadron * > G4QHadronPair
Definition: G4QHadron.hh:165
CLHEP::Hep3Vector G4ThreeVector
double G4double
Definition: G4Types.hh:64
int G4int
Definition: G4Types.hh:66
bool G4bool
Definition: G4Types.hh:67
#define G4endl
Definition: G4ios.hh:52
G4DLLIMPORT std::ostream G4cerr
G4DLLIMPORT std::ostream G4cout
#define C1
#define G4UniformRand()
Definition: Randomize.hh:53
double z() const
double x() const
double mag2() const
double y() const
void setZ(double)
HepLorentzRotation & rotateY(double delta)
HepLorentzRotation & rotateZ(double delta)
HepLorentzRotation inverse() const
double theta() const
Hep3Vector boostVector() const
HepLorentzVector & boost(double, double, double)
Hep3Vector vect() const
G4LorentzVector Get4Momentum() const
Definition: G4QHadron.hh:79
G4double GetMass() const
Definition: G4QHadron.hh:176
void SetFormationTime(G4double fT)
Definition: G4QHadron.hh:113
G4double GetFormationTime()
Definition: G4QHadron.hh:92
G4int GetPDGCode() const
Definition: G4QHadron.hh:170
const G4ThreeVector & GetPosition() const
Definition: G4QHadron.hh:182
void SetPosition(const G4ThreeVector &aPosition)
Definition: G4QHadron.hh:189
G4double GetMass2() const
Definition: G4QHadron.hh:177
void Set4Momentum(const G4LorentzVector &aMom)
Definition: G4QHadron.hh:187
G4QParton * GetParton1()
G4QParton * GetParton2()
G4int GetDirection()
void SetPDGCode(G4int aPDG)
Definition: G4QParton.cc:130
const G4ThreeVector & GetPosition() const
Definition: G4QParton.hh:83
const G4int & GetType() const
Definition: G4QParton.hh:88
G4int GetPDGCode() const
Definition: G4QParton.hh:81
const G4LorentzVector & Get4Momentum() const
Definition: G4QParton.hh:84
void Set4Momentum(const G4LorentzVector &aMomentum)
Definition: G4QParton.hh:75
G4QHadron * CreateHadron(G4QParton *black, G4QParton *white)
Definition: G4QString.cc:1223
G4bool StopFragmentation()
Definition: G4QString.hh:106
G4QHadron * CreateLowSpinHadron(G4QParton *black, G4QParton *white)
Definition: G4QString.cc:1256
G4QHadron * Splitup(G4bool QL)
Definition: G4QString.cc:877
G4ThreeVector DecayPt()
Definition: G4QString.cc:864
G4bool IsFragmentable()
Definition: G4QString.hh:112
G4QHadronVector * FragmentString(G4bool QL)
Definition: G4QString.cc:348
void LorentzRotate(const G4LorentzRotation &rotation)
Definition: G4QString.cc:131
G4QParton * GetLeftParton() const
Definition: G4QString.hh:87
void SetLeftPartonStable()
Definition: G4QString.cc:826
G4int GetDirection() const
Definition: G4QString.hh:89
G4LorentzVector * SplitEandP(G4QHadron *pHadron, G4bool QL)
Definition: G4QString.cc:959
G4QPartonPair CreatePartonPair(G4int NeedParticle, G4bool AllowDiquarks=true)
Definition: G4QString.cc:1072
void SetRightPartonStable()
Definition: G4QString.cc:833
static void SetParameters(G4double mCut, G4double sigQT, G4double DQSup, G4double DQBU, G4double smPar, G4double SSup, G4double SigPt)
Definition: G4QString.cc:181
G4bool StableIsQuark() const
Definition: G4QString.hh:97
G4LorentzVector Get4Momentum() const
Definition: G4QString.cc:124
G4int SampleQuarkFlavor()
Definition: G4QString.hh:140
G4QHadron * QuarkSplitup(G4QParton *decay, G4QParton *&created)
Definition: G4QString.cc:1007
G4QHadron * CreateHighSpinHadron(G4QParton *black, G4QParton *white)
Definition: G4QString.cc:1281
G4ThreeVector SampleQuarkPt()
Definition: G4QString.cc:1000
G4QParton * GetRightParton() const
Definition: G4QString.hh:88
G4double FragmentationMass(G4int HighSpin=0, G4QHadronPair *pdefs=0)
Definition: G4QString.cc:769
G4int GetDecayDirection() const
Definition: G4QString.cc:840
const G4ThreeVector & GetPosition() const
Definition: G4QString.hh:85
G4bool DecayIsQuark() const
Definition: G4QString.hh:96
G4double Mass2() const
Definition: G4QString.hh:99
G4QHadron * DiQuarkSplitup(G4QParton *decay, G4QParton *&created)
Definition: G4QString.cc:1022
void Boost(G4ThreeVector &Velocity)
Definition: G4QString.cc:152
G4QHadronVector * LightFragmentationTest()
Definition: G4QString.cc:702
void ExciteString(G4QParton *Col, G4QParton *AntiCol, G4int Dir)
Definition: G4QString.cc:254
ush Pos
Definition: deflate.h:82
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
Definition: G4Exception.cc:41
T sqr(const T &x)
Definition: templates.hh:145