24#include <TLorentzVector.h>
32#include "Framework/Conventions/GBuild.h"
56using std::ostringstream;
64 int pdgc,
const TLorentzVector & x4,
const TLorentzVector & p4,
65 double A,
double Z,
double nRpi,
double nRnuc,
const bool useOset,
66 const bool altOset,
const bool xsecNNCorr,
string INukeMode)
80 bool is_kaon = pdgc ==
kPdgKP;
83 if(!is_pion && !is_nucleon && !is_kaon && !is_gamma)
return 0.;
93 double momentum = p4.Vect().Mag();
94 double ring = (momentum>0) ? 1.240/momentum : 0;
96 if(A<=20) { ring /= 2.; }
105 if (is_pion ) { ring *= nRpi; }
106 else if (is_nucleon ) { ring *= nRnuc; }
107 else if (is_gamma || is_kaon || useOset) { ring = 0.;}
111 if (is_pion || is_kaon ) { ring *= nRpi; }
112 else if (is_nucleon ) { ring *= nRnuc; }
113 else if (is_gamma ) { ring = 0.; }
117 double rnow = x4.Vect().Mag();
123 double ke = (p4.Energy() - p4.M()) /
units::MeV;
130 double ppcnt = (double) Z/ (
double) A;
133 if (is_pion and (
INukeMode ==
"hN2025") and useOset and ke < 350.0)
136 { sigtot = fHadroData2025 -> XSecPipp_Tot() -> Evaluate(ke)*ppcnt;
137 sigtot+= fHadroData2025 -> XSecPipn_Tot() -> Evaluate(ke)*(1-ppcnt);}
139 { sigtot = fHadroData2025 -> XSecPi0p_Tot() -> Evaluate(ke)*ppcnt;
140 sigtot+= fHadroData2025 -> XSecPi0n_Tot() -> Evaluate(ke)*(1-ppcnt);}
142 { sigtot = fHadroData2025 -> XSecPipn_Tot() -> Evaluate(ke)*ppcnt;
143 sigtot+= fHadroData2025 -> XSecPipp_Tot() -> Evaluate(ke)*(1-ppcnt);}
146 sigtot = fHadroData2025 -> XSecPp_Tot() -> Evaluate(ke)*ppcnt;
151 double R0 = 1.25 * TMath::Power(A,1./3.) + 2.0 * 0.65;
152 double Mp = pLib->
Find(2212)->Mass();
153 double M = pLib->
Find(pdgc)->Mass();
156 if (Z*hc/137./x4.Vect().Mag() > E)
159 double Bc = z*Z*hc/137./R0;
161 double f = TMath::ACos(TMath::Power(x,0.5)) - TMath::Power(x*(1-x),0.5);
162 double B = 0.63*z*Z*TMath::Power((M/Mp)/E,0.5);
163 double Pc = TMath::Exp(-B*f);
166 sigtot+= fHadroData2025 -> XSecPn_Tot() -> Evaluate(ke)*(1-ppcnt);
168 double E0 = TMath::Power(A,0.2)*12.;
169 if (
INukeMode==
"hN2025"){
if(ke<E0){sigtot=0.0;}}
174 sigtot = fHadroData2025 -> XSecPn_Tot() -> Evaluate(ke)*ppcnt;
175 sigtot+= fHadroData2025 -> XSecNn_Tot() -> Evaluate(ke)*(1-ppcnt);
176 double E0 = TMath::Power(A,0.2)*12.;
177 if (
INukeMode==
"hN2025"){
if(ke<E0){sigtot=0.0;}}
181 { sigtot = fHadroData2025 -> XSecKpN_Tot() -> Evaluate(ke);
185 { sigtot = fHadroData2025 -> XSecGamp_fs() -> Evaluate(ke)*ppcnt;
186 sigtot+= fHadroData2025 -> XSecGamn_fs() -> Evaluate(ke)*(1-ppcnt);}
198 if (xsecNNCorr and is_nucleon)
203 if(sigtot<1E-6){sigtot=1E-6;}
206 double lamda = 1. / (rho * sigtot);
209 if( ! TMath::Finite(lamda) ) {
222 int pdgc,
const TLorentzVector & x4,
const TLorentzVector & p4,
double A)
237 if(!is_deltapp)
return 0.;
240 double rnow = x4.Vect().Mag();
245 double ke = (p4.Energy() - p4.M()) /
units::MeV;
246 ke = TMath::Max(1500., ke);
247 ke = TMath::Min( 0., ke);
252 else if (ke<1000) sig=40;
259 double lamda = 1. / (rho * sig);
262 if( ! TMath::Finite(lamda) ) {
270 int pdgc,
const TLorentzVector & x4,
const TLorentzVector & p4,
double A,
double ,
295 double NR = fsi_model.
GetNR();
298 double R0 = fsi_model.
GetR0();
314 double R = NR * R0 * TMath::Power(A, 1./3.);
316 TVector3 dr3 = p4.Vect().Unit();
317 TLorentzVector dr4(dr3,0);
323 <<
"Calculating survival probability for hadron with PDG code = " << pdgc
324 <<
" and momentum = " << p4.P() <<
" GeV";
326 <<
"mfp scale = " << mfp_scale_factor
327 <<
", nRpi = " << nRpi <<
", nRnuc = " << nRnuc <<
", NR = " << NR
328 <<
", R0 = " << R0 <<
" fm";
330 TLorentzVector x4_curr(x4);
333 double rnow = x4_curr.Vect().Mag();
334 if (rnow > (R+step))
break;
336 x4_curr += (step*dr4);
337 rnow = x4_curr.Vect().Mag();
340 remnA, remnZ, nRpi, nRnuc, useOset, altOset, xsecNNCorr, inuke_mode );
341 double mfp_twk = mfp * mfp_scale_factor;
343 double dprob = (mfp_twk>0) ? TMath::Exp(-step/mfp_twk) : 0.;
353 LOG(
"INukeUtils",
pDEBUG) <<
"Psurv = " << prob;
359 const TLorentzVector & x4,
const TLorentzVector & p4,
360 double A,
double NR,
double R0)
366 double R = NR * R0 * TMath::Power(A, 1./3.);
369 TVector3 dr3 = p4.Vect().Unit();
370 TLorentzVector dr4(dr3,0);
372 TLorentzVector x4_curr(x4);
376 double rnow = x4_curr.Vect().Mag();
377 x4_curr += (step*dr4);
379 rnow = x4_curr.Vect().Mag();
386 int pdgc,
const TLorentzVector & x4,
const TLorentzVector & p4,
387 double A,
double Z,
double NR,
double R0)
396 double R = NR * R0 * TMath::Power(A, 1./3.);
399 TVector3 dr3 = p4.Vect().Unit();
400 TLorentzVector dr4(dr3,0);
402 TLorentzVector x4_curr(x4);
407 double rnow = x4_curr.Vect().Mag();
408 x4_curr += (step*dr4);
410 rnow = x4_curr.Vect().Mag();
413 d_mfp += (step/lambda);
431#ifdef __GENIE_LOW_LEVEL_MESG_ENABLED__
433 <<
"Stepping particle [" << p->
Name() <<
"] by dr = " << step <<
" fm";
437 TVector3 dr = p->
P4()->Vect().Unit();
440 TLorentzVector dx4(dr,dt);
441 TLorentzVector x4new = *(p->
X4()) + dx4;
443 if(nuclear_radius > 0.) {
448 double r = x4new.Vect().Mag();
449 double rmax = nuclear_radius+
epsilon;
452 <<
"Particle was stepped too far away (r = " << r <<
" fm)";
455 <<
" fm outside the nucleus (r' = " << rmax <<
" fm)";
456 double scale = rmax/r;
461#ifdef __GENIE_LOW_LEVEL_MESG_ENABLED__
478 int &RemnA,
int &RemnZ, TLorentzVector &RemnP4,
483#ifdef __GENIE_LOW_LEVEL_MESG_ENABLED__
485 <<
"PreEquilibrium() is invoked for a : " << p->
Name()
486 <<
" whose kinetic energy is : " << p->
KinE();
493 bool allow_dup =
true;
496 double ppcnt = (double) RemnZ / (
double) RemnA;
505 if(rnd->
RndFsi().Rndm()<ppcnt)
514 ppcnt = (double) RemnZ / (
double) RemnA;
545 if(success)
LOG(
"INukeUtils2025",
pINFO) <<
"Successful phase space decay for pre-equilibrium nucleus FSI event";
549 exception.
SetReason(
"Phase space generation of pre-equilibrium nucleus final state failed, details above");
554 while(p_loc<ev->GetEntries())
569#ifdef __GENIE_LOW_LEVEL_MESG_ENABLED__
571 <<
"Particle at: " << p_loc;
578 int f_loc = p_loc + 1;
596 double max_en = energy;
598 for(
unsigned int j=0;j<descendants->size();j++)
600 loc = (*descendants)[j];
629 int &RemnA,
int &RemnZ, TLorentzVector &RemnP4,
634#ifdef __GENIE_LOW_LEVEL_MESG_ENABLED__
636 <<
"Equilibrium() is invoked for a : " << p->
Name()
637 <<
" whose kinetic energy is : " << p->
KinE();
644 bool allow_dup =
true;
648 double ppcnt = (double) RemnZ / (
double) RemnA;
658 if(rnd->
RndFsi().Rndm()<ppcnt)
667 ppcnt = (double) RemnZ / (
double) RemnA;
670#ifdef __GENIE_LOW_LEVEL_MESG_ENABLED__
672 <<
"Remnant nucleus (A,Z) = (" << RemnA <<
", " << RemnZ <<
")";
702 if (success)
LOG(
"INukeUtils",
pINFO) <<
"successful equilibrium interaction";
706 exception.
SetReason(
"Phase space generation of compound nucleus final state failed, details above");
715 GHepRecord* ev,
int pcode,
int tcode,
int scode,
int s2code,
double C3CM,
729 double E3L, P3L, E4L, P4L;
730 TVector3 tP1L, tPtot, tbeta, tbetadir, tTrans, tVect;
731 TVector3 tP1zCM, tP2zCM, tP3L, tP4L;
743 M1 = pLib->
Find(pcode)->Mass();
745 M3 = pLib->
Find(scode)->Mass();
746 M4 = pLib->
Find(s2code)->Mass();
749 TLorentzVector t4P1L = *p->
P4();
750 TLorentzVector t4P2L = *t->
P4();
753 double bindE = 0.025;
756 LOG(
"TwoBodyCollision",
pNOTICE) <<
"M1 = " << t4P1L.M() <<
" , M2 = " << t4P2L.M();
757 LOG(
"TwoBodyCollision",
pNOTICE) <<
"E1 = " << t4P1L.E() <<
" , E2 = " << t4P2L.E();
759 if ( (p->
Energy()-p->
Mass()) < bindE ){bindE = 0.;}
762 if((pcode==2112||pcode==2212)&&(t4P1L.E()-M1)<.1) bindE = 0.0;
763 if((pcode==211||pcode==-211||pcode==111)&&(t4P1L.E()-M1)<.08) bindE = 0.0;
764 if((pcode==321)&&(t4P1L.E()-M1)<.1) bindE = 0.0;
767 TLorentzVector t4P3L, t4P4L;
770 P3L = t4P3L.Vect().Mag();
771 P4L = t4P4L.Vect().Mag();
776 <<
"TwoBodyKinematics fails: C3CM, P3 = " << C3CM <<
" "
777 << P3L <<
" " << E3L <<
"\n" <<
" P4 = "
778 << P4L <<
" " << E4L ;
783 P3L = t4P3L.Vect().Mag();
784 P4L = t4P4L.Vect().Mag();
788 <<
"C3CM, P3 = " << C3CM <<
" "
789 << P3L <<
" " << E3L <<
"\n" <<
" P4 = "
790 << P4L <<
" " << E4L ;
793 if(!(TMath::Finite(P3L)) || P3L<.001)
796 <<
"Particle 3 momentum small or non-finite: " << P3L
797 <<
"\n" <<
"--> Assigning .001 as new momentum";
799 E3L = TMath::Sqrt(P3L*P3L + M3*M3);
801 if(!(TMath::Finite(P4L)) || P4L<.001)
804 <<
"Particle 4 momentum small or non-finite: " << P4L
805 <<
"\n" <<
"--> Assigning .001 as new momentum";
807 E4L = TMath::Sqrt(P4L*P4L + M4*M4);
826 <<
"t4P2L= " << t4P2L.E() <<
" " << t4P2L.Z()
827 <<
" RemnP4= " << RemnP4.E() <<
" " << RemnP4.Z() ;
853 LOG(
"INukeUtils",
pINFO) <<
"Successful 2 body collision";
859 double M3,
double M4, TLorentzVector t4P1L, TLorentzVector t4P2L,
860 TLorentzVector &t4P3L, TLorentzVector &t4P4L,
double C3CM, TLorentzVector &RemnP4,
double bindE)
880 double E1L, E2L, P1L, P2L, E3L, P3L;
884 double E1CM, E2CM, E3CM, P3CM;
887 double theta1, theta2, theta5, P1zL, P2zL, P1tL, P2tL;
888 TVector3 tbeta, tbetadir, tTrans, tVect;
889 TVector3 tP1zCM, tP2zCM, vP3L;
890 TLorentzVector t4P1buf, t4P2buf, t4Ptot;
899 if (C3CM < -1. || C3CM > 1.)
return false;
902 S3CM = TMath::Sqrt(1.0 - C3CM*C3CM);
913 t4Ptot = t4P1buf + t4P2buf;
915 LOG(
"INukeUtils",
pINFO) <<
"M1 "<<t4P1L.M()<<
", M2 "<<t4P2L.M();
916 LOG(
"INukeUtils",
pINFO) <<
"E1L "<<E1L<<
", E1CM "<<E1CM;
917 LOG(
"INukeUtils",
pINFO) <<
"bindE = " << bindE;
927 LOG(
"INukeUtils",
pNOTICE) <<
"TwoBodyKinematics Failed: Forbidden by binding energy";
928 LOG(
"INukeUtils",
pNOTICE) <<
"E1L, E2L, M3, M4 : "<< E1L <<
", "<< E2L <<
", "<< M3 <<
", "<< M4;
929 t4P3L.SetPxPyPzE(0,0,0,0);
930 t4P4L.SetPxPyPzE(0,0,0,0);
936 tbeta = t4Ptot.Vect() * (1.0 / (E1L + E2L));
937 tbetadir = tbeta.Unit();
939 gm = 1.0 / TMath::Sqrt(1.0 - beta*beta);
942 theta1 = t4P1buf.Angle(tbeta);
943 theta2 = t4P2buf.Angle(tbeta);
944 P1zL = P1L*TMath::Cos(theta1);
945 P2zL = P2L*TMath::Cos(theta2);
946 P1tL = TMath::Sqrt(P1L*P1L - P1zL*P1zL);
947 P2tL = -TMath::Sqrt(P2L*P2L - P2zL*P2zL);
949 if(TMath::Abs((tVect - tbetadir).Mag())<.01) tVect.SetXYZ(0,1,0);
950 theta5 = tVect.Angle(tbetadir);
951 tTrans = (tVect - TMath::Cos(theta5)*tbetadir).Unit();
954 E1CM = gm*E1L - gm*beta*P1zL;
955 tP1zCM = gm*P1zL*tbetadir - gm*tbeta*E1L;
956 E2CM = gm*E2L - gm*beta*P2zL;
957 tP2zCM = gm*P2zL*tbetadir - gm*tbeta*E2L;
961 LOG(
"INukeUtils",
pINFO) <<
"M1 "<<t4P1L.M()<<
", M2 "<<t4P2L.M();
962 LOG(
"INukeUtils",
pINFO) <<
"E1L "<<E1L<<
", E1CM "<<E1CM;
963 LOG(
"INukeUtils",
pINFO) <<
"P1zL "<<P1zL<<
", P1zCM "<<tP1zCM.Mag()<<
", P1tL "<<P1tL;
964 LOG(
"INukeUtils",
pINFO) <<
"E2L "<<E2L<<
", E2CM "<<E2CM;
965 LOG(
"INukeUtils",
pINFO) <<
"P2zL "<<P2zL<<
", P2zCM "<<tP2zCM.Mag()<<
", P2tL "<<P2tL;
966 LOG(
"INukeUtils",
pINFO) <<
"C3CM "<<C3CM;
969 E3CM = (Et*Et + M3*M3 - M4*M4) / (2.0 * Et);
972 if(E3CM*E3CM - M3*M3<0 || E3CM<0 || Et<0)
974 if (Et<0)
LOG(
"INukeUtils",
pNOTICE) <<
"TwoBodyKinematics Failed: Total energy is negative";
975 if (E3CM<M3)
LOG(
"INukeUtils",
pNOTICE) <<
"TwoBodyKinematics Failed: Scattered Particle 3 CM energy is too small";
976 if (E3CM*E3CM - M3*M3<0)
LOG(
"INukeUtils",
pNOTICE) <<
"TwoBodyKinematics Failed: Scattered Particle 3 CM momentum is nonreal";
977 t4P3L.SetPxPyPzE(0,0,0,0);
978 t4P4L.SetPxPyPzE(0,0,0,0);
981 P3CM = TMath::Sqrt(E3CM*E3CM - M3*M3);
984 P3zL = gm*beta*E3CM + gm*P3CM*C3CM;
987 P3L = TMath::Sqrt(P3zL*P3zL + P3tL*P3tL);
988 E3L = TMath::Sqrt(P3L*P3L + M3*M3);
992 double E4CM = Et-E3CM;
993 double P4zL = gm*beta*E4CM - gm*P3CM*C3CM;
994 double P4tL = -1.*P3tL;
995 double P4L = TMath::Sqrt(P4zL*P4zL + P4tL*P4tL);
996 double E4L = TMath::Sqrt(P4L*P4L + M4*M4);
998 LOG(
"INukeUtils",
pINFO) <<
"M3 "<< M3 <<
", M4 "<< M4;
999 LOG(
"INukeUtils",
pINFO) <<
"E3L "<<E3L<<
", E3CM "<<E3CM;
1000 LOG(
"INukeUtils",
pINFO) <<
"P3zL "<<P3zL<<
", P3tL "<<P3tL;
1001 LOG(
"INukeUtils",
pINFO) <<
"C3L "<<P3zL/P3L;
1002 LOG(
"INukeUtils",
pINFO) <<
"Check:";
1003 LOG(
"INukeUtils",
pINFO) <<
"E4L "<<E4L<<
", E4CM "<<E4CM;
1004 LOG(
"INukeUtils",
pINFO) <<
"P4zL "<<P4zL<<
", P4tL "<<P4tL;
1005 LOG(
"INukeUtils",
pINFO) <<
"P4L "<<P4L;
1006 LOG(
"INukeUtils",
pINFO) <<
"C4L "<<P4zL/P4L;
1008 double echeck = E1L + E2L - (E3L + E4L);
1009 double pzcheck = P1zL+ P2zL - (P3zL + P4zL);
1010 double ptcheck = P1tL+ P2tL - (P3tL + P4tL);
1012 LOG(
"INukeUtils",
pINFO) <<
"Check 4-momentum conservation - Energy "<<echeck<<
", z momentum "<<pzcheck <<
", transverse momentum " << ptcheck ;
1017 if(!(TMath::Finite(P3L)) || P3L<.001)
1020 <<
"Particle 3 momentum small or non-finite: " << P3L
1021 <<
"\n" <<
"--> Assigning .001 as new momentum";
1025 E3L = TMath::Sqrt(P3L*P3L + M3*M3);
1031 vP3L = P3zL*tbetadir + P3tL*tTrans;
1032 vP3L.Rotate(PHI3,tbetadir);
1034 t4P3L.SetVect(vP3L);
1037 t4P4L = t4P1buf + t4P2buf - t4P3L;
1038 t4P4L-= TLorentzVector(0,0,0,bindE);
1045 if(t4P4L.Mag2()<0 || t4P4L.E()<0)
1047 LOG(
"INukeUtils",
pNOTICE)<<
"TwoBodyKinematics Failed: Target mass or energy is negative";
1048 t4P3L.SetPxPyPzE(0,0,0,0);
1049 t4P4L.SetPxPyPzE(0,0,0,0);
1053 if (bindE!=0) RemnP4 += TLorentzVector(0,0,0,bindE);
1059 bool DoFermi,
double FermiFac,
double FermiMomentum,
const NuclearModelI* Nuclmodel)
1071 double M1, M2, M3, M4, M5;
1072 double P1L, P2L, P3L, P4L, P5L;
1073 double E1L, E2L, E3L, E4L, E5L;
1074 double E1CM, E2CM, P3tL;
1075 double PizL, PitL, PiL, EiL;
1076 double EiCM, P4CM2, E4CM2, E5CM2, P3CM, E3CM;
1077 double beta, gm, beta2, gm2;
1078 double P3zL, P4zL, P4tL, P5zL, P5tL;
1079 double Et, M, theta1, theta2;
1081 double theta3, theta4, phi3, phi4, theta5;
1082 TVector3 tP2L, tP1L, tPtot, tbeta, tbetadir, tTrans, tP4L, tP5L;
1083 TVector3 tP1zCM, tP2zCM, tP3L, tPiL, tbeta2, tbetadir2, tVect, tTrans2;
1091 M1 = pLib->
Find(p->
Pdg())->Mass();
1092 M2 = pLib->
Find(tcode)->Mass();
1093 M3 = pLib->
Find(s1->
Pdg())->Mass();
1094 M4 = pLib->
Find(s2->
Pdg())->Mass();
1095 M5 = pLib->
Find(s3->
Pdg())->Mass();
1105 tP2L = FermiFac * Nuclmodel->
Momentum3();
1107 E2L = TMath::Sqrt(tP2L.Mag2() + M2*M2);
1111 tP2L.SetXYZ(0.0, 0.0, 0.0);
1119 P1L = TMath::Sqrt(E1L*E1L - M1*M1);
1120 tP1L = p->
P4()->Vect();
1121 tPtot = tP1L + tP2L;
1123 tbeta = tPtot * (1.0 / (E1L + E2L));
1124 tbetadir = tbeta.Unit();
1126 gm = 1.0 / TMath::Sqrt(1.0 - beta*beta);
1128 theta1 = tP1L.Angle(tbeta);
1129 theta2 = tP2L.Angle(tbeta);
1130 P1zL = P1L*TMath::Cos(theta1);
1131 P2zL = P2L*TMath::Cos(theta2);
1132 tVect.SetXYZ(1,0,0);
1133 if(TMath::Abs((tVect - tbetadir).Mag())<.01) tVect.SetXYZ(0,1,0);
1134 theta5 = tVect.Angle(tbetadir);
1135 tTrans = (tVect - TMath::Cos(theta5)*tbetadir).Unit();
1137 E1CM = gm*E1L - gm*beta*P1zL;
1138 tP1zCM = gm*P1zL*tbetadir - gm*tbeta*E1L;
1139 E2CM = gm*E2L - gm*beta*P2zL;
1140 tP2zCM = gm*P2zL*tbetadir - gm*tbeta*E2L;
1142 M = (rnd->
RndFsi().Rndm()*(Et - M3 - M4 - M5)) + (M4 + M5);
1143 E3CM = (Et*Et + M3*M3 - M*M)/(2*Et);
1145 if(E3CM*E3CM - M3*M3<0)
1148 <<
"PionProduction P3 has non-real momentum - retry kinematics";
1149 LOG(
"INukeUtils",
pNOTICE) <<
"Energy, masses of 3 fs particales:"
1150 << E3CM <<
" " << M3 <<
" " <<
" " << M4 <<
" " << M5;
1152 exception.
SetReason(
"PionProduction particle 3 has non-real momentum");
1156 P3CM = TMath::Sqrt(E3CM*E3CM - M3*M3);
1163 P3zL = gm*beta*E3CM + gm*P3CM*TMath::Cos(theta3);
1164 P3tL = P3CM*TMath::Sin(theta3);
1165 PizL = gm*beta*EiCM - gm*P3CM*TMath::Cos(theta3);
1166 PitL = -P3CM*TMath::Sin(theta3);
1168 P3L = TMath::Sqrt(P3zL*P3zL + P3tL*P3tL);
1169 PiL = TMath::Sqrt(PizL*PizL + PitL*PitL);
1170 E3L = TMath::Sqrt(P3L*P3L + M3*M3);
1171 EiL = TMath::Sqrt(PiL*PiL + M*M);
1174 if(!(TMath::Finite(P3L)) || P3L < .001)
1177 <<
"Particle 3 " << M3 <<
" momentum small or non-finite: " << P3L
1178 <<
"\n" <<
"--> Assigning .001 as new momentum";
1182 E3L = TMath::Sqrt(P3L*P3L + M3*M3);
1185 tP3L = P3zL*tbetadir + P3tL*tTrans;
1186 tPiL = PizL*tbetadir + PitL*tTrans;
1187 tP3L.Rotate(phi3,tbetadir);
1188 tPiL.Rotate(phi3,tbetadir);
1191 tbeta2 = tPiL * (1.0 / EiL);
1192 tbetadir2 = tbeta2.Unit();
1193 beta2 = tbeta2.Mag();
1194 gm2 = 1.0 / TMath::Sqrt(1.0 - beta2*beta2);
1196 E4CM2 = (M*M + M4*M4 - M5*M5) / (2*M);
1198 P4CM2 = TMath::Sqrt(E4CM2*E4CM2 - M4*M4);
1200 tVect.SetXYZ(1,0,0);
1201 if(TMath::Abs((tVect - tbetadir2).Mag())<.01) tVect.SetXYZ(0,1,0);
1202 theta5 = tVect.Angle(tbetadir2);
1203 tTrans2 = (tVect - TMath::Cos(theta5)*tbetadir2).Unit();
1205 P4zL = gm2*beta2*E4CM2 + gm2*P4CM2*TMath::Cos(theta4);
1206 P4tL = P4CM2*TMath::Sin(theta4);
1207 P5zL = gm2*beta2*E5CM2 - gm2*P4CM2*TMath::Cos(theta4);
1210 P4L = TMath::Sqrt(P4zL*P4zL + P4tL*P4tL);
1211 P5L = TMath::Sqrt(P5zL*P5zL + P5tL*P5tL);
1212 E4L = TMath::Sqrt(P4L*P4L + M4*M4);
1213 E5L = TMath::Sqrt(P5L*P5L + M5*M5);
1216 if(!(TMath::Finite(P4L)) || P4L < .001)
1219 <<
"Particle 4 " << M4 <<
" momentum small or non-finite: " << P4L
1220 <<
"\n" <<
"--> Assigning .001 as new momentum";
1224 E4L = TMath::Sqrt(P4L*P4L + M4*M4);
1226 if(!(TMath::Finite(P5L)) || P5L < .001)
1229 <<
"Particle 5 " << M5 <<
" momentum small or non-finite: " << P5L
1230 <<
"\n" <<
"--> Assigning .001 as new momentum";
1234 E5L = TMath::Sqrt(P5L*P5L + M5*M5);
1237 tP4L = P4zL*tbetadir2 + P4tL*tTrans2;
1238 tP5L = P5zL*tbetadir2 + P5tL*tTrans2;
1239 tP4L.Rotate(phi4,tbetadir2);
1240 tP5L.Rotate(phi4,tbetadir2);
1246 <<
"PionProduction fails because of Pauli blocking - retry kinematics";
1248 exception.
SetReason(
"PionProduction final state not determined");
1262 TLorentzVector(tP3L,E3L);
1263 TLorentzVector(tP4L,E4L);
1264 TLorentzVector(tP5L,E5L);
1270 LOG (
"INukeUtils",
pDEBUG) <<
"in Pi Prod, mode = " << mode;
1288 TLorentzVector &RemnP4,
bool DoFermi,
double FermiFac,
double FermiMomentum,
const NuclearModelI* Nuclmodel)
1309 int pcode = p->
Pdg();
1311 int p1code = p->
Pdg();
1313 int p3code = 0, p4code = 0, p5code = 0;
1329 double kine = 1000*p->
KinE();
1337 double xsec2pi0n = TMath::Max(0.,TMath::Exp(8.82 - (573.2/(kine-107.3))));
1340 double xsecpippimn = TMath::Max(0.,TMath::Exp(11.06 - (985.9/(kine-88.2))));
1343 double xsecpimpi0p = TMath::Max(0.,TMath::Exp(9.58 - (1229.4/(kine-60.5))));
1344 double totpimp = xsec2pi0n + xsecpippimn + xsecpimpi0p;
1350 double xsec2pipn = TMath::Max(0.,TMath::Exp(5.64 - (222.6/(kine-150.))));
1353 double xsecpippi0p = TMath::Max(0.,TMath::Exp(7.95 - (852.6/(kine-77.8))));
1354 double totpipp = xsec2pipn + xsecpippi0p;
1356 if (totpimp<=0 && totpipp<=0) {
1357 LOG(
"INukeUtils",
pNOTICE) <<
"InelasticHN called below threshold energy";
1363 double xsecp, xsecn;
1365 case kPdgPi0: xsecp = 0.5 * (totpimp + totpipp); xsecn = xsecp;
break;
1366 case kPdgPiP: xsecp = totpipp; xsecn = totpimp;
break;
1367 case kPdgPiM: xsecp = totpimp; xsecn = totpipp;
break;
1369 LOG(
"INukeUtils",
pWARN) <<
"InelasticHN cannot handle probe: "
1372 exception.
SetReason(
"PionProduction final state not determined");
1381 xsecn *= RemnA-RemnZ;
1385 double rand = rnd->
RndFsi().Rndm() * (xsecp + xsecn);
1387 { rand /= RemnZ; ptarg =
true;}
1389 { rand -= xsecp; rand /= RemnA-RemnZ; ptarg =
false;}
1394 if (((ptarg==
true)&&(p1code==
kPdgPiP))
1395 || ((ptarg==
false)&&(p1code==
kPdgPiM)))
1397 if (rand < xsec2pipn)
1409 else if (((ptarg==
false)&&(p1code==
kPdgPiP))
1410 || ((ptarg==
true)&&(p1code==
kPdgPiM)))
1412 if (rand < xsec2pi0n)
1418 else if (rand < (xsec2pi0n + xsecpippimn))
1433 rand = rnd->
RndFsi().Rndm();
1434 if (rand < 191./270.)
1440 else if (rand < 7./135.)
1457 exception.
SetReason(
"PionProduction final state not determined");
1465 double tote = p->
Energy();
1466 double pMass = pLib->
Find(2212)->Mass();
1467 double nMass = pLib->
Find(2112)->Mass();
1468 double etapp2ppPi0 =
1470 double etapp2pnPip =
1472 pMass+nMass,pLib->
Find(211)->Mass());
1473 double etapn2nnPip =
1475 double etapn2ppPim =
1478 if ((etapp2ppPi0<=0.)&&(etapp2pnPip<=0.)&&(etapn2nnPip<=0.)&&(etapn2ppPim<=0.)) {
1479 LOG(
"INukeUtils",
pNOTICE) <<
"PionProduction() called below threshold energy";
1481 exception.
SetReason(
"PionProduction final state not possible - below threshold");
1487 double xsecppPi0=0,xsecpnPiP=0,xsecnnPiP=0,xsecppPiM=0;
1489 xsecppPi0 = 4511*(1-.91*TMath::Exp(-TMath::Power((etapp2ppPi0-.705),2)));
1490 xsecppPi0 *= (1-TMath::Exp(-TMath::Power((.556*etapp2ppPi0),3.5)));
1491 xsecppPi0 *= (1-TMath::Exp(-56.897/(etapp2ppPi0*etapp2ppPi0)));
1492 xsecppPi0 = TMath::Max(0.,xsecppPi0);}
1495 xsecpnPiP = 18840*(1-.808*TMath::Exp(-TMath::Power((etapp2pnPip-.371),2)));
1496 xsecpnPiP *= (1-TMath::Exp(-TMath::Power((.568*etapp2pnPip),3.2)));
1497 xsecpnPiP *= (1-TMath::Exp(-39.818/(etapp2pnPip*etapp2pnPip)));
1498 xsecpnPiP = TMath::Max(0.,xsecpnPiP);}
1501 xsecnnPiP = 7670*(1-.479*TMath::Exp(-TMath::Power((etapn2nnPip-.947),2)));
1502 xsecnnPiP *= (1-TMath::Exp(-TMath::Power((.35*etapn2nnPip),3.2)));
1503 xsecnnPiP *= (1-TMath::Exp(-71.53/(etapn2nnPip*etapn2nnPip)));
1504 xsecnnPiP = TMath::Max(0.,xsecnnPiP);}
1507 xsecppPiM = 7670*(1-.479*TMath::Exp(-TMath::Power((etapn2ppPim-.947),2)));
1508 xsecppPiM *= (1-TMath::Exp(-TMath::Power((.35*etapn2ppPim),3.2)));
1509 xsecppPiM *= (1-TMath::Exp(-71.53/(etapn2ppPim*etapn2ppPim)));
1510 xsecppPiM = TMath::Max(0.,xsecppPiM);}
1513 double sigma10 = TMath::Max(0.,xsecpnPiP - xsecppPi0);
1514 double sigma01 = TMath::Max(0.,xsecppPiM + xsecnnPiP - xsecppPi0);
1516 double xsecpnPi0 = .5*(sigma10 + sigma01);
1517 xsecpnPi0 = TMath::Max(xsecpnPi0,0.);
1519 LOG(
"INukeUtils",
pDEBUG) <<
'\n' <<
"Cross section values: "<<
'\n'
1520 << xsecppPi0 <<
" PP pi0" <<
'\n'
1521 << xsecpnPiP <<
" PN pi+" <<
'\n'
1522 << xsecnnPiP <<
" NN pi+" <<
'\n'
1523 << xsecpnPi0 <<
" PN pi0";
1525 double xsecp=0,xsecn=0;
1527 case kPdgProton: xsecp=xsecppPi0+xsecpnPiP; xsecn=xsecppPiM+xsecnnPiP+xsecpnPi0;
break;
1528 case kPdgNeutron: xsecp=xsecppPiM+xsecnnPiP+xsecpnPi0; xsecn=xsecppPi0+xsecpnPiP;
break;
1530 LOG(
"INukeUtils",
pWARN) <<
"InelasticHN cannot handle probe: "
1539 xsecn *= RemnA-RemnZ;
1543 double rand = rnd->
RndFsi().Rndm() * (xsecp + xsecn);
1545 { rand /= RemnZ; ptarg =
true;}
1547 { rand -= xsecp; rand /= RemnA-RemnZ; ptarg =
false;}
1581 <<
"Unable to handle probe (=" << p1code <<
") in InelasticHN()";
1588 LOG(
"INukeUtils",
pNOTICE) <<
"PionProduction() failed : no nucleons to produce pions";
1596 LOG(
"INukeUtils",
pNOTICE) <<
"PionProduction() failed : too few protons in nucleus";
1598 exception.
SetReason(
"PionProduction fails - too few protons available");
1624 LOG(
"INukeUtils",
pDEBUG) <<
"Remnant (A,Z) = (" <<RemnA<<
','<<RemnZ<<
')';
1626 RemnP4 -= *s1->
P4() + *s2->
P4() + *s3->
P4() - *p->
P4();
1631 exception.
SetReason(
"PionProduction final state not determined");
1638 double Mtwopart,
double Mpi)
1648 double Scm = Minc*Minc + Mtarg*Mtarg + 2*Mtarg*nrg;
1650 eta= TMath::Power(Scm,2) + TMath::Power(Mtwopart,4) + TMath::Power(Mpi,4);
1651 eta-= 2*TMath::Power(Mtwopart*Mpi,2);
1652 eta-= 2*Scm*TMath::Power(Mtwopart,2);
1653 eta-= 2*Scm*TMath::Power(Mpi,2);
1654 eta = TMath::Power(eta/Scm,1./2.);
1657 eta=TMath::Max(eta,0.);
1665 TLorentzVector &RemnP4,
double NucRmvE,
EINukeMode mode)
1671 LOG(
"INukeUtils",
pINFO) <<
"*** Performing a Phase Space Decay";
1672 assert(pdgv.size() > 1);
1674 LOG(
"INukeUtils",
pINFO) <<
"probe mass: M = " << p->
Mass();
1678 ostringstream state_sstream;
1679 state_sstream <<
"( ";
1680 vector<int>::const_iterator pdg_iter;
1682 double * mass =
new double[pdgv.size()];
1683 double mass_sum = 0;
1684 for(pdg_iter = pdgv.begin(); pdg_iter != pdgv.end(); ++pdg_iter) {
1685 int pdgc = *pdg_iter;
1690 state_sstream << nm <<
" ";
1692 state_sstream <<
")";
1694 TLorentzVector * pd = p->
GetP4();
1701 double availE = pd->Energy() + mass_sum;
1702 if(is_nuc||is_kaon) availE -= p->
Mass();
1706 <<
"size, mass_sum, availE, pd mass, energy = " << pdgv.size() <<
" "
1707 << mass_sum <<
" " << availE <<
" " << p->
Mass() <<
" " << p->
Energy() ;
1710 double dE = mass_sum;
1711 if(is_nuc||is_kaon) dE -= p->
Mass();
1712 TLorentzVector premnsub(0,0,0,dE);
1716 <<
"Final state = " << state_sstream.str() <<
" has N = " << pdgv.size()
1717 <<
" particles / total mass = " << mass_sum;
1722 TGenPhaseSpace GenPhaseSpace;
1723 bool permitted = GenPhaseSpace.SetDecay(*pd, pdgv.size(), mass);
1726 <<
" *** Phase space decay is not permitted \n"
1727 <<
" Total particle mass = " << mass_sum <<
"\n"
1744 for(
int k=0; k<200; k++) {
1745 double w = GenPhaseSpace.Generate();
1746 wmax = TMath::Max(wmax,w);
1751 <<
"Max phase space gen. weight @ current hadronic interaction: " << wmax;
1758 bool accept_decay=
false;
1759 unsigned int itry=0;
1761 while(!accept_decay)
1768 <<
"Couldn't generate an unweighted phase space decay after "
1769 << itry <<
" attempts";
1775 double w = GenPhaseSpace.Generate();
1776 double gw = wmax * rnd->
RndFsi().Rndm();
1780 <<
"Decay weight = " << w <<
" > max decay weight = " << wmax;
1783 LOG(
"INukeUtils",
pNOTICE) <<
"Decay weight = " << w <<
" / R = " << gw;
1784 accept_decay = (gw<=w);
1792 LOG(
"INukeUtils",
pNOTICE) <<
"mother index = " << mom;
1796 TLorentzVector * v4 = p->
GetX4();
1798 double checkpx = p->
Px();
1799 double checkpy = p->
Py();
1800 double checkpz = p->
Pz();
1801 double checkE = p->
E();
1805 for(pdg_iter = pdgv.begin(); pdg_iter != pdgv.end(); ++pdg_iter) {
1808 int pdgc = *pdg_iter;
1812 TLorentzVector * p4fin = GenPhaseSpace.GetDecay(i++);
1819 double En = p4fin->Energy();
1826 double dE_leftover = TMath::Min(NucRmvE, KE);
1829 double pmag_old = p4fin->P();
1830 double pmag_new = TMath::Sqrt(TMath::Max(0.,En*En-M*M));
1831 double scale = pmag_new / pmag_old;
1832 double pxn = scale * p4fin->Px();
1833 double pyn = scale * p4fin->Py();
1834 double pzn = scale * p4fin->Pz();
1836 TLorentzVector p4n(pxn,pyn,pzn,En);
1847 if (p4n.Vect().Mag()>=0.001)
1849 GHepParticle new_particle(pdgc, ist_pi, mom,-1,-1,-1, p4n, *v4);
1857 LOG(
"INukeUtils",
pINFO)<<
"Momentum too small; assigning 0.001 as new momentum";
1859 double phi = 2*
kPi*rnd->
RndFsi().Rndm();
1860 double omega = 2*rnd->
RndFsi().Rndm();
1863 double E4n = TMath::Sqrt(0.001*0.001+M*M);
1864 p4n.SetPxPyPzE(0.001,0,0,E4n);
1865 p4n.Rotate(TMath::ACos(1-omega),TVector3(0,0,1));
1866 p4n.Rotate(phi,TVector3(1,0,0));
1868 RemnP4 -= (p4n - TLorentzVector(0,0,0,M));
1870 GHepParticle new_particle(pdgc, ist, mom,-1,-1,-1, p4n, *v4);
1876 GHepParticle new_particle(pdgc, ist, mom,-1,-1,-1, p4n, *v4);
1882 double dpx = (1-scale)*p4fin->Px();
1883 double dpy = (1-scale)*p4fin->Py();
1884 double dpz = (1-scale)*p4fin->Pz();
1885 TLorentzVector premnadd(dpx,dpy,dpz,dE_leftover);
1889 LOG(
"INukeUtils",
pNOTICE) <<
"check conservation: Px = " << checkpx <<
" Py = " << checkpy
1890 <<
" Pz = " << checkpz <<
" E = " << checkE;
1901 const double &pionKineticEnergy,
1902 const double &density,
1904 const double &protonFraction,
1905 const bool &isTableChosen
1911 if (iNukeOset == NULL)
1916 static const std::string dataDir = (gSystem->Getenv(
"GINUKEHADRONDATA")) ?
1917 string(gSystem->Getenv(
"GINUKEHADRONDATA")) :
1918 string(gSystem->Getenv(
"GENIE")) +
1920 string(
"/data/evgen/intranuke/");
1922 static const std::string dataFile = dataDir +
"tot_xsec/"
1923 "intranuke-xsection-pi+N-Oset.dat";
1932 iNukeOset->
setupOset (density, pionKineticEnergy, pionPDG, protonFraction);
#define LOG(stream, priority)
A macro that returns the requested log4cpp::Category appending a string (using the FILE,...
Most commonly used PDG codes. A set of utility functions to handle PDG codes is provided in PDGUtils.
static INukeNucleonCorr * getInstance()
get single instance of INukeNucleonCorr; create if necessary
Table-based implementation of Oset model.
virtual void setupOset(const double &density, const double &pionTk, const int &pionPDG, const double &protonFraction)=0
use to set up Oset class (assign pion Tk, nuclear density etc)
double getTotalCrossSection() const
return total = (qel+cex+abs) cross section
STDHEP-like event record entry that can fit a particle or a nucleus.
string Name(void) const
Name that corresponds to the PDG code.
int FirstMother(void) const
void SetPosition(const TLorentzVector &v4)
void SetMomentum(const TLorentzVector &p4)
TLorentzVector * GetP4(void) const
void SetFirstMother(int m)
void SetLastMother(int m)
void SetRemovalEnergy(double Erm)
bool ComparePdgCodes(const GHepParticle *p) const
const TLorentzVector * P4(void) const
double Mass(void) const
Mass that corresponds to the PDG code.
int LastMother(void) const
const TLorentzVector * X4(void) const
TLorentzVector * GetX4(void) const
void SetStatus(GHepStatus_t s)
double Px(void) const
Get Px.
double E(void) const
Get energy.
double Pz(void) const
Get Pz.
double Py(void) const
Get Py.
bool CompareStatusCodes(const GHepParticle *p) const
double Energy(void) const
Get energy.
bool CompareMomentum(const GHepParticle *p) const
double KinE(bool mass_from_pdg=false) const
Get kinetic energy.
GENIE's GHEP MC event record.
virtual int ParticlePosition(int pdg, GHepStatus_t i, int start=0) const
virtual GHepParticle * TargetNucleus(void) const
virtual void AddParticle(const GHepParticle &p)
virtual vector< int > * GetStableDescendants(int position) const
virtual GHepParticle * Particle(int position) const
Singleton class to load & serve hadron x-section splines used by GENIE's version of the INTRANUKE cas...
static INukeHadroData2025 * Instance(void)
static double fMinKinEnergy
static double fMaxKinEnergyHN
double GetDelRPion() const
virtual string GetINukeMode() const
bool GetXsecNNCorr() const
double GetHadStep() const
double GetDelRNucleon() const
Pure abstract base class. Defines the NuclearModelI interface to be implemented by any physics model ...
const TVector3 & Momentum3(void) const
virtual bool GenerateNucleon(const Target &) const =0
void push_back(int pdg_code)
Singleton class to load & serve a TDatabasePDG.
static PDGLibrary * Instance(void)
TParticlePDG * Find(int pdgc, bool must_exist=true)
A singleton holding random number generator classes. All random number generation in GENIE should tak...
static RandomGen * Instance()
Access instance.
TRandom3 & RndFsi(void) const
rnd number generator used by intranuclear cascade monte carlos
A Neutrino Interaction Target. Is a transparent encapsulation of quite different physical systems suc...
void SetHitNucPdg(int pdgc)
An exception thrown by SimulateHadronState for kinematics problems. TwoBodyCollision/Kinematics used ...
void SetReason(string reason)
Misc GENIE control constants.
static const unsigned int kMaxUnweightDecayIterations
bool IsNeutronOrProton(int pdgc)
static constexpr double MeV
static constexpr double mb
static constexpr double fm2
double MeanFreePath(int pdgc, const TLorentzVector &x4, const TLorentzVector &p4, double A, double Z, double nRpi=0.5, double nRnuc=1.0, const bool useOset=false, const bool altOset=false, const bool xsecNNCorr=false, string INukeMode="XX2025")
Mean free path (pions, nucleons)
double ProbSurvival(int pdgc, const TLorentzVector &x4, const TLorentzVector &p4, double A, double Z, double mfp_scale_factor, const Intranuke2025 &fsi_model)
Hadron survival probability.
double sigmaTotalOset(const double &pionKineticEnergy, const double &density, const int &pionPDG, const double &protonFraction, const bool &isTableChosen=true)
bool PhaseSpaceDecay(GHepRecord *ev, GHepParticle *p, const PDGCodeList &pdgv, TLorentzVector &RemnP4, double NucRmvE, EINukeMode mode=kIMdHA)
general phase space decay method
double CalculateEta(double Minc, double ke, double Mtarg, double Mtwopart, double Mpi)
double Dist2Exit(const TLorentzVector &x4, const TLorentzVector &p4, double A, double NR=3, double R0=1.4)
Distance to exit.
void PreEquilibrium(GHepRecord *ev, GHepParticle *p, int &RemnA, int &RemnZ, TLorentzVector &RemnP4, bool DoFermi, double FermiFac, const NuclearModelI *Nuclmodel, double NucRmvE, EINukeMode mode=kIMdHN)
double Dist2ExitMFP(int pdgc, const TLorentzVector &x4, const TLorentzVector &p4, double A, double Z, double NR=3, double R0=1.4)
Distance to exit.
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 MeanFreePath_Delta(int pdgc, const TLorentzVector &x4, const TLorentzVector &p4, double A)
Mean free path (Delta++ test)
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)
void StepParticle(GHepParticle *p, double step, double nuclear_radius=-1.)
Step particle.
bool TwoBodyKinematics(double M3, double M4, TLorentzVector tP1L, TLorentzVector tP2L, TLorentzVector &tP3L, TLorentzVector &tP4L, double C3CM, TLorentzVector &RemnP4, double bindE=0)
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.
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)
double Density(double r, int A, double ring=0.)
string Vec3AsString(const TVector3 *vec)
string X4AsString(const TLorentzVector *x)
string P4AsString(const TLorentzVector *p)
Root of GENIE utility namespaces.
THE MAIN GENIE PROJECT NAMESPACE
@ kIStNucleonClusterTarget
const int kPdgCompNuclCluster
const int kPdgP33m1232_DeltaPP
enum genie::EGHepStatus GHepStatus_t