20 #if ROOT_VERSION_CODE >= ROOT_VERSION(5,15,6)
21 #include <TMCParticle.h>
23 #include <TMCParticle6.h>
47 using namespace genie;
48 using namespace genie::constants;
49 using namespace genie::controls;
51 extern "C" void py1ent_(
int *,
int *,
double *,
double *,
double *);
52 extern "C" void py2ent_(
int *,
int *,
int *,
double *);
90 TClonesArray * particle_list = this->
Hadronize(interaction);
92 if(! particle_list ) {
93 LOG(
"AGCharm2019",
pWARN) <<
"Got an empty particle list. Hadronizer failed!";
94 LOG(
"AGCharm2019",
pWARN) <<
"Quitting the current event generation thread";
99 exception.
SetReason(
"Could not simulate the hadronic system");
106 int mom =
event->FinalStateHadronicSystemPosition();
116 const TLorentzVector * had_syst =
event -> Particle(mom) -> P4() ;
117 TVector3 beta( 0., 0., had_syst -> P()/ had_syst -> Energy() ) ;
120 TVector3 unitvq = had_syst -> Vect().Unit();
123 const TLorentzVector & vtx = *(neutrino->
X4());
126 TIter particle_iter(particle_list);
127 while ((particle = (
GHepParticle *) particle_iter.Next())) {
129 int pdgc = particle -> Pdg() ;
132 particle -> P4() -> Boost( beta ) ;
133 particle -> P4() -> RotateUz( unitvq ) ;
146 particle -> SetStatus( ist ) ;
148 int im = mom + 1 + particle -> FirstMother() ;
149 int ifc = ( particle -> FirstDaughter() == -1) ? -1 : mom + 1 + particle -> FirstDaughter();
150 int ilc = ( particle -> LastDaughter() == -1) ? -1 : mom + 1 + particle -> LastDaughter();
152 particle -> SetFirstMother( im ) ;
154 particle -> SetFirstDaughter( ifc ) ;
155 particle -> SetLastDaughter( ilc ) ;
159 particle -> SetPosition( vtx ) ;
161 event->AddParticle(*particle);
164 particle_list -> Delete() ;
165 delete particle_list ;
175 LOG(
"CharmHad",
pNOTICE) <<
"** Running CHARM hadronizer";
183 const InitialState & init_state = interaction -> InitState();
184 const Kinematics & kinematics = interaction -> Kine();
185 const Target & target = init_state.
Tgt();
187 const TLorentzVector & p4Had = kinematics.
HadSystP4();
190 double W = kinematics.
W(
true);
192 TVector3 beta = -1 * p4Had.BoostVector();
193 TLorentzVector p4H(0,0,0,W);
195 double Eh = p4Had.Energy();
197 LOG(
"CharmHad",
pNOTICE) <<
"Ehad (LAB) = " << Eh <<
", W = " <<
W;
213 TLorentzVector p4C(0,0,0,0);
216 bool got_charmed_hadron =
false;
223 double mc = pdglib->
Find(pdg)->Mass();
226 <<
"Trying charm hadron = " << pdg <<
"(m = " << mc <<
")";
234 double mc2 = TMath::Power(mc,2);
235 double Ec2 = TMath::Power(Ec,2);
236 double pc2 = Ec2-mc2;
239 <<
"Trying charm hadron z = " << z <<
", E = " << Ec;
246 double plc2 = Ec2 - ptc2 - mc2;
248 <<
"Trying charm hadron pT^2 (tranv to pHad) = " << ptc2;
252 double ptc = TMath::Sqrt(ptc2);
253 double plc = TMath::Sqrt(plc2);
255 double pxc = ptc * TMath::Cos(phi);
256 double pyc = ptc * TMath::Sin(phi);
259 p4C.SetPxPyPzE(pxc,pyc,pzc,Ec);
272 TLorentzVector p4 = p4H - p4C;
275 <<
"Invariant mass of remnant hadronic system= " << wr;
277 LOG(
"CharmHad",
pINFO) <<
"Too small hadronic remnant mass!";
282 got_charmed_hadron =
true;
285 <<
"Generated charm hadron = " << pdg <<
"(m = " << mc <<
")";
287 <<
"Generated charm hadron z = " << z <<
", E = " << Ec;
298 bool used_lowW_strategy =
false;
299 int fs_nucleon_pdg = -1;
300 if(ch_pdg==-1 && W < 3.){
302 <<
"Had difficulty generating charm hadronic system near W threshold";
304 <<
"Trying an alternative strategy";
306 double qfsl = interaction->
FSPrimLepton()->Charge() / 3.;
307 double qinit = pdglib->
Find(nuc_pdg)->Charge() / 3.;
308 int qhad = (int) (qinit - qfsl);
317 }
else if(qhad == 1) {
323 }
else if(qhad == 0) {
325 }
else if(qhad == -1) {
329 double mc = pdglib->
Find(chrm_pdg)->Mass();
330 double mn = pdglib->
Find(remn_pdg)->Mass();
334 double mass[2] = {mc, mn};
340 for(
int i=0; i<200; i++) {
342 wmax = TMath::Max(wmax,w);
349 bool accept_decay=
false;
350 unsigned int idecay_try=0;
357 <<
"Couldn't generate an unweighted phase space decay after "
358 << idecay_try <<
" attempts";
363 <<
"Decay weight = " << w <<
" > max decay weight = " << wmax;
365 double gw = wmax * rnd->
RndHadro().Rndm();
366 accept_decay = (gw<=w);
369 used_lowW_strategy =
true;
373 fs_nucleon_pdg = remn_pdg;
387 <<
"Couldn't generate charm hadron for: " << *interaction;
391 TLorentzVector p4R = p4H - p4C;
395 LOG(
"CharmHad",
pNOTICE) <<
"Remnant hadronic system mass = " << WR;
403 TClonesArray * particle_list =
new TClonesArray(
"genie::GHepParticle", 2);
404 particle_list->SetOwner(
true);
408 -1,-1,-1,-1, p4C.Px(),p4C.Py(),p4C.Pz(),p4C.E(), 0,0,0,0);
410 -1,-1,-1,-1, p4R.Px(),p4R.Py(),p4R.Pz(),p4R.E(), 0,0,0,0);
412 return particle_list;
420 if(used_lowW_strategy) {
422 TClonesArray * particle_list =
new TClonesArray(
"genie::GHepParticle", 3);
423 particle_list->SetOwner(
true);
427 -1,-1,-1,-1, p4C.Px(),p4C.Py(),p4C.Pz(),p4C.E(), 0,0,0,0);
429 -1,-1,2,2, p4R.Px(),p4R.Py(),p4R.Pz(),p4R.E(), 0,0,0,0);
431 1,1,-1,-1, p4R.Px(),p4R.Py(),p4R.Pz(),p4R.E(), 0,0,0,0);
433 return particle_list;
446 TClonesArray * particle_list =
new TClonesArray(
"genie::GHepParticle");
447 particle_list->SetOwner(
true);
450 -1,-1,-1,-1, p4C.Px(),p4C.Py(),p4C.Pz(),p4C.E(), 0,0,0,0);
452 -1,-1,2,3, p4R.Px(),p4R.Py(),p4R.Pz(),p4R.E(), 0,0,0,0);
454 unsigned int rpos =2;
456 bool use_pythia = (WR>1.5);
564 if(qrkSyst1 == 0 && qrkSyst2 == 0) {
566 <<
"Couldn't generate quark systems for PYTHIA in: " << *interaction;
582 py2ent_(&ip, &qrkSyst1, &qrkSyst2, &WR);
587 TClonesArray * pythia_remnants = 0;
589 pythia_remnants =
dynamic_cast<TClonesArray *
>(
fPythia->ImportParticles(
"All"));
590 if(!pythia_remnants) {
591 LOG(
"CharmHad",
pWARN) <<
"Couldn't hadronize (non-charm) remnants!";
595 int np = pythia_remnants->GetEntries();
603 TVector3 rmnbeta = +1 * p4R.BoostVector();
605 TMCParticle * pythia_remn = 0;
607 TIter remn_iter(pythia_remnants);
608 while( (pythia_remn = (TMCParticle *) remn_iter.Next()) ) {
611 bremn =
new ((*particle_list)[rpos++])
GHepParticle ( pythia_remn->GetKF(),
613 pythia_remn->GetParent(),
615 pythia_remn->GetFirstChild(),
616 pythia_remn->GetLastChild(),
617 pythia_remn -> GetPx(),
618 pythia_remn -> GetPy(),
619 pythia_remn -> GetPz(),
620 pythia_remn -> GetEnergy(),
621 pythia_remn->GetVx(),
622 pythia_remn->GetVy(),
623 pythia_remn->GetVz(),
624 pythia_remn->GetTime()
628 bremn -> P4() -> Boost( rmnbeta ) ;
635 bremn -> SetFirstMother( (jp == 0 ? 1 : jp +1) );
636 bremn -> SetFirstDaughter ( (ifc == 0 ? -1 : ifc+1) );
637 bremn -> SetLastDaughter ( (ilc == 0 ? -1 : ilc+1) );
657 double qfsl = interaction->
FSPrimLepton()->Charge() / 3.;
658 double qinit = pdglib->
Find(nuc_pdg)->Charge() / 3.;
659 double qch = pdglib->
Find(ch_pdg)->Charge() / 3.;
660 int Q = (int) (qinit - qfsl - qch);
682 pdglib->
Find(pd[0])->Mass(), pdglib->
Find(pd[1])->Mass()
688 LOG(
"CharmHad",
pERROR) <<
" *** Phase space decay is not permitted";
693 for(
int i=0; i<200; i++) {
695 wmax = TMath::Max(wmax,w);
698 LOG(
"CharmHad",
pERROR) <<
" *** Non-positive maximum weight";
699 LOG(
"CharmHad",
pERROR) <<
" *** Can not generate an unweighted phase space decay";
704 <<
"Max phase space gen. weight @ current hadronic system: " << wmax;
708 bool accept_decay=
false;
709 unsigned int idectry=0;
716 <<
"Couldn't generate an unweighted phase space decay after "
717 << itry <<
" attempts";
723 <<
"Decay weight = " << w <<
" > max decay weight = " << wmax;
725 double gw = wmax * rnd->
RndHadro().Rndm();
726 accept_decay = (gw<=w);
728 <<
"Decay weight = " << w <<
" / R = " << gw <<
" - accepted: " << accept_decay;
730 for(
unsigned int i=0; i<2; i++) {
734 pdgc,
kIStStableFinalState,1,1,-1,-1,p4d->Px(),p4d->Py(),p4d->Pz(),p4d->Energy(),
741 return particle_list;
775 LOG(
"CharmHad",
pERROR) <<
"Could not generate a charm hadron!";
800 bool hadronize_remnants ;
801 GetParamDef(
"HadronizeRemnants", hadronize_remnants,
true ) ;
807 this->
SubAlg(
"FragmentationFunc"));
811 this ->
GetParam(
"PTFunction", pt_function ) ;
813 fCharmPT2pdf =
new TF1(
"fCharmPT2pdf", pt_function.c_str(),0,0.6);
819 std::vector<double> ec, d0frac, dpfrac, dsfrac ;
822 std::vector<std::string> bits ;
824 bool invalid_configuration = false ;
834 if ( d0frac.size() != ec.size() ) {
835 LOG(
"AGCharm2019",
pFATAL) <<
"E entries don't match D0 fraction entries";
836 LOG(
"AGCharm2019",
pFATAL) <<
"E: " << ec.size() ;
837 LOG(
"AGCharm2019",
pFATAL) <<
"D0: " << d0frac.size() ;
838 invalid_configuration = true ;
845 if ( dpfrac.size() != ec.size() ) {
846 LOG(
"AGCharm2019",
pFATAL) <<
"E entries don't match D+ fraction entries";
847 LOG(
"AGCharm2019",
pFATAL) <<
"E: " << ec.size() ;
848 LOG(
"AGCharm2019",
pFATAL) <<
"D+: " << dpfrac.size() ;
849 invalid_configuration = true ;
856 if ( dsfrac.size() != ec.size() ) {
857 LOG(
"AGCharm2019",
pFATAL) <<
"E entries don't match Ds fraction entries";
858 LOG(
"AGCharm2019",
pFATAL) <<
"E: " << ec.size() ;
859 LOG(
"AGCharm2019",
pFATAL) <<
"Ds: " << dsfrac.size() ;
860 invalid_configuration = true ;
872 if ( invalid_configuration ) {
875 <<
"Invalid configuration: Exiting" ;
const int kPdgP33m1232_DeltaPP
const int kPdgUUDiquarkS1
double W(bool selected=false) const
bool IsNeutrino(int pdgc)
static const double kNucleonMass
static RandomGen * Instance()
Access instance.
int HitNucPdg(void) const
Defines the EventRecordVisitorI interface. Concrete implementations of this interface use the 'Visito...
Spline * fDpFracSpl
nu charm fraction vs Ev: D+
int FirstDaughter(void) const
const int kPdgHadronicBlob
void Initialize(void) const
int GenerateCharmHadron(int nupdg, double EvLab) const
A numeric analysis tool class for interpolating 1-D functions.
bool IsNucleus(void) const
void Configure(const Registry &config)
int GetParamVect(const std::string &comm_name, std::vector< T > &v, bool is_top_call=true) const
Handle to load vectors of parameters.
TF1 * fCharmPT2pdf
charm hadron pT^2 pdf
Generated/set kinematical variables for an event.
TGenPhaseSpace fPhaseSpaceGenerator
a phase space generator
string P4AsString(const TLorentzVector *p)
static const unsigned int kMaxUnweightDecayIterations
bool IsDarkMatter(int pdgc)
bool IsChargedLepton(int pdgc)
virtual double Weight(void) const
const TLorentzVector & HadSystP4(void) const
double Evaluate(double x) const
A singleton holding random number generator classes. All random number generation in GENIE should tak...
Spline * fD0FracSpl
nu charm fraction vs Ev: D0
const int kPdgP33m1232_DeltaP
bool fCharmOnly
don't hadronize non-charm blob
const int kPdgP33m1232_DeltaM
double fFracMaxEnergy
Maximum energy available for the Meson fractions.
double W(const Interaction *const i)
int FirstMother(void) const
Summary information for an interaction.
TClonesArray * Hadronize(const Interaction *) 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...
const int kPdgUDDiquarkS1
double fD0BarFrac
nubar {D0} charm fraction
bool IsAntiNeutrino(int pdgc)
void ProcessEventRecord(GHepRecord *event) const
A Neutrino Interaction Target. Is a transparent encapsulation of quite different physical systems suc...
virtual void Configure(const Registry &config)
void py2ent_(int *, int *, int *, double *)
static const double kASmallNum
double Weight(void) const
const int kPdgUDDiquarkS0
const int kPdgP33m1232_Delta0
TParticlePDG * FSPrimLepton(void) const
final state primary lepton
Pure abstract base class. Defines the FragmentationFunctionI interface to be implemented by any algor...
bool IsNeutralLepton(int pdgc)
void py1ent_(int *, int *, double *, double *, double *)
TRandom3 & RndHadro(void) const
rnd number generator used by hadronization models
void SwitchOnFastForward(void)
static PDGLibrary * Instance(void)
void SetReason(string reason)
static const double kPionMass
Singleton class to load & serve a TDatabasePDG.
const TLorentzVector * X4(void) const
A registry. Provides the container for algorithm configuration parameters.
const FragmentationFunctionI * fFragmFunc
charm hadron fragmentation func
virtual double GenerateZ(void) const =0
const InitialState & InitState(void) const
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
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.
TPythia6 * fPythia
remnant (non-charm) hadronizer
void push_back(int pdg_code)
double fDmFrac
nubar D- charm fraction
enum genie::EGHepStatus GHepStatus_t
Initial State information.
Spline * fDsFracSpl
nu charm fraction vs Ev: Ds+
const int kPdgDDDiquarkS1
const Algorithm * SubAlg(const RgKey ®istry_key) const