GENIEGenerator
Loading...
Searching...
No Matches
AGCharmPythiaBaseHadro2023.cxx
Go to the documentation of this file.
1//____________________________________________________________________________
2/*
3 Copyright (c) 2003-2025, The GENIE Collaboration
4 For the full text of the license visit http://copyright.genie-mc.org
5
6 Costas Andreopoulos <c.andreopoulos \at cern.ch>
7 University of Liverpool
8
9 Changes required to implement the GENIE Boosted Dark Matter module
10 were installed by Josh Berger (Univ. of Wisconsin)
11*/
12//____________________________________________________________________________
13
14#include <RVersion.h>
15
16#include <TVector3.h>
17#include <TF1.h>
18#include <TROOT.h>
19
40
41using namespace genie;
42using namespace genie::constants;
43using namespace genie::controls;
44
45
46//____________________________________________________________________________
48EventRecordVisitorI("genie::AGCharmPythiaBaseHadro2023")
49{
50 this->Initialize();
51}
52//____________________________________________________________________________
54EventRecordVisitorI("genie::AGCharmPythiaBaseHadro2023", config)
55{
56 this->Initialize();
57}
58//____________________________________________________________________________
60EventRecordVisitorI(name, config)
61{
62 this->Initialize();
63}
64//____________________________________________________________________________
66{
67 delete fCharmPT2pdf;
68 fCharmPT2pdf = 0;
69
70 delete fD0FracSpl;
71 fD0FracSpl = 0;
72
73 delete fDpFracSpl;
74 fDpFracSpl = 0;
75
76 delete fDsFracSpl;
77 fDsFracSpl = 0;
78}
79//____________________________________________________________________________
81{
82
83}
84//____________________________________________________________________________
86{
87 Interaction * interaction = event->Summary();
88 TClonesArray * particle_list = this->Hadronize(interaction);
89
90 if(! particle_list ) {
91 LOG("AGCharm2023", pWARN) << "Got an empty particle list. Hadronizer failed!";
92 LOG("AGCharm2023", pWARN) << "Quitting the current event generation thread";
93
94 event->EventFlags()->SetBitNumber(kHadroSysGenErr, true);
95
97 exception.SetReason("Could not simulate the hadronic system");
98 exception.SwitchOnFastForward();
99 throw exception;
100
101 return;
102 }
103
104 int mom = event->FinalStateHadronicSystemPosition();
105 assert(mom!=-1);
106
107 // find the proper status for the particles we are going to put in event record
108 bool is_nucleus = interaction->InitState().Tgt().IsNucleus();
109 GHepStatus_t istfin = (is_nucleus) ?
111
112 // retrieve the hadronic blob lorentz boost
113 // Because Hadronize() returned particles not in the LAB reference frame
114 const TLorentzVector * had_syst = event -> Particle(mom) -> P4() ;
115 TVector3 beta( 0., 0., had_syst -> P()/ had_syst -> Energy() ) ;
116
117 // Vector defining rotation from LAB to LAB' (z:= \vec{phad})
118 TVector3 unitvq = had_syst -> Vect().Unit();
119
120 GHepParticle * neutrino = event->Probe();
121 const TLorentzVector & vtx = *(neutrino->X4());
122
123 GHepParticle * particle = 0;
124 TIter particle_iter(particle_list);
125 while ((particle = (GHepParticle *) particle_iter.Next())) {
126
127 int pdgc = particle -> Pdg() ;
128
129 // bring the particle in the LAB reference frame
130 particle -> P4() -> Boost( beta ) ;
131 particle -> P4() -> RotateUz( unitvq ) ;
132
133 // set the proper status according to a number of things:
134 // interaction on a nucleaus or nucleon, particle type
135 GHepStatus_t ist = ( particle -> Status() ==1 ) ? istfin : kIStDISPreFragmHadronicState;
136
137 // handle gammas, and leptons that might come from internal pythia decays
138 // mark them as final state particles
139 bool not_hadron = ( pdgc == kPdgGamma ||
140 pdg::IsNeutralLepton(pdgc) ||
141 pdg::IsChargedLepton(pdgc) ) ;
142
143 if(not_hadron) { ist = kIStStableFinalState; }
144 particle -> SetStatus( ist ) ;
145
146 int im = mom + 1 + particle -> FirstMother() ;
147 int ifc = ( particle -> FirstDaughter() == -1) ? -1 : mom + 1 + particle -> FirstDaughter();
148 int ilc = ( particle -> LastDaughter() == -1) ? -1 : mom + 1 + particle -> LastDaughter();
149
150 particle -> SetFirstMother( im ) ;
151 if ( ifc > -1 ) {
152 particle -> SetFirstDaughter( ifc ) ;
153 particle -> SetLastDaughter( ilc ) ;
154 }
155
156 // the Pythia particle position is overridden
157 particle -> SetPosition( vtx ) ;
158
159 event->AddParticle(*particle);
160 }
161
162 particle_list -> Delete() ;
163 delete particle_list ;
164
165 // update the weight of the event
166 event -> SetWeight ( Weight() * event->Weight() );
167
168}
169//____________________________________________________________________________
171 const Interaction * interaction) const
172{
173 LOG("CharmHad", pNOTICE) << "** Running CHARM hadronizer";
174
175 PDGLibrary * pdglib = PDGLibrary::Instance();
177
178 // ....................................................................
179 // Get information on the input event
180 //
181 const InitialState & init_state = interaction -> InitState();
182 const Kinematics & kinematics = interaction -> Kine();
183 const Target & target = init_state.Tgt();
184
185 const TLorentzVector & p4Had = kinematics.HadSystP4();
186
187 double Ev = init_state.ProbeE(kRfLab);
188 double W = kinematics.W(true);
189
190 TVector3 beta = -1 * p4Had.BoostVector(); // boost vector for LAB' -> HCM'
191 TLorentzVector p4H(0,0,0,W); // hadronic system 4p @ HCM'
192
193 double Eh = p4Had.Energy();
194
195 LOG("CharmHad", pNOTICE) << "Ehad (LAB) = " << Eh << ", W = " << W;
196
197 int nu_pdg = init_state.ProbePdg();
198 int nuc_pdg = target.HitNucPdg();
199//int qpdg = target.HitQrkPdg();
200//bool sea = target.HitSeaQrk();
201 bool isp = pdg::IsProton (nuc_pdg);
202 bool isn = pdg::IsNeutron(nuc_pdg);
203 bool isnu = pdg::IsNeutrino(nu_pdg);
204 bool isnub = pdg::IsAntiNeutrino(nu_pdg);
205 bool isdm = pdg::IsDarkMatter(nu_pdg);
206
207 // ....................................................................
208 // Attempt to generate a charmed hadron & its 4-momentum
209 //
210
211 TLorentzVector p4C(0,0,0,0);
212 int ch_pdg = -1;
213
214 bool got_charmed_hadron = false;
215 unsigned int itry=0;
216
217 while(itry++ < kRjMaxIterations && !got_charmed_hadron) {
218
219 // Generate a charmed hadron PDG code
220 int pdg = this->GenerateCharmHadron(nu_pdg,Ev); // generate hadron
221 double mc = pdglib->Find(pdg)->Mass(); // lookup mass
222
223 LOG("CharmHad", pNOTICE)
224 << "Trying charm hadron = " << pdg << "(m = " << mc << ")";
225
226 if(mc>=W) continue; // dont' accept
227
228 // Generate the charmed hadron energy based on the input
229 // fragmentation function
230 double z = fFragmFunc->GenerateZ(); // generate z(=Eh/Ev)
231 double Ec = z*Eh; // @ LAB'
232 double mc2 = TMath::Power(mc,2);
233 double Ec2 = TMath::Power(Ec,2);
234 double pc2 = Ec2-mc2;
235
236 LOG("CharmHad", pINFO)
237 << "Trying charm hadron z = " << z << ", E = " << Ec;
238
239 if(pc2<=0) continue;
240
241 // Generate the charm hadron pT^2 and pL^2 (with respect to the
242 // hadronic system direction @ the LAB)
243 double ptc2 = fCharmPT2pdf->GetRandom();
244 double plc2 = Ec2 - ptc2 - mc2;
245 LOG("CharmHad", pINFO)
246 << "Trying charm hadron pT^2 (tranv to pHad) = " << ptc2;
247 if(plc2<0) continue;
248
249 // Generate the charm hadron momentum components (@ LAB', z:\vec{pHad})
250 double ptc = TMath::Sqrt(ptc2);
251 double plc = TMath::Sqrt(plc2);
252 double phi = (2*kPi) * rnd->RndHadro().Rndm();
253 double pxc = ptc * TMath::Cos(phi);
254 double pyc = ptc * TMath::Sin(phi);
255 double pzc = plc;
256
257 p4C.SetPxPyPzE(pxc,pyc,pzc,Ec); // @ LAB'
258
259 // Boost charm hadron 4-momentum from the LAB' to the HCM' frame
260 //
261 LOG("CharmHad", pDEBUG)
262 << "Charm hadron p4 (@LAB') = " << utils::print::P4AsString(&p4C);
263
264 p4C.Boost(beta);
265
266 LOG("CharmHad", pDEBUG)
267 << "Charm hadron p4 (@HCM') = " << utils::print::P4AsString(&p4C);
268
269 // Hadronic non-charm remnant 4p at HCM'
270 TLorentzVector p4 = p4H - p4C;
271 double wr = p4.M();
272 LOG("CharmHad", pINFO)
273 << "Invariant mass of remnant hadronic system= " << wr;
274 if(wr < kNucleonMass + kPionMass + kASmallNum) {
275 LOG("CharmHad", pINFO) << "Too small hadronic remnant mass!";
276 continue;
277 }
278
279 ch_pdg = pdg;
280 got_charmed_hadron = true;
281
282 LOG("CharmHad", pNOTICE)
283 << "Generated charm hadron = " << pdg << "(m = " << mc << ")";
284 LOG("CharmHad", pNOTICE)
285 << "Generated charm hadron z = " << z << ", E = " << Ec;
286 }
287
288 // ....................................................................
289 // Check whether the code above had difficulty generating the charmed
290 // hadron near the W - threshold.
291 // If yes, attempt a phase space decay of a low mass charm hadron + nucleon
292 // pair that maintains the charge.
293 // That's a desperate solution but don't want to quit too early as that
294 // would distort the generated dsigma/dW distribution near threshold.
295 //
296 bool used_lowW_strategy = false;
297 int fs_nucleon_pdg = -1;
298 if(ch_pdg==-1 && W < 3.){
299 LOG("CharmHad", pNOTICE)
300 << "Had difficulty generating charm hadronic system near W threshold";
301 LOG("CharmHad", pNOTICE)
302 << "Trying an alternative strategy";
303
304 double qfsl = interaction->FSPrimLepton()->Charge() / 3.;
305 double qinit = pdglib->Find(nuc_pdg)->Charge() / 3.;
306 int qhad = (int) (qinit - qfsl);
307
308 int remn_pdg = -1;
309 int chrm_pdg = -1;
310
311 //cc-only: qhad(nu) = +1,+2, qhad(nubar)= -1,0
312 //
313 if(qhad == 2) {
314 chrm_pdg = kPdgDP; remn_pdg = kPdgProton;
315 } else if(qhad == 1) {
316 if(rnd->RndHadro().Rndm() > 0.5) {
317 chrm_pdg = kPdgD0; remn_pdg = kPdgProton;
318 } else {
319 chrm_pdg = kPdgDP; remn_pdg = kPdgNeutron;
320 }
321 } else if(qhad == 0) {
322 chrm_pdg = kPdgAntiD0; remn_pdg = kPdgNeutron;
323 } else if(qhad == -1) {
324 chrm_pdg = kPdgDM; remn_pdg = kPdgNeutron;
325 }
326
327 double mc = pdglib->Find(chrm_pdg)->Mass();
328 double mn = pdglib->Find(remn_pdg)->Mass();
329
330 if(mc+mn < W) {
331 // Set decay
332 double mass[2] = {mc, mn};
333 bool permitted = fPhaseSpaceGenerator.SetDecay(p4H, 2, mass);
334 assert(permitted);
335
336 // Get the maximum weight
337 double wmax = -1;
338 for(int i=0; i<200; i++) {
339 double w = fPhaseSpaceGenerator.Generate();
340 wmax = TMath::Max(wmax,w);
341 }
342
343 if(wmax>0) {
344 wmax *= 2;
345
346 // Generate unweighted decay
347 bool accept_decay=false;
348 unsigned int idecay_try=0;
349 while(!accept_decay)
350 {
351 idecay_try++;
352
353 if(idecay_try>kMaxUnweightDecayIterations) {
354 LOG("CharmHad", pWARN)
355 << "Couldn't generate an unweighted phase space decay after "
356 << idecay_try << " attempts";
357 }
358 double w = fPhaseSpaceGenerator.Generate();
359 if(w > wmax) {
360 LOG("CharmHad", pWARN)
361 << "Decay weight = " << w << " > max decay weight = " << wmax;
362 }
363 double gw = wmax * rnd->RndHadro().Rndm();
364 accept_decay = (gw<=w);
365
366 if(accept_decay) {
367 used_lowW_strategy = true;
368 TLorentzVector * p4 = fPhaseSpaceGenerator.GetDecay(0);
369 p4C = *p4;
370 ch_pdg = chrm_pdg;
371 fs_nucleon_pdg = remn_pdg;
372 }
373 } // decay loop
374 }//wmax>0
375
376 }// allowed decay
377 } // alt low-W strategy
378
379 // ....................................................................
380 // Check success in generating the charm hadron & compute 4p for
381 // remnant system
382 //
383 if(ch_pdg==-1){
384 LOG("CharmHad", pWARN)
385 << "Couldn't generate charm hadron for: " << *interaction;
386 return 0;
387 }
388
389 TLorentzVector p4R = p4H - p4C;
390 double WR = p4R.M();
391 //double MC = pdglib->Find(ch_pdg)->Mass();
392
393 LOG("CharmHad", pNOTICE) << "Remnant hadronic system mass = " << WR;
394
395 // ....................................................................
396 // Handle case where the user doesn't want to remnant system to be
397 // hadronized (add as 'hadronic blob')
398 //
399 if(fCharmOnly) {
400 // Create particle list (fragmentation record)
401 TClonesArray * particle_list = new TClonesArray("genie::GHepParticle", 2);
402 particle_list->SetOwner(true);
403
404 // insert the generated particles
405 new ((*particle_list)[0]) GHepParticle (ch_pdg,kIStStableFinalState,
406 -1,-1,-1,-1, p4C.Px(),p4C.Py(),p4C.Pz(),p4C.E(), 0,0,0,0);
407 new ((*particle_list)[1]) GHepParticle (kPdgHadronicBlob,kIStStableFinalState,
408 -1,-1,-1,-1, p4R.Px(),p4R.Py(),p4R.Pz(),p4R.E(), 0,0,0,0);
409
410 return particle_list;
411 }
412
413 // ....................................................................
414 // Handle case where the remnant system is already known and doesn't
415 // have to be hadronized. That happens when (close to the W threshold)
416 // the hadronic system was generated by a simple 2-body decay
417 //
418 if(used_lowW_strategy) {
419 // Create particle list (fragmentation record)
420 TClonesArray * particle_list = new TClonesArray("genie::GHepParticle", 3);
421 particle_list->SetOwner(true);
422
423 // insert the generated particles
424 new ((*particle_list)[0]) GHepParticle (ch_pdg,kIStStableFinalState,
425 -1,-1,-1,-1, p4C.Px(),p4C.Py(),p4C.Pz(),p4C.E(), 0,0,0,0);
426 new ((*particle_list)[1]) GHepParticle (kPdgHadronicBlob,kIStNucleonTarget,
427 -1,-1,2,2, p4R.Px(),p4R.Py(),p4R.Pz(),p4R.E(), 0,0,0,0);
428 new ((*particle_list)[2]) GHepParticle (fs_nucleon_pdg,kIStStableFinalState,
429 1,1,-1,-1, p4R.Px(),p4R.Py(),p4R.Pz(),p4R.E(), 0,0,0,0);
430
431 return particle_list;
432 }
433
434 // ....................................................................
435 // --------------------------------------------------------------------
436 // Hadronize non-charm hadronic blob using PYTHIA/JETSET
437 // --------------------------------------------------------------------
438 // ....................................................................
439
440 // Create output event record
441 // Insert the generated charm hadron & the hadronic (non-charm) blob.
442 // In this case the hadronic blob is entered as a pre-fragm. state.
443
444 TClonesArray * particle_list = new TClonesArray("genie::GHepParticle");
445 particle_list->SetOwner(true);
446
447 new ((*particle_list)[0]) GHepParticle (ch_pdg,kIStStableFinalState,
448 -1,-1,-1,-1, p4C.Px(),p4C.Py(),p4C.Pz(),p4C.E(), 0,0,0,0);
449 new ((*particle_list)[1]) GHepParticle (kPdgHadronicBlob,kIStNucleonTarget,
450 -1,-1,2,3, p4R.Px(),p4R.Py(),p4R.Pz(),p4R.E(), 0,0,0,0);
451
452 unsigned int rpos = 2; // offset in event record
453
454 bool use_pythia = (WR>1.5);
455
456/*
457 // Determining quark systems to input to PYTHIA based on simple quark model
458 // arguments
459 //
460 // Neutrinos
461 // ------------------------------------------------------------------
462 // Scattering off valence q
463 // ..................................................................
464 // p: [uu]+d
465 // |--> c --> D0 <c+\bar(u)> : [u]
466 // --> D+ <c+\bar(d)> : [d]
467 // --> Ds+ <c+\bar(s)> : [s]
468 // --> Lamda_c+ <c+ud > : [\bar(ud)]
469 //
470 // (for n: [uu] -> 50%[ud]_{0} + 50%[ud]_{1})
471 //
472 // Scattering off sea q
473 // ..................................................................
474 // p: [uud] + [\bar(d)]d (or)
475 // [\bar(s)]s
476 // |--> c --> D0 <c+\bar(u)> : [u]
477 // --> D+ <c+\bar(d)> : [d]
478 // --> Ds+ <c+\bar(s)> : [s]
479 // --> Lamda_c+ <c+ud > : [\bar(ud)]
480 // Anti-Neutrinos
481 // ------------------------------------------------------------------
482 // Scattering off sea q
483 // ..................................................................
484 // p: [uud] + [d] \bar(d) (or)
485 // [s] \bar(s)
486 // |----> \bar(c) --> \bar(D0) <\bar(c)+u> : [\bar(u)]
487 // --> D- <\bar(c)+d> : [\bar(d)]
488 // --> Ds- <\bar(c)+s> : [\bar(s)]
489 // [Summary]
490 // Qq
491 // | v + p [val/d] --> D0 + { u uu }(+2) / u,uu
492 // | v + p [val/d] --> D+ + { d uu }(+1) / d,uu
493 // | v + p [val/d] --> Ds+ + { s uu }(+1) / s,uu
494 // | v + p [val/d] --> Lc+ + { \bar(ud) uu }(+1) / \bar(d),u
495 // | v + n [val/d] --> D0 + { u ud }(+1) / u,ud
496 // | v + n [val/d] --> D+ + { d ud }( 0) / d,ud
497 // | v + n [val/d] --> Ds+ + { s ud }( 0) / s,ud
498 // | v + n [val/d] --> Lc+ + { \bar(ud) ud }( 0) / \bar(d),d
499 // | v + p [sea/d] --> D0 + { uud \bar(d) u }(+2) / u,uu
500 // | v + p [sea/d] --> D+ + { uud \bar(d) d }(+1) / d,uu
501 // | v + p [sea/d] --> Ds+ + { uud \bar(d) s }(+1) / s,uu
502 // | v + p [sea/d] --> Lc+ + { uud \bar(d) \bar(ud) }(+1) / \bar(d),u
503 // | v + n [sea/d] --> D0 + { udd \bar(d) u }(+1) / u,ud
504 // | v + n [sea/d] --> D+ + { udd \bar(d) d }( 0) / d,ud
505 // | v + n [sea/d] --> Ds+ + { udd \bar(d) s }( 0) / s,ud
506 // | v + n [sea/d] --> Lc+ + { udd \bar(d) \bar(ud) }( 0) / \bar(d),d
507 // | v + p [sea/s] --> D0 + { uud \bar(s) u }(+2) / u,uu
508 // | v + p [sea/s] --> D+ + { uud \bar(s) d }(+1) / d,uu
509 // | v + p [sea/s] --> Ds+ + { uud \bar(s) s }(+1) / s,uu
510 // | v + p [sea/s] --> Lc+ + { uud \bar(s) \bar(ud) }(+1) / \bar(d),u
511 // | v + n [sea/s] --> D0 + { udd \bar(s) u }(+1) / u,ud
512 // | v + n [sea/s] --> D+ + { udd \bar(s) d }( 0) / d,ud
513 // | v + n [sea/s] --> Ds+ + { udd \bar(s) s }( 0) / s,ud
514 // | v + n [sea/s] --> Lc+ + { udd \bar(s) \bar(ud) }( 0) / \bar(d),d
515
516 // | \bar(v) + p [sea/\bar(d)] --> \bar(D0) + { uud d \bar(u) }( 0) / d,ud
517 // | \bar(v) + p [sea/\bar(d)] --> D- + { uud d \bar(d) }(+1) / d,uu
518 // | \bar(v) + p [sea/\bar(d)] --> Ds- + { uud d \bar(s) }(+1) / d,uu
519 // | \bar(v) + n [sea/\bar(d)] --> \bar(D0) + { udd d \bar(u) }(-1) / d,dd
520 // | \bar(v) + n [sea/\bar(d)] --> D- + { udd d \bar(d) }( 0) / d,ud
521 // | \bar(v) + n [sea/\bar(d)] --> Ds- + { udd d \bar(s) }( 0) / d,ud
522 // | \bar(v) + p [sea/\bar(s)] --> \bar(D0) + { uud s \bar(u) }( 0) / d,ud
523 // | \bar(v) + p [sea/\bar(s)] --> D- + { uud s \bar(d) }(+1) / d,uu
524 // | \bar(v) + p [sea/\bar(s)] --> Ds- + { uud s \bar(s) }(+1) / d,uu
525 // | \bar(v) + n [sea/\bar(s)] --> \bar(D0) + { udd s \bar(u) }(-1) / d,dd
526 // | \bar(v) + n [sea/\bar(s)] --> D- + { udd s \bar(d) }( 0) / d,ud
527 // | \bar(v) + n [sea/\bar(s)] --> Ds- + { udd s \bar(s) }( 0) / d,ud
528 //
529 //
530 // Taking some short-cuts below :
531 // In the process of obtaining 2 q systems (while conserving the charge) I might tread
532 // d,s or \bar(d),\bar(s) as the same
533 // In the future I should perform the first steps of the multi-q hadronization manualy
534 // (to reduce the number of q's input to PYTHIA) or use py3ent_(), py4ent_() ...
535 //
536*/
537
538 if(use_pythia) {
539 int qrkSyst1 = 0;
540 int qrkSyst2 = 0;
541 if(isnu||isdm) { // neutrinos
542 if(ch_pdg==kPdgLambdaPc) {
543 if(isp) { qrkSyst1 = kPdgAntiDQuark; qrkSyst2 = kPdgUQuark; }
544 if(isn) { qrkSyst1 = kPdgAntiDQuark; qrkSyst2 = kPdgDQuark; }
545 } else {
546 if(isp) { qrkSyst2 = kPdgUUDiquarkS1; }
547 if(isn) { qrkSyst2 = (rnd->RndHadro().Rndm()<0.5) ? kPdgUDDiquarkS0 : kPdgUDDiquarkS1; }
548 if (ch_pdg==kPdgD0 ) { qrkSyst1 = kPdgUQuark; }
549 if (ch_pdg==kPdgDP ) { qrkSyst1 = kPdgDQuark; }
550 if (ch_pdg==kPdgDPs ) { qrkSyst1 = kPdgSQuark; }
551 }
552 }
553 if(isnub) { // antineutrinos
554 qrkSyst1 = kPdgDQuark;
555 if (isp && ch_pdg==kPdgAntiD0) { qrkSyst2 = (rnd->RndHadro().Rndm()<0.5) ? kPdgUDDiquarkS0 : kPdgUDDiquarkS1; }
556 if (isp && ch_pdg==kPdgDM ) { qrkSyst2 = kPdgUUDiquarkS1; }
557 if (isp && ch_pdg==kPdgDMs ) { qrkSyst2 = kPdgUUDiquarkS1; }
558 if (isn && ch_pdg==kPdgAntiD0) { qrkSyst2 = kPdgDDDiquarkS1; }
559 if (isn && ch_pdg==kPdgDM ) { qrkSyst2 = (rnd->RndHadro().Rndm()<0.5) ? kPdgUDDiquarkS0 : kPdgUDDiquarkS1; }
560 if (isn && ch_pdg==kPdgDMs ) { qrkSyst2 = (rnd->RndHadro().Rndm()<0.5) ? kPdgUDDiquarkS0 : kPdgUDDiquarkS1; }
561 }
562 if(qrkSyst1 == 0 && qrkSyst2 == 0) {
563 LOG("CharmHad", pWARN)
564 << "Couldn't generate quark systems for PYTHIA in: " << *interaction;
565 return 0;
566 }
567
568 bool remnant_hadronized = this->HadronizeRemnant(qrkSyst1,qrkSyst2,WR,p4R,rpos,particle_list);
569
570 if(!remnant_hadronized) {
571 LOG("CharmHad", pWARN) << "Couldn't hadronize (non-charm) remnants!";
572 return 0;
573 }
574
575 } // use_pythia
576
577 // ....................................................................
578 // Hadronizing low-W non-charm hadronic blob using a phase space decay
579 // ....................................................................
580
581 else {
582 // Just a small fraction of events (low-W remnant syste) causing trouble
583 // to PYTHIA/JETSET
584 // Set a 2-body N+pi system that matches the remnant system charge and
585 // do a simple phase space decay
586 //
587 // q(remn) remn/syst
588 // +2 : (p pi+)
589 // +1 : 50%(p pi0) + 50% n pi+
590 // 0 : 50%(p pi-) + 50% n pi0
591 // -1 : (n pi-)
592 //
593 double qfsl = interaction->FSPrimLepton()->Charge() / 3.;
594 double qinit = pdglib->Find(nuc_pdg)->Charge() / 3.;
595 double qch = pdglib->Find(ch_pdg)->Charge() / 3.;
596 int Q = (int) (qinit - qfsl - qch); // remnant hadronic system charge
597
598 bool allowdup=true;
599 PDGCodeList pd(allowdup);
600 if(Q==2) {
602 else if (Q==1) {
603 if(rnd->RndHadro().Rndm()<0.5) {
605 else {
607 }
608 else if (Q==0) {
609 if(rnd->RndHadro().Rndm()<0.5) {
611 else {
613 }
614 else if (Q==-1) {
616
617 double mass[2] = {
618 pdglib->Find(pd[0])->Mass(), pdglib->Find(pd[1])->Mass()
619 };
620
621 // Set the decay
622 bool permitted = fPhaseSpaceGenerator.SetDecay(p4R, 2, mass);
623 if(!permitted) {
624 LOG("CharmHad", pERROR) << " *** Phase space decay is not permitted";
625 return 0;
626 }
627 // Get the maximum weight
628 double wmax = -1;
629 for(int i=0; i<200; i++) {
630 double w = fPhaseSpaceGenerator.Generate();
631 wmax = TMath::Max(wmax,w);
632 }
633 if(wmax<=0) {
634 LOG("CharmHad", pERROR) << " *** Non-positive maximum weight";
635 LOG("CharmHad", pERROR) << " *** Can not generate an unweighted phase space decay";
636 return 0;
637 }
638
639 LOG("CharmHad", pINFO)
640 << "Max phase space gen. weight @ current hadronic system: " << wmax;
641
642 // *** generating an un-weighted decay ***
643 wmax *= 1.3;
644 bool accept_decay=false;
645 unsigned int idectry=0;
646 while(!accept_decay)
647 {
648 idectry++;
649 if(idectry>kMaxUnweightDecayIterations) {
650 // report, clean-up and return
651 LOG("Char,Had", pWARN)
652 << "Couldn't generate an unweighted phase space decay after "
653 << itry << " attempts";
654 return 0;
655 }
656 double w = fPhaseSpaceGenerator.Generate();
657 if(w > wmax) {
658 LOG("CharmHad", pWARN)
659 << "Decay weight = " << w << " > max decay weight = " << wmax;
660 }
661 double gw = wmax * rnd->RndHadro().Rndm();
662 accept_decay = (gw<=w);
663 LOG("CharmHad", pDEBUG)
664 << "Decay weight = " << w << " / R = " << gw << " - accepted: " << accept_decay;
665 }
666 for(unsigned int i=0; i<2; i++) {
667 int pdgc = pd[i];
668 TLorentzVector * p4d = fPhaseSpaceGenerator.GetDecay(i);
669 new ( (*particle_list)[rpos+i] ) GHepParticle(
670 pdgc,kIStStableFinalState,1,1,-1,-1,p4d->Px(),p4d->Py(),p4d->Pz(),p4d->Energy(),
671 0,0,0,0);
672 }
673 }
674
675 //-- Print & return the fragmentation record
676 //utils::fragmrec::Print(particle_list);
677 return particle_list;
678}
679//____________________________________________________________________________
680int AGCharmPythiaBaseHadro2023::GenerateCharmHadron(int nu_pdg, double EvLab) const
681{
682 // generate a charmed hadron pdg code using a charm fraction table
683
685 double r = rnd->RndHadro().Rndm();
686
687 // the ratios are giving up to a certain value.
688 // The rations saturates at high energies, so the values used above that enery
689 // are the evaluated at
690
691 if(pdg::IsNeutrino(nu_pdg)) {
692
693 // the ratios are giving up to a certain value.
694 // The rations saturates at high energies, so the values used above that enery
695 // are the evaluated at the maximum energies avaiable for the ratios
696
697 EvLab = TMath::Min( EvLab, fFracMaxEnergy ) ;
698
699 double tf = 0;
700 if (r < (tf+=fD0FracSpl->Evaluate(EvLab))) return kPdgD0; // D^0
701 else if (r < (tf+=fDpFracSpl->Evaluate(EvLab))) return kPdgDP; // D^+
702 else if (r < (tf+=fDsFracSpl->Evaluate(EvLab))) return kPdgDPs; // Ds^+
703 else return kPdgLambdaPc; // Lamda_c^+
704
705 } else if(pdg::IsAntiNeutrino(nu_pdg)) {
706 if (r < fD0BarFrac) return kPdgAntiD0;
707 else if (r < fD0BarFrac+fDmFrac) return kPdgDM;
708 else return kPdgDMs;
709 }
710
711 LOG("CharmHad", pERROR) << "Could not generate a charm hadron!";
712 return 0;
713}
714//____________________________________________________________________________
716{
717 return 1. ;
718}
719
720//____________________________________________________________________________
722{
723 Algorithm::Configure(config);
724 this->LoadConfig();
725}
726//____________________________________________________________________________
728{
729 Algorithm::Configure(config);
730 this->LoadConfig();
731}
732//____________________________________________________________________________
734{
735
736 bool hadronize_remnants ;
737 GetParamDef( "HadronizeRemnants", hadronize_remnants, true ) ;
738
739 fCharmOnly = ! hadronize_remnants ;
740
741 //-- Get a fragmentation function
742 fFragmFunc = dynamic_cast<const FragmentationFunctionI *> (
743 this->SubAlg("FragmentationFunc"));
744 assert(fFragmFunc);
745
746 string pt_function ;
747 this -> GetParam( "PTFunction", pt_function ) ;
748
749 fCharmPT2pdf = new TF1("fCharmPT2pdf", pt_function.c_str(),0,0.6);
750
751 // stop ROOT from deleting this object of its own volition
752 gROOT->GetListOfFunctions()->Remove(fCharmPT2pdf);
753
754 // neutrino charm fractions: D^0, D^+, Ds^+ (remainder: Lamda_c^+)
755 std::vector<double> ec, d0frac, dpfrac, dsfrac ;
756
757 std::string raw ;
758 std::vector<std::string> bits ;
759
760 bool invalid_configuration = false ;
761
762 // load energy points
763 this -> GetParamVect( "CharmFrac-E", ec ) ;
765
766 // load D0 fractions
767 this -> GetParamVect( "CharmFrac-D0", d0frac ) ;
768
769 // check the size
770 if ( d0frac.size() != ec.size() ) {
771 LOG("AGCharm2023", pFATAL) << "E entries don't match D0 fraction entries";
772 LOG("AGCharm2023", pFATAL) << "E: " << ec.size() ;
773 LOG("AGCharm2023", pFATAL) << "D0: " << d0frac.size() ;
774 invalid_configuration = true ;
775 }
776
777 // load D+ fractions
778 this -> GetParamVect( "CharmFrac-D+", dpfrac ) ;
779
780 // check the size
781 if ( dpfrac.size() != ec.size() ) {
782 LOG("AGCharm2023", pFATAL) << "E entries don't match D+ fraction entries";
783 LOG("AGCharm2023", pFATAL) << "E: " << ec.size() ;
784 LOG("AGCharm2023", pFATAL) << "D+: " << dpfrac.size() ;
785 invalid_configuration = true ;
786 }
787
788 // load D_s fractions
789 this -> GetParamVect( "CharmFrac-Ds", dsfrac ) ;
790
791 // check the size
792 if ( dsfrac.size() != ec.size() ) {
793 LOG("AGCharm2023", pFATAL) << "E entries don't match Ds fraction entries";
794 LOG("AGCharm2023", pFATAL) << "E: " << ec.size() ;
795 LOG("AGCharm2023", pFATAL) << "Ds: " << dsfrac.size() ;
796 invalid_configuration = true ;
797 }
798
799 fD0FracSpl = new Spline( ec.size(), & ec[0], & d0frac[0] );
800 fDpFracSpl = new Spline( ec.size(), & ec[0], & dpfrac[0] );
801 fDsFracSpl = new Spline( ec.size(), & ec[0], & dsfrac[0] );
802
803 // anti-neutrino charm fractions: bar(D^0), D^-, (remainder: Ds^-)
804
805 this -> GetParam( "CharmFrac-D0bar", fD0BarFrac ) ;
806 this -> GetParam( "CharmFrac-D-", fDmFrac ) ;
807
808 if ( invalid_configuration ) {
809
810 LOG("AGCharm2023", pFATAL)
811 << "Invalid configuration: Exiting" ;
812
813 // From the FreeBSD Library Functions Manual
814 //
815 // EX_CONFIG (78) Something was found in an unconfigured or miscon-
816 // figured state.
817
818 exit( 78 ) ;
819 }
820}
821//____________________________________________________________________________
#define pNOTICE
Definition Messenger.h:61
#define pINFO
Definition Messenger.h:62
#define pERROR
Definition Messenger.h:59
#define pFATAL
Definition Messenger.h:56
#define pDEBUG
Definition Messenger.h:63
#define LOG(stream, priority)
A macro that returns the requested log4cpp::Category appending a string (using the FILE,...
Definition Messenger.h:96
#define pWARN
Definition Messenger.h:60
Most commonly used PDG codes. A set of utility functions to handle PDG codes is provided in PDGUtils.
double fD0BarFrac
nubar \bar{D0} charm fraction
virtual bool HadronizeRemnant(int qrkSyst1, int qrkSyst2, double WR, TLorentzVector p4R, unsigned int &rpos, TClonesArray *particle_list) const =0
bool fCharmOnly
don't hadronize non-charm blob
Spline * fD0FracSpl
nu charm fraction vs Ev: D0
TGenPhaseSpace fPhaseSpaceGenerator
a phase space generator
TClonesArray * Hadronize(const Interaction *) const
Spline * fDsFracSpl
nu charm fraction vs Ev: Ds+
Spline * fDpFracSpl
nu charm fraction vs Ev: D+
void ProcessEventRecord(GHepRecord *event) const
int GenerateCharmHadron(int nupdg, double EvLab) const
double fFracMaxEnergy
Maximum energy available for the Meson fractions.
const FragmentationFunctionI * fFragmFunc
charm hadron fragmentation func
bool GetParam(const RgKey &name, T &p, bool is_top_call=true) const
int GetParamVect(const std::string &comm_name, std::vector< T > &v, bool is_top_call=true) const
Handle to load vectors of parameters.
virtual void Configure(const Registry &config)
Definition Algorithm.cxx:62
bool GetParamDef(const RgKey &name, T &p, const T &def) const
const Algorithm * SubAlg(const RgKey &registry_key) const
Pure abstract base class. Defines the FragmentationFunctionI interface to be implemented by any algor...
STDHEP-like event record entry that can fit a particle or a nucleus.
const TLorentzVector * X4(void) const
GENIE's GHEP MC event record.
Definition GHepRecord.h:45
virtual double Weight(void) const
Definition GHepRecord.h:124
Initial State information.
const Target & Tgt(void) const
int ProbePdg(void) const
double ProbeE(RefFrame_t rf) const
Summary information for an interaction.
Definition Interaction.h:56
TParticlePDG * FSPrimLepton(void) const
final state primary lepton
const InitialState & InitState(void) const
Definition Interaction.h:69
Generated/set kinematical variables for an event.
Definition Kinematics.h:39
const TLorentzVector & HadSystP4(void) const
Definition Kinematics.h:66
double W(bool selected=false) const
A list of PDG codes.
Definition PDGCodeList.h:32
void push_back(int pdg_code)
Singleton class to load & serve a TDatabasePDG.
Definition PDGLibrary.h:36
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...
Definition RandomGen.h:29
TRandom3 & RndHadro(void) const
rnd number generator used by hadronization models
Definition RandomGen.h:53
static RandomGen * Instance()
Access instance.
Definition RandomGen.cxx:74
A registry. Provides the container for algorithm configuration parameters.
Definition Registry.h:65
A numeric analysis tool class for interpolating 1-D functions.
Definition Spline.h:58
A Neutrino Interaction Target. Is a transparent encapsulation of quite different physical systems suc...
Definition Target.h:40
int HitNucPdg(void) const
Definition Target.cxx:304
bool IsNucleus(void) const
Definition Target.cxx:272
An exception thrown by EventRecordVisitorI when the normal processing sequence has to be disrupted (f...
Basic constants.
Misc GENIE control constants.
static const unsigned int kMaxUnweightDecayIterations
Definition Controls.h:61
static const unsigned int kRjMaxIterations
Definition Controls.h:26
static const double kASmallNum
Definition Controls.h:40
Utilities for improving the code readability when using PDG codes.
bool IsNeutrino(int pdgc)
Definition PDGUtils.cxx:110
bool IsProton(int pdgc)
Definition PDGUtils.cxx:336
bool IsChargedLepton(int pdgc)
Definition PDGUtils.cxx:101
bool IsNeutralLepton(int pdgc)
Definition PDGUtils.cxx:95
bool IsNeutron(int pdgc)
Definition PDGUtils.cxx:341
bool IsDarkMatter(int pdgc)
Definition PDGUtils.cxx:127
bool IsAntiNeutrino(int pdgc)
Definition PDGUtils.cxx:118
string P4AsString(const TLorentzVector *p)
THE MAIN GENIE PROJECT NAMESPACE
Definition AlgCmp.h:25
const int kPdgUQuark
Definition PDGCodes.h:42
const int kPdgPiM
Definition PDGCodes.h:159
const int kPdgDQuark
Definition PDGCodes.h:44
@ kIStHadronInTheNucleus
Definition GHepStatus.h:37
@ kIStDISPreFragmHadronicState
Definition GHepStatus.h:35
@ kIStStableFinalState
Definition GHepStatus.h:30
@ kIStNucleonTarget
Definition GHepStatus.h:34
const int kPdgAntiD0
Definition PDGCodes.h:184
const int kPdgDM
Definition PDGCodes.h:182
const int kPdgDP
Definition PDGCodes.h:181
const int kPdgUDDiquarkS0
Definition PDGCodes.h:56
const int kPdgAntiDQuark
Definition PDGCodes.h:45
const int kPdgUUDiquarkS1
Definition PDGCodes.h:58
const int kPdgProton
Definition PDGCodes.h:81
const int kPdgPi0
Definition PDGCodes.h:160
const int kPdgDPs
Definition PDGCodes.h:185
const int kPdgNeutron
Definition PDGCodes.h:83
enum genie::EGHepStatus GHepStatus_t
const int kPdgDMs
Definition PDGCodes.h:186
const int kPdgLambdaPc
Definition PDGCodes.h:99
const int kPdgUDDiquarkS1
Definition PDGCodes.h:57
const int kPdgSQuark
Definition PDGCodes.h:46
const int kPdgHadronicBlob
Definition PDGCodes.h:211
@ kRfLab
Definition RefFrame.h:26
const int kPdgPiP
Definition PDGCodes.h:158
const int kPdgD0
Definition PDGCodes.h:183
const int kPdgDDDiquarkS1
Definition PDGCodes.h:55
const int kPdgGamma
Definition PDGCodes.h:189
@ kHadroSysGenErr
Definition GHepFlags.h:32