37#include <TLorentzVector.h>
44#include "Framework/Conventions/GBuild.h"
63using std::ostringstream;
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)";
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)
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)
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;
983 M1 = pLib->
Find(p->
Pdg())->Mass();
984 M2 = pLib->
Find(tcode)->Mass();
985 M3 = pLib->
Find(s1->
Pdg())->Mass();
986 M4 = pLib->
Find(s2->
Pdg())->Mass();
987 M5 = pLib->
Find(s3->
Pdg())->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;
#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.
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 double fMaxKinEnergyHN
static INukeHadroData * Instance(void)
static double fMinKinEnergy
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)
Mean free path (pions, nucleons)
bool TwoBodyKinematics(double M3, double M4, TLorentzVector tP1L, TLorentzVector tP2L, TLorentzVector &tP3L, TLorentzVector &tP4L, double C3CM, TLorentzVector &RemnP4, double bindE=0)
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 PhaseSpaceDecay(GHepRecord *ev, GHepParticle *p, const PDGCodeList &pdgv, TLorentzVector &RemnP4, double NucRmvE, EINukeMode mode=kIMdHA)
general phase space decay method
double Dist2Exit(const TLorentzVector &x4, const TLorentzVector &p4, double A, double NR=3, double R0=1.4)
Distance to exit.
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)
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.
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 StepParticle(GHepParticle *p, double step, double nuclear_radius=-1.)
Step particle.
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 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.
double CalculateEta(double Minc, double ke, double Mtarg, double Mtwopart, double Mpi)
double Dist2ExitMFP(int pdgc, const TLorentzVector &x4, const TLorentzVector &p4, double A, double Z, double NR=3, double R0=1.4)
Distance to exit.
double MeanFreePath_Delta(int pdgc, const TLorentzVector &x4, const TLorentzVector &p4, double A)
Mean free path (Delta++ test)
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