// // ******************************************************************** // * 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: G4ElasticHadrNucleusHE.cc,v 1.79 2008/01/14 10:39:13 vnivanch Exp $ // GEANT4 tag $Name: geant4-09-02 $ // // // The generator of high energy hadron-nucleus elastic scattering // The hadron kinetic energy T > 1 GeV // N. Starkov 2003. // // 19.05.04 Variant for G4 6.1: The 'ApplyYourself' was changed // 19.11.05 The HE elastic scattering on proton is added (N.Starkov) // 16.11.06 The low energy boundary is shifted to T = 400 MeV (N.Starkov) // 23.11.06 General cleanup, ONQ0=3, use pointer instead of particle name (VI) // 02.05.07 Scale sampled t as p^2 (VI) // 15.05.07 Redesign and cleanup (V.Ivanchenko) // 17.05.07 cleanup (V.Grichine) // #include "G4ElasticHadrNucleusHE.hh" #include "Randomize.hh" #include "G4ios.hh" #include "G4ParticleTable.hh" #include "G4IonTable.hh" #include "G4Proton.hh" #include "G4NistManager.hh" using namespace std; /////////////////////////////////////////////////////////////// // // G4ElasticData::G4ElasticData(const G4ParticleDefinition* p, G4int Z, G4double AWeight, G4double* eGeV) { hadr = p; massGeV = p->GetPDGMass()/GeV; mass2GeV2= massGeV*massGeV; AtomicWeight = G4int(AWeight + 0.5); DefineNucleusParameters(AWeight); limitQ2 = 35./(R1*R1); // (GeV/c)^2 G4double dQ2 = limitQ2/(ONQ2 - 1.); TableQ2[0] = 0.0; for(G4int ii = 1; ii < ONQ2; ii++) { TableQ2[ii] = TableQ2[ii-1]+dQ2; } massA = AWeight*amu_c2/GeV; massA2 = massA*massA; for(G4int kk = 0; kk < NENERGY; kk++) { dnkE[kk] = 0; G4double elab = eGeV[kk] + massGeV; G4double plab2= eGeV[kk]*(eGeV[kk] + 2.0*massGeV); G4double Q2m = 4.0*plab2*massA2/(mass2GeV2 + massA2 + 2.*massA2*elab); if(Z == 1 && p == G4Proton::Proton()) Q2m *= 0.5; maxQ2[kk] = std::min(limitQ2, Q2m); TableCrossSec[ONQ2*kk] = 0.0; // G4cout<<" kk eGeV[kk] "< 3) Pnucl = 0.176 + 0.00275*A; else Pnucl = 0.4; //G4cout<<" Deault: A= "<= 100) Aeff = 0.7; else if(A < 100 && A > 75) Aeff = 1.5 - 0.008*A; else Aeff = 0.9; break; } //G4cout<<" Result: A= "<GetKineticEnergy(); if( ekin <= lowestEnergyLimit ) { theParticleChange.SetEnergyChange(ekin); theParticleChange.SetMomentumChange(aTrack.Get4Momentum().vect().unit()); return &theParticleChange; } G4double aTarget = targetNucleus.GetN(); G4double zTarget = targetNucleus.GetZ(); G4double plab = aParticle->GetTotalMomentum(); if (verboseLevel >1) { G4cout << "G4ElasticHadrNucleusHE: Incident particle plab=" << plab/GeV << " GeV/c " << " ekin(MeV) = " << ekin/MeV << " " << aParticle->GetDefinition()->GetParticleName() << G4endl; } // Scattered particle referred to axis of incident particle const G4ParticleDefinition* theParticle = aParticle->GetDefinition(); G4double m1 = theParticle->GetPDGMass(); G4int Z = static_cast(zTarget+0.5); G4int A = static_cast(aTarget+0.5); G4int projPDG = theParticle->GetPDGEncoding(); if (verboseLevel>1) { G4cout << "G4ElasticHadrNucleusHE for " << theParticle->GetParticleName() << " PDGcode= " << projPDG << " on nucleus Z= " << Z << " A= " << A << G4endl; } G4ParticleDefinition * theDef = 0; if (Z == 1 && A == 1) theDef = G4Proton::Proton(); else if (Z == 1 && A == 2) theDef = G4Deuteron::Deuteron(); else if (Z == 1 && A == 3) theDef = G4Triton::Triton(); else if (Z == 2 && A == 3) theDef = G4He3::He3(); else if (Z == 2 && A == 4) theDef = G4Alpha::Alpha(); else theDef = G4ParticleTable:: GetParticleTable()->FindIon(Z,A,0,Z); G4double m2 = theDef->GetPDGMass(); G4LorentzVector lv1 = aParticle->Get4Momentum(); G4LorentzVector lv(0.0,0.0,0.0,m2); lv += lv1; G4ThreeVector bst = lv.boostVector(); lv1.boost(-bst); G4ThreeVector p1 = lv1.vect(); G4double ptot = p1.mag(); G4double tmax = 4.0*ptot*ptot; G4double t = 0.0; // Choose generator G4bool swave = false; // S-wave for very low energy if(plab < plabLowLimit) swave = true; // normal sampling if(!swave) { t = SampleT(theParticle,plab,Z,A); if(t > tmax) swave = true; } if(swave) t = G4UniformRand()*tmax; // Sampling in CM system G4double phi = G4UniformRand()*twopi; G4double cost = 1. - 2.0*t/tmax; G4double sint; if( cost >= 1.0 ) { cost = 1.0; sint = 0.0; } else if( cost <= -1.0) { cost = -1.0; sint = 0.0; } else { sint = std::sqrt((1.0-cost)*(1.0+cost)); } if (verboseLevel>1) G4cout << "cos(t)=" << cost << " std::sin(t)=" << sint << G4endl; G4ThreeVector v1(sint*std::cos(phi),sint*std::sin(phi),cost); v1 *= ptot; G4LorentzVector nlv1( v1.x(), v1.y(), v1.z(), std::sqrt(ptot*ptot + m1*m1)); nlv1.boost(bst); G4double eFinal = nlv1.e() - m1; if (verboseLevel > 1) { G4cout << "Scattered: " << nlv1<<" m= " << m1 << " ekin(MeV)= " << eFinal << " Proj: 4-mom " << lv1 <GetDefinition()->GetParticleName() << " p(GeV/c)= " << plab << " on " << theDef->GetParticleName() << G4endl; eFinal = 0.0; nlv1.setE(m1); } theParticleChange.SetMomentumChange( nlv1.vect().unit() ); theParticleChange.SetEnergyChange(eFinal); G4LorentzVector nlv0 = lv - nlv1; G4double erec = nlv0.e() - m2; if (verboseLevel > 1) { G4cout << "Recoil: " << nlv0<<" m= " << m2 << " ekin(MeV)= " << erec <GetDefinition()->GetParticleName() << " p(GeV/c)= " << plab << " on " << theDef->GetParticleName() << G4endl; nlv0.setE(m2); } G4DynamicParticle * aSec = new G4DynamicParticle(theDef, nlv0); theParticleChange.AddSecondary(aSec); return &theParticleChange; } ////////////////////////////////////////////////////////////////////////// // // G4double G4ElasticHadrNucleusHE:: SampleT( const G4ParticleDefinition* p, G4double inLabMom, G4int Z, G4int N) { G4double plab = inLabMom/GeV; // (GeV/c) G4double Q2 = 0; iHadrCode = p->GetPDGEncoding(); NumbN = N; if(verboseLevel > 1) { G4cout<< " G4ElasticHadrNucleusHE::SampleT: " << " for " << p->GetParticleName() << " at Z= " << Z << " A= " << N << " plab(GeV)= " << plab << G4endl; } G4int idx; for( idx = 0 ; idx < NHADRONS; idx++) { if(iHadrCode == HadronCode[idx]) break; } // Hadron is not in the list if( idx >= NHADRONS ) return Q2; iHadron = HadronType[idx]; iHadrCode = HadronCode[idx]; if(Z==1) { hMass = p->GetPDGMass()/GeV; hMass2 = hMass*hMass; G4double T = sqrt(plab*plab+hMass2)-hMass; if(T > 0.4) Q2 = HadronProtonQ2(p, plab); if (verboseLevel>1) G4cout<<" Proton : Q2 "<GetAtomicMassAmu(Z); ElD1 = new G4ElasticData(p, Z, AWeight, Energy); SetOfElasticData[idx][Z] = ElD1; if(verboseLevel > 1) { G4cout<< " G4ElasticHadrNucleusHE::SampleT: new record " << idx << " for " << p->GetParticleName() << " Z= " << Z << G4endl; } } hMass = ElD1->massGeV; hMass2 = ElD1->mass2GeV2; G4double M = ElD1->massA; G4double M2 = ElD1->massA2; G4double plab2 = plab*plab; G4double Q2max = 4.*plab2*M2/ (hMass2 + M2 + 2.*M*std::sqrt(plab2 + hMass2)); // sample scattering G4double T = sqrt(plab2+hMass2)-hMass; if(T > 0.4) Q2 = HadronNucleusQ2_2(ElD1, Z, plab, Q2max); if(verboseLevel > 1) G4cout<<" SampleT: Q2(GeV^2)= "<TableQ2; G4int index = NumbOnE*ONQ2; // Select kinematics for node energy G4double T = Energy[NumbOnE]; hLabMomentum2 = T*(T + 2.*hMass); G4double Q2max = pElD->maxQ2[NumbOnE]; G4int length = pElD->dnkE[NumbOnE]; // Build vector if(length == 0) { R1 = pElD->R1; R2 = pElD->R2; Aeff = pElD->Aeff; Pnucl = pElD->Pnucl; hLabMomentum = std::sqrt(hLabMomentum2); DefineHadronValues(Z); if(verboseLevel >0) { G4cout<<"1 plab T "<CrossSecMaxQ2[NumbOnE] = 1.0; if(verboseLevel > 1) G4cout<<" HadrNucleusQ2_2: NumbOnE= " << NumbOnE << " length= " << length << " Q2max= " << Q2max << " ekin= " << ekin <TableCrossSec[index] = 0; dQ2 = pElD->TableQ2[1]-pElD->TableQ2[0]; GetHeavyFq2(NumbN, LineFq2); // %%%%%%%%%%%%%%%%%%%%%%%%% for(G4int ii=0; ii 2) // G4cout<<" ii LineFq2 "<TableCrossSec[index+ii] = LineFq2[ii]/LineFq2[ONQ2-1]; } pElD->dnkE[NumbOnE] = ONQ2; length = ONQ2; } G4double* dNumbFQ2 = &(pElD->TableCrossSec[index]); for( iNumbQ2 = 1; iNumbQ2TableCrossSec[index+iNumbQ2]) break; } Q2 = GetQ2_2(iNumbQ2, dNumbQ2, dNumbFQ2, Rand); if(tmax < Q2max) Q2 *= tmax/Q2max; if(verboseLevel > 1) G4cout<<" HadrNucleusQ2_2(2): Q2= "<2) G4cout<<" GetHeavy: Q2 dQ2 totSum "< 208 ? 1.0e-7 : 1.0e-6; G4double Stot = HadrTot*MbToGeV2; // Gev^-2 G4double Bhad = HadrSlope; // GeV^-2 G4double Asq = 1+HadrReIm*HadrReIm; G4double Rho2 = std::sqrt(Asq); // if(verboseLevel >1) G4cout<<" Fq2 Before for i Tot B Im "< 1) { G4cout << "GetFq2: Stot= " << Stot << " Bhad= " << Bhad <<" Im "< 10) TotP = TotN = 7.5*logE - 40.12525 + 103*std::pow(sHadr,-0.165); // mb else { // ================== neutron ================ //// if(iHadrCode == 2112) if( hLabMomentum > 1.4 ) TotN = 33.3+15.2*(hLabMomentum2-1.35)/ (std::pow(hLabMomentum,2.37)+0.95); else if(hLabMomentum > 0.8) { G4double A0 = logE + 0.0513; TotN = 33.0 + 25.5*A0*A0; } else { G4double A0 = logE - 0.2634; // log(1.3) TotN = 33.0 + 30.*A0*A0*A0*A0; } // ================= proton =============== // else if(iHadrCode == 2212) { if(hLabMomentum >= 1.05) { TotP = 39.0+75.*(hLabMomentum-1.2)/ (hLabMomentum2*hLabMomentum+0.15); } else if(hLabMomentum >= 0.7) { G4double A0 = logE + 0.3147; TotP = 23.0 + 40.*A0*A0; } else { TotP = 23.+50.*std::pow(std::log(0.73/hLabMomentum),3.5); } } } // HadrTot = 0.5*(82*TotP+126*TotN)/104; // $$$$$$$$$$$$$$$$$$ HadrTot = 0.5*(TotP+TotN); // ................................................... // Proton slope if(hLabMomentum >= 2.) HadrSlope = 5.44 + 0.88*logS; else if(hLabMomentum >= 0.5) HadrSlope = 3.73*hLabMomentum-0.37; else HadrSlope = 1.5; // ................................................... if(hLabMomentum >= 1.2) HadrReIm = 0.13*(logS - 5.8579332)*std::pow(sHadr,-0.18); else if(hLabMomentum >= 0.6) HadrReIm = -75.5*(std::pow(hLabMomentum,0.25)-0.95)/ (std::pow(3*hLabMomentum,2.2)+1); else HadrReIm = 15.5*hLabMomentum/(27*hLabMomentum2*hLabMomentum+2); // ................................................... DDSect2 = 2.2; //mb*GeV-2 DDSect3 = 0.6; //mb*GeV-2 // ================== lambda ================== if( iHadrCode == 3122) { HadrTot *= 0.88; HadrSlope *=0.85; } // ================== sigma + ================== else if( iHadrCode == 3222) { HadrTot *=0.81; HadrSlope *=0.85; } // ================== sigma 0,- ================== else if(iHadrCode == 3112 || iHadrCode == 3212 ) { HadrTot *=0.88; HadrSlope *=0.85; } // =================== xi ================= else if( iHadrCode == 3312 || iHadrCode == 3322 ) { HadrTot *=0.77; HadrSlope *=0.75; } // ================= omega ================= else if( iHadrCode == 3334) { HadrTot *=0.78; HadrSlope *=0.7; } break; // =========================================================== case 1: // antiproton case 7: // antineutron HadrTot = 5.2+5.2*logE + 123.2/sqrS; // mb HadrSlope = 8.32+0.57*logS; //(GeV/c)^-2 if( HadrEnergy < 1000 ) HadrReIm = 0.06*(sqrS-2.236)*(sqrS-14.14)*std::pow(sHadr,-0.8); else HadrReIm = 0.6*(logS - 5.8579332)*std::pow(sHadr,-0.25); DDSect2 = 11; //mb*(GeV/c)^-2 DDSect3 = 3; //mb*(GeV/c)^-2 // ================== lambda ================== if( iHadrCode == -3122) { HadrTot *= 0.88; HadrSlope *=0.85; } // ================== sigma + ================== else if( iHadrCode == -3222) { HadrTot *=0.81; HadrSlope *=0.85; } // ================== sigma 0,- ================== else if(iHadrCode == -3112 || iHadrCode == -3212 ) { HadrTot *=0.88; HadrSlope *=0.85; } // =================== xi ================= else if( iHadrCode == -3312 || iHadrCode == -3322 ) { HadrTot *=0.77; HadrSlope *=0.75; } // ================= omega ================= else if( iHadrCode == -3334) { HadrTot *=0.78; HadrSlope *=0.7; } break; // ------------------------------------------- case 2: // pi plus, pi minus case 3: if(hLabMomentum >= 3.5) TotP = 10.6+2.*logE + 25.*std::pow(HadrEnergy,-0.43); // mb // ========================================= else if(hLabMomentum >= 1.15) { G4double x = (hLabMomentum - 2.55)/0.55; G4double y = (hLabMomentum - 1.47)/0.225; TotP = 3.2*std::exp(-x*x) + 12.*std::exp(-y*y) + 27.5; } // ========================================= else if(hLabMomentum >= 0.4) { TotP = 88*(logE+0.2877)*(logE+0.2877)+14.0; } // ========================================= else { G4double x = (hLabMomentum - 0.29)/0.085; TotP = 20. + 180.*std::exp(-x*x); } // ------------------------------------------- if(hLabMomentum >= 3.0 ) TotN = 10.6 + 2.*logE + 30.*std::pow(HadrEnergy,-0.43); // mb else if(hLabMomentum >= 1.3) { G4double x = (hLabMomentum - 2.1)/0.4; G4double y = (hLabMomentum - 1.4)/0.12; TotN = 36.1+0.079 - 4.313*logE + 3.*std::exp(-x*x) + 1.5*std::exp(-y*y); } else if(hLabMomentum >= 0.65) { G4double x = (hLabMomentum - 0.72)/0.06; G4double y = (hLabMomentum - 1.015)/0.075; TotN = 36.1 + 10.*std::exp(-x*x) + 24*std::exp(-y*y); } else if(hLabMomentum >= 0.37) { G4double x = std::log(hLabMomentum/0.48); TotN = 26. + 110.*x*x; } else { G4double x = (hLabMomentum - 0.29)/0.07; TotN = 28.0 + 40.*std::exp(-x*x); } HadrTot = (TotP+TotN)/2; // ........................................ HadrSlope = 7.28+0.245*logS; // GeV-2 HadrReIm = 0.2*(logS - 4.6051702)*std::pow(sHadr,-0.15); DDSect2 = 0.7; //mb*GeV-2 DDSect3 = 0.27; //mb*GeV-2 break; // ========================================================== case 4: // K plus HadrTot = 10.6+1.8*logE + 9.0*std::pow(HadrEnergy,-0.55); // mb if(HadrEnergy>100) HadrSlope = 15.0; else HadrSlope = 1.0+1.76*logS - 2.84/sqrS; // GeV-2 HadrReIm = 0.4*(sHadr-20)*(sHadr-150)*std::pow(sHadr+50,-2.1); DDSect2 = 0.7; //mb*GeV-2 DDSect3 = 0.21; //mb*GeV-2 break; // ========================================================= case 5: // K minus HadrTot = 10+1.8*logE + 25./sqrS; // mb HadrSlope = 6.98+0.127*logS; // GeV-2 HadrReIm = 0.4*(sHadr-20)*(sHadr-20)*std::pow(sHadr+50,-2.1); DDSect2 = 0.7; //mb*GeV-2 DDSect3 = 0.27; //mb*GeV-2 break; } // ========================================================= if(verboseLevel>2) G4cout << "HadrTot= " << HadrTot << " HadrSlope= " << HadrSlope << " HadrReIm= " << HadrReIm << " DDSect2= " << DDSect2 << " DDSect3= " << DDSect3 << G4endl; if(Z != 1) return; // Scattering of protons Coeff0 = Coeff1 = Coeff2 = 0.0; Slope0 = Slope1 = 1.0; Slope2 = 5.0; // data for iHadron=0 static const G4double EnP0[6]={1.5,3.0,5.0,9.0,14.0,19.0}; static const G4double C0P0[6]={0.15,0.02,0.06,0.08,0.0003,0.0002}; static const G4double C1P0[6]={0.05,0.02,0.03,0.025,0.0,0.0}; static const G4double B0P0[6]={1.5,2.5,3.0,4.5,1.4,1.25}; static const G4double B1P0[6]={5.0,1.0,3.5,4.0,4.8,4.8}; // data for iHadron=6,7 static const G4double EnN[5]={1.5,5.0,10.0,14.0,20.0}; static const G4double C0N[5]={0.0,0.0,0.02,0.02,0.01}; static const G4double C1N[5]={0.06,0.008,0.0015,0.001,0.0003}; static const G4double B0N[5]={1.5,2.5,3.8,3.8,3.5}; static const G4double B1N[5]={1.5,2.2,3.6,4.5,4.8}; // data for iHadron=1 static const G4double EnP[2]={1.5,4.0}; static const G4double C0P[2]={0.001,0.0005}; static const G4double C1P[2]={0.003,0.001}; static const G4double B0P[2]={2.5,4.5}; static const G4double B1P[2]={1.0,4.0}; // data for iHadron=2 static const G4double EnPP[4]={1.0,2.0,3.0,4.0}; static const G4double C0PP[4]={0.0,0.0,0.0,0.0}; static const G4double C1PP[4]={0.15,0.08,0.02,0.01}; static const G4double B0PP[4]={1.5,2.8,3.8,3.8}; static const G4double B1PP[4]={0.8,1.6,3.6,4.6}; // data for iHadron=3 static const G4double EnPPN[4]={1.0,2.0,3.0,4.0}; static const G4double C0PPN[4]={0.0,0.0,0.0,0.0}; static const G4double C1PPN[4]={0.0,0.0,0.0,0.0}; static const G4double B0PPN[4]={1.5,2.8,3.8,3.8}; static const G4double B1PPN[4]={0.8,1.6,3.6,4.6}; // data for iHadron=4 static const G4double EnK[4]={1.4,2.33,3.0,5.0}; static const G4double C0K[4]={0.0,0.0,0.0,0.0}; static const G4double C1K[4]={0.01,0.007,0.005,0.003}; static const G4double B0K[4]={1.5,2.0,3.8,3.8}; static const G4double B1K[4]={1.6,1.6,1.6,1.6}; // data for iHadron=5 static const G4double EnKM[2]={1.4,4.0}; static const G4double C0KM[2]={0.006,0.002}; static const G4double C1KM[2]={0.00,0.00}; static const G4double B0KM[2]={2.5,3.5}; static const G4double B1KM[2]={1.6,1.6}; switch(iHadron) { case 0 : if(hLabMomentum 2) G4cout<<" HadrVal : Plasb "<1) G4cout<<"1 GetKin.: HadronName MomentumH " <GetParticleName()<<" "<1) G4cout<<"3 GetKin. : NumberH "<1) G4cout<<"Old: Coeff0 Coeff1 Coeff2 "< 0.0001) { if(delta>0) { DDD2 = DDD0; DDD0 = (DDD0+DDD1)*0.5; } else if(delta<0) { DDD1 = DDD0; DDD0 = (DDD0+DDD2)*0.5; } delta = GetDistrFun(DDD0)-Ran; } Q2 = DDD0; return Q2; } // ++++++++++++++++++++++++++++++++++++++++++ G4double G4ElasticHadrNucleusHE:: HadronProtonQ2(const G4ParticleDefinition * p, G4double inLabMom) { hMass = p->GetPDGMass()/GeV; hMass2 = hMass*hMass; hLabMomentum = inLabMom; hLabMomentum2 = hLabMomentum*hLabMomentum; HadrEnergy = sqrt(hLabMomentum2+hMass2); G4double Rand = G4UniformRand(); GetKinematics(p, inLabMom); G4double Q2 = GetQ2(Rand); return Q2; } // =========================================== /////////////////////////////////////////////////////////////////// // // void G4ElasticHadrNucleusHE::Binom() { G4int N, M; G4double Fact1, J; for(N = 0; N < 240; N++) { J = 1; for( M = 0; M <= N; M++ ) { Fact1 = 1; if ( ( N > 0 ) && ( N > M ) && M > 0 ) { J *= G4double(N-M+1)/G4double(M); Fact1 = J; } SetBinom[N][M] = Fact1; } } return; } // // ///////////////////////////////////////////////////////////