14 #include <TClonesArray.h>
15 #include <TLorentzVector.h>
16 #include <TDecayChannel.h>
18 #if ROOT_VERSION_CODE >= ROOT_VERSION(5,15,6)
19 #include <TMCParticle.h>
21 #include <TMCParticle6.h>
39 using namespace genie;
42 extern "C" void py1ent_(
int *,
int *,
double *,
double *,
double *);
52 Decayer(
"genie::PythiaDecayer", config)
65 <<
"Running PYTHIA6 particle decayer "
69 TObjArrayIter piter(event);
78 int pdg_code = p->
Pdg();
82 if(!this->
ToBeDecayed(pdg_code, status_code))
continue;
85 <<
"Decaying unstable particle: " << p->
Name();
87 bool decayed = this->
Decay(ipos, event);
92 <<
"Done finding & decaying unstable particles";
100 GHepParticle * decay_particle =
event->Particle(decay_particle_id);
101 if(!decay_particle)
return 0;
104 TLorentzVector decay_particle_p4 = *(decay_particle->
P4());
105 int decay_particle_pdg_code = decay_particle->
Pdg();
108 int kc =
fPythia->Pycomp(decay_particle_pdg_code);
109 int mdcy =
fPythia->GetMDCY(kc, 1);
113 <<
" decays are inhibited!";
121 <<
"The sum of enabled "
123 <<
" decay channel branching ratios is non-positive!";
130 double E = decay_particle_p4.Energy();
131 double theta = decay_particle_p4.Theta();
132 double phi = decay_particle_p4.Phi();
134 py1ent_(&ip, &decay_particle_pdg_code, &E, &theta, &phi);
138 TClonesArray * impl = (TClonesArray *)
fPythia->ImportParticles(
"All");
141 <<
"TPythia6::ImportParticles() returns a null list!";
151 bool in_nucleus = (target_nucleus!=0);
162 TIter particle_iter(impl);
163 while( (p = (TMCParticle *) particle_iter.Next()) ) {
176 p->GetVx() * space_scale ,
177 p->GetVy() * space_scale ,
178 p->GetVz() * space_scale ,
179 p->GetTime() * time_scale
184 int daughter_pdg_code = mcp.
Pdg();
186 <<
"Adding daughter particle wit PDG code = "
187 << daughter_pdg_code <<
", m = " << mcp.
Mass()
188 <<
" GeV, E = " << mcp.
Energy() <<
" GeV)";
196 TLorentzVector daughter_p4(
200 daughter_pdg_code, daughter_status_code,
201 decay_particle_id,-1,-1,-1,
202 daughter_p4, * mcp.
X4() );
206 double weight =
event->Weight() *
fWeight;
207 event->SetWeight(weight);
217 fPythia = TPythia6::Instance();
231 <<
"Can decay particle with PDG code = " << pdg_code
232 <<
"? " << ((is_handled)?
"Yes" :
"No");
241 int kc =
fPythia->Pycomp(pdg_code);
245 <<
"Switching OFF ALL decay channels for particle = " << pdg_code;
251 <<
"Switching OFF decay channel = " << dc->Number()
252 <<
" for particle = " << pdg_code;
256 fPythia->SetMDME(ichannel,1,0);
264 int kc =
fPythia->Pycomp(pdg_code);
268 <<
"Switching ON all PYTHIA decay channels for particle = " << pdg_code;
272 int first_channel =
fPythia->GetMDCY(kc,2);
273 int last_channel =
fPythia->GetMDCY(kc,2) +
fPythia->GetMDCY(kc,3) - 1;
275 for(
int ichannel = first_channel;
276 ichannel < last_channel; ichannel++) {
277 fPythia->SetMDME(ichannel,1,1);
283 <<
"Switching OFF decay channel = " << dc->Number()
284 <<
" for particle = " << pdg_code;
288 fPythia->SetMDME(ichannel,1,1);
298 int first_channel =
fPythia->GetMDCY(kc,2);
299 int last_channel =
fPythia->GetMDCY(kc,2) +
fPythia->GetMDCY(kc,3) - 1;
301 bool has_inhibited_channels=
false;
304 for(
int ichannel = first_channel;
305 ichannel < last_channel; ichannel++) {
307 bool enabled = (
fPythia->GetMDME(ichannel,1) == 1);
309 has_inhibited_channels =
true;
311 sumbr +=
fPythia->GetBRAT(ichannel);
315 if(!has_inhibited_channels)
return 1.;
316 LOG(
"Pythia6Decay",
pINFO) <<
"Sum{BR} = " << sumbr;
325 int first_channel =
fPythia->GetMDCY(kc,2);
326 int last_channel =
fPythia->GetMDCY(kc,2) +
fPythia->GetMDCY(kc,3) - 1;
328 bool found_match =
false;
331 for(
int ichannel = first_channel;
332 ichannel < last_channel; ichannel++) {
336 <<
"\nComparing PYTHIA's channel = " << ichannel
337 <<
" with TDecayChannel = " << dc->Number();
342 <<
" ** TDecayChannel id = " << dc->Number()
343 <<
" corresponds to PYTHIA6 channel id = " << ichannel;
349 <<
" ** No PYTHIA6 decay channel match found for "
350 <<
"TDecayChannel id = " << dc->Number();
358 int nd = dc->NDaughters();
361 for (
int i = 1; i <= 5; i++) {
362 if(
fPythia->GetKFDP(ichannel,i) != 0) py_nd++;
366 <<
"NDaughters: PYTHIA = " << py_nd <<
", ROOT's TDecayChannel = " << nd;
368 if(nd != py_nd)
return false;
375 vector<int> dc_daughter(nd);
377 for( ; k < nd; k++) {
378 dc_daughter[k] = dc->DaughterPdgCode(k);
381 vector<int> py_daughter(nd);
383 for(
int i = 1; i <= 5; i++) {
384 if(
fPythia->GetKFDP(ichannel,i) == 0)
continue;
385 py_daughter[k] =
fPythia->GetKFDP(ichannel,i);
390 sort( dc_daughter.begin(), dc_daughter.end() );
391 sort( py_daughter.begin(), py_daughter.end() );
394 for(
int i = 0; i < nd; i++) {
395 if(dc_daughter[i] != py_daughter[i])
return false;
virtual bool ToBeDecayed(int pdgc, GHepStatus_t ist) const
bool IsHandled(int pdgc) const
void UnInhibitDecay(int pdgc, TDecayChannel *ch=0) const
static RandomGen * Instance()
Access instance.
const TLorentzVector * P4(void) const
static constexpr double s
double Mass(void) const
Mass that corresponds to the PDG code.
double Pz(void) const
Get Pz.
GHepStatus_t Status(void) const
double Energy(void) const
Get energy.
double Px(void) const
Get Px.
string Name(void) const
Name that corresponds to the PDG code.
bool MatchDecayChannels(int ic, TDecayChannel *ch) const
#define LOG(stream, priority)
A macro that returns the requested log4cpp::Category appending a string (using the FILE...
void Initialize(void) const
bool fRunBefHadroTransp
is invoked before or after FSI?
bool Decay(int ip, GHepRecord *event) const
TPythia6 * fPythia
PYTHIA6 wrapper class.
double SumOfBranchingRatios(int kc) const
void py1ent_(int *, int *, double *, double *, double *)
static PDGLibrary * Instance(void)
const TLorentzVector * X4(void) const
void SetStatus(GHepStatus_t s)
Base class for decayer classes. Implements common configuration, allowing users to toggle on/off flag...
void InhibitDecay(int pdgc, TDecayChannel *ch=0) const
int FindPythiaDecayChannel(int kc, TDecayChannel *ch) const
static constexpr double mm
void ProcessEventRecord(GHepRecord *event) const
bool IsBaryonResonance(int pdgc)
is input a baryon resonance?
static constexpr double fm
#define SLOG(stream, priority)
A macro that returns the requested log4cpp::Category appending a short string (using the FUNCTION and...
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...
STDHEP-like event record entry that can fit a particle or a nucleus.
enum genie::EGHepStatus GHepStatus_t
double Py(void) const
Get Py.