// // ******************************************************************** // * 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. * // ******************************************************************** // // // $Id: G4QString.cc,v 1.17 2009/09/04 14:38:00 mkossov Exp $ // GEANT4 tag $Name: hadr-chips-V09-03-08 $ // // ------------------------------------------------------------ // GEANT 4 class implementation file // // ---------------- G4QString ---------------- // by Mikhail Kossov Oct, 2006 // class for excited string used by Parton String Models // For comparison mirror member functions are taken from G4 classes: // G4FragmentingString // G4ExcitedStringDecay // --------------------------------------------------------------------- // Short description: If partons from the G4QPartonPair are close in // rapidity, they create Quasmons, but if they are far in the rapidity // space, they can not interact directly. Say the bottom parton (quark) // has rapidity 0, and the top parton (antiquark) has rapidity 8, then // the top quark splits in two by radiating gluon, and each part has // rapidity 4, then the gluon splits in quark-antiquark pair (rapidity // 2 each), and then the quark gadiates anothe gluon and reachs rapidity // 1. Now it can interact with the bottom antiquark, creating a Quasmon // or a hadron. The intermediate partons is the string ladder. // --------------------------------------------------------------------- //#define debug //#define pdebug //#define edebug #include "G4QString.hh" #include // Static parameters definition G4double G4QString::MassCut=350.*MeV; // minimum mass cut for the string G4double G4QString::SigmaQT=0.5*GeV; // quarkTransverseMomentum distribution parameter G4double G4QString::DiquarkSuppress=0.1; // is Diquark suppression parameter G4double G4QString::DiquarkBreakProb=0.1; // is Diquark breaking probability G4double G4QString::SmoothParam=0.9; // QGS model parameter G4double G4QString::StrangeSuppress=0.435;// Strangeness suppression (u:d:s=1:1:0.3 ?M.K.) G4double G4QString::widthOfPtSquare=-0.72*GeV*GeV; // pt -width2 forStringExcitation G4QString::G4QString() : theDirection(0), thePosition(G4ThreeVector(0.,0.,0.)) {} G4QString::G4QString(G4QParton* Color, G4QParton* AntiColor, G4int Direction) { #ifdef debug G4cout<<"G4QString::PPD-Constructor: Direction="<>> String is excited"<GetParton1(), CAC->GetParton2(), CAC->GetDirection()); #ifdef debug G4cout<<"G4QString::PartonPair-Constructor: >>> String is excited"<GetPosition()) { thePartons.push_back(QCol); G4LorentzVector sum=QCol->Get4Momentum(); thePartons.push_back(Gluon); sum+=Gluon->Get4Momentum(); thePartons.push_back(QAntiCol); sum+=QAntiCol->Get4Momentum(); Pplus =sum.e() + sum.pz(); Pminus=sum.e() - sum.pz(); decaying=None; } G4QString::G4QString(const G4QString &right) : theDirection(right.GetDirection()), thePosition(right.GetPosition()) { //LeftParton=right.LeftParton; //RightParton=right.RightParton; Ptleft=right.Ptleft; Ptright=right.Ptright; Pplus=right.Pplus; Pminus=right.Pminus; decaying=right.decaying; } G4QString::~G4QString() {if(thePartons.size()) std::for_each(thePartons.begin(),thePartons.end(),DeleteQParton());} G4LorentzVector G4QString::Get4Momentum() const { G4LorentzVector momentum(0.,0.,0.,0.); for(unsigned i=0; iGet4Momentum(); return momentum; } void G4QString::LorentzRotate(const G4LorentzRotation & rotation) { for(unsigned i=0; iSet4Momentum(rotation*thePartons[i]->Get4Momentum()); } //void G4QString::InsertParton(G4QParton* aParton, const G4QParton* addafter) //{ // G4QPartonVector::iterator insert_index; // Begin by default (? M.K.) // if(addafter != NULL) // { // insert_index=std::find(thePartons.begin(), thePartons.end(), addafter); // if (insert_index == thePartons.end()) // No object addafter in thePartons // { // G4cerr<<"***G4QString::InsertParton: Addressed Parton is not found"<Get4Momentum(); Mom.boost(Velocity); thePartons[cParton]->Set4Momentum(Mom); } } //G4QParton* G4QString::GetColorParton(void) const //{ // G4QParton* start = *(thePartons.begin()); // G4QParton* end = *(thePartons.end()-1); // G4int Encoding = start->GetPDGCode(); // if (Encoding<-1000 || (Encoding < 1000 && Encoding > 0)) return start; // return end; //} //G4QParton* G4QString::GetAntiColorParton(void) const //{ // G4QParton* start = *(thePartons.begin()); // G4QParton* end = *(thePartons.end()-1); // G4int Encoding = start->GetPDGCode(); // if (Encoding < -1000 || (Encoding < 1000 && Encoding > 0)) return end; // return start; //} // Fill parameters void G4QString::SetParameters(G4double mCut, G4double sigQT, G4double DQSup, G4double DQBU, G4double smPar, G4double SSup, G4double SigPt) {// ============================================================================= MassCut = mCut; // minimum mass cut for the string SigmaQT = sigQT; // quark transverse momentum distribution parameter DiquarkSuppress = DQSup; // is Diquark suppression parameter DiquarkBreakProb= DQBU; // is Diquark breaking probability SmoothParam = smPar; // QGS model parameter StrangeSuppress = SSup; // Strangeness suppression parameter widthOfPtSquare = -2*SigPt*SigPt; // width^2 of pt for string excitation } // Pt distribution @@ one can use 1/(1+A*Pt^2)^B G4ThreeVector G4QString::GaussianPt(G4double widthSquare, G4double maxPtSquare) const { G4double pt2; do{pt2=widthSquare*std::log(G4UniformRand());} while (pt2>maxPtSquare); pt2=std::sqrt(pt2); G4double phi=G4UniformRand()*twopi; return G4ThreeVector(pt2*std::cos(phi),pt2*std::sin(phi),0.); } // End of GaussianPt // Diffractively excite the string //void G4QString::DiffString(G4QHadron* hadron, G4bool isProjectile) //{ // hadron->SplitUp(); // G4QParton* start = hadron->GetNextParton(); // if( start==NULL) // { // G4cerr<<"***G4QString::DiffString: No start parton found, nothing is done"<GetNextParton(); // if( end==NULL) // { // G4cerr<<"***G4QString::DiffString: No end parton found, nothing is done"<GetPosition()); // // momenta of string ends // G4double ptSquared= hadron->Get4Momentum().perp2(); // G4double hmins=hadron->Get4Momentum().minus(); // G4double hplus=hadron->Get4Momentum().plus(); // G4double transMassSquared=hplus*hmins; // G4double maxMomentum = std::sqrt(transMassSquared) - std::sqrt(ptSquared); // G4double maxAvailMomentumSquared = maxMomentum * maxMomentum; // G4ThreeVector pt=GaussianPt(widthOfPtSquare,maxAvailMomentumSquared); // G4LorentzVector Pstart(G4LorentzVector(pt,0.)); // G4LorentzVector Pend(hadron->Get4Momentum().px(), hadron->Get4Momentum().py(), 0.); // Pend-=Pstart; // G4double tm1=hmins+(Pend.perp2()-Pstart.perp2())/hplus; // G4double tm2=std::sqrt( std::max(0., tm1*tm1-4*Pend.perp2()*hmins/hplus ) ); // G4int Sign= isProjectile ? TARGET : PROJECTILE; // G4double endMinus = 0.5 * (tm1 + Sign*tm2); // G4double startMinus= hmins - endMinus; // G4double startPlus = Pstart.perp2() / startMinus; // G4double endPlus = hplus - startPlus; // Pstart.setPz(0.5*(startPlus - startMinus)); // Pstart.setE (0.5*(startPlus + startMinus)); // Pend.setPz (0.5*(endPlus - endMinus)); // Pend.setE (0.5*(endPlus + endMinus)); // start->Set4Momentum(Pstart); // end->Set4Momentum(Pend); //#ifdef debug // G4cout<<"G4QString::DiffString: StartQ="<GetPDGCode()<Get4Momentum()<<"(" // <Get4Momentum().mag()<<"), EndQ="<GetPDGCode()<Get4Momentum() // <<"("<Get4Momentum().mag()<<"), sumOfEnds="<yf); } else // Di-quarks (@@ Crazy codes are not checked) { if (absCode==3101||absCode==3103||absCode==3201||absCode==3203) d2=alft-ala-ala+arho; else if(absCode==1103||absCode==2101||absCode==2203||absCode==2103) d2=alft-an-an+arho; else d2=alft-aksi-aksi+arho; do { z = zmin + G4UniformRand()*(zmax - zmin); yf = std::pow(1.-z, d2); } while (G4UniformRand()>yf); } return z; } // End of GetQGSMLightConeZ // Diffractively excite the string (QL=true - QGS Light Cone, =false - Lund Light Cone) G4QHadronVector* G4QString::FragmentString(G4bool QL) { // Can no longer modify Parameters for Fragmentation. #ifdef edebug G4LorentzVector string4M=Get4Momentum(); // Just for Energy-Momentum ConservCheck #endif #ifdef debug G4cout<<"G4QString::FragmentString:-->Called,QL="< Res4M="<Get4Momentum(); // For recovery when failed G4LorentzVector right4M=GetRightParton()->Get4Momentum(); #ifdef debug G4cout<<"G4QString::FragmString: ***Remember*** L4M="<LOOP, attempt = "<Begin LOOP/LOOP, decaying="<Get4Momentum(); G4cout<<"-EMC-G4QString::FragmentString:LOOP/LOOP,d4M="<>G4QString::FragmentString: LOOP/LOOP-NO FRAGM-, dec="<0) LeftVector->push_back(Hadron); else RightVector->push_back(Hadron); } else { // @@ Try to convert to the resonance and decay, abandon if Mr4M/M2="<GetPDGCode()>0)?-1:1; else IsParticle=(GetLeftParton()->GetPDGCode()>0)?1:-1; G4QPartonPair QuarkPair = CreatePartonPair(IsParticle,false); // no diquarks RQuark = QuarkPair.GetParton2(); G4QParton* LQuark = QuarkPair.GetParton1(); LeftHadron = CreateHadron(LQuark, GetLeftParton()); // Create Left Hadron delete LQuark; // Delete the temporaryParton } RightHadron = CreateHadron(GetRightParton(), RQuark); // Create Right Hadron delete RQuark; // Delete the temporaryParton //... repeat procedure, if mass of cluster is too low to produce hadrons G4double LhM=LeftHadron->GetMass(); G4double RhM=RightHadron->GetMass(); #ifdef debug G4cout<<"G4QStr::FrSt:L="<GetPDGCode()<<",R="<GetPDGCode() <<",ML="<push_back(new G4QHadron(LeftHadron, 0, Pos, Lh4M)); delete LeftHadron; RightVector->push_back(new G4QHadron(RightHadron, 0, Pos, Rh4M)); delete RightHadron; } #ifdef debug G4cout<<">>>G4QStr::FragString:HFilled (L) PDG="<GetPDGCode()<<", 4M=" < Res4M="<empty()) { LeftVector->push_back(RightVector->back()); RightVector->erase(RightVector->end()-1); } delete RightVector; // @@ A trick, the real bug should be found !! G4QHadronVector::iterator ilv; // @@ for(ilv = LeftVector->begin(); ilv < LeftVector->end(); ilv++) // @@ { G4ThreeVector CV=(*ilv)->Get4Momentum().vect(); // @@ if(CV.x()==0. && CV.y()==0. && CV.z()==0.) LeftVector->erase(ilv); // @@ } // Calculate time and position of hadrons with @@ very rough formation time G4double StringMass=Get4Momentum().mag(); static const G4double dkappa = 2.0 * GeV/fermi; // @@ 2*kappa kappa=1 GeV/fermi (?) for(unsigned c1 = 0; c1 < LeftVector->size(); c1++) { G4double SumPz = 0; G4double SumE = 0; for(unsigned c2 = 0; c2 < c1; c2++) { G4LorentzVector hc2M=(*LeftVector)[c2]->Get4Momentum(); SumPz += hc2M.pz(); SumE += hc2M.e(); } G4QHadron* hc1=(*LeftVector)[c1]; G4LorentzVector hc1M=hc1->Get4Momentum(); G4double HadronE = hc1M.e(); G4double HadronPz= hc1M.pz(); hc1->SetFormationTime((StringMass-SumPz-SumPz+HadronE-HadronPz)/dkappa); hc1->SetPosition(G4ThreeVector(0,0,(StringMass-SumE-SumE-HadronE+HadronPz)/dkappa)); } G4LorentzRotation toObserverFrame(toCms.inverse()); #ifdef debug G4cout<<"G4QString::FragmentString: beforeLoop LVsize = "<size()<size(); C1++) { G4QHadron* Hadron = (*LeftVector)[C1]; G4LorentzVector Momentum = Hadron->Get4Momentum(); Momentum = toObserverFrame*Momentum; Hadron->Set4Momentum(Momentum); G4LorentzVector Coordinate(Hadron->GetPosition(), Hadron->GetFormationTime()); Momentum = toObserverFrame*Coordinate; Hadron->SetFormationTime(Momentum.e()); Hadron->SetPosition(GetPosition()+Momentum.vect()); } #ifdef edebug G4LorentzVector sLA=string4M; for(unsigned L = 0; L < LeftVector->size(); L++) { G4QHadron* LH = (*LeftVector)[L]; G4LorentzVector L4M=LH->Get4Momentum(); sLA-=L4M; G4cout<<"-EMC-G4QStr::FragmStri:L#"<GetPDGCode()<<",4M="< Res4M="<"<GetMass(); G4double h2M = h2->GetMass(); #ifdef debug G4cout<<"G4QString::LightFragTest:tM="<push_back(new G4QHadron(hadrons.first, 0, GetPosition(), h4M1)); result->push_back(new G4QHadron(hadrons.second,0, GetPosition(), h4M2)); } #ifdef edebug G4int L=result->size(); if(L) for(G4int i=0; iGet4Momentum(); G4cout<<"-EMC-G4QString::LightFragTest: i="<>>>>G4QString::Splitup: HFilled 4M="<<*HadronMomentum<<",PDG=" <GetPDGCode()<<",s4M-h4M="<Set4Momentum(theDecayParton->Get4Momentum()-*HadronMomentum); Hadron->Set4Momentum(*HadronMomentum); Hadron->SetPosition(GetPosition()); if(decaying == Left) { G4QParton* theFirst = thePartons[0]; // Substitute for the First Parton delete theFirst; // The OldParton instance is deleted thePartons[0] = newStringEnd; // Delete equivalent for newStringEnd #ifdef debug G4cout<<"G4QString::Splitup: theFirstPDG="<GetPDGCode()<vect(); Ptleft.setZ(0.); // @@ (Z is anyway ignored) M.K. (?) } else if (decaying == Right) { G4QParton* theLast = thePartons[thePartons.size()-1]; // Substitute for theLastParton delete theLast; // The OldParton instance is deleted thePartons[thePartons.size()-1] = newStringEnd; // Delete equivalent for newStringEnd #ifdef debug G4cout<<"G4QString::Splitup: theLastPDG="<GetPDGCode()<<", nP=" <vect(); Ptright.setZ(0.); // @@ (Z is anyway ignored) M.K. (?) } else { G4cerr<<"***G4QString::Splitup: wrong oldDecay="<e() + HadronMomentum->pz();// Reduce Pplus ofTheString (Left) Pminus -= HadronMomentum->e() - HadronMomentum->pz();// Reduce Pminus ofTheString(Rite) #ifdef debug G4cout<<"G4QString::Splitup: P+="<...>G4QString::Splitup: NewString4M="<= zMax) return 0; // have to start all over! G4double z=0; if(QL) z = GetQGSMLightConeZ(zMin, zMax, theDecayParton->GetPDGCode(), pHadron, HadronPt.x(), HadronPt.y()); else z = GetLundLightConeZ(zMin, zMax, theDecayParton->GetPDGCode(), pHadron, HadronPt.x(), HadronPt.y()); //... now compute hadron longitudinal momentum and energy // longitudinal hadron momentum component HadronPz G4double zl= z; if (decaying == Left ) zl*=Pplus; else if (decaying == Right ) zl*=Pminus; else // @@ Is that possible? { G4cerr<<"***G4QString::SplitEandP: wrong DecayDirection="<GetPDGCode()>0) ? -1 : +1; // a quark needs antiquark or diquark G4QPartonPair QuarkPair = CreatePartonPair(IsParticle); created = QuarkPair.GetParton2(); // New Parton after splitting #ifdef debug G4cout<<"G4QString::QuarkSplitup: ***Called*** crP="<GetPDGCode()<GetPDGCode()/1000; G4int decayQuarkEncoding = (decay->GetPDGCode()/100)%10; if (G4UniformRand() < 0.5) { G4int Swap = stableQuarkEncoding; stableQuarkEncoding = decayQuarkEncoding; decayQuarkEncoding = Swap; } G4int IsParticle=(decayQuarkEncoding>0) ? -1 : +1;// Diquark is equivalent to antiquark G4QPartonPair QuarkPair = CreatePartonPair(IsParticle,false); // no diquarks wanted G4QParton* P2=QuarkPair.GetParton2(); G4int QuarkEncoding=P2->GetPDGCode(); delete P2; 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 = new G4QParton(NewDecayEncoding); #ifdef debug G4cout<<"G4QString::DiQuarkSplitup: inside, crP="<GetPDGCode()<GetPDGCode()>0) ? +1 : -1; G4QPartonPair QuarkPair = CreatePartonPair(IsParticle,false); // no diquarks wanted created = QuarkPair.GetParton2(); #ifdef debug G4cout<<"G4QString::DiQuarkSplitup: diQ not break, crP="<GetPDGCode()<3) { G4cerr<<"***G4QString::CreateMeson: q1="< 3) { G4cerr<<"***G4QString::CreateBaryon: q1="< kfle && kfle > kflf) { // Spin J=1/2 and all three quarks different // Two states exist: (uds -> lambda or sigma0) // - lambda: s(ud)0 s : 3122; ie. reverse the two lighter quarks // - sigma0: s(ud)1 s : 3212 if(diquarkSpin == 1 ) { if ( kfla == kfld) kfll = 1; // heaviest quark in diquark else kfll = G4int(0.25 + G4UniformRand()); } if(diquarkSpin==3 && kfla!=kfld) kfll = G4int(0.75+G4UniformRand()); } G4int PDGEncoding=0; if (kfll == 1) PDGEncoding = 1000 * kfld + 100 * kflf + 10 * kfle + theSpin; else PDGEncoding = 1000 * kfld + 100 * kfle + 10 * kflf + theSpin; if (id1 < 0) PDGEncoding = -PDGEncoding; G4QHadron* Baryon= new G4QHadron(PDGEncoding); #ifdef debug G4cout<<"G4QString::CreateBaryon: Baryon is created with PDG="<GetType(); G4int wT=white->GetType(); #ifdef debug G4cout<<"G4QString::CreateHadron: bT="<GetPDGCode()<<"), wT="<GetPDGCode()<<")"< Baryon is under creation"< Meson is under creation"<GetType(); G4int wT=white->GetType(); #ifdef debug G4cout<<"G4QString::CreateLowSpinHadron: ***Called***, bT="<GetPDGCode() <<"), wT="<GetPDGCode()<<")"< Meson is under creation"< Baryon is under creation"<GetType(); G4int wT=white->GetType(); #ifdef debug G4cout<<"G4QString::CreateHighSpinHadron:***Called***, bT="<GetPDGCode() <<"), wT="<GetPDGCode()<<")"< Meson is created"< Baryon is created"<