16 #include "Framework/Conventions/GBuild.h" 42 using namespace genie;
48 const double eps = std::numeric_limits<double>::epsilon();
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;
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;
virtual double MaxXSec(GHepRecord *evrec) const
bool GetTlCostlFromq0q3(double q0, double q3, double Enu, double ml, double &Tl, double &costl)
double RemovalEnergy(void) const
bool fGenerateUniformly
uniform over allowed phase space + event weight?
THE MAIN GENIE PROJECT NAMESPACE
virtual void ProcessEventRecord(GHepRecord *event_rec) const =0
double E(void) const
Get energy.
TRandom3 & RndLep(void) const
rnd number generator used by final state primary lepton generators
static const double kNucleonMass
double Q2(const Interaction *const i)
virtual Interaction * Summary(void) const
static RandomGen * Instance()
Access instance.
void SetQ2(double Q2, bool selected=false)
const TLorentzVector * P4(void) const
Kinematics * KinePtr(void) const
Defines the EventRecordVisitorI interface. Concrete implementations of this interface use the 'Visito...
double fSafetyFactor
maxxsec -> maxxsec * safety_factor
int FirstDaughter(void) const
virtual double XSec(const Interaction *i, KinePhaseSpace_t k=kPSfE) const =0
Compute the cross section for the input interaction.
int RecoilNucleonPdg(void) const
recoil nucleon pdg
virtual void AssertXSecLimits(const Interaction *in, double xsec, double xsec_max) const
bool IsNucleus(void) const
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)
double fMaxXSecDiffTolerance
max{100*(xsec-maxxsec)/.5*(xsec+maxxsec)} if xsec>maxxsec
Defines the EventGeneratorI interface.
Generated/set kinematical variables for an event.
void SelectLeptonKinematics(GHepRecord *event) const
const TLorentzVector & HadSystP4(void) const
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.
Abstract class. Provides a data caching mechanism for for concrete implementations of the EventRecord...
A singleton holding random number generator classes. All random number generation in GENIE should tak...
double Pz(void) const
Get Pz.
void AddTargetNucleusRemnant(GHepRecord *event) const
string AsString(void) const
double XYtoW(double Ev, double M, double x, double y)
const TVector3 & Momentum3(void) const
const XSecAlgorithmI * fXSecModel
static const double kMinQ2Limit
double Px(void) const
Get Px.
virtual GHepParticle * Probe(void) const
Summary information for an interaction.
double ComputeMaxXSec(const Interaction *in) const
int LastDaughter(void) const
An exception thrown by EventRecordVisitorI when the normal processing sequence has to be disrupted (f...
#define LOG(stream, priority)
A macro that returns the requested log4cpp::Category appending a string (using the FILE...
void SetFSLeptonP4(const TLorentzVector &p4)
static constexpr double cm2
void GenerateNucleon(GHepRecord *event) const
A Neutrino Interaction Target. Is a transparent encapsulation of quite different physical systems suc...
virtual void Configure(const Registry &config)
bool Getq0q3FromTlCostl(double Tl, double costl, double Enu, double ml, double &q0, double &q3)
static int max(int a, int b)
TRandom3 & RndKine(void) const
rnd number generator used by kinematics generators
Misc GENIE control constants.
virtual const XSecAlgorithmI * CrossSectionAlg(void) const =0
TParticlePDG * FSPrimLepton(void) const
final state primary lepton
void Setx(double x, bool selected=false)
void SetKV(KineVar_t kv, double value)
static RunningThreadInfo * Instance(void)
void SetW(double W, bool selected=false)
void SwitchOnFastForward(void)
static PDGLibrary * Instance(void)
void SetReason(string reason)
const EventRecordVisitorI * fFreeNucleonEventGenerator
double Q2YtoX(double Ev, double M, double Q2, double y)
const TLorentzVector * X4(void) const
void ProcessEventRecord(GHepRecord *event) const
void Configure(const Registry &config)
A registry. Provides the container for algorithm configuration parameters.
void SetHitNucPdg(int pdgc)
void Sety(double y, bool selected=false)
double fEMin
min E for which maxxsec is cached - forcing explicit calc.
int IonPdgCode(int A, int Z)
void SetHadSystP4(const TLorentzVector &p4)
virtual bool GenerateNucleon(const Target &) const =0
const InitialState & InitState(void) const
const ProcessInfo & ProcInfo(void) const
double NonNegative(double x)
int IonPdgCodeToZ(int pdgc)
TParticlePDG * Find(int pdgc, bool must_exist=true)
bool GetParamDef(const RgKey &name, T &p, const T &def) const
bool GetParam(const RgKey &name, T &p, bool is_top_call=true) const
const Target & Tgt(void) const
static const unsigned int kRjMaxIterations
const EventGeneratorI * RunningThread(void)
#define SLOG(stream, priority)
A macro that returns the requested log4cpp::Category appending a short string (using the FUNCTION and...
double ProbeE(RefFrame_t rf) const
GENIE's GHEP MC event record.
Most commonly used PDG codes. A set of utility functions to handle PDG codes is provided in PDGUtils...
STDHEP-like event record entry that can fit a particle or a nucleus.
Keep info on the event generation thread currently on charge. This is used so that event generation m...
const NuclearModelI * fNuclModel
Root of GENIE utility namespaces.
cet::coded_exception< error, detail::translate > exception
Event finding and building.
enum genie::EGHepStatus GHepStatus_t
double Py(void) const
Get Py.
const Algorithm * SubAlg(const RgKey ®istry_key) const