// // ******************************************************************** // * License and Disclaimer * // * * // * The Geant4 software is copyright of the Copyright Holders of * // * the Geant4 Collaboration. It is provided under the terms and * // * conditions of the Geant4 Software License, included in the file * // * LICENSE and available at http://cern.ch/geant4/license . These * // * include a list of copyright holders. * // * * // * Neither the authors of this software system, nor their employing * // * institutes,nor the agencies providing financial support for this * // * work make any representation or warranty, express or implied, * // * regarding this software system or assume any liability for its * // * use. Please see the license in the file LICENSE and URL above * // * for the full disclaimer and the limitation of liability. * // * * // * This code implementation is the result of the scientific and * // * technical work of the GEANT4 collaboration. * // * By using, copying, modifying or distributing the software (or * // * any work based on the software) you agree to acknowledge its * // * use in resulting scientific publications, and indicate your * // * acceptance of all terms of the Geant4 Software license. * // ******************************************************************** // // // // ----------------------------------------------------------------------------- // GEANT 4 class implementation file // // History: first implementation, Maxim Komogorov, 10-Jul-1998 // ----------------------------------------------------------------------------- #include "G4LundStringFragmentation.hh" #include "G4PhysicalConstants.hh" #include "G4SystemOfUnits.hh" #include "Randomize.hh" #include "G4FragmentingString.hh" #include "G4DiQuarks.hh" #include "G4Quarks.hh" #include "G4Exp.hh" #include "G4Pow.hh" //#define debug_LUNDfragmentation // Class G4LundStringFragmentation //************************************************************************************* G4LundStringFragmentation::G4LundStringFragmentation() { SetMassCut(210.*MeV); // Mpi + Delta // For ProduceOneHadron it is required // that no one pi-meson can be produced. SigmaQT = 0.435 * GeV; SetStringTensionParameter(1.*GeV/fermi); SetDiquarkBreakProbability(0.5); SetStrangenessSuppression((1.0 - 0.13)/2.0); SetDiquarkSuppression(0.15); // For the time being, set to 0.0 the probabilities for c-cbar and b-bbar creation. SetProbCCbar(0.0); //(0.005); // According to O.I. Piskunova Yad. Fiz. 56 (1993) 1094 SetProbBBbar(0.0); //(5.0e-5); // According to O.I. Piskunova Yad. Fiz. 56 (1993) 1094 SetMinMasses(); // For treating of small string decays } //-------------------------------------------------------------------------------------- G4KineticTrackVector* G4LundStringFragmentation::FragmentString(const G4ExcitedString& theString) { // Can no longer modify Parameters for Fragmentation. PastInitPhase=true; G4FragmentingString aString(theString); SetMinimalStringMass(&aString); #ifdef debug_LUNDfragmentation G4cout<GetPDGcode()<<" " <GetPDGcode()<<" " <Get4Momentum()<Get4Momentum()<operator[](0)->SetFormationTime(theString.GetTimeOfCreation()); LeftVector->operator[](0)->SetPosition(theString.GetPosition()); if (LeftVector->size() > 1) { // 2 hadrons created from qq-qqbar are stored LeftVector->operator[](1)->SetFormationTime(theString.GetTimeOfCreation()); LeftVector->operator[](1)->SetPosition(theString.GetPosition()); } return LeftVector; } #ifdef debug_LUNDfragmentation G4cout<<"The string will be fragmented. "<begin(), LeftVector->end(), DeleteKineticTrack()); LeftVector->clear(); std::for_each(RightVector->begin(), RightVector->end(), DeleteKineticTrack()); delete RightVector; return LeftVector; } // Join Left- and RightVector into LeftVector in correct order. while (!RightVector->empty()) { LeftVector->push_back(RightVector->back()); RightVector->erase(RightVector->end()-1); } delete RightVector; return LeftVector; } //---------------------------------------------------------------------------------- G4bool G4LundStringFragmentation::IsItFragmentable(const G4FragmentingString * const string) { SetMinimalStringMass(string); //G4cout<<"MinM StrM "<Get4Momentum().mag()<Get4Momentum().mag(); //MinimalStringMass is negative and large for a string with unknown particles in a final 2-particle decay. } //---------------------------------------------------------------------------------------- G4bool G4LundStringFragmentation::Loop_toFragmentString( const G4ExcitedString &theString, G4KineticTrackVector * & LeftVector, G4KineticTrackVector * & RightVector ) { #ifdef debug_LUNDfragmentation G4cout<<"Loop_toFrag "<GetPDGcode()<<" " <Get4Momentum()<GetPDGcode()<<" " <Get4Momentum()<begin(), LeftVector->end(), DeleteKineticTrack()); LeftVector->clear(); std::for_each(RightVector->begin(), RightVector->end(), DeleteKineticTrack()); RightVector->clear(); // Main fragmentation loop until the string will not be able to fragment inner_success=true; // set false on failure. const G4int maxNumberOfLoops = 1000; G4int loopCounter = -1; while ( (! StopFragmenting(currentString)) && ++loopCounter < maxNumberOfLoops ) { // Split current string into hadron + new string #ifdef debug_LUNDfragmentation G4cout<<"The string will fragment. "<GetDecayDirection()<TransformToAlignedCms(); toObserverFrame= toCms.inverse(); #ifdef debug_LUNDfragmentation //G4cout<<"CMS Left mom "<GetPleft()<GetPright()<GetPstring()<GetDefinition()->GetParticleName()<GetDecayDirection()<Set4Momentum(toObserverFrame*Hadron->Get4Momentum()); G4double TimeOftheStringCreation=theString.GetTimeOfCreation(); G4ThreeVector PositionOftheStringCreation(theString.GetPosition()); G4LorentzVector Coordinate(Hadron->GetPosition(), Hadron->GetFormationTime()); G4LorentzVector Momentum = toObserverFrame*Coordinate; Hadron->SetFormationTime(TimeOftheStringCreation + Momentum.e() - fermi/c_light); G4ThreeVector aPosition(Momentum.vect()); Hadron->SetPosition(PositionOftheStringCreation+aPosition); // Open to protect hadron production at fragmentation if ( currentString->GetDecayDirection() > 0 ) { LeftVector->push_back(Hadron); } else { RightVector->push_back(Hadron); } delete currentString; currentString=newString; } else { if ( newString ) delete newString; } currentString->LorentzRotate(toObserverFrame); }; if ( loopCounter >= maxNumberOfLoops ) { inner_success=false; } // Split remaining string into 2 final hadrons. #ifdef debug_LUNDfragmentation if (inner_success) G4cout<<"Split remaining string into 2 final hadrons."<IsAFourQuarkString()) { return G4UniformRand() < G4Exp(-0.0005*(string->Mass() - MinimalStringMass)); } else { if (MinimalStringMass < 0.0 ) return false; // For a string with di-quark having c or b quarks and s, c, b quarks G4bool Result = G4UniformRand() < G4Exp(-0.66e-6*(string->Mass()*string->Mass() - MinimalStringMass*MinimalStringMass)); // G4bool Result = string->Mass() < MinimalStringMass + 150.*MeV*G4UniformRand(); // a'la LUND #ifdef debug_LUNDfragmentation G4cout<<"StopFragmenting MinimalStringMass string->Mass() "<Mass()<GetLeftParton()->GetPDGEncoding()<<" " <GetRightParton()->GetPDGEncoding()<<" " <<"Direction " <GetDecayDirection()<SetLeftPartonStable(); } else { string->SetRightPartonStable(); } G4ParticleDefinition *newStringEnd; G4ParticleDefinition * HadronDefinition; G4double StringMass=string->Mass(); G4double ProbDqADq = GetDiquarkSuppress(); G4double ProbSaS = 1.0 - 2.0 * GetStrangeSuppress(); #ifdef debug_LUNDfragmentation G4cout<<"StrMass DiquarkSuppression "<GetLeftParton()->GetParticleSubType() != "quark") NumberOfpossibleBaryons++; if (string->GetRightParton()->GetParticleSubType() != "quark") NumberOfpossibleBaryons++; G4double ActualProb = ProbDqADq ; ActualProb *= (1.0-sqr(NumberOfpossibleBaryons*1400.0/StringMass)); SetDiquarkSuppression(ActualProb); G4double Mth = 1250.0; // 2 Mk + Mpi if ( NumberOfpossibleBaryons == 3 ){Mth = 2520.0;} // Mlambda/Msigma + Mk + Mpi else if ( NumberOfpossibleBaryons == 4 ){Mth = 2380.0;} // 2 Mlambda/Msigma + Mk + Mpi else {} ActualProb = ProbSaS * (1.0 - G4Pow::GetInstance()->powA( Mth/StringMass , 4.0 )); if ( ActualProb < 0.0 ) ActualProb = 0.0; SetStrangenessSuppression((1.0-ActualProb)/2.0); #ifdef debug_LUNDfragmentation G4cout<<"StrMass DiquarkSuppression corrected "<DecayIsQuark()) { HadronDefinition= QuarkSplitup(string->GetDecayParton(), newStringEnd); } else { HadronDefinition= DiQuarkSplitup(string->GetDecayParton(), newStringEnd); } SetDiquarkSuppression(ProbDqADq); SetStrangenessSuppression((1.0-ProbSaS)/2.0); if ( HadronDefinition == NULL ) { G4KineticTrack * Hadron =0; return Hadron; } #ifdef debug_LUNDfragmentation G4cout<<"The parton "<GetDecayParton()->GetPDGEncoding()<<" " <<" produces hadron "<GetParticleName() <<" and is transformed to "<GetPDGEncoding()<GetPDGEncoding()/1000; G4int decayQuarkEncoding = (decay->GetPDGEncoding()/100)%10; if (G4UniformRand() < 0.5) { G4int Swap = stableQuarkEncoding; stableQuarkEncoding = decayQuarkEncoding; decayQuarkEncoding = Swap; } G4int IsParticle=(decayQuarkEncoding>0) ? -1 : +1; // if we have a quark, we need antiquark) pDefPair QuarkPair = CreatePartonPair(IsParticle,false); // no diquarks wanted //... Build new Diquark G4int QuarkEncoding=QuarkPair.second->GetPDGEncoding(); G4int i10 = std::max(std::abs(QuarkEncoding), std::abs(stableQuarkEncoding)); G4int i20 = std::min(std::abs(QuarkEncoding), std::abs(stableQuarkEncoding)); G4int spin = (i10 != i20 && G4UniformRand() <= 0.5)? 1 : 3; G4int NewDecayEncoding = -1*IsParticle*(i10 * 1000 + i20 * 100 + spin); created = FindParticle(NewDecayEncoding); G4ParticleDefinition * decayQuark=FindParticle(decayQuarkEncoding); G4ParticleDefinition * had=hadronizer->Build(QuarkPair.first, decayQuark); StrangeSuppress=StrSup; return had; } else { //... Diquark does not break G4int IsParticle=(decay->GetPDGEncoding()>0) ? +1 : -1; // if we have a diquark, we need quark StrangeSuppress=(1.0 - ProbQQbar * 0.9)/2.0; pDefPair QuarkPair = CreatePartonPair(IsParticle,false); // no diquarks wanted created = QuarkPair.second; G4ParticleDefinition * had=hadronizer->Build(QuarkPair.first, decay); StrangeSuppress=StrSup; return had; } } //----------------------------------------------------------------------------- G4LorentzVector * G4LundStringFragmentation::SplitEandP(G4ParticleDefinition * pHadron, G4FragmentingString * string, G4FragmentingString * newString) { G4LorentzVector String4Momentum=string->Get4Momentum(); G4double StringMT2=string->MassT2(); G4double StringMT =std::sqrt(StringMT2); G4double HadronMass = pHadron->GetPDGMass(); SetMinimalStringMass(newString); if ( MinimalStringMass < 0.0 ) return nullptr; #ifdef debug_LUNDfragmentation G4cout<GetParticleName()< string->Mass()) || MinimalStringMass < 0.) { #ifdef debug_LUNDfragmentation G4cout<<"Mass of the string is not sufficient to produce the hadron!"< StringLoopInterrupt) {return 0;} HadronMt = HadronMass - 300.0*G4Log(G4UniformRand()); Pt2 = sqr(HadronMt)-sqr(HadronMass); Pt=std::sqrt(Pt2); phi = 2.*pi*G4UniformRand(); G4ThreeVector SampleQuarkPtw= G4ThreeVector(Pt * std::cos(phi),Pt * std::sin(phi),0); HadronPt =SampleQuarkPtw + string->DecayPt(); HadronPt.setZ(0); RemSysPt = StringPt - HadronPt; HadronMassT2 = sqr(HadronMass) + HadronPt.mag2(); ResidualMassT2=sqr(MinimalStringMass) + RemSysPt.mag2(); } while (std::sqrt(HadronMassT2) + std::sqrt(ResidualMassT2) > StringMT); //... sample z to define hadron longitudinal momentum and energy //... but first check the available phase space G4double Pz2 = (sqr(StringMT2 - HadronMassT2 - ResidualMassT2) - 4*HadronMassT2 * ResidualMassT2)/4./StringMT2; if (Pz2 < 0 ) {return 0;} // have to start all over! //... then compute allowed z region z_min <= z <= z_max G4double Pz = std::sqrt(Pz2); G4double zMin = (std::sqrt(HadronMassT2+Pz2) - Pz)/std::sqrt(StringMT2); // G4double zMin = (std::sqrt(HadronMassT2+Pz2) - 0.)/std::sqrt(StringMT2); // For testing purposes G4double zMax = (std::sqrt(HadronMassT2+Pz2) + Pz)/std::sqrt(StringMT2); if (zMin >= zMax) return 0; // have to start all over! G4double z = GetLightConeZ(zMin, zMax, string->GetDecayParton()->GetPDGEncoding(), pHadron, HadronPt.x(), HadronPt.y()); //... now compute hadron longitudinal momentum and energy // longitudinal hadron momentum component HadronPz HadronPt.setZ(0.5* string->GetDecayDirection() * (z * string->LightConeDecay() - HadronMassT2/(z * string->LightConeDecay()))); G4double HadronE = 0.5* (z * string->LightConeDecay() + HadronMassT2/(z * string->LightConeDecay())); G4LorentzVector * a4Momentum= new G4LorentzVector(HadronPt,HadronE); #ifdef debug_LUNDfragmentation G4cout<GetDecayDirection() "<GetDecayDirection()<LightConeDecay() "<LightConeDecay()<GetPDGMass(); G4int HadronEncoding=std::abs(pHadron->GetPDGEncoding()); G4double Mt2 = Px*Px + Py*Py + Mass*Mass; G4double Alund, Blund; G4double zOfMaxyf(0.), maxYf(1.), z(0.), yf(1.); if (!((std::abs(PDGEncodingOfDecayParton) > 1000) && (HadronEncoding > 1000)) ) { // ---------------- Quark fragmentation and qq-> meson ---------------------- Alund=1.; Blund=0.7/GeV/GeV; G4double BMt2 = Blund*Mt2; if (Alund == 1.0) { zOfMaxyf=BMt2/(Blund*Mt2 + 1.);} else { zOfMaxyf = ((1.0+BMt2) - std::sqrt(sqr(1.0-BMt2) + 4.0*BMt2*Alund))/2.0/(1.-Alund); } if (zOfMaxyf < zmin) {zOfMaxyf=zmin;} if (zOfMaxyf > zmax) {zOfMaxyf=zmax;} maxYf=(1-zOfMaxyf)/zOfMaxyf * G4Exp(-Blund*Mt2/zOfMaxyf); const G4int maxNumberOfLoops = 1000; G4int loopCounter = 0; do { z = zmin + G4UniformRand()*(zmax-zmin); //yf = (1-z)/z * G4Exp(-Blund*Mt2/z); yf = G4Pow::GetInstance()->powA(1.0-z,Alund)/z*G4Exp(-BMt2/z); } while ( (G4UniformRand()*maxYf > yf) && ++loopCounter < maxNumberOfLoops ); if ( loopCounter >= maxNumberOfLoops ) { z = 0.5*(zmin + zmax); // Just a value between zmin and zmax, no physics considerations at all! } return z; } if (std::abs(PDGEncodingOfDecayParton) > 1000) { G4double an = 2.5; an +=(sqr(Px)+sqr(Py))/sqr(GeV)-0.5; z=zmin + (zmax-zmin)*G4Pow::GetInstance()->powA(G4UniformRand(),1./an); } return z; } //---------------------------------------------------------------------------------------------------------- G4bool G4LundStringFragmentation::SplitLast(G4FragmentingString * string, G4KineticTrackVector * LeftVector, G4KineticTrackVector * RightVector) { //... perform last cluster decay SetMinimalStringMass( string); if ( MinimalStringMass < 0.) return false; #ifdef debug_LUNDfragmentation G4cout<GetLeftParton()->GetPDGEncoding()<<" "<GetPleft()<GetRightParton()->GetPDGEncoding()<<" "<GetPright()<GetPstring()<<" "<GetPstring().mag()<Get4Momentum(); G4LorentzRotation toCms=string->TransformToAlignedCms(); G4LorentzRotation toObserverFrame= toCms.inverse(); G4double StringMass=string->Mass(); G4ParticleDefinition * LeftHadron(0), * RightHadron(0); NumberOf_FS=0; for (G4int i=0; i<350; i++) {FS_Weight[i]=0.;} G4int sampledState = 0; #ifdef debug_LUNDfragmentation G4cout<<"StrMass "<GetLeftParton()->GetParticleName()<<" " <GetRightParton()->GetParticleName()<SetLeftPartonStable(); // to query quark contents.. if (string->IsAFourQuarkString() ) { // The string is qq-qqbar type. Diquarks are on the string ends if (StringMass-MinimalStringMass < 0.) { if (! Diquark_AntiDiquark_belowThreshold_lastSplitting(string, LeftHadron, RightHadron) ) { return false; } } else { Diquark_AntiDiquark_aboveThreshold_lastSplitting(string, LeftHadron, RightHadron); if (NumberOf_FS == 0) return false; sampledState = SampleState(); if (string->GetLeftParton()->GetPDGEncoding() < 0) { LeftHadron =FS_LeftHadron[sampledState]; RightHadron=FS_RightHadron[sampledState]; } else { LeftHadron =FS_RightHadron[sampledState]; RightHadron=FS_LeftHadron[sampledState]; } } } else { if (string->DecayIsQuark() && string->StableIsQuark() ) { //... there are quarks on cluster ends #ifdef debug_LUNDfragmentation G4cout<<"Q Q string LastSplit"<GetLeftParton()->GetPDGEncoding() < 0) { LeftHadron =FS_RightHadron[sampledState]; RightHadron=FS_LeftHadron[sampledState]; } else { LeftHadron =FS_LeftHadron[sampledState]; RightHadron=FS_RightHadron[sampledState]; } } else { //... there is a Diquark on one of the cluster ends #ifdef debug_LUNDfragmentation G4cout<<"DiQ Q string Last Split"<GetLeftParton()->GetParticleSubType() == "quark") { LeftHadron =FS_LeftHadron[sampledState]; RightHadron=FS_RightHadron[sampledState]; } else { LeftHadron =FS_RightHadron[sampledState]; RightHadron=FS_LeftHadron[sampledState]; } } } #ifdef debug_LUNDfragmentation G4cout<<"Sampled hadrons: "<GetParticleName()<<" "<GetParticleName()<GetPleft(), P_right = string->GetPright(); G4LorentzVector LeftMom, RightMom; G4ThreeVector Pos; Sample4Momentum(&LeftMom, LeftHadron->GetPDGMass(), &RightMom, RightHadron->GetPDGMass(), StringMass); // Sample4Momentum ascribes LeftMom.pz() along positive Z axis for baryons in many cases. // It must be negative in case when the system is moving against Z axis. if (!(string->DecayIsQuark() && string->StableIsQuark() )) { // Only for qq - q, q - qq, and qq - qqbar ------------------- if (std::abs(string->GetLeftParton()->GetPDGEncoding()) > 1000) { if (P_left.z() <= 0.) {G4LorentzVector tmp = LeftMom; LeftMom=RightMom; RightMom=tmp;} } else { if (P_right.z() >= 0.) {G4LorentzVector tmp = LeftMom; LeftMom=RightMom; RightMom=tmp;} } } LeftMom *=toObserverFrame; RightMom*=toObserverFrame; LeftVector->push_back(new G4KineticTrack(LeftHadron, 0, Pos, LeftMom)); RightVector->push_back(new G4KineticTrack(RightHadron, 0, Pos, RightMom)); string->LorentzRotate(toObserverFrame); return true; } //---------------------------------------------------------------------------------------- G4bool G4LundStringFragmentation:: Diquark_AntiDiquark_belowThreshold_lastSplitting(G4FragmentingString * & string, G4ParticleDefinition * & LeftHadron, G4ParticleDefinition * & RightHadron) { G4double StringMass = string->Mass(); G4bool isOK = false; G4int cClusterInterrupt = 0; do { G4int LeftQuark1= string->GetLeftParton()->GetPDGEncoding()/1000; G4int LeftQuark2=(string->GetLeftParton()->GetPDGEncoding()/100)%10; G4int RightQuark1= string->GetRightParton()->GetPDGEncoding()/1000; G4int RightQuark2=(string->GetRightParton()->GetPDGEncoding()/100)%10; if (G4UniformRand()<0.5) { LeftHadron =hadronizer->Build(FindParticle( LeftQuark1), FindParticle(RightQuark1)); RightHadron= (LeftHadron == nullptr) ? nullptr : hadronizer->Build(FindParticle( LeftQuark2), FindParticle(RightQuark2)); } else { LeftHadron =hadronizer->Build(FindParticle( LeftQuark1), FindParticle(RightQuark2)); RightHadron=(LeftHadron == nullptr) ? nullptr : hadronizer->Build(FindParticle( LeftQuark2), FindParticle(RightQuark1)); } isOK = (LeftHadron != nullptr) && (RightHadron != nullptr); if(isOK) { isOK = (StringMass > LeftHadron->GetPDGMass() + RightHadron->GetPDGMass()); } ++cClusterInterrupt; //... repeat procedure, if mass of cluster is too low to produce hadrons //... ClusterMassCut = 0.15*GeV model parameter } while (isOK == false || cClusterInterrupt < ClusterLoopInterrupt); /* Loop checking, 07.08.2015, A.Ribon */ return isOK; } //---------------------------------------------------------------------------------------- G4bool G4LundStringFragmentation:: Diquark_AntiDiquark_aboveThreshold_lastSplitting(G4FragmentingString * & string, G4ParticleDefinition * & LeftHadron, G4ParticleDefinition * & RightHadron) { // StringMass-MinimalStringMass > 0. Creation of 2 baryons is possible ---- G4double StringMass = string->Mass(); G4double StringMassSqr= sqr(StringMass); G4ParticleDefinition * Di_Quark; G4ParticleDefinition * Anti_Di_Quark; if (string->GetLeftParton()->GetPDGEncoding() < 0) { Anti_Di_Quark =string->GetLeftParton(); Di_Quark=string->GetRightParton(); } else { Anti_Di_Quark =string->GetRightParton(); Di_Quark=string->GetLeftParton(); } G4int IDAnti_di_quark =Anti_Di_Quark->GetPDGEncoding(); G4int AbsIDAnti_di_quark =std::abs(IDAnti_di_quark); G4int IDdi_quark =Di_Quark->GetPDGEncoding(); G4int AbsIDdi_quark =std::abs(IDdi_quark); G4int ADi_q1=AbsIDAnti_di_quark/1000; G4int ADi_q2=(AbsIDAnti_di_quark-ADi_q1*1000)/100; G4int Di_q1=AbsIDdi_quark/1000; G4int Di_q2=(AbsIDdi_quark-Di_q1*1000)/100; NumberOf_FS=0; for (G4int ProdQ=1; ProdQ < 6; ProdQ++) { G4int StateADiQ=0; const G4int maxNumberOfLoops = 1000; G4int loopCounter = 0; do // while(Meson[AbsIDquark-1][ProdQ-1][StateQ]<>0); { LeftHadron=G4ParticleTable::GetParticleTable()->FindParticle( -Baryon[ADi_q1-1][ADi_q2-1][ProdQ-1][StateADiQ]); if (LeftHadron == NULL) continue; G4double LeftHadronMass=LeftHadron->GetPDGMass(); G4int StateDiQ=0; const G4int maxNumberOfInternalLoops = 1000; G4int internalLoopCounter = 0; do // while(Baryon[Di_q1-1][Di_q2-1][ProdQ-1][StateDiQ]<>0); { RightHadron=G4ParticleTable::GetParticleTable()->FindParticle( +Baryon[Di_q1-1][Di_q2-1][ProdQ-1][StateDiQ]); if (RightHadron == NULL) continue; G4double RightHadronMass=RightHadron->GetPDGMass(); if (StringMass > LeftHadronMass + RightHadronMass) { if ( NumberOf_FS > 349 ) { G4ExceptionDescription ed; ed << " NumberOf_FS exceeds its limit: NumberOf_FS=" << NumberOf_FS << G4endl; G4Exception( "G4LundStringFragmentation::Diquark_AntiDiquark_aboveThreshold_lastSplitting ", "HAD_LUND_001", JustWarning, ed ); NumberOf_FS = 349; } G4double FS_Psqr=lambda(StringMassSqr,sqr(LeftHadronMass), sqr(RightHadronMass)); //FS_Psqr=1.; FS_Weight[NumberOf_FS]=std::sqrt(FS_Psqr)*FS_Psqr* BaryonWeight[ADi_q1-1][ADi_q2-1][ProdQ-1][StateADiQ]* BaryonWeight[Di_q1-1][Di_q2-1][ProdQ-1][StateDiQ]* Prob_QQbar[ProdQ-1]; FS_LeftHadron[NumberOf_FS] = LeftHadron; FS_RightHadron[NumberOf_FS]= RightHadron; NumberOf_FS++; } // End of if (StringMass > LeftHadronMass + RightHadronMass) StateDiQ++; } while( (Baryon[Di_q1-1][Di_q2-1][ProdQ-1][StateDiQ]!=0) && ++internalLoopCounter < maxNumberOfInternalLoops ); if ( internalLoopCounter >= maxNumberOfInternalLoops ) { return false; } StateADiQ++; } while( (Baryon[ADi_q1-1][ADi_q2-1][ProdQ-1][StateADiQ]!=0) && ++loopCounter < maxNumberOfLoops ); if ( loopCounter >= maxNumberOfLoops ) { return false; } } // End of for (G4int ProdQ=1; ProdQ < 4; ProdQ++) return true; } //---------------------------------------------------------------------------------------- G4bool G4LundStringFragmentation::Quark_Diquark_lastSplitting(G4FragmentingString * & string, G4ParticleDefinition * & LeftHadron, G4ParticleDefinition * & RightHadron) { G4double StringMass = string->Mass(); G4double StringMassSqr= sqr(StringMass); G4ParticleDefinition * Di_Quark; G4ParticleDefinition * Quark; if (string->GetLeftParton()->GetParticleSubType()== "quark") { Quark =string->GetLeftParton(); Di_Quark=string->GetRightParton(); } else { Quark =string->GetRightParton(); Di_Quark=string->GetLeftParton(); } G4int IDquark =Quark->GetPDGEncoding(); G4int AbsIDquark =std::abs(IDquark); G4int IDdi_quark =Di_Quark->GetPDGEncoding(); G4int AbsIDdi_quark=std::abs(IDdi_quark); G4int Di_q1=AbsIDdi_quark/1000; G4int Di_q2=(AbsIDdi_quark-Di_q1*1000)/100; G4int SignDiQ= 1; if (IDdi_quark < 0) SignDiQ=-1; NumberOf_FS=0; for (G4int ProdQ=1; ProdQ < 4; ProdQ++) { G4int SignQ; if (IDquark > 0) { SignQ=-1; if (IDquark == 2) SignQ= 1; if ((IDquark == 1) && (ProdQ == 3)) SignQ= 1; // K0 if ((IDquark == 3) && (ProdQ == 1)) SignQ=-1; // K0bar } else { SignQ= 1; if (IDquark == -2) SignQ=-1; if ((IDquark ==-1) && (ProdQ == 3)) SignQ=-1; // K0bar if ((IDquark ==-3) && (ProdQ == 1)) SignQ= 1; // K0 } if (AbsIDquark == ProdQ) SignQ= 1; G4int StateQ=0; const G4int maxNumberOfLoops = 1000; G4int loopCounter = 0; do // while(Meson[AbsIDquark-1][ProdQ-1][StateQ]<>0); { LeftHadron=G4ParticleTable::GetParticleTable()->FindParticle(SignQ* Meson[AbsIDquark-1][ProdQ-1][StateQ]); if (LeftHadron == NULL) continue; G4double LeftHadronMass=LeftHadron->GetPDGMass(); G4int StateDiQ=0; const G4int maxNumberOfInternalLoops = 1000; G4int internalLoopCounter = 0; do // while(Baryon[Di_q1-1][Di_q2-1][ProdQ-1][StateDiQ]<>0); { RightHadron=G4ParticleTable::GetParticleTable()->FindParticle(SignDiQ* Baryon[Di_q1-1][Di_q2-1][ProdQ-1][StateDiQ]); if (RightHadron == NULL) continue; G4double RightHadronMass=RightHadron->GetPDGMass(); if (StringMass > LeftHadronMass + RightHadronMass) { if ( NumberOf_FS > 349 ) { G4ExceptionDescription ed; ed << " NumberOf_FS exceeds its limit: NumberOf_FS=" << NumberOf_FS << G4endl; G4Exception( "G4LundStringFragmentation::Quark_Diquark_lastSplitting ", "HAD_LUND_002", JustWarning, ed ); NumberOf_FS = 349; } G4double FS_Psqr=lambda(StringMassSqr,sqr(LeftHadronMass), sqr(RightHadronMass)); FS_Weight[NumberOf_FS]=std::sqrt(FS_Psqr)* MesonWeight[AbsIDquark-1][ProdQ-1][StateQ]* BaryonWeight[Di_q1-1][Di_q2-1][ProdQ-1][StateDiQ]* Prob_QQbar[ProdQ-1]; FS_LeftHadron[NumberOf_FS] = LeftHadron; FS_RightHadron[NumberOf_FS]= RightHadron; NumberOf_FS++; } // End of if (StringMass > LeftHadronMass + RightHadronMass) StateDiQ++; } while( (Baryon[Di_q1-1][Di_q2-1][ProdQ-1][StateDiQ]!=0) && ++internalLoopCounter < maxNumberOfInternalLoops ); if ( internalLoopCounter >= maxNumberOfInternalLoops ) { return false; } StateQ++; } while( (Meson[AbsIDquark-1][ProdQ-1][StateQ]!=0) && ++loopCounter < maxNumberOfLoops ); /* Loop checking, 07.08.2015, A.Ribon */ if ( loopCounter >= maxNumberOfLoops ) { return false; } } return true; } //---------------------------------------------------------------------------------------- G4bool G4LundStringFragmentation::Quark_AntiQuark_lastSplitting(G4FragmentingString * & string, G4ParticleDefinition * & LeftHadron, G4ParticleDefinition * & RightHadron) { G4double StringMass = string->Mass(); G4double StringMassSqr= sqr(StringMass); G4ParticleDefinition * Quark; G4ParticleDefinition * Anti_Quark; if (string->GetLeftParton()->GetPDGEncoding()>0) { Quark =string->GetLeftParton(); Anti_Quark=string->GetRightParton(); } else { Quark =string->GetRightParton(); Anti_Quark=string->GetLeftParton(); } G4int IDquark =Quark->GetPDGEncoding(); G4int AbsIDquark =std::abs(IDquark); G4int QuarkCharge =Qcharge[IDquark-1]; G4int IDanti_quark =Anti_Quark->GetPDGEncoding(); G4int AbsIDanti_quark =std::abs(IDanti_quark); G4int AntiQuarkCharge =-Qcharge[AbsIDanti_quark-1]; G4int LeftHadronCharge(0), RightHadronCharge(0); //G4cout<<"Q Qbar "<FindParticle(SignQ* Meson[AbsIDquark-1][ProdQ-1][StateQ]); //G4cout<<"LeftHadron "<GetParticleName()<GetPDGMass(); G4int StateAQ=0; const G4int maxNumberOfInternalLoops = 1000; G4int internalLoopCounter = 0; do { //G4cout<<" [AbsIDanti_quark-1][ProdQ-1][StateAQ] "<FindParticle(SignAQ* Meson[AbsIDanti_quark-1][ProdQ-1][StateAQ]); //G4cout<<"RightHadron "<GetParticleName()<GetPDGMass(); if (StringMass > LeftHadronMass + RightHadronMass) { if ( NumberOf_FS > 349 ) { G4ExceptionDescription ed; ed << " NumberOf_FS exceeds its limit: NumberOf_FS=" << NumberOf_FS << G4endl; G4Exception( "G4LundStringFragmentation::Quark_AntiQuark_lastSplitting ", "HAD_LUND_003", JustWarning, ed ); NumberOf_FS = 349; } G4double FS_Psqr=lambda(StringMassSqr,sqr(LeftHadronMass), sqr(RightHadronMass)); //FS_Psqr=1.; FS_Weight[NumberOf_FS]=std::sqrt(FS_Psqr)* MesonWeight[AbsIDquark-1][ProdQ-1][StateQ]* MesonWeight[AbsIDanti_quark-1][ProdQ-1][StateAQ]* Prob_QQbar[ProdQ-1]; if (string->GetLeftParton()->GetPDGEncoding()>0) { FS_LeftHadron[NumberOf_FS] = RightHadron; FS_RightHadron[NumberOf_FS]= LeftHadron; } else { FS_LeftHadron[NumberOf_FS] = LeftHadron; FS_RightHadron[NumberOf_FS]= RightHadron; } NumberOf_FS++; } StateAQ++; //G4cout<<" StateAQ Meson[AbsIDanti_quark-1][ProdQ-1][StateAQ] "<= maxNumberOfInternalLoops ) { return false; } StateQ++; //G4cout<<"StateQ Meson[AbsIDquark-1][ProdQ-1][StateQ] "<= maxNumberOfLoops ) { return false; } } // End of for (G4int ProdQ=1; ProdQ < 4; ProdQ++) return true; } //---------------------------------------------------------------------------------------------------------- G4int G4LundStringFragmentation::SampleState(void) { if ( NumberOf_FS > 349 ) { G4ExceptionDescription ed; ed << " NumberOf_FS exceeds its limit: NumberOf_FS=" << NumberOf_FS << G4endl; G4Exception( "G4LundStringFragmentation::SampleState ", "HAD_LUND_004", JustWarning, ed ); NumberOf_FS = 349; } G4double SumWeights=0.; for (G4int i=0; i= ksi) break; } return indexPosition; } //---------------------------------------------------------------------------------------------------------- void G4LundStringFragmentation::Sample4Momentum(G4LorentzVector* Mom, G4double Mass, G4LorentzVector* AntiMom, G4double AntiMass, G4double InitialMass) { // ------ Sampling of momenta of 2 last produced hadrons -------------------- G4ThreeVector Pt; G4double MassMt, AntiMassMt; G4double AvailablePz, AvailablePz2; #ifdef debug_LUNDfragmentation G4cout<<"Sampling of momenta of 2 last produced hadrons ----------------"< 0.)? std::sqrt(r_val)/(2.*InitialMass) : 0; const G4int maxNumberOfLoops = 1000; G4double SigmaQTw=SigmaQT; if (Mass > 930. || AntiMass > 930.) SigmaQT *=(1.0-0.55*sqr((Mass+AntiMass)/InitialMass)); G4int loopCounter = 0; do { Pt=SampleQuarkPt(Pabs); Pt.setZ(0); G4double Pt2=Pt.mag2(); MassMt = std::sqrt( Mass * Mass + Pt2); AntiMassMt= std::sqrt(AntiMass * AntiMass + Pt2); } while ( (InitialMass < MassMt + AntiMassMt) && ++loopCounter < maxNumberOfLoops ); if (Mass > 930. || AntiMass > 930.) SigmaQT=SigmaQTw; if ( loopCounter >= maxNumberOfLoops ) { AvailablePz2 = 0.0; } AvailablePz2= sqr(InitialMass*InitialMass - sqr(MassMt) - sqr(AntiMassMt)) - 4.*sqr(MassMt*AntiMassMt); AvailablePz2 /=(4.*InitialMass*InitialMass); AvailablePz = std::sqrt(AvailablePz2); G4double Px=Pt.getX(); G4double Py=Pt.getY(); Mom->setPx(Px); Mom->setPy(Py); Mom->setPz(AvailablePz); Mom->setE(std::sqrt(sqr(MassMt)+AvailablePz2)); AntiMom->setPx(-Px); AntiMom->setPy(-Py); AntiMom->setPz(-AvailablePz); AntiMom->setE (std::sqrt(sqr(AntiMassMt)+AvailablePz2)); #ifdef debug_LUNDfragmentation G4cout<<"Fmass Mom "<getX()<<" "<getY()<<" "<getZ()<<" "<getT()<getX()<<" "<getY()<<" "<getZ() <<" "<getT()<