37 #include <TLorentzVector.h>
44 #include "Framework/Conventions/GBuild.h"
63 using std::ostringstream;
64 using namespace genie;
65 using namespace genie::utils;
66 using namespace genie::constants;
67 using namespace genie::controls;
71 int pdgc,
const TLorentzVector & x4,
const TLorentzVector & p4,
72 double A,
double Z,
double nRpi,
double nRnuc)
86 bool is_kaon = pdgc ==
kPdgKP;
89 if(!is_pion && !is_nucleon && !is_kaon && !is_gamma)
return 0.;
99 double momentum = p4.Vect().Mag();
100 double ring = (momentum>0) ? 1.240/momentum : 0;
102 if(A<=20) { ring /= 2.; }
104 if (is_pion || is_kaon ) { ring *= nRpi; }
105 else if (is_nucleon ) { ring *= nRnuc; }
106 else if (is_gamma ) { ring = 0.; }
109 double rnow = x4.Vect().Mag();
115 double ke = (p4.Energy() - p4.M()) /
units::MeV;
122 double ppcnt = (double) Z/ (
double)
A;
126 { sigtot = fHadroData -> XSecPipp_Tot() -> Evaluate(ke)*ppcnt;
127 sigtot+= fHadroData -> XSecPipn_Tot() -> Evaluate(ke)*(1-ppcnt);}
129 { sigtot = fHadroData -> XSecPi0p_Tot() -> Evaluate(ke)*ppcnt;
130 sigtot+= fHadroData -> XSecPi0n_Tot() -> Evaluate(ke)*(1-ppcnt);}
132 { sigtot = fHadroData -> XSecPipn_Tot() -> Evaluate(ke)*ppcnt;
133 sigtot+= fHadroData -> XSecPipp_Tot() -> Evaluate(ke)*(1-ppcnt);}
135 { sigtot = fHadroData -> XSecPp_Tot() -> Evaluate(ke)*ppcnt;
136 sigtot+= fHadroData -> XSecPn_Tot() -> Evaluate(ke)*(1-ppcnt);}
138 { sigtot = fHadroData -> XSecPn_Tot() -> Evaluate(ke)*ppcnt;
139 sigtot+= fHadroData -> XSecNn_Tot() -> Evaluate(ke)*(1-ppcnt);}
141 { sigtot = fHadroData -> XSecKpN_Tot() -> Evaluate(ke);
144 { sigtot = fHadroData -> XSecGamp_fs() -> Evaluate(ke)*ppcnt;
145 sigtot+= fHadroData -> XSecGamn_fs() -> Evaluate(ke)*(1-ppcnt);}
155 double lamda = 1. / (rho * sigtot);
158 if( ! TMath::Finite(lamda) ) {
171 int pdgc,
const TLorentzVector & x4,
const TLorentzVector & p4,
double A)
186 if(!is_deltapp)
return 0.;
189 double rnow = x4.Vect().Mag();
194 double ke = (p4.Energy() - p4.M()) /
units::MeV;
195 ke = TMath::Max(1500., ke);
196 ke = TMath::Min( 0., ke);
201 else if (ke<1000) sig=40;
208 double lamda = 1. / (rho * sig);
211 if( ! TMath::Finite(lamda) ) {
219 int pdgc,
const TLorentzVector & x4,
const TLorentzVector & p4,
double A,
double Z,
220 double mfp_scale_factor,
double nRpi,
double nRnuc,
double NR,
double R0)
239 double R = NR * R0 * TMath::Power(A, 1./3.);
241 TVector3 dr3 = p4.Vect().Unit();
242 TLorentzVector dr4(dr3,0);
245 <<
"Calculating survival probability for hadron with PDG code = " << pdgc
246 <<
" and momentum = " << p4.P() <<
" GeV";
248 <<
"mfp scale = " << mfp_scale_factor
249 <<
", nRpi = " << nRpi <<
", nRnuc = " << nRnuc <<
", NR = " << NR
250 <<
", R0 = " << R0 <<
" fm";
252 TLorentzVector x4_curr(x4);
255 double rnow = x4_curr.Vect().Mag();
256 if (rnow > (R+step))
break;
258 x4_curr += (step*dr4);
259 rnow = x4_curr.Vect().Mag();
262 double mfp_twk = mfp * mfp_scale_factor;
264 double dprob = (mfp_twk>0) ? TMath::Exp(-step/mfp_twk) : 0.;
274 LOG(
"INukeUtils",
pDEBUG) <<
"Psurv = " << prob;
280 const TLorentzVector & x4,
const TLorentzVector & p4,
281 double A,
double NR,
double R0)
287 double R = NR * R0 * TMath::Power(A, 1./3.);
290 TVector3 dr3 = p4.Vect().Unit();
291 TLorentzVector dr4(dr3,0);
293 TLorentzVector x4_curr(x4);
297 double rnow = x4_curr.Vect().Mag();
298 x4_curr += (step*dr4);
300 rnow = x4_curr.Vect().Mag();
307 int pdgc,
const TLorentzVector & x4,
const TLorentzVector & p4,
308 double A,
double Z,
double NR,
double R0)
317 double R = NR * R0 * TMath::Power(A, 1./3.);
320 TVector3 dr3 = p4.Vect().Unit();
321 TLorentzVector dr4(dr3,0);
323 TLorentzVector x4_curr(x4);
328 double rnow = x4_curr.Vect().Mag();
329 x4_curr += (step*dr4);
331 rnow = x4_curr.Vect().Mag();
334 d_mfp += (step/lambda);
352 #ifdef __GENIE_LOW_LEVEL_MESG_ENABLED__
354 <<
"Stepping particle [" << p->
Name() <<
"] by dr = " << step <<
" fm";
358 TVector3 dr = p->
P4()->Vect().Unit();
361 TLorentzVector dx4(dr,dt);
362 TLorentzVector x4new = *(p->
X4()) + dx4;
364 if(nuclear_radius > 0.) {
369 double r = x4new.Vect().Mag();
370 double rmax = nuclear_radius+
epsilon;
373 <<
"Particle was stepped too far away (r = " << r <<
" fm)";
375 <<
"Placing it " << epsilon
376 <<
" fm outside the nucleus (r' = " << rmax <<
" fm)";
377 double scale = rmax/r;
382 #ifdef __GENIE_LOW_LEVEL_MESG_ENABLED__
400 #ifdef __GENIE_LOW_LEVEL_MESG_ENABLED__
402 <<
"PreEquilibrium() is invoked for a : " << p->
Name()
403 <<
" whose kinetic energy is : " << p->
KinE();
410 bool allow_dup =
true;
413 double ppcnt = (double) RemnZ / (
double) RemnA;
422 if(rnd->
RndFsi().Rndm()<ppcnt)
431 ppcnt = (double) RemnZ / (
double) RemnA;
438 TVector3 pBuf = p->
P4()->Vect();
439 double mBuf = p->
Mass();
440 double eBuf = TMath::Sqrt(pBuf.Mag2() + mBuf*mBuf);
441 TLorentzVector tSum(pBuf,eBuf);
443 vector<int>::const_iterator pdg_iter;
444 for(pdg_iter=++(list.begin());pdg_iter!=list.end();++pdg_iter)
446 target.SetHitNucPdg(*pdg_iter);
448 mBuf = pLib->
Find(*pdg_iter)->Mass();
450 pBuf = FermiFac * Nuclmodel->
Momentum3();
451 eBuf = TMath::Sqrt(pBuf.Mag2() + mBuf*mBuf);
452 tSum += TLorentzVector(pBuf,eBuf);
453 RemnP4 -= TLorentzVector(pBuf,eBuf-mBuf);
455 TLorentzVector dP4 = tSum + TLorentzVector(TVector3(0,0,0),-mSum);
461 if(success)
LOG(
"INukeUtils",
pINFO) <<
"Successful phase space decay for pre-equilibrium nucleus FSI event";
465 exception.
SetReason(
"Phase space generation of pre-equilibrium nucleus final state failed, details above");
470 while(p_loc<ev->GetEntries())
485 #ifdef __GENIE_LOW_LEVEL_MESG_ENABLED__
487 <<
"Particle at: " << p_loc;
494 int f_loc = p_loc + 1;
512 double max_en = energy;
514 for(
unsigned int j=0;j<descendants->size();j++)
516 loc = (*descendants)[j];
547 #ifdef __GENIE_LOW_LEVEL_MESG_ENABLED__
549 <<
"Equilibrium() is invoked for a : " << p->
Name()
550 <<
" whose kinetic energy is : " << p->
KinE();
557 bool allow_dup =
true;
561 double ppcnt = (double) RemnZ / (
double) RemnA;
571 if(rnd->
RndFsi().Rndm()<ppcnt)
580 ppcnt = (double) RemnZ / (
double) RemnA;
583 #ifdef __GENIE_LOW_LEVEL_MESG_ENABLED__
585 <<
"Remnant nucleus (A,Z) = (" << RemnA <<
", " << RemnZ <<
")";
592 TVector3 pBuf = p->
P4()->Vect();
593 double mBuf = p->
Mass();
594 double eBuf = TMath::Sqrt(pBuf.Mag2() + mBuf*mBuf);
595 TLorentzVector tSum(pBuf,eBuf);
597 vector<int>::const_iterator pdg_iter;
598 for(pdg_iter=++(list.begin());pdg_iter!=list.end();++pdg_iter)
600 target.SetHitNucPdg(*pdg_iter);
602 mBuf = pLib->
Find(*pdg_iter)->Mass();
604 pBuf = FermiFac * Nuclmodel->
Momentum3();
605 eBuf = TMath::Sqrt(pBuf.Mag2() + mBuf*mBuf);
606 tSum += TLorentzVector(pBuf,eBuf);
607 RemnP4 -= TLorentzVector(pBuf,eBuf-mBuf);
609 TLorentzVector dP4 = tSum + TLorentzVector(TVector3(0,0,0),-mSum);
615 if (success)
LOG(
"INukeUtils",
pINFO) <<
"successful pre-equilibrium interaction";
619 exception.
SetReason(
"Phase space generation of compound nucleus final state failed, details above");
626 GHepRecord* ev,
int ,
int tcode,
int scode,
int s2code,
double C3CM,
641 double E3L, P3L, E4L, P4L;
642 TVector3 tP1L, tPtot, tbeta, tbetadir, tTrans, tVect;
643 TVector3 tP1zCM, tP2zCM, tP3L, tP4L;
655 M3 = pLib->
Find(scode)->Mass();
656 M4 = pLib->
Find(s2code)->Mass();
659 TLorentzVector t4P1L = *p->
P4();
660 TLorentzVector t4P2L = *t->
P4();
663 double bindE = 0.025;
667 TLorentzVector t4P3L, t4P4L;
670 P3L = t4P3L.Vect().Mag();
671 P4L = t4P4L.Vect().Mag();
676 <<
"TwoBodyKinematics fails: C3CM, P3 = " << C3CM <<
" "
677 << P3L <<
" " << E3L <<
"\n" <<
" P4 = "
678 << P4L <<
" " << E4L ;
683 P3L = t4P3L.Vect().Mag();
684 P4L = t4P4L.Vect().Mag();
688 <<
"C3CM, P3 = " << C3CM <<
" "
689 << P3L <<
" " << E3L <<
"\n" <<
" P4 = "
690 << P4L <<
" " << E4L ;
693 if(!(TMath::Finite(P3L)) || P3L<.001)
696 <<
"Particle 3 momentum small or non-finite: " << P3L
697 <<
"\n" <<
"--> Assigning .001 as new momentum";
699 E3L = TMath::Sqrt(P3L*P3L + M3*M3);
701 if(!(TMath::Finite(P4L)) || P4L<.001)
704 <<
"Particle 4 momentum small or non-finite: " << P4L
705 <<
"\n" <<
"--> Assigning .001 as new momentum";
707 E4L = TMath::Sqrt(P4L*P4L + M4*M4);
749 LOG(
"INukeUtils",
pINFO) <<
"Successful 2 body collision";
755 double M3,
double M4, TLorentzVector t4P1L, TLorentzVector t4P2L,
756 TLorentzVector &t4P3L, TLorentzVector &t4P4L,
double C3CM, TLorentzVector &RemnP4,
double bindE)
776 double E1L, E2L, P1L, P2L, E3L, P3L;
780 double E1CM, E2CM, E3CM, P3CM;
783 double theta1, theta2, theta5, P1zL, P2zL, P1tL, P2tL;
784 TVector3 tbeta, tbetadir, tTrans, tVect;
785 TVector3 tP1zCM, tP2zCM, vP3L;
786 TLorentzVector t4P1buf, t4P2buf, t4Ptot;
795 if (C3CM < -1. || C3CM > 1.)
return false;
798 S3CM = TMath::Sqrt(1.0 - C3CM*C3CM);
809 t4Ptot = t4P1buf + t4P2buf;
819 LOG(
"INukeUtils",
pNOTICE) <<
"TwoBodyKinematics Failed: Forbidden by binding energy";
820 LOG(
"INukeUtils",
pNOTICE) <<
"E1L, E2L, M3, M4 : "<< E1L <<
", "<< E2L <<
", "<< M3 <<
", "<< M4;
821 t4P3L.SetPxPyPzE(0,0,0,0);
822 t4P4L.SetPxPyPzE(0,0,0,0);
828 tbeta = t4Ptot.Vect() * (1.0 / (E1L + E2L));
829 tbetadir = tbeta.Unit();
831 gm = 1.0 / TMath::Sqrt(1.0 - beta*beta);
834 theta1 = t4P1buf.Angle(tbeta);
835 theta2 = t4P2buf.Angle(tbeta);
836 P1zL = P1L*TMath::Cos(theta1);
837 P2zL = P2L*TMath::Cos(theta2);
838 P1tL = TMath::Sqrt(P1L*P1L - P1zL*P1zL);
839 P2tL = -TMath::Sqrt(P2L*P2L - P2zL*P2zL);
841 if(TMath::Abs((tVect - tbetadir).Mag())<.01) tVect.SetXYZ(0,1,0);
842 theta5 = tVect.Angle(tbetadir);
843 tTrans = (tVect - TMath::Cos(theta5)*tbetadir).Unit();
846 E1CM = gm*E1L - gm*beta*P1zL;
847 tP1zCM = gm*P1zL*tbetadir - gm*tbeta*E1L;
848 E2CM = gm*E2L - gm*beta*P2zL;
849 tP2zCM = gm*P2zL*tbetadir - gm*tbeta*E2L;
853 LOG(
"INukeUtils",
pINFO) <<
"M1 "<<t4P1L.M()<<
", M2 "<<t4P2L.M();
854 LOG(
"INukeUtils",
pINFO) <<
"E1L "<<E1L<<
", E1CM "<<E1CM;
855 LOG(
"INukeUtils",
pINFO) <<
"P1zL "<<P1zL<<
", P1zCM "<<tP1zCM.Mag()<<
", P1tL "<<P1tL;
856 LOG(
"INukeUtils",
pINFO) <<
"E2L "<<E2L<<
", E2CM "<<E2CM;
857 LOG(
"INukeUtils",
pINFO) <<
"P2zL "<<P2zL<<
", P2zCM "<<tP2zCM.Mag()<<
", P2tL "<<P2tL;
858 LOG(
"INukeUtils",
pINFO) <<
"C3CM "<<C3CM;
861 E3CM = (Et*Et + M3*M3 - M4*M4) / (2.0 * Et);
864 if(E3CM*E3CM - M3*M3<0 || E3CM<0 || Et<0)
866 if (Et<0)
LOG(
"INukeUtils",
pNOTICE) <<
"TwoBodyKinematics Failed: Total energy is negative";
867 if (E3CM<M3)
LOG(
"INukeUtils",
pNOTICE) <<
"TwoBodyKinematics Failed: Scattered Particle 3 CM energy is too small";
868 if (E3CM*E3CM - M3*M3<0)
LOG(
"INukeUtils",
pNOTICE) <<
"TwoBodyKinematics Failed: Scattered Particle 3 CM momentum is nonreal";
869 t4P3L.SetPxPyPzE(0,0,0,0);
870 t4P4L.SetPxPyPzE(0,0,0,0);
873 P3CM = TMath::Sqrt(E3CM*E3CM - M3*M3);
876 P3zL = gm*beta*E3CM + gm*P3CM*C3CM;
879 P3L = TMath::Sqrt(P3zL*P3zL + P3tL*P3tL);
880 E3L = TMath::Sqrt(P3L*P3L + M3*M3);
884 double E4CM = Et-E3CM;
885 double P4zL = gm*beta*E4CM - gm*P3CM*C3CM;
886 double P4tL = -1.*P3tL;
887 double P4L = TMath::Sqrt(P4zL*P4zL + P4tL*P4tL);
888 double E4L = TMath::Sqrt(P4L*P4L + M4*M4);
890 LOG(
"INukeUtils",
pINFO) <<
"M3 "<< M3 <<
", M4 "<< M4;
891 LOG(
"INukeUtils",
pINFO) <<
"E3L "<<E3L<<
", E3CM "<<E3CM;
892 LOG(
"INukeUtils",
pINFO) <<
"P3zL "<<P3zL<<
", P3tL "<<P3tL;
893 LOG(
"INukeUtils",
pINFO) <<
"C3L "<<P3zL/P3L;
895 LOG(
"INukeUtils",
pINFO) <<
"E4L "<<E4L<<
", E4CM "<<E4CM;
896 LOG(
"INukeUtils",
pINFO) <<
"P4zL "<<P4zL<<
", P4tL "<<P4tL;
897 LOG(
"INukeUtils",
pINFO) <<
"P4L "<<P4L;
898 LOG(
"INukeUtils",
pINFO) <<
"C4L "<<P4zL/P4L;
900 double echeck = E1L + E2L - (E3L + E4L);
901 double pzcheck = P1zL+ P2zL - (P3zL + P4zL);
902 double ptcheck = P1tL+ P2tL - (P3tL + P4tL);
904 LOG(
"INukeUtils",
pINFO) <<
"Check 4-momentum conservation - Energy "<<echeck<<
", z momentum "<<pzcheck <<
", transverse momentum " << ptcheck ;
909 if(!(TMath::Finite(P3L)) || P3L<.001)
912 <<
"Particle 3 momentum small or non-finite: " << P3L
913 <<
"\n" <<
"--> Assigning .001 as new momentum";
917 E3L = TMath::Sqrt(P3L*P3L + M3*M3);
923 vP3L = P3zL*tbetadir + P3tL*tTrans;
924 vP3L.Rotate(PHI3,tbetadir);
929 t4P4L = t4P1buf + t4P2buf - t4P3L;
930 t4P4L-= TLorentzVector(0,0,0,bindE);
937 if(t4P4L.Mag2()<0 || t4P4L.E()<0)
939 LOG(
"INukeUtils",
pNOTICE)<<
"TwoBodyKinematics Failed: Target mass or energy is negative";
940 t4P3L.SetPxPyPzE(0,0,0,0);
941 t4P4L.SetPxPyPzE(0,0,0,0);
945 if (bindE!=0) RemnP4 += TLorentzVector(0,0,0,bindE);
951 bool DoFermi,
double FermiFac,
double FermiMomentum,
const NuclearModelI* Nuclmodel)
963 double M1, M2, M3, M4, M5;
964 double P1L, P2L, P3L, P4L, P5L;
965 double E1L, E2L, E3L, E4L, E5L;
966 double E1CM, E2CM, P3tL;
967 double PizL, PitL, PiL, EiL;
968 double EiCM, P4CM2, E4CM2, E5CM2, P3CM, E3CM;
969 double beta, gm, beta2, gm2;
970 double P3zL, P4zL, P4tL, P5zL, P5tL;
971 double Et, M, theta1, theta2;
973 double theta3, theta4, phi3, phi4, theta5;
974 TVector3 tP2L, tP1L, tPtot, tbeta, tbetadir, tTrans, tP4L, tP5L;
975 TVector3 tP1zCM, tP2zCM, tP3L, tPiL, tbeta2, tbetadir2, tVect, tTrans2;
984 M2 = pLib->
Find(tcode)->Mass();
997 tP2L = FermiFac * Nuclmodel->
Momentum3();
999 E2L = TMath::Sqrt(tP2L.Mag2() + M2*M2);
1003 tP2L.SetXYZ(0.0, 0.0, 0.0);
1011 P1L = TMath::Sqrt(E1L*E1L - M1*M1);
1012 tP1L = p->
P4()->Vect();
1013 tPtot = tP1L + tP2L;
1015 tbeta = tPtot * (1.0 / (E1L + E2L));
1016 tbetadir = tbeta.Unit();
1018 gm = 1.0 / TMath::Sqrt(1.0 - beta*beta);
1020 theta1 = tP1L.Angle(tbeta);
1021 theta2 = tP2L.Angle(tbeta);
1022 P1zL = P1L*TMath::Cos(theta1);
1023 P2zL = P2L*TMath::Cos(theta2);
1024 tVect.SetXYZ(1,0,0);
1025 if(TMath::Abs((tVect - tbetadir).Mag())<.01) tVect.SetXYZ(0,1,0);
1026 theta5 = tVect.Angle(tbetadir);
1027 tTrans = (tVect - TMath::Cos(theta5)*tbetadir).Unit();
1029 E1CM = gm*E1L - gm*beta*P1zL;
1030 tP1zCM = gm*P1zL*tbetadir - gm*tbeta*E1L;
1031 E2CM = gm*E2L - gm*beta*P2zL;
1032 tP2zCM = gm*P2zL*tbetadir - gm*tbeta*E2L;
1034 M = (rnd->
RndFsi().Rndm()*(Et - M3 - M4 - M5)) + (M4 + M5);
1035 E3CM = (Et*Et + M3*M3 - M*M)/(2*Et);
1037 if(E3CM*E3CM - M3*M3<0)
1040 <<
"PionProduction P3 has non-real momentum - retry kinematics";
1041 LOG(
"INukeUtils",
pNOTICE) <<
"Energy, masses of 3 fs particales:"
1042 << E3CM <<
" " << M3 <<
" " <<
" " << M4 <<
" " << M5;
1044 exception.
SetReason(
"PionProduction particle 3 has non-real momentum");
1048 P3CM = TMath::Sqrt(E3CM*E3CM - M3*M3);
1055 P3zL = gm*beta*E3CM + gm*P3CM*TMath::Cos(theta3);
1056 P3tL = P3CM*TMath::Sin(theta3);
1057 PizL = gm*beta*EiCM - gm*P3CM*TMath::Cos(theta3);
1058 PitL = -P3CM*TMath::Sin(theta3);
1060 P3L = TMath::Sqrt(P3zL*P3zL + P3tL*P3tL);
1061 PiL = TMath::Sqrt(PizL*PizL + PitL*PitL);
1062 E3L = TMath::Sqrt(P3L*P3L + M3*M3);
1063 EiL = TMath::Sqrt(PiL*PiL + M*M);
1066 if(!(TMath::Finite(P3L)) || P3L < .001)
1069 <<
"Particle 3 " << M3 <<
" momentum small or non-finite: " << P3L
1070 <<
"\n" <<
"--> Assigning .001 as new momentum";
1074 E3L = TMath::Sqrt(P3L*P3L + M3*M3);
1077 tP3L = P3zL*tbetadir + P3tL*tTrans;
1078 tPiL = PizL*tbetadir + PitL*tTrans;
1079 tP3L.Rotate(phi3,tbetadir);
1080 tPiL.Rotate(phi3,tbetadir);
1083 tbeta2 = tPiL * (1.0 / EiL);
1084 tbetadir2 = tbeta2.Unit();
1085 beta2 = tbeta2.Mag();
1086 gm2 = 1.0 / TMath::Sqrt(1.0 - beta2*beta2);
1088 E4CM2 = (M*M + M4*M4 - M5*M5) / (2*M);
1090 P4CM2 = TMath::Sqrt(E4CM2*E4CM2 - M4*M4);
1092 tVect.SetXYZ(1,0,0);
1093 if(TMath::Abs((tVect - tbetadir2).Mag())<.01) tVect.SetXYZ(0,1,0);
1094 theta5 = tVect.Angle(tbetadir2);
1095 tTrans2 = (tVect - TMath::Cos(theta5)*tbetadir2).Unit();
1097 P4zL = gm2*beta2*E4CM2 + gm2*P4CM2*TMath::Cos(theta4);
1098 P4tL = P4CM2*TMath::Sin(theta4);
1099 P5zL = gm2*beta2*E5CM2 - gm2*P4CM2*TMath::Cos(theta4);
1102 P4L = TMath::Sqrt(P4zL*P4zL + P4tL*P4tL);
1103 P5L = TMath::Sqrt(P5zL*P5zL + P5tL*P5tL);
1104 E4L = TMath::Sqrt(P4L*P4L + M4*M4);
1105 E5L = TMath::Sqrt(P5L*P5L + M5*M5);
1108 if(!(TMath::Finite(P4L)) || P4L < .001)
1111 <<
"Particle 4 " << M4 <<
" momentum small or non-finite: " << P4L
1112 <<
"\n" <<
"--> Assigning .001 as new momentum";
1116 E4L = TMath::Sqrt(P4L*P4L + M4*M4);
1118 if(!(TMath::Finite(P5L)) || P5L < .001)
1121 <<
"Particle 5 " << M5 <<
" momentum small or non-finite: " << P5L
1122 <<
"\n" <<
"--> Assigning .001 as new momentum";
1126 E5L = TMath::Sqrt(P5L*P5L + M5*M5);
1129 tP4L = P4zL*tbetadir2 + P4tL*tTrans2;
1130 tP5L = P5zL*tbetadir2 + P5tL*tTrans2;
1131 tP4L.Rotate(phi4,tbetadir2);
1132 tP5L.Rotate(phi4,tbetadir2);
1138 <<
"PionProduction fails because of Pauli blocking - retry kinematics";
1140 exception.
SetReason(
"PionProduction final state not determined");
1154 TLorentzVector(tP3L,E3L);
1155 TLorentzVector(tP4L,E4L);
1156 TLorentzVector(tP5L,E5L);
1162 LOG (
"INukeUtils",
pDEBUG) <<
"in Pi Prod, mode = " << mode;
1180 TLorentzVector &RemnP4,
bool DoFermi,
double FermiFac,
double FermiMomentum,
const NuclearModelI* Nuclmodel)
1201 int pcode = p->
Pdg();
1203 int p1code = p->
Pdg();
1205 int p3code = 0, p4code = 0, p5code = 0;
1221 double kine = 1000*p->
KinE();
1229 double xsec2pi0n = TMath::Max(0.,TMath::Exp(8.82 - (573.2/(kine-107.3))));
1232 double xsecpippimn = TMath::Max(0.,TMath::Exp(11.06 - (985.9/(kine-88.2))));
1235 double xsecpimpi0p = TMath::Max(0.,TMath::Exp(9.58 - (1229.4/(kine-60.5))));
1236 double totpimp = xsec2pi0n + xsecpippimn + xsecpimpi0p;
1242 double xsec2pipn = TMath::Max(0.,TMath::Exp(5.64 - (222.6/(kine-150.))));
1245 double xsecpippi0p = TMath::Max(0.,TMath::Exp(7.95 - (852.6/(kine-77.8))));
1246 double totpipp = xsec2pipn + xsecpippi0p;
1248 if (totpimp<=0 && totpipp<=0) {
1249 LOG(
"INukeUtils",
pNOTICE) <<
"InelasticHN called below threshold energy";
1255 double xsecp, xsecn;
1257 case kPdgPi0: xsecp = 0.5 * (totpimp + totpipp); xsecn = xsecp;
break;
1258 case kPdgPiP: xsecp = totpipp; xsecn = totpimp;
break;
1259 case kPdgPiM: xsecp = totpimp; xsecn = totpipp;
break;
1261 LOG(
"INukeUtils",
pWARN) <<
"InelasticHN cannot handle probe: "
1264 exception.
SetReason(
"PionProduction final state not determined");
1273 xsecn *= RemnA-RemnZ;
1277 double rand = rnd->
RndFsi().Rndm() * (xsecp + xsecn);
1279 { rand /= RemnZ; ptarg =
true;}
1281 { rand -= xsecp; rand /= RemnA-RemnZ; ptarg =
false;}
1286 if (((ptarg==
true)&&(p1code==
kPdgPiP))
1287 || ((ptarg==
false)&&(p1code==
kPdgPiM)))
1289 if (rand < xsec2pipn)
1301 else if (((ptarg==
false)&&(p1code==
kPdgPiP))
1302 || ((ptarg==
true)&&(p1code==
kPdgPiM)))
1304 if (rand < xsec2pi0n)
1310 else if (rand < (xsec2pi0n + xsecpippimn))
1325 rand = rnd->
RndFsi().Rndm();
1326 if (rand < 191./270.)
1332 else if (rand < 7./135.)
1349 exception.
SetReason(
"PionProduction final state not determined");
1357 double tote = p->
Energy();
1358 double pMass = pLib->
Find(2212)->Mass();
1359 double nMass = pLib->
Find(2112)->Mass();
1360 double etapp2ppPi0 =
1362 double etapp2pnPip =
1364 pMass+nMass,pLib->
Find(211)->Mass());
1365 double etapn2nnPip =
1367 double etapn2ppPim =
1370 if ((etapp2ppPi0<=0.)&&(etapp2pnPip<=0.)&&(etapn2nnPip<=0.)&&(etapn2ppPim<=0.)) {
1371 LOG(
"INukeUtils",
pNOTICE) <<
"PionProduction() called below threshold energy";
1373 exception.
SetReason(
"PionProduction final state not possible - below threshold");
1379 double xsecppPi0=0,xsecpnPiP=0,xsecnnPiP=0,xsecppPiM=0;
1381 xsecppPi0 = 4511*(1-.91*TMath::Exp(-TMath::Power((etapp2ppPi0-.705),2)));
1382 xsecppPi0 *= (1-TMath::Exp(-TMath::Power((.556*etapp2ppPi0),3.5)));
1383 xsecppPi0 *= (1-TMath::Exp(-56.897/(etapp2ppPi0*etapp2ppPi0)));
1384 xsecppPi0 = TMath::Max(0.,xsecppPi0);}
1387 xsecpnPiP = 18840*(1-.808*TMath::Exp(-TMath::Power((etapp2pnPip-.371),2)));
1388 xsecpnPiP *= (1-TMath::Exp(-TMath::Power((.568*etapp2pnPip),3.2)));
1389 xsecpnPiP *= (1-TMath::Exp(-39.818/(etapp2pnPip*etapp2pnPip)));
1390 xsecpnPiP = TMath::Max(0.,xsecpnPiP);}
1393 xsecnnPiP = 7670*(1-.479*TMath::Exp(-TMath::Power((etapn2nnPip-.947),2)));
1394 xsecnnPiP *= (1-TMath::Exp(-TMath::Power((.35*etapn2nnPip),3.2)));
1395 xsecnnPiP *= (1-TMath::Exp(-71.53/(etapn2nnPip*etapn2nnPip)));
1396 xsecnnPiP = TMath::Max(0.,xsecnnPiP);}
1399 xsecppPiM = 7670*(1-.479*TMath::Exp(-TMath::Power((etapn2ppPim-.947),2)));
1400 xsecppPiM *= (1-TMath::Exp(-TMath::Power((.35*etapn2ppPim),3.2)));
1401 xsecppPiM *= (1-TMath::Exp(-71.53/(etapn2ppPim*etapn2ppPim)));
1402 xsecppPiM = TMath::Max(0.,xsecppPiM);}
1405 double sigma10 = TMath::Max(0.,xsecpnPiP - xsecppPi0);
1406 double sigma01 = TMath::Max(0.,xsecppPiM + xsecnnPiP - xsecppPi0);
1408 double xsecpnPi0 = .5*(sigma10 + sigma01);
1409 xsecpnPi0 = TMath::Max(xsecpnPi0,0.);
1411 LOG(
"INukeUtils",
pDEBUG) <<
'\n' <<
"Cross section values: "<<
'\n'
1412 << xsecppPi0 <<
" PP pi0" <<
'\n'
1413 << xsecpnPiP <<
" PN pi+" <<
'\n'
1414 << xsecnnPiP <<
" NN pi+" <<
'\n'
1415 << xsecpnPi0 <<
" PN pi0";
1417 double xsecp=0,xsecn=0;
1419 case kPdgProton: xsecp=xsecppPi0+xsecpnPiP; xsecn=xsecppPiM+xsecnnPiP+xsecpnPi0;
break;
1420 case kPdgNeutron: xsecp=xsecppPiM+xsecnnPiP+xsecpnPi0; xsecn=xsecppPi0+xsecpnPiP;
break;
1422 LOG(
"INukeUtils",
pWARN) <<
"InelasticHN cannot handle probe: "
1431 xsecn *= RemnA-RemnZ;
1435 double rand = rnd->
RndFsi().Rndm() * (xsecp + xsecn);
1437 { rand /= RemnZ; ptarg =
true;}
1439 { rand -= xsecp; rand /= RemnA-RemnZ; ptarg =
false;}
1473 <<
"Unable to handle probe (=" << p1code <<
") in InelasticHN()";
1480 LOG(
"INukeUtils",
pNOTICE) <<
"PionProduction() failed : no nucleons to produce pions";
1488 LOG(
"INukeUtils",
pNOTICE) <<
"PionProduction() failed : too few protons in nucleus";
1490 exception.
SetReason(
"PionProduction fails - too few protons available");
1516 LOG(
"INukeUtils",
pDEBUG) <<
"Remnant (A,Z) = (" <<RemnA<<
','<<RemnZ<<
')';
1518 RemnP4 -= *s1->
P4() + *s2->
P4() + *s3->
P4() - *p->
P4();
1523 exception.
SetReason(
"PionProduction final state not determined");
1530 double Mtwopart,
double Mpi)
1540 double Scm = Minc*Minc + Mtarg*Mtarg + 2*Mtarg*nrg;
1542 eta= TMath::Power(Scm,2) + TMath::Power(Mtwopart,4) + TMath::Power(Mpi,4);
1543 eta-= 2*TMath::Power(Mtwopart*Mpi,2);
1544 eta-= 2*Scm*TMath::Power(Mtwopart,2);
1545 eta-= 2*Scm*TMath::Power(Mpi,2);
1546 eta = TMath::Power(eta/Scm,1./2.);
1549 eta=TMath::Max(eta,0.);
1557 TLorentzVector &RemnP4,
double NucRmvE,
EINukeMode mode)
1563 LOG(
"INukeUtils",
pINFO) <<
"*** Performing a Phase Space Decay";
1564 assert(pdgv.size() > 1);
1568 ostringstream state_sstream;
1569 state_sstream <<
"( ";
1570 vector<int>::const_iterator pdg_iter;
1572 double * mass =
new double[pdgv.size()];
1573 double mass_sum = 0;
1574 for(pdg_iter = pdgv.begin(); pdg_iter != pdgv.end(); ++pdg_iter) {
1575 int pdgc = *pdg_iter;
1580 state_sstream << nm <<
" ";
1582 state_sstream <<
")";
1584 TLorentzVector * pd = p->
GetP4();
1590 double availE = pd->Energy() + mass_sum;
1591 if(is_nuc||is_kaon) availE -= p->
Mass();
1595 <<
"size, mass_sum, availE, pd mass, energy = " << pdgv.size() <<
" "
1596 << mass_sum <<
" " << availE <<
" " << p->
Mass() <<
" " << p->
Energy() ;
1599 double dE = mass_sum;
1600 if(is_nuc||is_kaon) dE -= p->
Mass();
1601 TLorentzVector premnsub(0,0,0,dE);
1605 <<
"Final state = " << state_sstream.str() <<
" has N = " << pdgv.size()
1606 <<
" particles / total mass = " << mass_sum;
1611 TGenPhaseSpace GenPhaseSpace;
1612 bool permitted = GenPhaseSpace.SetDecay(*pd, pdgv.size(), mass);
1615 <<
" *** Phase space decay is not permitted \n"
1616 <<
" Total particle mass = " << mass_sum <<
"\n"
1634 for(
int idec=0; idec<200; idec++) {
1635 double w = GenPhaseSpace.Generate();
1636 wmax = TMath::Max(wmax,w);
1641 <<
"Max phase space gen. weight @ current hadronic interaction: " << wmax;
1648 bool accept_decay=
false;
1649 unsigned int itry=0;
1651 while(!accept_decay)
1658 <<
"Couldn't generate an unweighted phase space decay after "
1659 << itry <<
" attempts";
1665 double w = GenPhaseSpace.Generate();
1666 double gw = wmax * rnd->
RndFsi().Rndm();
1670 <<
"Decay weight = " << w <<
" > max decay weight = " << wmax;
1673 LOG(
"INukeUtils",
pNOTICE) <<
"Decay weight = " << w <<
" / R = " << gw;
1674 accept_decay = (gw<=w);
1682 LOG(
"INukeUtils",
pNOTICE) <<
"mother index = " << mom;
1686 TLorentzVector * v4 = p->
GetX4();
1688 double checkpx = p->
Px();
1689 double checkpy = p->
Py();
1690 double checkpz = p->
Pz();
1691 double checkE = p->
E();
1693 for(pdg_iter = pdgv.begin(); pdg_iter != pdgv.end(); ++pdg_iter) {
1696 int pdgc = *pdg_iter;
1700 TLorentzVector * p4fin = GenPhaseSpace.GetDecay(i++);
1707 double En = p4fin->Energy();
1709 double dE_leftover = TMath::Min(NucRmvE, KE);
1712 double pmag_old = p4fin->P();
1713 double pmag_new = TMath::Sqrt(TMath::Max(0.,En*En-M*M));
1714 double scale = pmag_new / pmag_old;
1715 double pxn = scale * p4fin->Px();
1716 double pyn = scale * p4fin->Py();
1717 double pzn = scale * p4fin->Pz();
1719 TLorentzVector p4n(pxn,pyn,pzn,En);
1730 if (p4n.Vect().Mag()>=0.001)
1732 GHepParticle new_particle(pdgc, ist_pi, mom,-1,-1,-1, p4n, *v4);
1740 LOG(
"INukeUtils",
pINFO)<<
"Momentum too small; assigning 0.001 as new momentum";
1742 double phi = 2*
kPi*rnd->
RndFsi().Rndm();
1743 double omega = 2*rnd->
RndFsi().Rndm();
1746 double E4n = TMath::Sqrt(0.001*0.001+M*M);
1747 p4n.SetPxPyPzE(0.001,0,0,E4n);
1748 p4n.Rotate(TMath::ACos(1-omega),TVector3(0,0,1));
1749 p4n.Rotate(phi,TVector3(1,0,0));
1751 RemnP4 -= (p4n - TLorentzVector(0,0,0,M));
1753 GHepParticle new_particle(pdgc, ist, mom,-1,-1,-1, p4n, *v4);
1759 GHepParticle new_particle(pdgc, ist, mom,-1,-1,-1, p4n, *v4);
1765 double dpx = (1-scale)*p4fin->Px();
1766 double dpy = (1-scale)*p4fin->Py();
1767 double dpz = (1-scale)*p4fin->Pz();
1768 TLorentzVector premnadd(dpx,dpy,dpz,dE_leftover);
1771 LOG(
"INukeUtils",
pNOTICE) <<
"check conservation: Px = " << checkpx <<
" Py = " << checkpy
1772 <<
" Pz = " << checkpz <<
" E = " << checkE;
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
double E(void) const
Get energy.
static RandomGen * Instance()
Access instance.
const TLorentzVector * P4(void) const
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)
double Density(double r, int A, double ring=0.)
double MeanFreePath_Delta(int pdgc, const TLorentzVector &x4, const TLorentzVector &p4, double A)
Mean free path (Delta++ test)
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.
double Dist2ExitMFP(int pdgc, const TLorentzVector &x4, const TLorentzVector &p4, double A, double Z, double NR=3, double R0=1.4)
Distance to exit.
static constexpr double MeV
A singleton holding random number generator classes. All random number generation in GENIE should tak...
double Pz(void) const
Get Pz.
const TVector3 & Momentum3(void) const
double Energy(void) const
Get energy.
double Px(void) const
Get Px.
bool CompareMomentum(const GHepParticle *p) const
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...
static constexpr double A
bool PhaseSpaceDecay(GHepRecord *ev, GHepParticle *p, const PDGCodeList &pdgv, TLorentzVector &RemnP4, double NucRmvE, EINukeMode mode=kIMdHA)
general phase space decay method
static double fMinKinEnergy
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)
static constexpr double mb
void SetReason(string reason)
TLorentzVector * GetP4(void) const
bool ComparePdgCodes(const GHepParticle *p) const
static constexpr double fm2
static INukeHadroData * Instance(void)
A Neutrino Interaction Target. Is a transparent encapsulation of quite different physical systems suc...
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.
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
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)
bool CompareStatusCodes(const GHepParticle *p) const
void SetRemovalEnergy(double Erm)
double CalculateEta(double Minc, double ke, double Mtarg, double Mtwopart, double Mpi)
double KinE(bool mass_from_pdg=false) const
Get kinetic energy.
static PDGLibrary * Instance(void)
double Dist2Exit(const TLorentzVector &x4, const TLorentzVector &p4, double A, double NR=3, double R0=1.4)
Distance to exit.
void SetLastMother(int m)
void StepParticle(GHepParticle *p, double step, double nuclear_radius=-1.)
Step particle.
Singleton class to load & serve a TDatabasePDG.
const TLorentzVector * X4(void) const
void SetStatus(GHepStatus_t s)
void SetHitNucPdg(int pdgc)
bool IsNeutronOrProton(int pdgc)
static double fMaxKinEnergyHN
virtual void AddParticle(const GHepParticle &p)
TParticlePDG * Find(int pdgc, bool must_exist=true)
Singleton class to load & serve hadron x-section splines used by GENIE's version of the INTRANUKE cas...
string X4AsString(const TLorentzVector *x)
virtual bool GenerateNucleon(const Target &) const =0
void Equilibrium(GHepRecord *ev, GHepParticle *p, int &RemnA, int &RemnZ, TLorentzVector &RemnP4, bool DoFermi, double FermiFac, const NuclearModelI *Nuclmodel, double NucRmvE, EINukeMode mode=kIMdHN)
GENIE's GHEP MC event record.
static constexpr double m
Most commonly used PDG codes. A set of utility functions to handle PDG codes is provided in PDGUtils...
void PreEquilibrium(GHepRecord *ev, GHepParticle *p, int &RemnA, int &RemnZ, TLorentzVector &RemnP4, bool DoFermi, double FermiFac, const NuclearModelI *Nuclmodel, double NucRmvE, EINukeMode mode=kIMdHN)
STDHEP-like event record entry that can fit a particle or a nucleus.
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.
string Vec3AsString(const TVector3 *vec)
void push_back(int pdg_code)
enum genie::EGHepStatus GHepStatus_t
double Py(void) const
Get Py.