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