// // ******************************************************************** // * 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: G4QHadron.cc,v 1.64 2009/09/02 15:45:19 mkossov Exp $ // GEANT4 tag $Name: hadr-chips-V09-03-08 $ // // ---------------- G4QHadron ---------------- // by Mikhail Kossov, Sept 1999. // class for Quasmon initiated Hadrons generated by CHIPS Model // ------------------------------------------------------------------- // Short description: In CHIPS all particles are G4QHadrons, while they // can be leptons, gammas or nuclei. The G4QPDGCode makes the difference. // In addition the 4-momentum is a basic value, so the mass can be // different from the GS mass (e.g. for the virtual gamma). // ------------------------------------------------------------------- // //#define debug //#define edebug //#define pdebug //#define sdebug //#define ppdebug #include "G4QHadron.hh" #include using namespace std; G4double G4QHadron::StrangeSuppress = 0.48; // ? M.K. G4double G4QHadron::sigmaPt = 1.7*GeV; // Can be 0 ? G4double G4QHadron::widthOfPtSquare = 0.01*GeV*GeV; // ? M.K. G4QHadron::G4QHadron(): theMomentum(0.,0.,0.,0.), theQPDG(0), valQ(0,0,0,0,0,0), nFragm(0), thePosition(0.,0.,0.), theCollisionCount(0), isSplit(false), Direction(true), Color(), AntiColor(), bindE(0.), formTime(0.) {} G4QHadron::G4QHadron(G4LorentzVector p): theMomentum(p), theQPDG(0), valQ(0,0,0,0,0,0), nFragm(0), thePosition(0.,0.,0.), theCollisionCount(0), isSplit(false), Direction(true), Color(), AntiColor(), bindE(0.), formTime(0.) {} // For Chipolino or Quasmon doesn't make any sense G4QHadron::G4QHadron(G4int PDGCode, G4LorentzVector p): theMomentum(p), theQPDG(PDGCode), nFragm(0),thePosition(0.,0.,0.),theCollisionCount(0),isSplit(false),Direction(true), Color(), AntiColor(), bindE(0.), formTime(0.) { #ifdef debug G4cout<<"G4QHadron must be created with PDG="<0) curPDG=valQ.GetZNSPDGCode(); if(curPDG&&curPDG!=10) theQPDG.SetPDGCode(curPDG); else theQPDG.InitByQCont(QC); } G4QHadron::G4QHadron(G4int PDGCode, G4double aMass, G4QContent QC) : theMomentum(0.,0.,0.,aMass), theQPDG(PDGCode), valQ(QC), nFragm(0),thePosition(0.,0.,0.), theCollisionCount(0), isSplit(false), Direction(true), Color(), AntiColor(), bindE(0.), formTime(0.) {} G4QHadron::G4QHadron(G4QPDGCode QPDG, G4double aMass, G4QContent QC) : theMomentum(0.,0.,0.,aMass), theQPDG(QPDG), valQ(QC), nFragm(0), thePosition(0.,0.,0.), theCollisionCount(0), isSplit(false), Direction(true), Color(), AntiColor(), bindE(0.), formTime(0.) {} G4QHadron::G4QHadron(G4int PDGCode, G4LorentzVector p, G4QContent QC) : theMomentum(p), theQPDG(PDGCode), valQ(QC), nFragm(0), thePosition(0.,0.,0.), theCollisionCount(0), isSplit(false), Direction(true), Color(), AntiColor(), bindE(0.), formTime(0.) {} G4QHadron::G4QHadron(G4QPDGCode QPDG, G4LorentzVector p, G4QContent QC) : theMomentum(p), theQPDG(QPDG), valQ(QC), nFragm(0), thePosition(0.,0.,0.), theCollisionCount(0), isSplit(false), Direction(true), Color(), AntiColor(), bindE(0.), formTime(0.) {} G4QHadron::G4QHadron(G4QParticle* pPart, G4double maxM) : theMomentum(0.,0.,0.,0.), theQPDG(pPart->GetQPDG()), nFragm(0), thePosition(0.,0.,0.), theCollisionCount(0), isSplit(false), Direction(true), Color(), AntiColor(), bindE(0.), formTime(0.) { #ifdef debug G4cout<<"G4QHadron is created & randomized with maxM="<theMomentum; theQPDG = right->theQPDG; valQ = right->valQ; nFragm = right->nFragm; thePosition = right->thePosition; theCollisionCount = 0; isSplit = false; Direction = right->Direction; bindE = right->bindE; formTime = right->formTime; } G4QHadron::G4QHadron(const G4QHadron* right, G4int C, G4ThreeVector P, G4LorentzVector M) { theMomentum = M; theQPDG = right->theQPDG; valQ = right->valQ; nFragm = right->nFragm; thePosition = P; theCollisionCount = C; isSplit = false; Direction = right->Direction; bindE = right->bindE; formTime = right->formTime; } const G4QHadron& G4QHadron::operator=(const G4QHadron &right) { if(this != &right) // Beware of self assignment { theMomentum = right.theMomentum; theQPDG = right.theQPDG; valQ = right.valQ; nFragm = right.nFragm; thePosition = right.thePosition; theCollisionCount = 0; isSplit = false; Direction = right.Direction; bindE = right.bindE; } return *this; } G4QHadron::~G4QHadron() { std::list::iterator ipos = Color.begin(); std::list::iterator epos = Color.end(); for( ; ipos != epos; ipos++) {delete [] *ipos;} Color.clear(); ipos = AntiColor.begin(); epos = AntiColor.end(); for( ; ipos != epos; ipos++) {delete [] *ipos;} AntiColor.clear(); } // Define quark content of the particle with a particular PDG Code void G4QHadron::DefineQC(G4int PDGCode) { //G4cout<<"G4QHadron::DefineQC is called with PDGCode="<700) { n-=1000; dz--; } G4int z =sz%1000-dz; if(z>700) { z-=1000; ds--; } G4int Sq =sz/1000-ds; G4int zns=z+n+Sq; G4int Dq=n+zns; G4int Uq=z+zns; if (Dq<0&&Uq<0&&Sq<0)valQ=G4QContent(0 ,0 ,0 ,-Dq,-Uq,-Sq); else if (Uq<0&&Sq<0) valQ=G4QContent(Dq,0 ,0 ,0 ,-Uq,-Sq); else if (Dq<0&&Sq<0) valQ=G4QContent(0 ,Uq,0 ,-Dq,0 ,-Sq); else if (Dq<0&&Uq<0) valQ=G4QContent(0 ,0 ,Sq,-Dq,-Uq,0 ); else if (Uq<0) valQ=G4QContent(Dq,0 ,Sq,0 ,-Uq,0 ); else if (Sq<0) valQ=G4QContent(Dq,Uq,0 ,0 ,0 ,-Sq); else if (Dq<0) valQ=G4QContent(0 ,Uq,Sq,-Dq,0 ,0 ); else valQ=G4QContent(Dq,Uq,Sq,0 ,0 ,0 ); } // Redefine a Hadron with a new PDGCode void G4QHadron::SetQPDG(const G4QPDGCode& newQPDG) { theQPDG = newQPDG; G4int PDG= newQPDG.GetPDGCode(); G4int Q = newQPDG.GetQCode(); #ifdef debug G4cout<<"G4QHadron::SetQPDG is called with PDGCode="<fM="< 1.) maxCost= 1.; if(minCost<-1.) minCost=-1.; if(maxCost<-1.) maxCost=-1.; if(minCost> 1.) minCost= 1.; if(minCost> maxCost) minCost=maxCost; if(fabs(iM-fM-sM)<.00000001) { G4double fR=fM/iM; G4double sR=sM/iM; f4Mom=fR*theMomentum; s4Mom=sR*theMomentum; return true; } else if (iM+.001iM="<1.) ct=1.; if(ct<-1.) ct=-1.; } G4ThreeVector pVect=(ps*sin(phi))*vz+(ps*cos(phi))*vy+p*ct*vx; #ifdef ppdebug G4cout<<"G4QH::RelDIn2:ct="<0: ~cost^cp, cp<0: ~(1-cost)^(-cp)] G4bool G4QHadron::CopDecayIn2(G4LorentzVector& f4Mom, G4LorentzVector& s4Mom, G4LorentzVector& dir, G4double cosp) {// =================================================================== G4double fM2 = f4Mom.m2(); G4double fM = sqrt(fM2); // Mass of the 1st Hadron G4double sM2 = s4Mom.m2(); G4double sM = sqrt(sM2); // Mass of the 2nd Hadron G4double iM2 = theMomentum.m2(); G4double iM = sqrt(iM2); // Mass of the decaying hadron G4double vP = theMomentum.rho(); // Momentum of the decaying hadron G4double dE = theMomentum.e(); // Energy of the decaying hadron G4bool neg=false; // Negative (backward) distribution of t if(cosp<0) { cosp=-cosp; neg=true; } if(dEfM="<iM="<1.) ct=1.; if(ct<-1.) ct=-1.; } G4ThreeVector pVect=(ps*sin(phi))*vz+(ps*cos(phi))*vy+p*ct*vx; #ifdef ppdebug G4cout<<"G4QH::CopDIn2:ct="< fM="< iM="<fM="< iM="<corE="<r+s+t G4bool G4QHadron::DecayIn3 (G4LorentzVector& f4Mom, G4LorentzVector& s4Mom, G4LorentzVector& t4Mom) {// ==================================================================================== #ifdef debug G4cout<<"G4QH::DIn3:"<pf="< iM="< rR) { m12s = m12sMin + m12sBase*G4UniformRand(); G4double e1=m12s+fM2-sM2; G4double e2=iM2-m12s-tM2; G4double four12=4*m12s; G4double m13sRange=0.; G4double dif=(e1*e1-four12*fM2)*(e2*e2-four12*tM2); if(dif<0.) { #ifdef debug if(dif<-.01) G4cerr<<"*G4QHadron::DecayIn3:iM="< Exception2"<f+s+t (t is with respect to minCf="< iM="< rR) { m12s = m12sMin + m12sBase*G4UniformRand(); G4double e1=m12s+fM2-sM2; G4double e2=iM2-m12s-tM2; G4double four12=4*m12s; G4double m13sRange=0.; G4double dif=(e1*e1-four12*fM2)*(e2*e2-four12*tM2); if(dif<0.) { #ifdef debug if(dif<-.01) G4cerr<<"G4QHadron::RelDecayIn3:iM="< Exception2"<f+s+t. dN/dO [cp>0:~cost^cp, cp<0:~(1-cost)^(-cp)] G4bool G4QHadron::CopDecayIn3(G4LorentzVector& f4Mom, G4LorentzVector& s4Mom, G4LorentzVector& t4Mom, G4LorentzVector& dir, G4double cosp) {// ==================================================================================== #ifdef debug G4cout<<"G4QH::CopDIn3:"<f="< iM="< rR) { m12s = m12sMin + m12sBase*G4UniformRand(); G4double e1=m12s+fM2-sM2; G4double e2=iM2-m12s-tM2; G4double four12=4*m12s; G4double m13sRange=0.; G4double dif=(e1*e1-four12*fM2)*(e2*e2-four12*tM2); if(dif<0.) { #ifdef debug if(dif<-.01) G4cerr<<"G4QHadron::CopDecayIn3:iM="< Exception2"<maxM="<MinMassOfFragm(); if(minM>maxM) { #ifdef debug G4cout<<"***G4QHadron::RandomizeMass:for PDG="< maxM="<SetSpinZ(-firstPartonSpinZ); aParton->SetColour(-firstPartonColour); #ifdef pdebug G4cout<<"G4QHadron::SplUp:Sft,P2="<Get4Momentum()<<",i="<Get4Momentum(); AntiColor.push_back(aParton); // Anti-quark/diquark is filled #ifdef pdebug G4cout<<"G4QHadron::SplUp:*Sft* Antiquark is filled, i="<GetPDGCode(); #ifdef pdebug G4int AntiColorEncoding = pAntiColorParton->GetPDGCode(); G4cout<<"G4QHadron::SplUp:*Sft*,C="< End, ColSize="<SetPosition(GetPosition()); G4ThreeVector aPtVector = GaussianPt(sigmaPt, DBL_MAX); G4LorentzVector a4Momentum(aPtVector, 0); result->Set4Momentum(a4Momentum); return result; } // End of BuildSeaQuark // Fast non-iterative CHIPS algorithm G4double* G4QHadron::RandomX(G4int nPart) { G4double* x = 0; if(nPart<2) { G4cout<<"-Warning-G4QHadron::RandomX: nPart="<j; --k) x[k]=x[k-1]; x[j]=r; break; } if(j==i) x[i]=r; } x[nP1]=1.; for(G4int i=nP1; i>0; --i) x[i]-=x[i-1]; return x; } // Non-iterative recursive phase-space CHIPS algorthm G4double G4QHadron::SampleCHIPSX(G4double anXtot, G4int nSea) { G4double ns=nSea; if(nSea<1 || anXtot<=0.) G4cout<<"-Warning-G4QHad::SCX:N="<SetPosition(GetPosition()); // G4cerr << "G4QGSMSplitableHadron::GetValenceQuarkFlavors()" << G4endl; // G4cerr << "Parton 1: " // << " PDGcode: " << aEnd // << " - Name: " << Parton1->GetDefinition()->GetParticleName() // << " - Type: " << Parton1->GetDefinition()->GetParticleType() // << " - Spin-3: " << Parton1->GetSpinZ() // << " - Colour: " << Parton1->GetColour() << G4endl; Parton2 = new G4QParton(bEnd); Parton2->SetPosition(GetPosition()); // G4cerr << "Parton 2: " // << " PDGcode: " << bEnd // << " - Name: " << Parton2->GetDefinition()->GetParticleName() // << " - Type: " << Parton2->GetDefinition()->GetParticleType() // << " - Spin-3: " << Parton2->GetSpinZ() // << " - Colour: " << Parton2->GetColour() << G4endl; // G4cerr << "... now checking for color and spin conservation - yielding: " << G4endl; // colour of parton 1 choosen at random by G4QParton(aEnd) // colour of parton 2 is the opposite: Parton2->SetColour(-(Parton1->GetColour())); // isospin-3 of both partons is handled by G4Parton(PDGCode) // spin-3 of parton 1 and 2 choosen at random by G4QParton(aEnd) // spin-3 of parton 2 may be constrained by spin of original particle: if ( std::abs(Parton1->GetSpinZ() + Parton2->GetSpinZ()) > GetSpin()) Parton2->SetSpinZ(-(Parton2->GetSpinZ())); // G4cerr << "Parton 2: " // << " PDGcode: " << bEnd // << " - Name: " << Parton2->GetDefinition()->GetParticleName() // << " - Type: " << Parton2->GetDefinition()->GetParticleType() // << " - Spin-3: " << Parton2->GetSpinZ() // << " - Colour: " << Parton2->GetColour() << G4endl; // G4cerr << "------------" << G4endl; } // End of GetValenceQuarkFlavors G4bool G4QHadron::SplitMeson(G4int PDGcode, G4int* aEnd, G4int* bEnd) { G4bool result = true; G4int absPDGcode = std::abs(PDGcode); if (absPDGcode >= 1000) return false; if(absPDGcode == 22 || absPDGcode == 111) // only u-ubar, d-dbar configurations { G4int it=1; if(G4UniformRand()<.5) it++; *aEnd = it; *bEnd = -it; } else if(absPDGcode == 130 || absPDGcode == 310) // K0-K0bar mixing { G4int it=1; if(G4UniformRand()<.5) it=-1; *aEnd = it; if(it>0) *bEnd = -3; else *bEnd = 3; } else { G4int heavy = absPDGcode/100; G4int light = (absPDGcode%100)/10; G4int anti = 1 - 2*(std::max(heavy, light)%2); if (PDGcode < 0 ) anti = -anti; heavy *= anti; light *= -anti; if ( anti < 0) G4SwapObj(&heavy, &light); *aEnd = heavy; *bEnd = light; } return result; } G4bool G4QHadron::SplitBaryon(G4int PDGcode, G4int* quark, G4int* diQuark) { static const G4double r2=.5; static const G4double r3=1./3.; static const G4double d3=2./3.; static const G4double r4=1./4.; static const G4double r6=1./6.; static const G4double r12=1./12.; // std::pair qdq[5]; G4double prb[5]; G4int nc=0; G4int aPDGcode=std::abs(PDGcode); if(aPDGcode==2212) // ==> Proton { nc=3; qdq[0]=make_pair(2203, 1); prb[0]=r3; // uu_1, d qdq[1]=make_pair(2103, 2); prb[1]=r6; // ud_1, u qdq[2]=make_pair(2101, 2); prb[2]=r2; // ud_0, u } else if(aPDGcode==2112) // ==> Neutron { nc=3; qdq[0]=make_pair(2103, 1); prb[0]=r6; // ud_1, d qdq[1]=make_pair(2101, 1); prb[1]=r2; // ud_0, d qdq[2]=make_pair(1103, 2); prb[2]=r3; // dd_1, u } else if(aPDGcode%10<3) // ==> Spin 1/2 Hyperons { if(aPDGcode==3122) // Lambda { nc=5; qdq[0]=make_pair(2103, 3); prb[0]=r3; // ud_1, s qdq[1]=make_pair(3203, 1); prb[1]=r4; // su_1, d qdq[2]=make_pair(3201, 1); prb[2]=r12; // su_0, d qdq[3]=make_pair(3103, 2); prb[3]=r4; // sd_1, u qdq[4]=make_pair(3101, 2); prb[4]=r12; // sd_0, u } else if(aPDGcode==3222) // Sigma+ { nc=3; qdq[0]=make_pair(2203, 3); prb[0]=r3; // uu_1, s qdq[1]=make_pair(3203, 2); prb[1]=r6; // su_1, d qdq[2]=make_pair(3201, 2); prb[2]=r2; // su_0, d } else if(aPDGcode==3212) // Sigma0 { nc=5; qdq[0]=make_pair(2103, 3); prb[0]=r3; // ud_1, s qdq[1]=make_pair(3203, 1); prb[1]=r12; // su_1, d qdq[2]=make_pair(3201, 1); prb[2]=r4; // su_0, d qdq[3]=make_pair(3103, 2); prb[3]=r12; // sd_1, u qdq[4]=make_pair(3101, 2); prb[4]=r4; // sd_0, u } else if(aPDGcode==3112) // Sigma- { nc=3; qdq[0]=make_pair(1103, 3); prb[0]=r3; // dd_1, s qdq[1]=make_pair(3103, 1); prb[1]=r6; // sd_1, d qdq[2]=make_pair(3101, 1); prb[2]=r2; // sd_0, d } else if(aPDGcode==3312) // Xi- { nc=3; qdq[0]=make_pair(3103, 3); prb[0]=r6; // sd_1, s qdq[1]=make_pair(3101, 3); prb[1]=r2; // sd_0, s qdq[2]=make_pair(3303, 1); prb[2]=r3; // ss_1, d } else if(aPDGcode==3322) // Xi0 { nc=3; qdq[0]=make_pair(3203, 3); prb[0]=r6; // su_1, s qdq[1]=make_pair(3201, 3); prb[1]=r2; // su_0, s qdq[2]=make_pair(3303, 2); prb[2]=r3; // ss_1, u } else return false; } else // ==> Spin 3/2 Baryons (Spin>3/2 is ERROR) { if(aPDGcode==3334) { nc=1; qdq[0]=make_pair(3303, 3); prb[0]=1.; // ss_1, s } else if(aPDGcode==2224) { nc=1; qdq[0]=make_pair(2203, 2); prb[0]=1.; // uu_1, s } else if(aPDGcode==2214) { nc=2; qdq[0]=make_pair(2203, 1); prb[0]=r3; // uu_1, d qdq[1]=make_pair(2103, 2); prb[1]=d3; // ud_1, u } else if(aPDGcode==2114) { nc=2; qdq[0]=make_pair(1103, 2); prb[0]=r3; // dd_1, u qdq[1]=make_pair(2103, 1); prb[1]=d3; // ud_1, d } else if(aPDGcode==1114) { nc=1; qdq[0]=make_pair(1103, 1); prb[0]=1.; // uu_1, s } else if(aPDGcode==3224) { nc=2; qdq[0]=make_pair(2203, 3); prb[0]=r3; // uu_1, s qdq[1]=make_pair(3203, 2); prb[1]=d3; // su_1, u } else if(aPDGcode==3214) // @@ SU(3) is broken because of the s-quark mass { nc=3; qdq[0]=make_pair(2103, 3); prb[0]=r3; // ud_1, s qdq[1]=make_pair(3203, 1); prb[1]=r3; // su_1, d qdq[2]=make_pair(3103, 2); prb[2]=r3; // sd_1, u } else if(aPDGcode==3114) { nc=2; qdq[0]=make_pair(1103, 3); prb[0]=r3; // dd_1, s qdq[1]=make_pair(3103, 1); prb[1]=d3; // sd_1, d } else if(aPDGcode==3324) { nc=2; qdq[0]=make_pair(3203, 3); prb[0]=r3; // su_1, s qdq[1]=make_pair(3303, 2); prb[1]=d3; // ss_1, u } else if(aPDGcode==3314) { nc=2; qdq[0]=make_pair(3103, 3); prb[0]=d3; // sd_1, s qdq[1]=make_pair(3303, 1); prb[1]=r3; // ss_1, d } else return false; } G4double random = G4UniformRand(); G4double sum = 0.; for(G4int i=0; irandom) { if(PDGcode>0) { *diQuark= qdq[i].first; *quark = qdq[i].second; } else { *diQuark= -qdq[i].second; *quark = -qdq[i].first; } break; } } return true; } // This is not usual Gaussian, in fact it is dN/d(pt) ~ pt * exp(-pt^2/pt0^2) G4ThreeVector G4QHadron::GaussianPt(G4double widthSquare, G4double maxPtSquare) { G4double R=0.; while ((R = -widthSquare*std::log(G4UniformRand())) > maxPtSquare){} R = std::sqrt(R); G4double phi = twopi*G4UniformRand(); return G4ThreeVector(R*std::cos(phi), R*std::sin(phi), 0.); } G4QParton* G4QHadron::GetNextParton() { if(Color.size()==0) return 0; G4QParton* result = Color.back(); Color.pop_back(); return result; } G4QParton* G4QHadron::GetNextAntiParton() { if(AntiColor.size() == 0) return 0; G4QParton* result = AntiColor.front(); AntiColor.pop_front(); return result; } // Random Split of the Hadron in 2 Partons (caller is responsible for G4QPartonPair delete) G4QPartonPair* G4QHadron::SplitInTwoPartons() // If result=0: impossible to split (?) { if(std::abs(GetBaryonNumber())>1) // Not Baryons or Mesons or Anti-Baryons { G4cerr<<"***G4QHadron::SplitInTwoPartons: Can not split QC="< PP = valQ.MakePartonPair(); return new G4QPartonPair(new G4QParton(PP.first), new G4QParton(PP.second)); }