16#include "Framework/Conventions/GBuild.h"
48 const double eps = std::numeric_limits<double>::epsilon();
102 if ( interaction->
ProcInfo().
IsEM() ) Q2min = genie::utils::kinematics
103 ::electromagnetic::kMinQ2Limit;
112 TLorentzVector v4(*event->
Probe()->
X4());
113 TLorentzVector tempp4(0.,0.,0.,0.);
116 bool have_nucleus = nucleus != 0;
120 double CosthMax = 1.0;
121 double CosthMin = -1.0;
124 double TMax = std::numeric_limits<double>::max();
138 TMax = Enu - LepMass;
148 TMin = TMath::Sqrt(TMath::Power(LepMass, 2) + TMath::Power((Enu -
fQ3Max), 2)) - LepMass;
149 CosthMin = TMath::Sqrt(1 - TMath::Power((
fQ3Max / Enu ), 2));
157 unsigned int iter = 0;
162 if ( NuPDG == 11 ) maxIter *= 1000;
165 double XSecMax = this->
MaxXSec( event );
167 LOG(
"Kinematics",
pDEBUG) <<
"Max XSec = " << XSecMax;
175 <<
"Couldn't select a valid Tmu, CosTheta pair after "
176 << iter <<
" iterations";
177 event->EventFlags()->SetBitNumber(
kKineGenErr,
true);
179 exception.
SetReason(
"Couldn't select lepton kinematics");
185 T = TMin + (TMax-TMin)*rnd->
RndKine().Rndm();
186 Costh = CosthMin + (CosthMax-CosthMin)*rnd->
RndKine().Rndm();
189 Plep = TMath::Sqrt( T * (T + (2.0 * LepMass)));
190 Q3 = TMath::Sqrt(Plep*Plep + Enu*Enu - 2.0 * Plep * Enu * Costh);
193 Q0 = Enu - (T + LepMass);
201 LOG(
"QELEvent",
pDEBUG) <<
" Anu elastic case. T, Costh: " << T <<
", " << Costh ;
202 LOG(
"QELEvent",
pDEBUG) <<
" Anu elastic case. Q0, Q3: " << Q0 <<
", " << Q3 ;
207 if ( Q3 < fQ3Max && Q2 >= Q2min ){
211 LOG(
"QELEvent",
pDEBUG) <<
" T, Costh, Q2: " << T <<
", " << Costh <<
", " << Q2;
216 if (XSec > XSecMax) {
220 LOG(
"QELEvent",
pERROR) <<
" T, Costh, Q2: " << T <<
", " << Costh <<
", " << Q2;
221 LOG(
"QELEvent",
pERROR) <<
"XSec is > XSecMax for nucleus " << TgtPDG <<
" "
222 << XSec <<
" > " << XSecMax
223 <<
" don't let this happen.";
227 accept = XSec > XSecMax*rnd->
RndKine().Rndm();
228 LOG(
"QELEvent",
pINFO) <<
"Xsec, Max, Accept: " << XSec <<
", "
229 << XSecMax <<
", " << accept;
244 double PlepZ = Plep * Costh;
245 double PlepXY = Plep * TMath::Sqrt(1. - TMath::Power(Costh,2));
248 double phi= 2 *
kPi * rnd->
RndLep().Rndm();
250 double PlepX = PlepXY * TMath::Cos(phi);
251 double PlepY = PlepXY * TMath::Sin(phi);
255 TVector3 unit_nudir =
event->Probe()->P4()->Vect().Unit();
256 TVector3 p3l(PlepX, PlepY, PlepZ);
257 p3l.RotateUz(unit_nudir);
260 Elep = TMath::Sqrt(LepMass*LepMass + PlepX*PlepX + PlepY*PlepY + PlepZ*PlepZ);
261 TLorentzVector p4l(p3l,Elep);
265 int momidx =
event->ProbePosition();
271 double gy = Q0 / Enu;
284 LOG(
"QELEvent",
pDEBUG) <<
"~~~ LEPTON DONE ~~~";
291 LOG(
"QELEvent",
pINFO) <<
"Adding final state nucleus";
299 bool have_nucleus = nucleus != 0;
300 if (!have_nucleus)
return;
302 int A = nucleus->
A();
303 int Z = nucleus->
Z();
308 for(
int id = fd;
id <= ld;
id++) {
313 int pdgc = particle->
Pdg();
318 if (is_p || is_n) A--;
320 Px += particle->
Px();
321 Py += particle->
Py();
322 Pz += particle->
Pz();
327 TParticlePDG * remn = 0;
332 <<
"No particle with [A = " << A <<
", Z = " << Z
333 <<
", pdgc = " << ipdgc <<
"] in PDGLibrary!";
337 double Mi = nucleus->
Mass();
345 <<
"Adding nucleus [A = " << A <<
", Z = " << Z
346 <<
", pdgc = " << ipdgc <<
"]";
348 int imom =
event->TargetNucleusPosition();
350 ipdgc,
kIStStableFinalState, imom,-1,-1,-1, Px,Py,Pz,E, 0,0,0,0);
361 LOG(
"QELEvent",
pDEBUG) <<
"Generate Nucleon - Start";
366 TLorentzVector p4nu(*neutrino->
P4());
371 TLorentzVector p4l(*fsl->
P4());
374 TLorentzVector Q4 = p4nu - p4l;
380 bool have_nucleus = (target_nucleus != 0);
383 assert(initial_nucleon);
384 GHepParticle * remnant_nucleus =
event->RemnantNucleus();
390 if(have_nucleus) tgtpdg = target_nucleus->
Pdg();
397 unsigned int iter = 0;
399 int initial_nucleon_pdg = initial_nucleon->
Pdg();
402 TLorentzVector p4initial_nucleon;
403 TLorentzVector p4final_nucleon;
404 double removalenergy;
422 <<
"Couldn't select a valid nucleon after "
423 << iter <<
" iterations";
424 event->EventFlags()->SetBitNumber(
kKineGenErr,
true);
426 exception.
SetReason(
"Couldn't select initial hadron kinematics");
435 double hitNucPos = initial_nucleon->
X4()->Vect().Mag();
448 double q3 = Q4.Vect().Mag();
453 p3i.SetXYZ(0.0,0.0,0.0);
459 removalenergy = -0.017687 + 0.0564*q3;
462 removalenergy = 0.0289558;
466 if(removalenergy<0.005) removalenergy=0.005;
472 LOG(
"QELEvent",
pDEBUG) <<
"q3 for this event:" << q3;
473 LOG(
"QELEvent",
pDEBUG) <<
"Removal energy:" << removalenergy;
477 double mass2 = mass*mass;
478 double energy = TMath::Sqrt(p3i.Mag2() + mass2);
479 p4initial_nucleon.SetPxPyPzE(p3i.Px(),p3i.Py(),p3i.Pz(),energy);
486 if(
fForceBound && (energy-mass>removalenergy))
continue;
489 TLorentzVector tLVebind(0., 0., 0., -1.0 * (removalenergy));
493 p4final_nucleon = p4initial_nucleon + Q4 + tLVebind;
500 double En = p4final_nucleon.E();
502 double pmag_old = p4final_nucleon.Vect().Mag();
505 double scale = pmag_new / pmag_old;
507 double pxn = scale * p4final_nucleon.Px();
508 double pyn = scale * p4final_nucleon.Py();
509 double pzn = scale * p4final_nucleon.Pz();
511 p4final_nucleon.SetPxPyPzE(pxn,pyn,pzn,En);
516 pxb = p4nu.Px()-p4l.Px()-p4final_nucleon.Px();
517 pyb = p4nu.Py()-p4l.Py()-p4final_nucleon.Py();
518 pzb = p4nu.Pz()-p4l.Pz()-p4final_nucleon.Pz();
520 LOG(
"QELEvent",
pDEBUG) <<
"Remnant momentum is: (" << pxb <<
", " << pyb <<
", " << pzb <<
")";
529 LOG(
"QELEvent",
pDEBUG) <<
"Rejected nucleon, can't be put on-shell";
530 LOG(
"QELEvent",
pDEBUG) <<
"Nucleon invariant mass:" << p4final_nucleon.M();
532 LOG(
"QELEvent",
pDEBUG) <<
"Nucleon 4 momenutum:";
534 LOG(
"QELEvent",
pDEBUG) <<
"Removal energy:" << removalenergy;
535 LOG(
"QELEvent",
pDEBUG) <<
"Q4 transfer:";
540 LOG(
"QELEvent",
pDEBUG) <<
"Nucleon accepted, Q4 is";
542 LOG(
"QELEvent",
pDEBUG) <<
"Initial nucleon mass is" << sqrt((p4initial_nucleon.E()*p4initial_nucleon.E())-(p4initial_nucleon.Vect().Mag()*p4initial_nucleon.Vect().Mag()));
543 LOG(
"QELEvent",
pDEBUG) <<
"Final nucleon mass is" << sqrt((p4final_nucleon.E()*p4final_nucleon.E())-(p4final_nucleon.Vect().Mag()*p4final_nucleon.Vect().Mag()));
544 LOG(
"QELEvent",
pDEBUG) <<
"Nucleon invariant mass:" << p4final_nucleon.M();
546 LOG(
"QELEvent",
pDEBUG) <<
"Nucleon 4 momenutum:";
548 LOG(
"QELEvent",
pDEBUG) <<
"Removal energy:" << removalenergy;
549 LOG(
"QELEvent",
pDEBUG) <<
"Q4 transfer:";
563 remnant_nucleus->
SetMomentum(pxb,pyb,pzb, Mi - p4initial_nucleon.E() + removalenergy);
569 TLorentzVector v4(*neutrino->
X4());
578 LOG(
"QELEvent",
pDEBUG) <<
"Generate Nucleon - End";
597 RgKey nuclkey =
"NuclearModel";
604 this->
SubAlg(
"FreeNucleonEventGenerator") );
621 this->
GetParam(
"RFG-NucRemovalE@Pdg=1000060120",
fEbC);
660 #ifdef __GENIE_LOW_LEVEL_MESG_ENABLED__
662 SLOG(
"QELKinematics",
pDEBUG) <<
"Max xsec in phase space = " << max_xsec;
#define LOG(stream, priority)
A macro that returns the requested log4cpp::Category appending a string (using the FILE,...
#define SLOG(stream, priority)
A macro that returns the requested log4cpp::Category appending a short string (using the FUNCTION and...
Most commonly used PDG codes. A set of utility functions to handle PDG codes is provided in PDGUtils.
bool GetParam(const RgKey &name, T &p, bool is_top_call=true) const
virtual void Configure(const Registry &config)
bool GetParamDef(const RgKey &name, T &p, const T &def) const
const Algorithm * SubAlg(const RgKey ®istry_key) const
Defines the EventGeneratorI interface.
virtual const XSecAlgorithmI * CrossSectionAlg(void) const =0
Defines the EventRecordVisitorI interface. Concrete implementations of this interface use the 'Visito...
STDHEP-like event record entry that can fit a particle or a nucleus.
void SetMomentum(const TLorentzVector &p4)
const TLorentzVector * P4(void) const
double Mass(void) const
Mass that corresponds to the PDG code.
const TLorentzVector * X4(void) const
int LastDaughter(void) const
double Px(void) const
Get Px.
double E(void) const
Get energy.
double Pz(void) const
Get Pz.
double Py(void) const
Get Py.
int FirstDaughter(void) const
GENIE's GHEP MC event record.
virtual GHepParticle * Probe(void) const
virtual Interaction * Summary(void) const
virtual int HitNucleonPosition(void) const
const Target & Tgt(void) const
double ProbeE(RefFrame_t rf) const
Summary information for an interaction.
string AsString(void) const
int RecoilNucleonPdg(void) const
recoil nucleon pdg
const ProcessInfo & ProcInfo(void) const
TParticlePDG * FSPrimLepton(void) const
final state primary lepton
const InitialState & InitState(void) const
Kinematics * KinePtr(void) const
virtual void AssertXSecLimits(const Interaction *in, double xsec, double xsec_max) const
bool fGenerateUniformly
uniform over allowed phase space + event weight?
double fMaxXSecDiffTolerance
max{100*(xsec-maxxsec)/.5*(xsec+maxxsec)} if xsec>maxxsec
double fEMin
min E for which maxxsec is cached - forcing explicit calc.
double fSafetyFactor
ComputeMaxXSec -> ComputeMaxXSec * fSafetyFactor.
virtual double MaxXSec(GHepRecord *evrec, const int nkey=0) const
const XSecAlgorithmI * fXSecModel
Generated/set kinematical variables for an event.
void SetHadSystP4(const TLorentzVector &p4)
void Setx(double x, bool selected=false)
void SetQ2(double Q2, bool selected=false)
const TLorentzVector & HadSystP4(void) const
void Sety(double y, bool selected=false)
void SetW(double W, bool selected=false)
void SetFSLeptonP4(const TLorentzVector &p4)
Pure abstract base class. Defines the NuclearModelI interface to be implemented by any physics model ...
static PDGLibrary * Instance(void)
TParticlePDG * Find(int pdgc, bool must_exist=true)
void GenerateNucleon(GHepRecord *event) const
void AddTargetNucleusRemnant(GHepRecord *event) const
const EventRecordVisitorI * fFreeNucleonEventGenerator
void SelectLeptonKinematics(GHepRecord *event) const
void Configure(const Registry &config)
void ProcessEventRecord(GHepRecord *event) const
const NuclearModelI * fNuclModel
double ComputeMaxXSec(const Interaction *in) const
A singleton holding random number generator classes. All random number generation in GENIE should tak...
static RandomGen * Instance()
Access instance.
TRandom3 & RndLep(void) const
rnd number generator used by final state primary lepton generators
TRandom3 & RndKine(void) const
rnd number generator used by kinematics generators
A registry. Provides the container for algorithm configuration parameters.
Keep info on the event generation thread currently on charge. This is used so that event generation m...
static RunningThreadInfo * Instance(void)
const EventGeneratorI * RunningThread(void)
A Neutrino Interaction Target. Is a transparent encapsulation of quite different physical systems suc...
void SetHitNucPdg(int pdgc)
bool IsNucleus(void) const
An exception thrown by EventRecordVisitorI when the normal processing sequence has to be disrupted (f...
void SwitchOnFastForward(void)
void SetReason(string reason)
static const double kNucleonMass
Misc GENIE control constants.
static const double kMinQ2Limit
static const unsigned int kRjMaxIterations
int IonPdgCode(int A, int Z)
int IonPdgCodeToZ(int pdgc)
static constexpr double cm2
Simple functions for loading and reading nucleus dependent keys from config files.
double Q2YtoX(double Ev, double M, double Q2, double y)
double XYtoW(double Ev, double M, double x, double y)
double NonNegative(double x)
bool GetTlCostlFromq0q3(double q0, double q3, double Enu, double ml, double &Tl, double &costl)
double GetMaxXSecTlctl(const XSecAlgorithmI &xsec_model, const Interaction &inter, const double tolerance=0.01, const double safety_factor=1.2, const int max_n_layers=100)
bool Getq0q3FromTlCostl(double Tl, double costl, double Enu, double ml, double &q0, double &q3)
Root of GENIE utility namespaces.
THE MAIN GENIE PROJECT NAMESPACE
enum genie::EGHepStatus GHepStatus_t