HNIntranuke.cxx
Go to the documentation of this file.
1 
2 //____________________________________________________________________________
3 /*
4  Copyright (c) 2003-2017, GENIE Neutrino MC Generator Collaboration
5  For the full text of the license visit http://copyright.genie-mc.org
6  or see $GENIE/LICENSE
7 
8  Author: Steve Dytman <dytman+@pitt.edu>, Pittsburgh Univ.
9  Aaron Meyer <asm58@pitt.edu>, Pittsburgh Univ.
10  Alex Bell, Pittsburgh Univ.
11  Hugh Gallagher <gallag@minos.phy.tufts.edu>, Tufts Univ.
12  Costas Andreopoulos <costas.andreopoulos \at stfc.ac.uk>, Rutherford Lab.
13  September 20, 2005
14 
15  For the class documentation see the corresponding header file.
16 
17  Important revisions after version 2.0.0 :
18  @ Nov 30, 2007 - SD
19  Changed the hadron tracking algorithm to take into account the radial
20  nuclear density dependence. Using the somewhat empirical approach of
21  increasing the nuclear radius by a const (tunable) number times the tracked
22  particle's de Broglie wavelength as this helps getting the hadron+nucleus
23  cross sections right.
24  @ Mar 08, 2008 - CA
25  Fixed code retrieving the remnant nucleus which stopped working as soon as
26  simulation of nuclear de-excitation started pushing photons in the target
27  nucleus daughter list.
28  @ Jun 20, 2008 - CA
29  Fix a mem leak: The (clone of the) GHepParticle being re-scattered was not
30  deleted after it was added at the GHEP event record.
31  @ Jul 15, 2010 - AM
32  The hN mode is now implemented in Intranuke. Similar to hA mode, but particles
33  produced by reactions are stepped through the nucleus like probe particles.
34  Particles react with nucleons instead of the entire nucleus, and final states
35  are determined after reactions are finished, not before.
36 */
37 //____________________________________________________________________________
38 
39 #include <cstdlib>
40 #include <sstream>
41 
42 #include <TMath.h>
43 
45 #include "Algorithm/AlgFactory.h"
46 #include "Conventions/GBuild.h"
47 #include "Conventions/Constants.h"
48 #include "Conventions/Controls.h"
50 #include "GHEP/GHepFlags.h"
51 #include "GHEP/GHepStatus.h"
52 #include "GHEP/GHepRecord.h"
53 #include "GHEP/GHepParticle.h"
60 #include "Messenger/Messenger.h"
61 #include "Numerical/RandomGen.h"
62 #include "Numerical/Spline.h"
63 #include "PDG/PDGLibrary.h"
64 #include "PDG/PDGCodes.h"
65 #include "PDG/PDGCodeList.h"
66 #include "PDG/PDGUtils.h"
67 #include "Utils/PrintUtils.h"
68 #include "Utils/NuclearUtils.h"
69 
70 using std::ostringstream;
71 
72 using namespace genie;
73 using namespace genie::utils;
74 using namespace genie::utils::intranuke;
75 using namespace genie::constants;
76 using namespace genie::controls;
77 
78 //___________________________________________________________________________
79 //___________________________________________________________________________
80 // Methods specific to INTRANUKE's HN-mode
81 //___________________________________________________________________________
82 //___________________________________________________________________________
84 Intranuke("genie::HNIntranuke")
85 {
86 
87 }
88 //___________________________________________________________________________
90 Intranuke("genie::HNIntranuke",config)
91 {
92 
93 }
94 //___________________________________________________________________________
96 {
97 
98 }
99 //___________________________________________________________________________
101 {
102  LOG("HNIntranuke", pNOTICE)
103  << "************ Running HN MODE INTRANUKE ************";
104 
105  LOG("HNIntranuke", pWARN)
107  "Experimental code (INTRANUKE/hN model) - Run at your own risk");
108 
110 
111  LOG("HNIntranuke", pINFO) << "Done with this event";
112 }
113 //___________________________________________________________________________
115 {
116 // Simulate a hadron interaction for the input particle p in HN mode
117 //
118  if(!p || !ev)
119  {
120  LOG("HNIntranuke", pERROR) << "** Null input!";
121  return;
122  }
123 
124  // check particle id
125  int pdgc = p->Pdg();
126  bool is_pion = (pdgc==kPdgPiP || pdgc==kPdgPiM || pdgc==kPdgPi0);
127  // bool is_kaon = (pdgc==kPdgKP); // UNUSED - comment to quiet compiler warnings
128  bool is_baryon = (pdgc==kPdgProton || pdgc==kPdgNeutron);
129  bool is_gamma = (pdgc==kPdgGamma);
130  if(!(is_pion || is_baryon || is_gamma))
131  {
132  LOG("HNIntranuke", pERROR) << "** Cannot handle particle: " << p->Name();
133  return;
134  }
135  try
136  {
137  // select a fate for the input particle
138  INukeFateHN_t fate = this->HadronFateHN(p);
139 
140  // store the fate
141  ev->Particle(p->FirstMother())->SetRescatterCode((int)fate);
142 
143  if(fate == kIHNFtUndefined)
144  {
145  LOG("HNIntranuke", pERROR) << "** Couldn't select a fate";
146  LOG("HNIntranuke", pERROR) << "** Num Protons: " << fRemnZ
147  << ", Num Neutrons: "<<(fRemnA-fRemnZ);
148  LOG("HNIntranuke", pERROR) << "** Particle: " << "\n" << (*p);
149  //LOG("HNIntranuke", pERROR) << "** Event Record: " << "\n" << (*ev);
150  //p->SetStatus(kIStUndefined);
151  p->SetStatus(kIStStableFinalState);
152  ev->AddParticle(*p);
153  return;
154  }
155 
156  LOG("HNIntranuke", pNOTICE)
157  << "Selected " << p->Name() << " fate: " << INukeHadroFates::AsString(fate);
158 
159  // handle the reaction
160  if(fate == kIHNFtCEx || fate == kIHNFtElas)
161  {
162  this->ElasHN(ev,p,fate);
163  }
164  else if(fate == kIHNFtAbs) {this-> AbsorbHN(ev,p,fate);}
165  else if(fate == kIHNFtInelas && pdgc != kPdgGamma)
166  {
167 #ifdef __GENIE_LOW_LEVEL_MESG_ENABLED__
168  LOG("HNIntranuke", pDEBUG)
169  << "Invoking InelasticHN() for a : " << p->Name()
170  << " whose fate is : " << INukeHadroFates::AsString(fate);
171 #endif
172 
173  this-> InelasticHN(ev,p);
174  }
175  else if(fate == kIHNFtInelas && pdgc == kPdgGamma) {this-> GammaInelasticHN(ev,p,fate);}
176  else if(fate == kIHNFtNoInteraction)
177  {
179  ev->AddParticle(*p);
180  return;
181  }
182  }
184  {
185  this->SimulateHadronicFinalState(ev,p);
186  LOG("HNIntranuke", pNOTICE)
187  << "retry call to SimulateHadronicFinalState ";
188  LOG("HNIntranuke", pNOTICE) << exception;
189 
190  }
191 }
192 //___________________________________________________________________________
194 {
195 // Select a hadron fate in HN mode
196 //
197  RandomGen * rnd = RandomGen::Instance();
198 
199  // get pdgc code & kinetic energy in MeV
200  int pdgc = p->Pdg();
201  double ke = p->KinE() / units::MeV;
202 
203  LOG("HNIntranuke", pINFO)
204  << "Selecting hN fate for " << p->Name() << " with KE = " << ke << " MeV";
205 
206  // try to generate a hadron fate
207  unsigned int iter = 0;
208  while(iter++ < kRjMaxIterations) {
209 
210  // handle pions
211  //
212  if (pdgc==kPdgPiP || pdgc==kPdgPiM || pdgc==kPdgPi0) {
213 
214  double frac_cex = this->FateWeight(pdgc, kIHNFtCEx)
215  * fHadroData->Frac(pdgc, kIHNFtCEx, ke, fRemnA, fRemnZ);
216  double frac_elas = this->FateWeight(pdgc, kIHNFtElas)
217  * fHadroData->Frac(pdgc, kIHNFtElas, ke, fRemnA, fRemnZ);
218  double frac_inel = this->FateWeight(pdgc, kIHNFtInelas)
219  * fHadroData->Frac(pdgc, kIHNFtInelas, ke, fRemnA, fRemnZ);
220  double frac_abs = this->FateWeight(pdgc, kIHNFtAbs)
221  * fHadroData->Frac(pdgc, kIHNFtAbs, ke, fRemnA, fRemnZ);
222  frac_cex *= fNucCEXFac; // scaling factors
223  frac_abs *= fNucAbsFac;
224  frac_elas *= fNucQEFac;
225  if(pdgc==kPdgPi0) frac_abs*= 0.665; //isospin factor
226 
227  LOG("HNIntranuke", pINFO)
228  << "\n frac{" << INukeHadroFates::AsString(kIHNFtCEx) << "} = " << frac_cex
229  << "\n frac{" << INukeHadroFates::AsString(kIHNFtElas) << "} = " << frac_elas
230  << "\n frac{" << INukeHadroFates::AsString(kIHNFtInelas) << "} = " << frac_inel
231  << "\n frac{" << INukeHadroFates::AsString(kIHNFtAbs) << "} = " << frac_abs;
232 
233  // compute total fraction (can be <1 if fates have been switched off)
234  double tf = frac_cex +
235  frac_elas +
236  frac_inel +
237  frac_abs;
238 
239  double r = tf * rnd->RndFsi().Rndm();
240 #ifdef __GENIE_LOW_LEVEL_MESG_ENABLED__
241  LOG("HNIntranuke", pDEBUG) << "r = " << r << " (max = " << tf << ")";
242 #endif
243 
244  double cf=0; // current fraction
245 
246  if(r < (cf += frac_cex )) return kIHNFtCEx; //cex
247  if(r < (cf += frac_elas )) return kIHNFtElas; //elas
248  if(r < (cf += frac_inel )) return kIHNFtInelas; //inelas
249  if(r < (cf += frac_abs )) return kIHNFtAbs; //abs
250 
251  LOG("HNIntranuke", pWARN)
252  << "No selection after going through all fates! "
253  << "Total fraction = " << tf << " (r = " << r << ")";
254  ////////////////////////////
255  return kIHNFtUndefined;
256  }
257 
258  // handle nucleons
259  else if (pdgc==kPdgProton || pdgc==kPdgNeutron) {
260 
261  double frac_elas = this->FateWeight(pdgc, kIHNFtElas)
262  * fHadroData->Frac(pdgc, kIHNFtElas, ke, fRemnA, fRemnZ);
263  double frac_inel = this->FateWeight(pdgc, kIHNFtInelas)
264  * fHadroData->Frac(pdgc, kIHNFtInelas, ke, fRemnA, fRemnZ);
265 
266  LOG("HNIntranuke", pINFO)
267  << "\n frac{" << INukeHadroFates::AsString(kIHNFtElas) << "} = " << frac_elas
268  << "\n frac{" << INukeHadroFates::AsString(kIHNFtInelas) << "} = " << frac_inel;
269 
270  // compute total fraction (can be <1 if fates have been switched off)
271  double tf = frac_elas +
272  frac_inel;
273 
274  double r = tf * rnd->RndFsi().Rndm();
275 
276 #ifdef __GENIE_LOW_LEVEL_MESG_ENABLED__
277  LOG("HNIntranuke", pDEBUG) << "r = " << r << " (max = " << tf << ")";
278 #endif
279 
280  double cf=0; // current fraction
281  if(r < (cf += frac_elas )) return kIHNFtElas; // elas
282  if(r < (cf += frac_inel )) return kIHNFtInelas; // inelas
283 
284  LOG("HNIntranuke", pWARN)
285  << "No selection after going through all fates! "
286  << "Total fraction = " << tf << " (r = " << r << ")";
287  //////////////////////////
288  return kIHNFtUndefined;
289  }
290 
291  // handle gamma -- does not currently consider the elastic case
292  else if (pdgc==kPdgGamma) return kIHNFtInelas;
293 
294  // handle kaon -- currently only elastic case
295  else if (pdgc==kPdgKP) return kIHNFtElas;
296 
297  }//iterations
298 
299  return kIHNFtUndefined;
300 }
301 //___________________________________________________________________________
302 double HNIntranuke::FateWeight(int pdgc, INukeFateHN_t fate) const
303 {
304  // turn fates off if the remnant nucleus does not have the number of p,n
305  // required
306 
307  int np = fRemnZ;
308  int nn = fRemnA - fRemnZ;
309 
310  if (np < 1 && nn < 1)
311  {
312  LOG("HNIntranuke", pERROR) << "** Nothing left in nucleus!!! **";
313  return 0;
314  }
315  else
316  {
317  if (fate == kIHNFtCEx && pdgc==kPdgPiP ) { return (nn>=1) ? 1. : 0.; }
318  if (fate == kIHNFtCEx && pdgc==kPdgPiM ) { return (np>=1) ? 1. : 0.; }
319  if (fate == kIHNFtAbs) { return ((nn>=1) && (np>=1)) ? 1. : 0.; }
320  }
321 
322  return 1.;
323 }
324 //___________________________________________________________________________
326  GHepRecord * ev, GHepParticle * p, INukeFateHN_t fate) const
327 {
328  // handles pi+d->2p, pi-d->nn, pi0 d->pn absorbtion, all using pi+d values
329 
330  int pdgc = p->Pdg();
331 
332 #ifdef __GENIE_LOW_LEVEL_MESG_ENABLED__
333  LOG("HNIntranuke", pDEBUG)
334  << "AbsorbHN() is invoked for a : " << p->Name()
335  << " whose fate is : " << INukeHadroFates::AsString(fate);
336 #endif
337 
338  // check fate
339  if(fate!=kIHNFtAbs)
340  {
341  LOG("HNIntranuke", pWARN)
342  << "AbsorbHN() cannot handle fate: " << INukeHadroFates::AsString(fate);
343  return;
344  }
345 
346  // random number generator
347  RandomGen * rnd = RandomGen::Instance();
348 
349  // Notes on the kinematics
350  // -- Simple variables are used for efficiency
351  // -- Variables are numbered according to particle
352  // -- -- #1 -> incoming particle
353  // -- -- #2 -> target (here, 2_1 and 2_2 for individual particles)
354  // -- -- #3 -> scattered incoming (Particle tracked in hA mode)
355  // -- -- #4 -> other scattered particle
356  // -- Suffix "L" is for lab frame, suffix "CM" is for center of mass frame
357  // -- Subscript "z" is for parallel component, "t" is for transverse
358 
359  int pcode, t1code, t2code, scode, s2code; // particles
360  double M1, M2_1, M2_2, M3, M4; // rest energies, in GeV
361  double E1L, P1L, E2L, P2L, E3L, P3L, E4L, P4L;
362  double P1zL, P2zL;
363  double beta, gm; // speed and gamma for CM frame in lab
364  double Et, E2CM;
365  double C3CM, S3CM; // cos and sin of scattering angle
366  double Theta1, Theta2, theta5;
367  double PHI3; // transverse scattering angle
368  double E1CM, E3CM, E4CM, P3CM;
369  double P3zL, P3tL, P4zL, P4tL;
370  double E2_1L, E2_2L;
371  TVector3 tP2_1L, tP2_2L, tP1L, tP2L, tPtot, P1zCM, P2zCM;
372  TVector3 tP3L, tP4L;
373  TVector3 bDir, tTrans, tbeta, tVect;
374 
375  // Library instance for reference
376  PDGLibrary * pLib = PDGLibrary::Instance();
377 
378  // Handle fermi target
379  Target target(ev->TargetNucleus()->Pdg());
380 
381  // Target should be a deuteron, but for now
382  // handling it as seperate nucleons
383  if(pdgc==211) // pi-plus
384  {
385  pcode = 211;
386  t1code = 2212; // proton
387  t2code = 2112; // neutron
388  scode = 2212;
389  s2code = 2212;
390  }
391  else if(pdgc==-211) // pi-minus
392  {
393  pcode = -211;
394  t1code = 2212;
395  t2code = 2112;
396  scode = 2112;
397  s2code = 2112;
398  }
399  else if(pdgc==111) // pi-zero
400  {
401  pcode = 111;
402  t1code = 2212;
403  t2code = 2112;
404  scode = 2212;
405  s2code = 2112;
406  }
407  else
408  {
409  LOG("HNIntranuke", pWARN)
410  << "AbsorbHN() cannot handle probe: " << pdgc;
411  return;
412  }
413 
414  // assign proper masses
415  M1 = pLib->Find(pcode) ->Mass();
416  M2_1 = pLib->Find(t1code)->Mass();
417  M2_2 = pLib->Find(t2code)->Mass();
418  M3 = pLib->Find(scode) ->Mass();
419  M4 = pLib->Find(s2code)->Mass();
420 
421  // handle fermi momentum
422  if(fDoFermi)
423  {
424  target.SetHitNucPdg(t1code);
426  tP2_1L=fFermiFac * fNuclmodel->Momentum3();
427  E2_1L = TMath::Sqrt(tP2_1L.Mag2() + M2_1*M2_1);
428 
429  target.SetHitNucPdg(t2code);
431  tP2_2L=fFermiFac * fNuclmodel->Momentum3();
432  E2_2L = TMath::Sqrt(tP2_2L.Mag2() + M2_2*M2_2);
433  }
434  else
435  {
436  tP2_1L.SetXYZ(0.0, 0.0, 0.0);
437  E2_1L = M2_1;
438 
439  tP2_2L.SetXYZ(0.0, 0.0, 0.0);
440  E2_2L = M2_2;
441  }
442 
443  E2L = E2_1L + E2_2L;
444 
445  // adjust p to reflect scattering
446  // get random scattering angle
447  C3CM = fHadroData->IntBounce(p,t1code,scode,fate);
448  if (C3CM<-1.)
449  {
451  ev->AddParticle(*p);
452  return;
453  }
454  S3CM = TMath::Sqrt(1.0 - C3CM*C3CM);
455 
456  // Get lab energy and momenta
457  E1L = p->E();
458  if(E1L<0.001) E1L=0.001;
459  P1L = TMath::Sqrt(E1L*E1L - M1*M1);
460  tP1L = p->P4()->Vect();
461  tP2L = tP2_1L + tP2_2L;
462  P2L = tP2L.Mag();
463  tPtot = tP1L + tP2L;
464 
465  // get unit vectors and angles needed for later
466  bDir = tPtot.Unit();
467  Theta1 = tP1L.Angle(bDir);
468  Theta2 = tP2L.Angle(bDir);
469 
470  // get parallel and transverse components
471  P1zL = P1L*TMath::Cos(Theta1);
472  P2zL = P2L*TMath::Cos(Theta2);
473  tVect.SetXYZ(1,0,0);
474  if(TMath::Abs((tVect - bDir).Mag())<.01) tVect.SetXYZ(0,1,0);
475  theta5 = tVect.Angle(bDir);
476  tTrans = (tVect - TMath::Cos(theta5)*bDir).Unit();
477 
478  // calculate beta and gamma
479  tbeta = tPtot * (1.0 / (E1L + E2L));
480  beta = tbeta.Mag();
481  gm = 1.0 / TMath::Sqrt(1.0 - beta*beta);
482 
483  // boost to CM frame to get scattered particle momenta
484  E1CM = gm*E1L - gm*beta*P1zL;
485  P1zCM = gm*P1zL*bDir - gm*tbeta*E1L;
486  E2CM = gm*E2L - gm*beta*P2zL;
487  P2zCM = gm*P2zL*bDir - gm*tbeta*E2L;
488  Et = E1CM + E2CM;
489  E3CM = (Et*Et + (M3*M3) - (M4*M4)) / (2.0*Et);
490  E4CM = Et - E3CM;
491  P3CM = TMath::Sqrt(E3CM*E3CM - M3*M3);
492 
493  // boost back to lab
494  P3zL = gm*beta*E3CM + gm*P3CM*C3CM;
495  P3tL = P3CM*S3CM;
496  P4zL = gm*beta*E4CM + gm*P3CM*(-C3CM);
497  P4tL = P3CM*(-S3CM);
498 
499  P3L = TMath::Sqrt(P3zL*P3zL + P3tL*P3tL);
500  P4L = TMath::Sqrt(P4zL*P4zL + P4tL*P4tL);
501 
502  // check for too small values
503  // may introduce error, so warn if it occurs
504  if(!(TMath::Finite(P3L))||P3L<.001)
505  {
506  LOG("HNIntranuke",pINFO)
507  << "Particle 3 " << M3 << " momentum small or non-finite: " << P3L
508  << "\n" << "--> Assigning .001 as new momentum";
509  P3tL = 0;
510  P3zL = .001;
511  P3L = .001;
512  E3L = TMath::Sqrt(P3L*P3L + M3*M3);
513  }
514 
515  if(!(TMath::Finite(P4L))||P4L<.001)
516  {
517  LOG("HNIntranuke",pINFO)
518  << "Particle 4 " << M4 << " momentum small or non-finite: " << P4L
519  << "\n" << "--> Assigning .001 as new momentum";
520  P4tL = 0;
521  P4zL = .001;
522  P4L = .001;
523  E4L = TMath::Sqrt(P4L*P4L + M4*M4);
524  }
525 
526  // pauli blocking
527  if(P3L < fFermiMomentum || P4L < fFermiMomentum)
528  {
529 #ifdef __GENIE_LOW_LEVEL_MESG_ENABLED__
530  LOG("HNIntranuke",pINFO) << "AbsorbHN failed: Pauli blocking";
531 #endif
534  ev->AddParticle(*p);
535  return;
536  }
537 
538  // handle remnant nucleus updates
539  fRemnZ--;
540  fRemnA -=2;
541  fRemnP4 -= TLorentzVector(tP2_1L,E2_1L);
542  fRemnP4 -= TLorentzVector(tP2_2L,E2_2L);
543 
544  // get random phi angle, distributed uniformally in 360 deg
545  PHI3 = 2 * kPi * rnd->RndFsi().Rndm();
546 
547  tP3L = P3zL*bDir + P3tL*tTrans;
548  tP4L = P4zL*bDir + P4tL*tTrans;
549 
550  tP3L.Rotate(PHI3,bDir); // randomize transverse components
551  tP4L.Rotate(PHI3,bDir);
552 
553  E3L = TMath::Sqrt(P3L*P3L + M3*M3);
554  E4L = TMath::Sqrt(P4L*P4L + M4*M4);
555 
556  // create t particle w/ appropriate momenta, code, and status
557  // set target's mom to be the mom of the hadron that was cloned
558  GHepParticle * t = new GHepParticle(*p);
559  t->SetFirstMother(p->FirstMother());
560  t->SetLastMother(p->LastMother());
561 
562  TLorentzVector t4P4L(tP4L,E4L);
563  t->SetPdgCode(s2code);
564  t->SetMomentum(t4P4L);
566 
567  // adjust p to reflect scattering
568  TLorentzVector t4P3L(tP3L,E3L);
569  p->SetPdgCode(scode);
570  p->SetMomentum(t4P3L);
572 
573 #ifdef __GENIE_LOW_LEVEL_MESG_ENABLED__
574  LOG("HNIntranuke", pDEBUG)
575  << "|p3| = " << (P3L) << ", E3 = " << (E3L);
576  LOG("HNIntranuke", pDEBUG)
577  << "|p4| = " << (P4L) << ", E4 = " << (E4L);
578 #endif
579 
580  ev->AddParticle(*p);
581  ev->AddParticle(*t);
582 
583  delete t; // delete particle clone
584 }
585 //___________________________________________________________________________
587  GHepRecord * ev, GHepParticle * p, INukeFateHN_t fate) const
588 {
589  // scatters particle within nucleus
590 
591 #ifdef __GENIE_LOW_LEVEL_MESG_ENABLED__
592  LOG("HNIntranuke", pDEBUG)
593  << "ElasHN() is invoked for a : " << p->Name()
594  << " whose fate is : " << INukeHadroFates::AsString(fate);
595 #endif
596 
597  if(fate!=kIHNFtCEx && fate!=kIHNFtElas)
598  {
599  LOG("HNIntranuke", pWARN)
600  << "ElasHN() cannot handle fate: " << INukeHadroFates::AsString(fate);
601  return;
602  }
603 
604  // Random number generator
605  RandomGen * rnd = RandomGen::Instance();
606 
607  // vars for incoming particle, target, and scattered pdg codes
608  int pcode = p->Pdg();
609  int tcode, scode, s2code;
610  double ppcnt = (double) fRemnZ / (double) fRemnA; // % of protons
611 
612  // Select a target randomly, weighted to #
613  // -- Unless, of course, the fate is CEx,
614  // -- in which case the target may be deterministic
615  // Also assign scattered particle code
616  if(fate==kIHNFtCEx)
617  {
618  if(pcode==kPdgPiP) {tcode = kPdgNeutron; scode = kPdgPi0; s2code = kPdgProton;}
619  else if(pcode==kPdgPiM) {tcode = kPdgProton; scode = kPdgPi0; s2code = kPdgNeutron;}
620  else
621  {
622  // for pi0
623  tcode = (rnd->RndFsi().Rndm()<=ppcnt)?(kPdgProton) :(kPdgNeutron);
624  scode = (tcode == kPdgProton) ?(kPdgPiP) :(kPdgPiM);
625  s2code = (tcode == kPdgProton) ?(kPdgNeutron):(kPdgProton);
626  }
627  }
628  else
629  {
630  tcode = (rnd->RndFsi().Rndm()<=ppcnt)?(kPdgProton):(kPdgNeutron);
631  scode = pcode;
632  s2code = tcode;
633  }
634 
635  // get random scattering angle
636  double C3CM = fHadroData->IntBounce(p,tcode,scode,fate);
637  if (C3CM<-1.)
638  {
640  ev->AddParticle(*p);
641  return;
642  }
643 
644  // create scattered particle
645  GHepParticle * t = new GHepParticle(*p);
646  t->SetPdgCode(tcode);
647  double Mt = t->Mass();
648  //t->SetMomentum(TLorentzVector(0,0,0,Mt));
649 
650  // handle fermi momentum
651  if(fDoFermi)
652  {
653  // Handle fermi target
654  Target target(ev->TargetNucleus()->Pdg());
655 
656  target.SetHitNucPdg(tcode);
658  TVector3 tP3L = fFermiFac * fNuclmodel->Momentum3();
659  double tE = TMath::Sqrt(tP3L.Mag2() + Mt*Mt);
660  t->SetMomentum(TLorentzVector(tP3L,tE));
661  }
662  else
663  {
664  t->SetMomentum(TLorentzVector(0,0,0,Mt));
665  }
666 
667  bool pass = utils::intranuke::TwoBodyCollision(ev,pcode,tcode,scode,s2code,C3CM,
669 
670 #ifdef __GENIE_LOW_LEVEL_MESG_ENABLED__
671  LOG("HNIntranuke",pDEBUG)
672  << "|p3| = " << P3L << ", E3 = " << E3L;
673  LOG("HNIntranuke",pDEBUG)
674  << "|p4| = " << P4L << ", E4 = " << E4L;
675 #endif
676 
677  if (pass==true)
678  {
679  // give each of the particles a free step
682  ev->AddParticle(*p);
683  ev->AddParticle(*t);
684  } else
685  {
686 
687  delete t; //fixes memory leak
688 
689  LOG("HNIntranuke", pINFO) << "Elastic in hN failed calling TwoBodyCollision";
691  exception.SetReason("hN scattering kinematics through TwoBodyCollision failed");
692  throw exception;
693  }
694 
695  delete t;
696 
697 }
698 //___________________________________________________________________________
700 {
701  // Aaron Meyer (Jan 2010)
702  // Updated version of InelasticHN
703 
704  GHepParticle * s1 = new GHepParticle(*p);
705  GHepParticle * s2 = new GHepParticle(*p);
706  GHepParticle * s3 = new GHepParticle(*p);
707 
709  {
710  // set status of particles and return
711 
715 
716  ev->AddParticle(*s1);
717  ev->AddParticle(*s2);
718  ev->AddParticle(*s3);
719  }
720  else
721  {
722 
723  delete s1; //prevent potential memory leak
724  delete s2;
725  delete s3;
726 
727  LOG("HNIntranuke", pNOTICE) << "Error: could not create pion production final state";
729  exception.SetReason("PionProduction in hN failed");
730  throw exception;
731  }
732 
733  delete s1;
734  delete s2;
735  delete s3;
736  return;
737 
738 }
739 //___________________________________________________________________________
741 {
742  // This function handles pion photoproduction reactions
743 
744 #ifdef __GENIE_LOW_LEVEL_MESG_ENABLED__
745  LOG("HNIntranuke", pDEBUG)
746  << "GammaInelasticHN() is invoked for a : " << p->Name()
747  << " whose fate is : " << INukeHadroFates::AsString(fate);
748 #endif
749 
750  if(fate!=kIHNFtInelas && p->Pdg()!=kPdgGamma)
751  {
752  LOG("HNIntranuke", pWARN)
753  << "GammaInelasticHN() cannot handle fate: " << INukeHadroFates::AsString(fate);
754  return;
755  }
756 
757  // random number generator
758  RandomGen * rnd = RandomGen::Instance();
759 
760  // vars for incoming particle, target, and scattered reaction products
761  double ppcnt = (double) fRemnZ / (double) fRemnA; // % of protons
762  int pcode = p->Pdg();
763  int tcode = (rnd->RndFsi().Rndm()<=ppcnt)?(kPdgProton):(kPdgNeutron);
764  int scode, s2code;
765  double ke = p->KinE() / units::MeV;
766 
767  LOG("HNIntranuke", pNOTICE)
768  << "Particle code: " << pcode << ", target: " << tcode;
769 
770 
771  if (rnd->RndFsi().Rndm() * (fHadroData -> XSecGamp_fs() -> Evaluate(ke) +
772  fHadroData -> XSecGamn_fs() -> Evaluate(ke) )
773  <= fHadroData -> XSecGamp_fs() -> Evaluate(ke) ) { scode = kPdgProton; }
774  else { scode = kPdgNeutron; }
775 
776  //scode=fHadroData->AngleAndProduct(p,tcode,C3CM,fate);
777  //double C3CM = 0.0; // cos of scattering angle
778  double C3CM = fHadroData->IntBounce(p,tcode,scode,fate);
779 
780  if ((tcode == kPdgProton ) && (scode==kPdgProton )) {s2code=kPdgPi0;}
781  else if ((tcode == kPdgProton ) && (scode==kPdgNeutron)) {s2code=kPdgPiP;}
782  else if ((tcode == kPdgNeutron) && (scode==kPdgProton )) {s2code=kPdgPiM;}
783  else if ((tcode == kPdgNeutron) && (scode==kPdgNeutron)) {s2code=kPdgPi0;}
784  else {
785  LOG("HNIntranuke", pERROR)
786  << "Error: could not determine particle final states";
787  ev->AddParticle(*p);
788  return;
789  }
790 
791  LOG("HNIntranuke", pNOTICE)
792  << "GammaInelastic fate: " << INukeHadroFates::AsString(fate);
793  LOG("HNIntranuke", pNOTICE)
794  << " final state: " << scode << " and " << s2code;
795  LOG("HNIntranuke", pNOTICE)
796  << " scattering angle: " << C3CM;
797 
798  GHepParticle * t = new GHepParticle(*p);
799  t->SetPdgCode(tcode);
800  double Mt = t->Mass();
801 
802  // handle fermi momentum
803  if(fDoFermi)
804  {
805  // Handle fermi target
806  Target target(ev->TargetNucleus()->Pdg());
807 
808  target.SetHitNucPdg(tcode);
810  TVector3 tP3L = fFermiFac * fNuclmodel->Momentum3();
811  double tE = TMath::Sqrt(tP3L.Mag2() + Mt*Mt);
812  t->SetMomentum(TLorentzVector(tP3L,tE));
813  }
814  else
815  {
816  t->SetMomentum(TLorentzVector(0,0,0,Mt));
817  }
818 
819  bool pass = utils::intranuke::TwoBodyCollision(ev,pcode,tcode,scode,s2code,C3CM,
821 
822 #ifdef __GENIE_LOW_LEVEL_MESG_ENABLED__
823  LOG("HNIntranuke",pDEBUG)
824  << "|p3| = " << P3L << ", E3 = " << E3L;
825  LOG("HNIntranuke",pDEBUG)
826  << "|p4| = " << P4L << ", E4 = " << E4L;
827 #endif
828 
829  if (pass==true)
830  {
831  //p->SetStatus(kIStStableFinalState);
832  //t->SetStatus(kIStStableFinalState);
833  ev->AddParticle(*p);
834  ev->AddParticle(*t);
835  } else
836  {
837  ev->AddParticle(*p);
838  }
839 
840  delete t;
841 
842 }
843 //___________________________________________________________________________
845 {
846 
847  // handle compound nucleus option
848  // -- Call the PreEquilibrium function
850  { // random number generator
851  RandomGen * rnd = RandomGen::Instance();
852 
853  double rpreeq = rnd->RndFsi().Rndm(); // sdytman test
854 
855  if((p->KinE() < fEPreEq) )
856  {
857  if(fRemnA>5&&rpreeq<0.12)
858  {
859  GHepParticle * sp = new GHepParticle(*p);
860  sp->SetFirstMother(mom);
863  delete sp;
864  return true;
865  }
866  else
867  {
868  // nothing left to interact with!
869  LOG("HNIntranuke", pNOTICE)
870  << "*** Nothing left to interact with, escaping.";
871  GHepParticle * sp = new GHepParticle(*p);
872  sp->SetFirstMother(mom);
874  ev->AddParticle(*sp);
875  delete sp;
876  return true;
877  }
878  }
879  }
880  return false;
881 }
882 //___________________________________________________________________________
884 {
886  const Registry * gc = confp->GlobalParameterList();
887 
888  // load hadronic cross sections
890 
891  // fermi momentum setup
893  fNuclmodel = dynamic_cast<const NuclearModelI *>
894  (fAlgf->GetAlgorithm("genie::FGMBodekRitchie","Default"));
895 
896  // other intranuke config params
897  fR0 = fConfig->GetDoubleDef ("R0", gc->GetDouble("NUCL-R0")); // fm
898  fNR = fConfig->GetDoubleDef ("NR", gc->GetDouble("NUCL-NR"));
899  fNucRmvE = fConfig->GetDoubleDef ("NucRmvE", gc->GetDouble("INUKE-NucRemovalE")); // GeV
900  fDelRPion = fConfig->GetDoubleDef ("DelRPion", gc->GetDouble("HNINUKE-DelRPion"));
901  fDelRNucleon = fConfig->GetDoubleDef ("DelRNucleon", gc->GetDouble("HNINUKE-DelRNucleon"));
902  fHadStep = fConfig->GetDoubleDef ("HadStep", gc->GetDouble("INUKE-HadStep")); // fm
903  fNucAbsFac = fConfig->GetDoubleDef ("NucAbsFac", gc->GetDouble("INUKE-NucAbsFac"));
904  fNucQEFac = fConfig->GetDoubleDef ("NucQEFac", gc->GetDouble("INUKE-NucQEFac"));
905  fNucCEXFac = fConfig->GetDoubleDef ("NucCEXFac", gc->GetDouble("INUKE-NucCEXFac"));
906  fEPreEq = fConfig->GetDoubleDef ("EPreEq", gc->GetDouble("INUKE-Energy_Pre_Eq"));
907  fFermiFac = fConfig->GetDoubleDef ("FermiFac", gc->GetDouble("INUKE-FermiFac"));
908  fFermiMomentum = fConfig->GetDoubleDef ("FermiMomentum",gc->GetDouble("INUKE-FermiMomentum"));
909  fDoFermi = fConfig->GetBoolDef ("DoFermi", gc->GetBool("INUKE-DoFermi"));
910  fFreeStep = fConfig->GetDoubleDef ("FreeStep", gc->GetDouble("INUKE-FreeStep"));
911  fDoCompoundNucleus = fConfig->GetBoolDef ("DoCompoundNucleus", gc->GetBool("INUKE-DoCompoundNucleus"));
912 
913 
914  // report
915  LOG("HNIntranuke", pINFO) << "Settings for INTRANUKE mode: " << INukeMode::AsString(kIMdHN);
916  LOG("HNIntranuke", pWARN) << "R0 = " << fR0 << " fermi";
917  LOG("HNIntranuke", pWARN) << "NR = " << fNR;
918  LOG("HNIntranuke", pWARN) << "DelRPion = " << fDelRPion;
919  LOG("HNIntranuke", pWARN) << "DelRNucleon = " << fDelRNucleon;
920  LOG("HNIntranuke", pWARN) << "HadStep = " << fHadStep << " fermi";
921  LOG("HNIntranuke", pWARN) << "NucAbsFac = " << fNucAbsFac;
922  LOG("HNIntranuke", pWARN) << "NucQEFac = " << fNucQEFac;
923  LOG("HNIntranuke", pWARN) << "NucCEXFac = " << fNucCEXFac;
924  LOG("HNIntranuke", pWARN) << "EPreEq = " << fEPreEq;
925  LOG("HNIntranuke", pWARN) << "FermiFac = " << fFermiFac;
926  LOG("HNIntranuke", pWARN) << "FreeStep = " << fFreeStep; // free step in fm
927  LOG("HNIntranuke", pWARN) << "FermiMomtm = " << fFermiMomentum;
928  LOG("HNIntranuke", pWARN) << "DoFermi? = " << ((fDoFermi)?(true):(false));
929  LOG("HNIntranuke", pWARN) << "DoCmpndNuc? = " << ((fDoCompoundNucleus)?(true):(false));
930 }
931 //___________________________________________________________________________
double fFermiMomentum
whether or not particle collision is pauli blocked
Definition: Intranuke.h:113
static string AsString(INukeMode_t mode)
Definition: INukeMode.h:41
bool HandleCompoundNucleus(GHepRecord *ev, GHepParticle *p, int mom) const
RgDbl GetDoubleDef(RgKey key, RgDbl def_opt, bool set_def=true)
Definition: Registry.cxx:549
An exception thrown by SimulateHadronState for kinematics problems. TwoBodyCollision/Kinematics used ...
void SetFirstMother(int m)
Definition: GHepParticle.h:131
Basic constants.
virtual GHepParticle * Particle(int position) const
Definition: GHepRecord.cxx:148
TRandom3 & RndFsi(void) const
rnd number generator used by intranuclear cascade monte carlos
Definition: RandomGen.h:60
#include "Numerical/GSFunc.h"
Definition: AlgCmp.h:26
#define pERROR
Definition: Messenger.h:50
INukeHadroData * fHadroData
a collection of h+N,h+A data & calculations
Definition: Intranuke.h:93
double E(void) const
Get energy.
Definition: GHepParticle.h:90
TLorentzVector fRemnP4
P4 of remnant system.
Definition: Intranuke.h:98
static RandomGen * Instance()
Access instance.
Definition: RandomGen.cxx:79
void GammaInelasticHN(GHepRecord *ev, GHepParticle *p, INukeFateHN_t fate) const
A singleton class holding all configuration registries built while parsing all loaded XML configurati...
Definition: AlgConfigPool.h:41
static const double MeV
Definition: Units.h:130
The INTRANUKE intranuclear hadron transport MC. Is a concrete implementation of the EventRecordVisito...
Definition: Intranuke.h:54
double fHadStep
step size for intranuclear hadron transport
Definition: Intranuke.h:107
Pure abstract base class. Defines the NuclearModelI interface to be implemented by any physics model ...
Definition: NuclearModelI.h:42
double fFreeStep
produced particle free stem, in fm
Definition: Intranuke.h:112
void ElasHN(GHepRecord *ev, GHepParticle *p, INukeFateHN_t fate) const
double fTrackingRadius
tracking radius for the nucleus in the current event
Definition: Intranuke.h:91
virtual void ProcessEventRecord(GHepRecord *event_rec) const
Definition: Intranuke.cxx:114
void SetMomentum(const TLorentzVector &p4)
void ProcessEventRecord(GHepRecord *event_rec) const
double Mass(void) const
Mass that corresponds to the PDG code.
RgDbl GetDouble(RgKey key) const
Definition: Registry.cxx:488
Definition: tf_graph.h:23
AlgFactory * fAlgf
algorithm factory instance
Definition: Intranuke.h:94
A singleton holding random number generator classes. All random number generation in GENIE should tak...
Definition: RandomGen.h:30
double Frac(int hpdgc, INukeFateHA_t fate, double ke) const
void LoadConfig(void)
int LastMother(void) const
Definition: GHepParticle.h:68
int Pdg(void) const
Definition: GHepParticle.h:64
double fDelRNucleon
factor by which Nucleon Compton wavelength gets multiplied to become nuclear size enhancement ...
Definition: Intranuke.h:106
int FirstMother(void) const
Definition: GHepParticle.h:67
string Name(void) const
Name that corresponds to the PDG code.
double fDelRPion
factor by which Pion Compton wavelength gets multiplied to become nuclear size enhancement ...
Definition: Intranuke.h:105
const HLTPathStatus pass
#define LOG(stream, priority)
A macro that returns the requested log4cpp::Category appending a string (using the FILE...
Definition: Messenger.h:87
void SimulateHadronicFinalState(GHepRecord *ev, GHepParticle *p) const
bool PionProduction(GHepRecord *ev, GHepParticle *p, GHepParticle *s1, GHepParticle *s2, GHepParticle *s3, int &RemnA, int &RemnZ, TLorentzVector &RemnP4, bool DoFermi, double FermiFac, double FermiMomentum, const NuclearModelI *Nuclmodel)
const int kPdgGamma
Definition: PDGCodes.h:163
static INukeHadroData * Instance(void)
A Neutrino Interaction Target. Is a transparent encapsulation of quite different physical systems suc...
Definition: Target.h:41
const Algorithm * GetAlgorithm(const AlgId &algid)
Definition: AlgFactory.cxx:86
const int kPdgKP
Definition: PDGCodes.h:146
bool fDoCompoundNucleus
whether or not to do compound nucleus considerations
Definition: Intranuke.h:116
const int kPdgPiP
Definition: PDGCodes.h:132
const int kPdgPi0
Definition: PDGCodes.h:134
double fR0
effective nuclear size param
Definition: Intranuke.h:102
virtual GHepParticle * TargetNucleus(void) const
Definition: GHepRecord.cxx:323
double FateWeight(int pdgc, INukeFateHN_t fate) const
#define pINFO
Definition: Messenger.h:53
int fRemnA
remnant nucleus A
Definition: Intranuke.h:96
Misc GENIE control constants.
enum genie::EINukeFateHN_t INukeFateHN_t
Registry * GlobalParameterList(void) const
#define pWARN
Definition: Messenger.h:51
void AbsorbHN(GHepRecord *ev, GHepParticle *p, INukeFateHN_t fate) const
double fNucRmvE
binding energy to subtract from cascade nucleons
Definition: Intranuke.h:104
void InelasticHN(GHepRecord *ev, GHepParticle *p) const
p
Definition: test.py:228
double IntBounce(const GHepParticle *p, int target, int s1, INukeFateHN_t fate)
double fNucAbsFac
absorption xsec correction factor (hN Mode)
Definition: Intranuke.h:108
double KinE(bool mass_from_pdg=false) const
Get kinetic energy.
static PDGLibrary * Instance(void)
Definition: PDGLibrary.cxx:45
static AlgFactory * Instance()
Definition: AlgFactory.cxx:75
void SetLastMother(int m)
Definition: GHepParticle.h:132
double fEPreEq
threshold for pre-equilibrium reaction
Definition: Intranuke.h:110
void StepParticle(GHepParticle *p, double step, double nuclear_radius=-1.)
Step particle.
Definition: INukeUtils.cxx:341
Singleton class to load & serve a TDatabasePDG.
Definition: PDGLibrary.h:27
void SetStatus(GHepStatus_t s)
Definition: GHepParticle.h:125
virtual TVector3 Momentum3(void) const
Definition: NuclearModelI.h:59
static string AsString(INukeFateHN_t fate)
A registry. Provides the container for algorithm configuration parameters.
Definition: Registry.h:66
bool IsNeutronOrProton(int pdgc)
Definition: PDGUtils.cxx:321
TParticlePDG * Find(int pdgc)
Definition: PDGLibrary.cxx:63
RgBool GetBool(RgKey key) const
Definition: Registry.cxx:474
double fNucCEXFac
charge exchange xsec correction factor (hN Mode)
Definition: Intranuke.h:109
int fRemnZ
remnant nucleus Z
Definition: Intranuke.h:97
const int kPdgPiM
Definition: PDGCodes.h:133
bool fDoFermi
whether or not to do fermi mom.
Definition: Intranuke.h:114
string PrintFramedMesg(string mesg, unsigned int nl=1, const char f='*')
Definition: PrintUtils.cxx:171
virtual bool GenerateNucleon(const Target &) const =0
Registry * fConfig
config. (either owned or pointing to config pool)
Definition: Algorithm.h:122
virtual void AddParticle(const GHepParticle &p)
Definition: GHepRecord.cxx:526
double fFermiFac
testing parameter to modify fermi momentum
Definition: Intranuke.h:111
const int kPdgProton
Definition: PDGCodes.h:62
#define pNOTICE
Definition: Messenger.h:52
static const unsigned int kRjMaxIterations
Definition: Controls.h:27
TLorentzVector * P4(void) const
Definition: GHepParticle.h:79
INukeFateHN_t HadronFateHN(const GHepParticle *p) const
const int kPdgNeutron
Definition: PDGCodes.h:64
GENIE&#39;s GHEP MC event record.
Definition: GHepRecord.h:46
static const double kPi
Definition: Constants.h:38
Most commonly used PDG codes. A set of utility functions to handle PDG codes is provided in PDGUtils...
void PreEquilibrium(GHepRecord *ev, GHepParticle *p, int &RemnA, int &RemnZ, TLorentzVector &RemnP4, bool DoFermi, double FermiFac, const NuclearModelI *Nuclmodel, double NucRmvE, EINukeMode mode=kIMdHN)
Definition: INukeUtils.cxx:395
STDHEP-like event record entry that can fit a particle or a nucleus.
Definition: GHepParticle.h:40
RgBool GetBoolDef(RgKey key, RgBool def_opt, bool set_def=true)
Definition: Registry.cxx:539
bool TwoBodyCollision(GHepRecord *ev, int pcode, int tcode, int scode, int s2code, double C3CM, GHepParticle *p, GHepParticle *t, int &RemnA, int &RemnZ, TLorentzVector &RemnP4, EINukeMode mode=kIMdHA)
Intranuke utility functions.
Definition: INukeUtils.cxx:625
bool IsInNucleus(const GHepParticle *p) const
Definition: Intranuke.cxx:248
Root of GENIE utility namespaces.
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
const NuclearModelI * fNuclmodel
nuclear model used to generate fermi momentum
Definition: Intranuke.h:95
static AlgConfigPool * Instance()
double fNR
param multiplying the nuclear radius, determining how far to track hadrons beyond the "nuclear bounda...
Definition: Intranuke.h:103
#define pDEBUG
Definition: Messenger.h:54
void SetPdgCode(int c)