40 #include <TLorentzVector.h> 47 #include "Conventions/GBuild.h" 66 using std::ostringstream;
67 using namespace genie;
74 int pdgc,
const TLorentzVector & x4,
const TLorentzVector & p4,
75 double A,
double Z,
double nRpi,
double nRnuc)
89 bool is_kaon = pdgc ==
kPdgKP;
92 if(!is_pion && !is_nucleon && !is_kaon && !is_gamma)
return 0.;
102 double momentum = p4.Vect().Mag();
103 double ring = (momentum>0) ? 1.240/momentum : 0;
105 if(A<=20) { ring /= 2.; }
107 if (is_pion || is_kaon ) { ring *= nRpi; }
108 else if (is_nucleon ) { ring *= nRnuc; }
109 else if (is_gamma ) { ring = 0.; }
112 double rnow = x4.Vect().Mag();
118 double ke = (p4.Energy() - p4.M()) /
units::MeV;
125 double ppcnt = (double) Z/ (
double)
A;
129 { sigtot = fHadroData2014 -> XSecPipp_Tot() -> Evaluate(ke)*ppcnt;
130 sigtot+= fHadroData2014 -> XSecPipn_Tot() -> Evaluate(ke)*(1-ppcnt);}
132 { sigtot = fHadroData2014 -> XSecPi0p_Tot() -> Evaluate(ke)*ppcnt;
133 sigtot+= fHadroData2014 -> XSecPi0n_Tot() -> Evaluate(ke)*(1-ppcnt);}
135 { sigtot = fHadroData2014 -> XSecPipn_Tot() -> Evaluate(ke)*ppcnt;
136 sigtot+= fHadroData2014 -> XSecPipp_Tot() -> Evaluate(ke)*(1-ppcnt);}
138 { sigtot = fHadroData2014 -> XSecPp_Tot() -> Evaluate(ke)*ppcnt;
139 sigtot+= fHadroData2014 -> XSecPn_Tot() -> Evaluate(ke)*(1-ppcnt);}
141 { sigtot = fHadroData2014 -> XSecPn_Tot() -> Evaluate(ke)*ppcnt;
142 sigtot+= fHadroData2014 -> XSecNn_Tot() -> Evaluate(ke)*(1-ppcnt);}
144 { sigtot = fHadroData2014 -> XSecKpN_Tot() -> Evaluate(ke);
147 { sigtot = fHadroData2014 -> XSecGamp_fs() -> Evaluate(ke)*ppcnt;
148 sigtot+= fHadroData2014 -> XSecGamn_fs() -> Evaluate(ke)*(1-ppcnt);}
158 double lamda = 1. / (rho * sigtot);
161 if( ! TMath::Finite(lamda) ) {
174 int pdgc,
const TLorentzVector & x4,
const TLorentzVector & p4,
double A)
189 if(!is_deltapp)
return 0.;
192 double rnow = x4.Vect().Mag();
197 double ke = (p4.Energy() - p4.M()) /
units::MeV;
198 ke = TMath::Max(1500., ke);
199 ke = TMath::Min( 0., ke);
204 else if (ke<1000) sig=40;
211 double lamda = 1. / (rho * sig);
214 if( ! TMath::Finite(lamda) ) {
222 int pdgc,
const TLorentzVector & x4,
const TLorentzVector & p4,
double A,
double Z,
223 double mfp_scale_factor,
double nRpi,
double nRnuc,
double NR,
double R0)
242 double R = NR * R0 * TMath::Power(A, 1./3.);
244 TVector3 dr3 = p4.Vect().Unit();
245 TLorentzVector dr4(dr3,0);
248 <<
"Calculating survival probability for hadron with PDG code = " << pdgc
249 <<
" and momentum = " << p4.P() <<
" GeV";
251 <<
"mfp scale = " << mfp_scale_factor
252 <<
", nRpi = " << nRpi <<
", nRnuc = " << nRnuc <<
", NR = " << NR
253 <<
", R0 = " << R0 <<
" fm";
255 TLorentzVector x4_curr(x4);
258 double rnow = x4_curr.Vect().Mag();
259 if (rnow > (R+step))
break;
261 x4_curr += (step*dr4);
262 rnow = x4_curr.Vect().Mag();
265 double mfp_twk = mfp * mfp_scale_factor;
267 double dprob = (mfp_twk>0) ? TMath::Exp(-step/mfp_twk) : 0.;
277 LOG(
"INukeUtils",
pDEBUG) <<
"Psurv = " << prob;
283 const TLorentzVector & x4,
const TLorentzVector & p4,
284 double A,
double NR,
double R0)
290 double R = NR * R0 * TMath::Power(A, 1./3.);
293 TVector3 dr3 = p4.Vect().Unit();
294 TLorentzVector dr4(dr3,0);
296 TLorentzVector x4_curr(x4);
300 double rnow = x4_curr.Vect().Mag();
301 x4_curr += (step*dr4);
303 rnow = x4_curr.Vect().Mag();
310 int pdgc,
const TLorentzVector & x4,
const TLorentzVector & p4,
311 double A,
double Z,
double NR,
double R0)
320 double R = NR * R0 * TMath::Power(A, 1./3.);
323 TVector3 dr3 = p4.Vect().Unit();
324 TLorentzVector dr4(dr3,0);
326 TLorentzVector x4_curr(x4);
331 double rnow = x4_curr.Vect().Mag();
332 x4_curr += (step*dr4);
334 rnow = x4_curr.Vect().Mag();
337 d_mfp += (step/lambda);
355 #ifdef __GENIE_LOW_LEVEL_MESG_ENABLED__ 357 <<
"Stepping particle [" << p->
Name() <<
"] by dr = " << step <<
" fm";
361 TVector3 dr = p->
P4()->Vect().Unit();
364 TLorentzVector dx4(dr,dt);
365 TLorentzVector x4new = *(p->
X4()) + dx4;
367 if(nuclear_radius > 0.) {
372 double r = x4new.Vect().Mag();
373 double rmax = nuclear_radius+epsilon;
376 <<
"Particle was stepped too far away (r = " << r <<
" fm)";
378 <<
"Placing it " << epsilon
379 <<
" fm outside the nucleus (r' = " << rmax <<
" fm)";
385 #ifdef __GENIE_LOW_LEVEL_MESG_ENABLED__ 403 #ifdef __GENIE_LOW_LEVEL_MESG_ENABLED__ 405 <<
"PreEquilibrium() is invoked for a : " << p->
Name()
406 <<
" whose kinetic energy is : " << p->
KinE();
413 bool allow_dup =
true;
416 double ppcnt = (double) RemnZ / (
double) RemnA;
425 if(rnd->
RndFsi().Rndm()<ppcnt)
434 ppcnt = (double) RemnZ / (
double) RemnA;
441 TVector3 pBuf = p->
P4()->Vect();
442 double mBuf = p->
Mass();
443 double eBuf = TMath::Sqrt(pBuf.Mag2() + mBuf*mBuf);
444 TLorentzVector tSum(pBuf,eBuf);
447 for(pdg_iter=++(list.begin());pdg_iter!=list.end();++pdg_iter)
449 target.SetHitNucPdg(*pdg_iter);
451 mBuf = pLib->
Find(*pdg_iter)->Mass();
453 pBuf = FermiFac * Nuclmodel->
Momentum3();
454 eBuf = TMath::Sqrt(pBuf.Mag2() + mBuf*mBuf);
455 tSum += TLorentzVector(pBuf,eBuf);
456 RemnP4 -= TLorentzVector(pBuf,eBuf-mBuf);
458 TLorentzVector dP4 = tSum + TLorentzVector(TVector3(0,0,0),-mSum);
464 if(success)
LOG(
"INukeUtils",
pINFO) <<
"Successful phase space decay for pre-equilibrium nucleus FSI event";
468 exception.
SetReason(
"Phase space generation of pre-equilibrium nucleus final state failed, details above");
473 while(p_loc<ev->GetEntries())
488 #ifdef __GENIE_LOW_LEVEL_MESG_ENABLED__ 490 <<
"Particle at: " << p_loc;
497 int f_loc = p_loc + 1;
517 for(
unsigned int j=0;j<descendants->size();j++)
519 loc = (*descendants)[j];
550 #ifdef __GENIE_LOW_LEVEL_MESG_ENABLED__ 552 <<
"Equilibrium() is invoked for a : " << p->
Name()
553 <<
" whose kinetic energy is : " << p->
KinE();
560 bool allow_dup =
true;
564 double ppcnt = (double) RemnZ / (
double) RemnA;
574 if(rnd->
RndFsi().Rndm()<ppcnt)
583 ppcnt = (double) RemnZ / (
double) RemnA;
586 #ifdef __GENIE_LOW_LEVEL_MESG_ENABLED__ 588 <<
"Remnant nucleus (A,Z) = (" << RemnA <<
", " << RemnZ <<
")";
595 TVector3 pBuf = p->
P4()->Vect();
596 double mBuf = p->
Mass();
597 double eBuf = TMath::Sqrt(pBuf.Mag2() + mBuf*mBuf);
598 TLorentzVector tSum(pBuf,eBuf);
601 for(pdg_iter=++(list.begin());pdg_iter!=list.end();++pdg_iter)
603 target.SetHitNucPdg(*pdg_iter);
605 mBuf = pLib->
Find(*pdg_iter)->Mass();
607 pBuf = FermiFac * Nuclmodel->
Momentum3();
608 eBuf = TMath::Sqrt(pBuf.Mag2() + mBuf*mBuf);
609 tSum += TLorentzVector(pBuf,eBuf);
610 RemnP4 -= TLorentzVector(pBuf,eBuf-mBuf);
612 TLorentzVector dP4 = tSum + TLorentzVector(TVector3(0,0,0),-mSum);
618 if (success)
LOG(
"INukeUtils",
pINFO) <<
"successful pre-equilibrium interaction";
622 exception.
SetReason(
"Phase space generation of compound nucleus final state failed, details above");
629 GHepRecord* ev,
int pcode,
int tcode,
int scode,
int s2code,
double C3CM,
643 double E3L, P3L, E4L, P4L;
644 TVector3 tP1L, tPtot, tbeta, tbetadir, tTrans, tVect;
645 TVector3 tP1zCM, tP2zCM, tP3L, tP4L;
657 M3 = pLib->
Find(scode)->Mass();
658 M4 = pLib->
Find(s2code)->Mass();
661 TLorentzVector t4P1L = *p->
P4();
662 TLorentzVector t4P2L = *t->
P4();
665 double bindE = 0.025;
669 TLorentzVector t4P3L, t4P4L;
672 P3L = t4P3L.Vect().Mag();
673 P4L = t4P4L.Vect().Mag();
678 <<
"TwoBodyKinematics fails: C3CM, P3 = " << C3CM <<
" " 679 << P3L <<
" " << E3L <<
"\n" <<
" P4 = " 680 << P4L <<
" " << E4L ;
685 P3L = t4P3L.Vect().Mag();
686 P4L = t4P4L.Vect().Mag();
690 <<
"C3CM, P3 = " << C3CM <<
" " 691 << P3L <<
" " << E3L <<
"\n" <<
" P4 = " 692 << P4L <<
" " << E4L ;
695 if(!(TMath::Finite(P3L)) || P3L<.001)
698 <<
"Particle 3 momentum small or non-finite: " << P3L
699 <<
"\n" <<
"--> Assigning .001 as new momentum";
701 E3L = TMath::Sqrt(P3L*P3L + M3*M3);
703 if(!(TMath::Finite(P4L)) || P4L<.001)
706 <<
"Particle 4 momentum small or non-finite: " << P4L
707 <<
"\n" <<
"--> Assigning .001 as new momentum";
709 E4L = TMath::Sqrt(P4L*P4L + M4*M4);
751 LOG(
"INukeUtils",
pINFO) <<
"Successful 2 body collision";
757 double M3,
double M4, TLorentzVector t4P1L, TLorentzVector t4P2L,
758 TLorentzVector &t4P3L, TLorentzVector &t4P4L,
double C3CM, TLorentzVector &RemnP4,
double bindE)
778 double E1L, E2L, P1L, P2L, E3L, P3L;
782 double E1CM, E2CM, E3CM, P3CM;
785 double theta1, theta2, theta5, P1zL, P2zL, P1tL, P2tL;
786 TVector3 tbeta, tbetadir, tTrans, tVect;
787 TVector3 tP1zCM, tP2zCM, vP3L;
788 TLorentzVector t4P1buf, t4P2buf, t4Ptot;
797 if (C3CM < -1. || C3CM > 1.)
return false;
800 S3CM = TMath::Sqrt(1.0 - C3CM*C3CM);
811 t4Ptot = t4P1buf + t4P2buf;
821 LOG(
"INukeUtils",
pNOTICE) <<
"TwoBodyKinematics Failed: Forbidden by binding energy";
822 LOG(
"INukeUtils",
pNOTICE) <<
"E1L, E2L, M3, M4 : "<< E1L <<
", "<< E2L <<
", "<< M3 <<
", "<< M4;
823 t4P3L.SetPxPyPzE(0,0,0,0);
824 t4P4L.SetPxPyPzE(0,0,0,0);
830 tbeta = t4Ptot.Vect() * (1.0 / (E1L + E2L));
831 tbetadir = tbeta.Unit();
833 gm = 1.0 / TMath::Sqrt(1.0 - beta*beta);
836 theta1 = t4P1buf.Angle(tbeta);
837 theta2 = t4P2buf.Angle(tbeta);
838 P1zL = P1L*TMath::Cos(theta1);
839 P2zL = P2L*TMath::Cos(theta2);
840 P1tL = TMath::Sqrt(P1L*P1L - P1zL*P1zL);
841 P2tL = -TMath::Sqrt(P2L*P2L - P2zL*P2zL);
843 if(TMath::Abs((tVect - tbetadir).Mag())<.01) tVect.SetXYZ(0,1,0);
844 theta5 = tVect.Angle(tbetadir);
845 tTrans = (tVect - TMath::Cos(theta5)*tbetadir).Unit();
848 E1CM = gm*E1L - gm*beta*P1zL;
849 tP1zCM = gm*P1zL*tbetadir - gm*tbeta*E1L;
850 E2CM = gm*E2L - gm*beta*P2zL;
851 tP2zCM = gm*P2zL*tbetadir - gm*tbeta*E2L;
855 LOG(
"INukeUtils",
pINFO) <<
"M1 "<<t4P1L.M()<<
", M2 "<<t4P2L.M();
856 LOG(
"INukeUtils",
pINFO) <<
"E1L "<<E1L<<
", E1CM "<<E1CM;
857 LOG(
"INukeUtils",
pINFO) <<
"P1zL "<<P1zL<<
", P1zCM "<<tP1zCM.Mag()<<
", P1tL "<<P1tL;
858 LOG(
"INukeUtils",
pINFO) <<
"E2L "<<E2L<<
", E2CM "<<E2CM;
859 LOG(
"INukeUtils",
pINFO) <<
"P2zL "<<P2zL<<
", P2zCM "<<tP2zCM.Mag()<<
", P2tL "<<P2tL;
860 LOG(
"INukeUtils",
pINFO) <<
"C3CM "<<C3CM;
863 E3CM = (Et*Et + M3*M3 - M4*M4) / (2.0 * Et);
866 if(E3CM*E3CM - M3*M3<0 || E3CM<0 || Et<0)
868 if (Et<0)
LOG(
"INukeUtils",
pNOTICE) <<
"TwoBodyKinematics Failed: Total energy is negative";
869 if (E3CM<M3)
LOG(
"INukeUtils",
pNOTICE) <<
"TwoBodyKinematics Failed: Scattered Particle 3 CM energy is too small";
870 if (E3CM*E3CM - M3*M3<0)
LOG(
"INukeUtils",
pNOTICE) <<
"TwoBodyKinematics Failed: Scattered Particle 3 CM momentum is nonreal";
871 t4P3L.SetPxPyPzE(0,0,0,0);
872 t4P4L.SetPxPyPzE(0,0,0,0);
875 P3CM = TMath::Sqrt(E3CM*E3CM - M3*M3);
878 P3zL = gm*beta*E3CM + gm*P3CM*C3CM;
881 P3L = TMath::Sqrt(P3zL*P3zL + P3tL*P3tL);
882 E3L = TMath::Sqrt(P3L*P3L + M3*M3);
886 double E4CM = Et-E3CM;
887 double P4zL = gm*beta*E4CM - gm*P3CM*C3CM;
888 double P4tL = -1.*P3tL;
889 double P4L = TMath::Sqrt(P4zL*P4zL + P4tL*P4tL);
890 double E4L = TMath::Sqrt(P4L*P4L + M4*M4);
892 LOG(
"INukeUtils",
pINFO) <<
"M3 "<< M3 <<
", M4 "<< M4;
893 LOG(
"INukeUtils",
pINFO) <<
"E3L "<<E3L<<
", E3CM "<<E3CM;
894 LOG(
"INukeUtils",
pINFO) <<
"P3zL "<<P3zL<<
", P3tL "<<P3tL;
895 LOG(
"INukeUtils",
pINFO) <<
"C3L "<<P3zL/P3L;
897 LOG(
"INukeUtils",
pINFO) <<
"E4L "<<E4L<<
", E4CM "<<E4CM;
898 LOG(
"INukeUtils",
pINFO) <<
"P4zL "<<P4zL<<
", P4tL "<<P4tL;
899 LOG(
"INukeUtils",
pINFO) <<
"P4L "<<P4L;
900 LOG(
"INukeUtils",
pINFO) <<
"C4L "<<P4zL/P4L;
902 double echeck = E1L + E2L - (E3L + E4L);
903 double pzcheck = P1zL+ P2zL - (P3zL + P4zL);
904 double ptcheck = P1tL+ P2tL - (P3tL + P4tL);
906 LOG(
"INukeUtils",
pINFO) <<
"Check 4-momentum conservation - Energy "<<echeck<<
", z momentum "<<pzcheck <<
", transverse momentum " << ptcheck ;
911 if(!(TMath::Finite(P3L)) || P3L<.001)
914 <<
"Particle 3 momentum small or non-finite: " << P3L
915 <<
"\n" <<
"--> Assigning .001 as new momentum";
919 E3L = TMath::Sqrt(P3L*P3L + M3*M3);
925 vP3L = P3zL*tbetadir + P3tL*tTrans;
926 vP3L.Rotate(PHI3,tbetadir);
931 t4P4L = t4P1buf + t4P2buf - t4P3L;
932 t4P4L-= TLorentzVector(0,0,0,bindE);
939 if(t4P4L.Mag2()<0 || t4P4L.E()<0)
941 LOG(
"INukeUtils",
pNOTICE)<<
"TwoBodyKinematics Failed: Target mass or energy is negative";
942 t4P3L.SetPxPyPzE(0,0,0,0);
943 t4P4L.SetPxPyPzE(0,0,0,0);
947 if (bindE!=0) RemnP4 += TLorentzVector(0,0,0,bindE);
953 bool DoFermi,
double FermiFac,
double FermiMomentum,
const NuclearModelI* Nuclmodel)
965 double M1, M2, M3, M4, M5;
966 double P1L, P2L, P3L, P4L, P5L;
967 double E1L, E2L, E3L, E4L, E5L;
968 double E1CM, E2CM, P3tL;
969 double PizL, PitL, PiL, EiL;
970 double EiCM, P4CM2, E4CM2, E5CM2, P3CM, E3CM;
971 double beta, gm, beta2, gm2;
972 double P3zL, P4zL, P4tL, P5zL, P5tL;
973 double Et, M, theta1, theta2;
975 double theta3, theta4, phi3, phi4, theta5;
976 TVector3 tP2L, tP1L, tPtot, tbeta, tbetadir, tTrans, tP4L, tP5L;
977 TVector3 tP1zCM, tP2zCM, tP3L, tPiL, tbeta2, tbetadir2, tVect, tTrans2;
986 M2 = pLib->
Find(tcode)->Mass();
997 target.SetHitNucPdg(tcode);
999 tP2L = FermiFac * Nuclmodel->
Momentum3();
1001 E2L = TMath::Sqrt(tP2L.Mag2() + M2*M2);
1005 tP2L.SetXYZ(0.0, 0.0, 0.0);
1013 P1L = TMath::Sqrt(E1L*E1L - M1*M1);
1014 tP1L = p->
P4()->Vect();
1015 tPtot = tP1L + tP2L;
1017 tbeta = tPtot * (1.0 / (E1L + E2L));
1018 tbetadir = tbeta.Unit();
1020 gm = 1.0 / TMath::Sqrt(1.0 - beta*beta);
1022 theta1 = tP1L.Angle(tbeta);
1023 theta2 = tP2L.Angle(tbeta);
1024 P1zL = P1L*TMath::Cos(theta1);
1025 P2zL = P2L*TMath::Cos(theta2);
1026 tVect.SetXYZ(1,0,0);
1027 if(TMath::Abs((tVect - tbetadir).Mag())<.01) tVect.SetXYZ(0,1,0);
1028 theta5 = tVect.Angle(tbetadir);
1029 tTrans = (tVect - TMath::Cos(theta5)*tbetadir).Unit();
1031 E1CM = gm*E1L - gm*beta*P1zL;
1032 tP1zCM = gm*P1zL*tbetadir - gm*tbeta*E1L;
1033 E2CM = gm*E2L - gm*beta*P2zL;
1034 tP2zCM = gm*P2zL*tbetadir - gm*tbeta*E2L;
1036 M = (rnd->
RndFsi().Rndm()*(Et - M3 - M4 - M5)) + (M4 + M5);
1037 E3CM = (Et*Et + M3*M3 - M*M)/(2*Et);
1039 if(E3CM*E3CM - M3*M3<0)
1042 <<
"PionProduction P3 has non-real momentum - retry kinematics";
1043 LOG(
"INukeUtils",
pNOTICE) <<
"Energy, masses of 3 fs particales:" 1044 << E3CM <<
" " << M3 <<
" " <<
" " << M4 <<
" " << M5;
1046 exception.
SetReason(
"PionProduction particle 3 has non-real momentum");
1050 P3CM = TMath::Sqrt(E3CM*E3CM - M3*M3);
1057 P3zL = gm*beta*E3CM + gm*P3CM*TMath::Cos(theta3);
1058 P3tL = P3CM*TMath::Sin(theta3);
1059 PizL = gm*beta*EiCM - gm*P3CM*TMath::Cos(theta3);
1060 PitL = -P3CM*TMath::Sin(theta3);
1062 P3L = TMath::Sqrt(P3zL*P3zL + P3tL*P3tL);
1063 PiL = TMath::Sqrt(PizL*PizL + PitL*PitL);
1064 E3L = TMath::Sqrt(P3L*P3L + M3*M3);
1065 EiL = TMath::Sqrt(PiL*PiL + M*M);
1068 if(!(TMath::Finite(P3L)) || P3L < .001)
1071 <<
"Particle 3 " << M3 <<
" momentum small or non-finite: " << P3L
1072 <<
"\n" <<
"--> Assigning .001 as new momentum";
1076 E3L = TMath::Sqrt(P3L*P3L + M3*M3);
1079 tP3L = P3zL*tbetadir + P3tL*tTrans;
1080 tPiL = PizL*tbetadir + PitL*tTrans;
1081 tP3L.Rotate(phi3,tbetadir);
1082 tPiL.Rotate(phi3,tbetadir);
1085 tbeta2 = tPiL * (1.0 / EiL);
1086 tbetadir2 = tbeta2.Unit();
1087 beta2 = tbeta2.Mag();
1088 gm2 = 1.0 / TMath::Sqrt(1.0 - beta2*beta2);
1090 E4CM2 = (M*M + M4*M4 - M5*M5) / (2*M);
1092 P4CM2 = TMath::Sqrt(E4CM2*E4CM2 - M4*M4);
1094 tVect.SetXYZ(1,0,0);
1095 if(TMath::Abs((tVect - tbetadir2).Mag())<.01) tVect.SetXYZ(0,1,0);
1096 theta5 = tVect.Angle(tbetadir2);
1097 tTrans2 = (tVect - TMath::Cos(theta5)*tbetadir2).Unit();
1099 P4zL = gm2*beta2*E4CM2 + gm2*P4CM2*TMath::Cos(theta4);
1100 P4tL = P4CM2*TMath::Sin(theta4);
1101 P5zL = gm2*beta2*E5CM2 - gm2*P4CM2*TMath::Cos(theta4);
1104 P4L = TMath::Sqrt(P4zL*P4zL + P4tL*P4tL);
1105 P5L = TMath::Sqrt(P5zL*P5zL + P5tL*P5tL);
1106 E4L = TMath::Sqrt(P4L*P4L + M4*M4);
1107 E5L = TMath::Sqrt(P5L*P5L + M5*M5);
1110 if(!(TMath::Finite(P4L)) || P4L < .001)
1113 <<
"Particle 4 " << M4 <<
" momentum small or non-finite: " << P4L
1114 <<
"\n" <<
"--> Assigning .001 as new momentum";
1118 E4L = TMath::Sqrt(P4L*P4L + M4*M4);
1120 if(!(TMath::Finite(P5L)) || P5L < .001)
1123 <<
"Particle 5 " << M5 <<
" momentum small or non-finite: " << P5L
1124 <<
"\n" <<
"--> Assigning .001 as new momentum";
1128 E5L = TMath::Sqrt(P5L*P5L + M5*M5);
1131 tP4L = P4zL*tbetadir2 + P4tL*tTrans2;
1132 tP5L = P5zL*tbetadir2 + P5tL*tTrans2;
1133 tP4L.Rotate(phi4,tbetadir2);
1134 tP5L.Rotate(phi4,tbetadir2);
1140 <<
"PionProduction fails because of Pauli blocking - retry kinematics";
1142 exception.
SetReason(
"PionProduction final state not determined");
1156 TLorentzVector(tP3L,E3L);
1157 TLorentzVector(tP4L,E4L);
1158 TLorentzVector(tP5L,E5L);
1182 TLorentzVector &RemnP4,
bool DoFermi,
double FermiFac,
double FermiMomentum,
const NuclearModelI* Nuclmodel)
1203 int pcode = p->
Pdg();
1205 int p1code = p->
Pdg();
1207 int p3code = 0, p4code = 0, p5code = 0;
1223 double kine = 1000*p->
KinE();
1231 double xsec2pi0n = TMath::Max(0.,TMath::Exp(8.82 - (573.2/(kine-107.3))));
1234 double xsecpippimn = TMath::Max(0.,TMath::Exp(11.06 - (985.9/(kine-88.2))));
1237 double xsecpimpi0p = TMath::Max(0.,TMath::Exp(9.58 - (1229.4/(kine-60.5))));
1238 double totpimp = xsec2pi0n + xsecpippimn + xsecpimpi0p;
1244 double xsec2pipn = TMath::Max(0.,TMath::Exp(5.64 - (222.6/(kine-150.))));
1247 double xsecpippi0p = TMath::Max(0.,TMath::Exp(7.95 - (852.6/(kine-77.8))));
1248 double totpipp = xsec2pipn + xsecpippi0p;
1250 if (totpimp<=0 && totpipp<=0) {
1251 LOG(
"INukeUtils",
pNOTICE) <<
"InelasticHN called below threshold energy";
1257 double xsecp, xsecn;
1259 case kPdgPi0: xsecp = 0.5 * (totpimp + totpipp); xsecn = xsecp;
break;
1260 case kPdgPiP: xsecp = totpipp; xsecn = totpimp;
break;
1261 case kPdgPiM: xsecp = totpimp; xsecn = totpipp;
break;
1263 LOG(
"INukeUtils",
pWARN) <<
"InelasticHN cannot handle probe: " 1266 exception.
SetReason(
"PionProduction final state not determined");
1275 xsecn *= RemnA-RemnZ;
1279 double rand = rnd->
RndFsi().Rndm() * (xsecp + xsecn);
1281 { rand /= RemnZ; ptarg =
true;}
1283 { rand -= xsecp; rand /= RemnA-RemnZ; ptarg =
false;}
1288 if (((ptarg==
true)&&(p1code==
kPdgPiP))
1289 || ((ptarg==
false)&&(p1code==
kPdgPiM)))
1291 if (rand < xsec2pipn)
1303 else if (((ptarg==
false)&&(p1code==
kPdgPiP))
1304 || ((ptarg==
true)&&(p1code==
kPdgPiM)))
1306 if (rand < xsec2pi0n)
1312 else if (rand < (xsec2pi0n + xsecpippimn))
1327 rand = rnd->
RndFsi().Rndm();
1328 if (rand < 191./270.)
1334 else if (rand < 7./135.)
1351 exception.
SetReason(
"PionProduction final state not determined");
1359 double tote = p->
Energy();
1360 double pMass = pLib->
Find(2212)->Mass();
1361 double nMass = pLib->
Find(2112)->Mass();
1362 double etapp2ppPi0 =
1364 double etapp2pnPip =
1366 pMass+nMass,pLib->
Find(211)->Mass());
1367 double etapn2nnPip =
1369 double etapn2ppPim =
1372 if ((etapp2ppPi0<=0.)&&(etapp2pnPip<=0.)&&(etapn2nnPip<=0.)&&(etapn2ppPim<=0.)) {
1373 LOG(
"INukeUtils",
pNOTICE) <<
"PionProduction() called below threshold energy";
1375 exception.
SetReason(
"PionProduction final state not possible - below threshold");
1381 double xsecppPi0=0,xsecpnPiP=0,xsecnnPiP=0,xsecppPiM=0;
1383 xsecppPi0 = 4511*(1-.91*TMath::Exp(-TMath::Power((etapp2ppPi0-.705),2)));
1384 xsecppPi0 *= (1-TMath::Exp(-TMath::Power((.556*etapp2ppPi0),3.5)));
1385 xsecppPi0 *= (1-TMath::Exp(-56.897/(etapp2ppPi0*etapp2ppPi0)));
1386 xsecppPi0 = TMath::Max(0.,xsecppPi0);}
1389 xsecpnPiP = 18840*(1-.808*TMath::Exp(-TMath::Power((etapp2pnPip-.371),2)));
1390 xsecpnPiP *= (1-TMath::Exp(-TMath::Power((.568*etapp2pnPip),3.2)));
1391 xsecpnPiP *= (1-TMath::Exp(-39.818/(etapp2pnPip*etapp2pnPip)));
1392 xsecpnPiP = TMath::Max(0.,xsecpnPiP);}
1395 xsecnnPiP = 7670*(1-.479*TMath::Exp(-TMath::Power((etapn2nnPip-.947),2)));
1396 xsecnnPiP *= (1-TMath::Exp(-TMath::Power((.35*etapn2nnPip),3.2)));
1397 xsecnnPiP *= (1-TMath::Exp(-71.53/(etapn2nnPip*etapn2nnPip)));
1398 xsecnnPiP = TMath::Max(0.,xsecnnPiP);}
1401 xsecppPiM = 7670*(1-.479*TMath::Exp(-TMath::Power((etapn2ppPim-.947),2)));
1402 xsecppPiM *= (1-TMath::Exp(-TMath::Power((.35*etapn2ppPim),3.2)));
1403 xsecppPiM *= (1-TMath::Exp(-71.53/(etapn2ppPim*etapn2ppPim)));
1404 xsecppPiM = TMath::Max(0.,xsecppPiM);}
1407 double sigma10 = TMath::Max(0.,xsecpnPiP - xsecppPi0);
1408 double sigma01 = TMath::Max(0.,xsecppPiM + xsecnnPiP - xsecppPi0);
1410 double xsecpnPi0 = .5*(sigma10 + sigma01);
1411 xsecpnPi0 = TMath::Max(xsecpnPi0,0.);
1413 LOG(
"INukeUtils",
pDEBUG) <<
'\n' <<
"Cross section values: "<<
'\n' 1414 << xsecppPi0 <<
" PP pi0" <<
'\n' 1415 << xsecpnPiP <<
" PN pi+" <<
'\n' 1416 << xsecnnPiP <<
" NN pi+" <<
'\n' 1417 << xsecpnPi0 <<
" PN pi0";
1419 double xsecp=0,xsecn=0;
1421 case kPdgProton: xsecp=xsecppPi0+xsecpnPiP; xsecn=xsecppPiM+xsecnnPiP+xsecpnPi0;
break;
1422 case kPdgNeutron: xsecp=xsecppPiM+xsecnnPiP+xsecpnPi0; xsecn=xsecppPi0+xsecpnPiP;
break;
1424 LOG(
"INukeUtils",
pWARN) <<
"InelasticHN cannot handle probe: " 1433 xsecn *= RemnA-RemnZ;
1437 double rand = rnd->
RndFsi().Rndm() * (xsecp + xsecn);
1439 { rand /= RemnZ; ptarg =
true;}
1441 { rand -= xsecp; rand /= RemnA-RemnZ; ptarg =
false;}
1475 <<
"Unable to handle probe (=" << p1code <<
") in InelasticHN()";
1482 LOG(
"INukeUtils",
pNOTICE) <<
"PionProduction() failed : no nucleons to produce pions";
1490 LOG(
"INukeUtils",
pNOTICE) <<
"PionProduction() failed : too few protons in nucleus";
1492 exception.
SetReason(
"PionProduction fails - too few protons available");
1518 LOG(
"INukeUtils",
pDEBUG) <<
"Remnant (A,Z) = (" <<RemnA<<
','<<RemnZ<<
')';
1520 RemnP4 -= *s1->
P4() + *s2->
P4() + *s3->
P4() - *p->
P4();
1525 exception.
SetReason(
"PionProduction final state not determined");
1532 double Mtwopart,
double Mpi)
1542 double Scm = Minc*Minc + Mtarg*Mtarg + 2*Mtarg*nrg;
1544 eta= TMath::Power(Scm,2) + TMath::Power(Mtwopart,4) + TMath::Power(Mpi,4);
1545 eta-= 2*TMath::Power(Mtwopart*Mpi,2);
1546 eta-= 2*Scm*TMath::Power(Mtwopart,2);
1547 eta-= 2*Scm*TMath::Power(Mpi,2);
1548 eta = TMath::Power(eta/Scm,1./2.);
1551 eta=TMath::Max(eta,0.);
1565 LOG(
"INukeUtils",
pINFO) <<
"*** Performing a Phase Space Decay";
1566 assert(pdgv.size() > 1);
1570 ostringstream state_sstream;
1571 state_sstream <<
"( ";
1574 double * mass =
new double[pdgv.size()];
1575 double mass_sum = 0;
1576 for(pdg_iter = pdgv.begin(); pdg_iter != pdgv.end(); ++pdg_iter) {
1577 int pdgc = *pdg_iter;
1582 state_sstream << nm <<
" ";
1584 state_sstream <<
")";
1586 TLorentzVector * pd = p->
GetP4();
1592 double availE = pd->Energy() + mass_sum;
1593 if(is_nuc||is_kaon) availE -= p->
Mass();
1597 <<
"size, mass_sum, availE, pd mass, energy = " << pdgv.size() <<
" " 1598 << mass_sum <<
" " << availE <<
" " << p->
Mass() <<
" " << p->
Energy() ;
1601 double dE = mass_sum;
1602 if(is_nuc||is_kaon) dE -= p->
Mass();
1603 TLorentzVector premnsub(0,0,0,dE);
1607 <<
"Final state = " << state_sstream.str() <<
" has N = " << pdgv.size()
1608 <<
" particles / total mass = " << mass_sum;
1613 TGenPhaseSpace GenPhaseSpace;
1614 bool permitted = GenPhaseSpace.SetDecay(*pd, pdgv.size(), mass);
1617 <<
" *** Phase space decay is not permitted \n" 1618 <<
" Total particle mass = " << mass_sum <<
"\n" 1636 for(
int idec=0; idec<200; idec++) {
1637 double w = GenPhaseSpace.Generate();
1638 wmax = TMath::Max(wmax,w);
1643 <<
"Max phase space gen. weight @ current hadronic interaction: " << wmax;
1650 bool accept_decay=
false;
1651 unsigned int itry=0;
1653 while(!accept_decay)
1660 <<
"Couldn't generate an unweighted phase space decay after " 1661 << itry <<
" attempts";
1667 double w = GenPhaseSpace.Generate();
1668 double gw = wmax * rnd->
RndFsi().Rndm();
1672 <<
"Decay weight = " << w <<
" > max decay weight = " << wmax;
1675 LOG(
"INukeUtils",
pNOTICE) <<
"Decay weight = " << w <<
" / R = " << gw;
1676 accept_decay = (gw<=
w);
1684 LOG(
"INukeUtils",
pNOTICE) <<
"mother index = " << mom;
1688 TLorentzVector * v4 = p->
GetX4();
1690 double checkpx = p->
Px();
1691 double checkpy = p->
Py();
1692 double checkpz = p->
Pz();
1693 double checkE = p->
E();
1695 for(pdg_iter = pdgv.begin(); pdg_iter != pdgv.end(); ++pdg_iter) {
1698 int pdgc = *pdg_iter;
1702 TLorentzVector * p4fin = GenPhaseSpace.GetDecay(i++);
1709 double En = p4fin->Energy();
1711 double dE_leftover = TMath::Min(NucRmvE, KE);
1714 double pmag_old = p4fin->P();
1715 double pmag_new = TMath::Sqrt(TMath::Max(0.,En*En-M*M));
1716 double scale = pmag_new / pmag_old;
1717 double pxn = scale * p4fin->Px();
1718 double pyn = scale * p4fin->Py();
1719 double pzn = scale * p4fin->Pz();
1721 TLorentzVector p4n(pxn,pyn,pzn,En);
1732 if (p4n.Vect().Mag()>=0.001)
1734 GHepParticle new_particle(pdgc, ist_pi, mom,-1,-1,-1, p4n, *v4);
1742 LOG(
"INukeUtils",
pINFO)<<
"Momentum too small; assigning 0.001 as new momentum";
1744 double phi = 2*
kPi*rnd->
RndFsi().Rndm();
1745 double omega = 2*rnd->
RndFsi().Rndm();
1748 double E4n = TMath::Sqrt(0.001*0.001+M*M);
1749 p4n.SetPxPyPzE(0.001,0,0,E4n);
1750 p4n.Rotate(TMath::ACos(1-omega),TVector3(0,0,1));
1751 p4n.Rotate(phi,TVector3(1,0,0));
1753 RemnP4 -= (p4n - TLorentzVector(0,0,0,M));
1755 GHepParticle new_particle(pdgc, ist, mom,-1,-1,-1, p4n, *v4);
1761 GHepParticle new_particle(pdgc, ist, mom,-1,-1,-1, p4n, *v4);
1767 double dpx = (1-
scale)*p4fin->Px();
1768 double dpy = (1-
scale)*p4fin->Py();
1769 double dpz = (1-
scale)*p4fin->Pz();
1770 TLorentzVector premnadd(dpx,dpy,dpz,dE_leftover);
1773 LOG(
"INukeUtils",
pNOTICE) <<
"check conservation: Px = " << checkpx <<
" Py = " << checkpy
1774 <<
" Pz = " << checkpz <<
" E = " << checkE;
static double fMinKinEnergy
const int kPdgP33m1232_DeltaPP
An exception thrown by SimulateHadronState for kinematics problems. TwoBodyCollision/Kinematics used ...
void SetFirstMother(int m)
virtual GHepParticle * Particle(int position) const
virtual int ParticlePosition(int pdg, GHepStatus_t i, int start=0) const
TLorentzVector * GetX4(void) const
TRandom3 & RndFsi(void) const
rnd number generator used by intranuclear cascade monte carlos
#include "Numerical/GSFunc.h"
bool TwoBodyCollision(GHepRecord *ev, int pcode, int tcode, int scode, int s2code, double C3CM, GHepParticle *p, GHepParticle *t, int &RemnA, int &RemnZ, TLorentzVector &RemnP4, EINukeMode mode=kIMdHA)
Intranuke utility functions.
double E(void) const
Get energy.
static RandomGen * Instance()
Access instance.
double Density(double r, int A, double ring=0.)
enum genie::EGHepStatus GHepStatus_t
string P4AsString(const TLorentzVector *p)
static const unsigned int kMaxUnweightDecayIterations
Pure abstract base class. Defines the NuclearModelI interface to be implemented by any physics model ...
double Mass(Resonance_t res)
resonance mass (GeV)
void SetMomentum(const TLorentzVector &p4)
double Mass(void) const
Mass that corresponds to the PDG code.
A singleton holding random number generator classes. All random number generation in GENIE should tak...
double CalculateEta(double Minc, double ke, double Mtarg, double Mtwopart, double Mpi)
double Pz(void) const
Get Pz.
void StepParticle(GHepParticle *p, double step, double nuclear_radius=-1.)
Step particle.
double Energy(void) const
Get energy.
void Equilibrium(GHepRecord *ev, GHepParticle *p, int &RemnA, int &RemnZ, TLorentzVector &RemnP4, bool DoFermi, double FermiFac, const NuclearModelI *Nuclmodel, double NucRmvE, EINukeMode mode=kIMdHN)
double Px(void) const
Get Px.
bool ThreeBodyKinematics(GHepRecord *ev, GHepParticle *p, int tcode, GHepParticle *s1, GHepParticle *s2, GHepParticle *s3, bool DoFermi=false, double FermiFac=0, double FermiMomentum=0, const NuclearModelI *Nuclmodel=(const NuclearModelI *) 0)
bool CompareMomentum(const GHepParticle *p) const
bool TwoBodyKinematics(double M3, double M4, TLorentzVector tP1L, TLorentzVector tP2L, TLorentzVector &tP3L, TLorentzVector &tP4L, double C3CM, TLorentzVector &RemnP4, double bindE=0)
int LastMother(void) const
int FirstMother(void) const
string Name(void) const
Name that corresponds to the PDG code.
const int kPdgCompNuclCluster
void SetPosition(const TLorentzVector &v4)
#define LOG(stream, priority)
A macro that returns the requested log4cpp::Category appending a string (using the FILE...
double MeanFreePath(int pdgc, const TLorentzVector &x4, const TLorentzVector &p4, double A, double Z, double nRpi=0.5, double nRnuc=1.0)
Mean free path (pions, nucleons)
double MeanFreePath_Delta(int pdgc, const TLorentzVector &x4, const TLorentzVector &p4, double A)
Mean free path (Delta++ test)
void PreEquilibrium(GHepRecord *ev, GHepParticle *p, int &RemnA, int &RemnZ, TLorentzVector &RemnP4, bool DoFermi, double FermiFac, const NuclearModelI *Nuclmodel, double NucRmvE, EINukeMode mode=kIMdHN)
void SetReason(string reason)
TLorentzVector * GetP4(void) const
bool ComparePdgCodes(const GHepParticle *p) const
A Neutrino Interaction Target. Is a transparent encapsulation of quite different physical systems suc...
bool TwoBodyKinematics(double M3, double M4, TLorentzVector tP1L, TLorentzVector tP2L, TLorentzVector &tP3L, TLorentzVector &tP4L, double C3CM, TLorentzVector &RemnP4, double bindE=0)
virtual GHepParticle * TargetNucleus(void) const
virtual vector< int > * GetStableDescendants(int position) const
bool PionProduction(GHepRecord *ev, GHepParticle *p, GHepParticle *s1, GHepParticle *s2, GHepParticle *s3, int &RemnA, int &RemnZ, TLorentzVector &RemnP4, bool DoFermi, double FermiFac, double FermiMomentum, const NuclearModelI *Nuclmodel)
Misc GENIE control constants.
static double fMaxKinEnergyHN
bool CompareStatusCodes(const GHepParticle *p) const
void SetRemovalEnergy(double Erm)
double Dist2Exit(const TLorentzVector &x4, const TLorentzVector &p4, double A, double NR=3, double R0=1.4)
Distance to exit.
double KinE(bool mass_from_pdg=false) const
Get kinetic energy.
static PDGLibrary * Instance(void)
bool PhaseSpaceDecay(GHepRecord *ev, GHepParticle *p, const PDGCodeList &pdgv, TLorentzVector &RemnP4, double NucRmvE, EINukeMode mode=kIMdHA)
general phase space decay method
void SetLastMother(int m)
Singleton class to load & serve a TDatabasePDG.
TLorentzVector * X4(void) const
void SetStatus(GHepStatus_t s)
virtual TVector3 Momentum3(void) const
bool IsNeutronOrProton(int pdgc)
TParticlePDG * Find(int pdgc)
virtual bool GenerateNucleon(const Target &) const =0
virtual void AddParticle(const GHepParticle &p)
double Dist2ExitMFP(int pdgc, const TLorentzVector &x4, const TLorentzVector &p4, double A, double Z, double NR=3, double R0=1.4)
Distance to exit.
string X4AsString(const TLorentzVector *x)
TLorentzVector * P4(void) const
GENIE's GHEP MC event record.
Most commonly used PDG codes. A set of utility functions to handle PDG codes is provided in PDGUtils...
STDHEP-like event record entry that can fit a particle or a nucleus.
string Vec3AsString(const TVector3 *vec)
double ProbSurvival(int pdgc, const TLorentzVector &x4, const TLorentzVector &p4, double A, double Z, double mfp_scale_factor=1.0, double nRpi=0.5, double nRnuc=1.0, double NR=3, double R0=1.4)
Hadron survival probability.
Root of GENIE utility namespaces.
cet::coded_exception< error, detail::translate > exception
void push_back(int pdg_code)
static INukeHadroData2014 * Instance(void)
double Py(void) const
Get Py.