Intranuke2015.cxx
Go to the documentation of this file.
1 //____________________________________________________________________________
2 /*
3  Copyright (c) 2003-2017, GENIE Neutrino MC Generator Collaboration
4  For the full text of the license visit http://copyright.genie-mc.org
5  or see $GENIE/LICENSE
6 
7  Author: Steve Dytman <dytman+@pitt.edu>, Pittsburgh Univ.
8  Aaron Meyer <asm58@pitt.edu>, Pittsburgh Univ.
9  Alex Bell, Pittsburgh Univ.
10  Hugh Gallagher <gallag@minos.phy.tufts.edu>, Tufts Univ.
11  Costas Andreopoulos <costas.andreopoulos \at stfc.ac.uk>, Rutherford Lab.
12  September 20, 2005
13 
14  For the class documentation see the corresponding header file.
15 
16  Important revisions after version 2.0.0 :
17  @ Nov 30, 2007 - SD
18  Changed the hadron tracking algorithm to take into account the radial
19  nuclear density dependence. Using the somewhat empirical approach of
20  increasing the nuclear radius by a const (tunable) number times the tracked
21  particle's de Broglie wavelength as this helps getting the hadron+nucleus
22  cross sections right.
23  @ Mar 08, 2008 - CA
24  Fixed code retrieving the remnant nucleus which stopped working as soon as
25  simulation of nuclear de-excitation started pushing photons in the target
26  nucleus daughter list.
27  @ Jun 20, 2008 - CA
28  Fix a mem leak: The (clone of the) GHepParticle being re-scattered was not
29  deleted after it was added at the GHEP event record.
30  @ Jan 28, 2009 - CA
31  The nuclear remnant is now marked as a kIStFinalStateNuclearRemnant, not
32  as a kIStStableFinalState.
33  @ Sep 15, 2009 - CA
34  IsFake() and IsNucleus() are no longer available in GHepParticle.
35  Use pdg::IsPseudoParticle() and pdg::IsIon().
36  @ Sep 15, 2009 - CA
37  Store the rescattering code (hadron fate) in the GHEP record so as to
38  facilitate event reweighting.
39  @ Jul 15, 2010 - AM
40  Split Intranuke class into two separate classes, one for each interaction mode.
41  Intranuke.cxx now only contains methods common to both classes and associated
42  with the stepping of the hadrons through the nucleus and with configuration.
43  @ Nov 20, 2011 - CA
44  Tweaked the way TransportHadrons() looks-up the nuclear environment so that
45  it works for the nucleon decay mode as well.
46  @ Dec 08, 2011 - CA
47  Some minor structural changes. The new GEvGenMode_t is determined at the
48  start of the event processing and is used throughout. fInTestMode flag and
49  special INTRANUKE configs not needed. ProcessEventRecord() was added by
50  factoring out code from HNIntranuke and HAIntranuke. Some comments added.
51  @ Dec 23, 2014 - TG, SD
52  New 2014 class for latest Intranuke model
53 
54 */
55 //____________________________________________________________________________
56 
57 #include <cstdlib>
58 #include <sstream>
59 
60 #include <TMath.h>
61 
63 #include "Algorithm/AlgFactory.h"
64 #include "Conventions/GBuild.h"
65 #include "Conventions/Constants.h"
66 #include "Conventions/Controls.h"
67 #include "GHEP/GHepStatus.h"
68 #include "GHEP/GHepRecord.h"
69 #include "GHEP/GHepParticle.h"
75 #include "Messenger/Messenger.h"
76 #include "Numerical/RandomGen.h"
77 #include "Numerical/Spline.h"
78 #include "PDG/PDGLibrary.h"
79 #include "PDG/PDGCodes.h"
80 #include "PDG/PDGCodeList.h"
81 #include "PDG/PDGUtils.h"
82 #include "Utils/PrintUtils.h"
83 #include "Utils/NuclearUtils.h"
84 
85 using std::ostringstream;
86 
87 using namespace genie;
88 using namespace genie::utils;
89 using namespace genie::constants;
90 using namespace genie::controls;
91 
92 //___________________________________________________________________________
95 {
96 
97 }
98 //___________________________________________________________________________
101 {
102 
103 }
104 //___________________________________________________________________________
106 EventRecordVisitorI(name, config)
107 {
108 
109 }
110 //___________________________________________________________________________
112 {
113 
114 }
115 //___________________________________________________________________________
117 {
118  // Do not continue if there is no nuclear target
119  GHepParticle * nucltgt = evrec->TargetNucleus();
120  if (!nucltgt) {
121  LOG("HNIntranuke2015", pINFO) << "No nuclear target found - INTRANUKE exits";
122  return;
123  }
124 
125  // Decide tracking radius for the current nucleus (few * R0 * A^1/3)
126  this->SetTrackingRadius(nucltgt);
127 
128  // Understand what the event generation mode is (hadron/photon-nucleus,
129  // lepton-nucleus, nucleon decay) from the input event.
130  // The determined mode has an effect on INTRANUKE behaviour (how to lookup
131  // the residual nucleus, whether to set an intranuclear vtx etc) but it
132  // does not affect the INTRANUKE physics.
133  fGMode = evrec->EventGenerationMode();
134 
135  // For lepton-nucleus scattering and for nucleon decay intranuclear vtx
136  // position (in the target nucleus coord system) is set elsewhere.
137  // This method only takes effect in hadron/photon-nucleus interactions.
138  // In this special mode, an interaction vertex is set at the periphery
139  // of the target nucleus.
140  if(fGMode == kGMdHadronNucleus ||
142  {
143  this->GenerateVertex(evrec);
144  }
145 
146  // Now transport all hadrons outside the tracking radius.
147  // Stepping part is common for both HA and HN.
148  // Once it has been estabished that an interaction takes place then
149  // HA and HN specific code takes over in order to simulate the final state.
150  this->TransportHadrons(evrec);
151 }
152 //___________________________________________________________________________
154 {
155 // Sets a vertex in the nucleus periphery
156 // Called onlt in hadron/photon-nucleus interactions.
157 
158  GHepParticle * nucltgt = evrec->TargetNucleus();
159  assert(nucltgt);
160 
161  RandomGen * rnd = RandomGen::Instance();
162  TVector3 vtx(999999.,999999.,999999.);
163 
164  // *** For h+A events (test mode):
165  // Assume a hadron beam with uniform intensity across an area,
166  // so we need to choose events uniformly within that area.
167  double x=999999., y=999999., epsilon = 0.001;
168  double R2 = TMath::Power(fTrackingRadius,2.);
169  double rp2 = TMath::Power(x,2.) + TMath::Power(y,2.);
170  while(rp2 > R2-epsilon) {
171  x = (fTrackingRadius-epsilon) * rnd->RndFsi().Rndm();
172  y = -fTrackingRadius + 2*fTrackingRadius * rnd->RndFsi().Rndm();
173  y -= ((y>0) ? epsilon : -epsilon);
174  rp2 = TMath::Power(x,2.) + TMath::Power(y,2.);
175  }
176  vtx.SetXYZ(x,y, -1.*TMath::Sqrt(TMath::Max(0.,R2-rp2)) + epsilon);
177 
178  // get the actual unit vector along the incoming hadron direction
179  TVector3 direction = evrec->Probe()->P4()->Vect().Unit();
180 
181  // rotate the vtx position
182  vtx.RotateUz(direction);
183 
184  LOG("Intranuke2015", pNOTICE)
185  << "Generated vtx @ R = " << vtx.Mag() << " fm / "
186  << print::Vec3AsString(&vtx);
187 
188  TObjArrayIter piter(evrec);
189  GHepParticle * p = 0;
190  while( (p = (GHepParticle *) piter.Next()) )
191  {
192  if(pdg::IsPseudoParticle(p->Pdg())) continue;
193  if(pdg::IsIon (p->Pdg())) continue;
194 
195  p->SetPosition(vtx.x(), vtx.y(), vtx.z(), 0.);
196  }
197 }
198 //___________________________________________________________________________
200 {
201  assert(p && pdg::IsIon(p->Pdg()));
202  double A = p->A();
203  fTrackingRadius = fR0 * TMath::Power(A, 1./3.);
204 
205  // multiply that by some input factor so that hadrons are tracked
206  // beyond the nuclear 'boundary' since the nuclear density distribution
207  // is not zero there
208  fTrackingRadius *= fNR;
209 
210  LOG("Intranuke2015", pNOTICE)
211  << "Setting tracking radius to R = " << fTrackingRadius;
212 }
213 //___________________________________________________________________________
215 {
216 // checks whether the particle should be rescattered
217 
218  assert(p);
219 
220  if(fGMode == kGMdHadronNucleus ||
222  // hadron/photon-nucleus scattering propagate the incoming particle
223  return (
225  && !pdg::IsIon(p->Pdg()));
226  }
227  else {
228  // attempt to rescatter anything marked as 'hadron in the nucleus'
229  return (p->Status() == kIStHadronInTheNucleus);
230  }
231 }
232 //___________________________________________________________________________
234 {
235 // checks whether a particle that needs to be rescattered, can in fact be
236 // rescattered by this cascade MC
237 
238  assert(p);
239  return ( p->Pdg() == kPdgPiP ||
240  p->Pdg() == kPdgPiM ||
241  p->Pdg() == kPdgPi0 ||
242  p->Pdg() == kPdgProton ||
243  p->Pdg() == kPdgNeutron ||
244  // p->Pdg() == kPdgGamma ||
245  p->Pdg() == kPdgKP //||
246  // p->Pdg() == kPdgKM
247  );
248 }
249 //___________________________________________________________________________
251 {
252 // check whether the input particle is still within the nucleus
253 //
254  return (p->X4()->Vect().Mag() < fTrackingRadius + fHadStep);
255 }
256 //___________________________________________________________________________
258 {
259 // transport all hadrons outside the nucleus
260 
261  int inucl = -1;
262  fRemnA = -1;
263  fRemnZ = -1;
264 
265  // Get 'nuclear environment' at the beginning of hadron transport
266  // and keep track of the remnant nucleus A,Z
267 
268  if(fGMode == kGMdHadronNucleus ||
270  {
271  inucl = evrec->TargetNucleusPosition();
272  }
273  else
274  if(fGMode == kGMdLeptonNucleus ||
276  {
277  inucl = evrec->RemnantNucleusPosition();
278  }
279 
280  LOG("Intranuke2015", pNOTICE)
281  << "Propagating hadrons within nucleus found in position = " << inucl;
282  GHepParticle * nucl = evrec->Particle(inucl);
283  if(!nucl) {
284  LOG("Intranuke2015", pERROR)
285  << "No nucleus found in position = " << inucl;
286  LOG("Intranuke2015", pERROR)
287  << *evrec;
288  return;
289  }
290 
291  fRemnA = nucl->A();
292  fRemnZ = nucl->Z();
293 
294  LOG("Intranuke2015", pNOTICE)
295  << "Nucleus (A,Z) = (" << fRemnA << ", " << fRemnZ << ")";
296 
297  const TLorentzVector & p4nucl = *(nucl->P4());
298  fRemnP4 = p4nucl;
299 
300  // Loop over GHEP and run intranuclear rescattering on handled particles
301  TObjArrayIter piter(evrec);
302  GHepParticle * p = 0;
303  int icurr = -1;
304 
305  while( (p = (GHepParticle *) piter.Next()) )
306  {
307  icurr++;
308 
309  // Check whether the particle needs rescattering, otherwise skip it
310  if( ! this->NeedsRescattering(p) ) continue;
311 
312  LOG("Intranuke2015", pNOTICE)
313  << " >> Stepping a " << p->Name()
314  << " with kinetic E = " << p->KinE() << " GeV";
315 
316  // Rescatter a clone, not the original particle
317  GHepParticle * sp = new GHepParticle(*p);
318 
319  // Set clone's mom to be the hadron that was cloned
320  sp->SetFirstMother(icurr);
321 
322  // Check whether the particle can be rescattered
323  if(!this->CanRescatter(sp)) {
324 
325  // if I can't rescatter it, I will just take it out of the nucleus
326  LOG("Intranuke2015", pNOTICE)
327  << "... Current version can't rescatter a " << sp->Name();
328  sp->SetFirstMother(icurr);
330  evrec->AddParticle(*sp);
331  delete sp;
332  continue; // <-- skip to next GHEP entry
333  }
334 
335  // Start stepping particle out of the nucleus
336  bool has_interacted = false;
337  while ( this-> IsInNucleus(sp) )
338  {
339  // advance the hadron by a step
341 
342  // check whether it interacts
343  double d = this->GenerateStep(evrec,sp);
344  has_interacted = (d<fHadStep);
345  if(has_interacted) break;
346  }//stepping
347 
348  //updating the position of the original particle with the position of the clone
349  evrec->Particle(sp->FirstMother())->SetPosition(*(sp->X4()));
350 
351  if(has_interacted && fRemnA>0) {
352  // the particle interacts - simulate the hadronic interaction
353  LOG("Intranuke2015", pNOTICE)
354  << "Particle has interacted at location: "
355  << sp->X4()->Vect().Mag() << " / nucl rad= " << fTrackingRadius;
356  this->SimulateHadronicFinalState(evrec,sp);
357  } else if(has_interacted && fRemnA<=0) {
358  // nothing left to interact with!
359  LOG("Intranuke2015", pNOTICE)
360  << "*** Nothing left to interact with, escaping.";
362  evrec->AddParticle(*sp);
363  evrec->Particle(sp->FirstMother())->SetRescatterCode(1);
364  } else {
365  // the exits the nucleus without interacting - Done with it!
366  LOG("Intranuke2015", pNOTICE)
367  << "*** Hadron escaped the nucleus! Done with it.";
369  evrec->AddParticle(*sp);
370  evrec->Particle(sp->FirstMother())->SetRescatterCode(1);
371  }
372  delete sp;
373 
374  // Current snapshot
375  //LOG("Intranuke2015", pINFO) << "Current event record snapshot: " << *evrec;
376 
377  }// GHEP entries
378 
379  // Add remnant nucleus - that 'hadronic blob' has all the remaining hadronic
380  // 4p not put explicitly into the simulated particles
381  TLorentzVector v4(0.,0.,0.,0.);
382  GHepParticle remnant_nucleus(
384  evrec->AddParticle(remnant_nucleus);
385  // Mark the initial remnant nucleus as an intermediate state
386  // Don't do that in the hadron/photon-nucleus scatterig mode since the initial
387  // remnant nucleus and the target nucleus coincide.
388  if(fGMode != kGMdHadronNucleus &&
390  evrec->Particle(inucl)->SetStatus(kIStIntermediateState);
391  }
392 }
393 //___________________________________________________________________________
394 double Intranuke2015::GenerateStep(GHepRecord* /*evrec*/, GHepParticle* p) const //Added ev to get tgt argument//
395 {
396 // Generate a step (in fermis) for particle p in the input event.
397 // Computes the mean free path L and generate an 'interaction' distance d
398 // from an exp(-d/L) distribution
399 
400  RandomGen * rnd = RandomGen::Instance();
401 
402  string fINukeMode = this->GetINukeMode();
403 
404  double L = utils::intranuke2015::MeanFreePath(p->Pdg(), *p->X4(), *p->P4(), fRemnA,
406  double d = -1.*L * TMath::Log(rnd->RndFsi().Rndm());
407 
408  LOG("Intranuke2015", pDEBUG)
409  << "Mean free path = " << L << " fm / "
410  << "Generated path length = " << d << " fm";
411  return d;
412 }
413 //___________________________________________________________________________
415 {
416  Algorithm::Configure(config);
417  this->LoadConfig();
418 }
419 //___________________________________________________________________________
420 void Intranuke2015::Configure(string param_set)
421 {
422  Algorithm::Configure(param_set);
423  this->LoadConfig();
424 }
425 //___________________________________________________________________________
int Z(void) const
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
bool CanRescatter(const GHepParticle *p) const
bool fUseOset
Oset model for low energy pion in hN.
#define pERROR
Definition: Messenger.h:50
double fR0
effective nuclear size param
static RandomGen * Instance()
Access instance.
Definition: RandomGen.cxx:79
Defines the EventRecordVisitorI interface. Concrete implementations of this interface use the &#39;Visito...
virtual string GetINukeMode() const
Definition: Intranuke2015.h:72
const int kPdgHadronicBlob
Definition: PDGCodes.h:182
virtual int RemnantNucleusPosition(void) const
Definition: GHepRecord.cxx:424
string Vec3AsString(const TVector3 *vec)
bool fXsecNNCorr
use nuclear medium correction for NN cross section
bool IsInNucleus(const GHepParticle *p) const
double fTrackingRadius
tracking radius for the nucleus in the current event
Definition: Intranuke2015.h:93
double MeanFreePath(int pdgc, const TLorentzVector &x4, const TLorentzVector &p4, double A, double Z, double nRpi=0.5, double nRnuc=1.0, const bool useOset=false, const bool altOset=false, const bool xsecNNCorr=false, string INukeMode="XX2015")
Mean free path (pions, nucleons)
A singleton holding random number generator classes. All random number generation in GENIE should tak...
Definition: RandomGen.h:30
GHepStatus_t Status(void) const
Definition: GHepParticle.h:65
void GenerateVertex(GHepRecord *ev) const
double fNR
param multiplying the nuclear radius, determining how far to track hadrons beyond the "nuclear bounda...
virtual GHepParticle * Probe(void) const
Definition: GHepRecord.cxx:314
int Pdg(void) const
Definition: GHepParticle.h:64
int FirstMother(void) const
Definition: GHepParticle.h:67
void Configure(const Registry &config)
Configure the algorithm.
string Name(void) const
Name that corresponds to the PDG code.
double y
void SetPosition(const TLorentzVector &v4)
#define LOG(stream, priority)
A macro that returns the requested log4cpp::Category appending a string (using the FILE...
Definition: Messenger.h:87
virtual void SimulateHadronicFinalState(GHepRecord *ev, GHepParticle *p) const =0
virtual void Configure(const Registry &config)
Configure the algorithm.
Definition: Algorithm.cxx:70
GEvGenMode_t EventGenerationMode(void) const
Definition: GHepRecord.cxx:253
const int kPdgKP
Definition: PDGCodes.h:146
const int kPdgPiP
Definition: PDGCodes.h:132
void StepParticle(GHepParticle *p, double step, double nuclear_radius=-1.)
Step particle.
const int kPdgPi0
Definition: PDGCodes.h:134
virtual void LoadConfig(void)=0
virtual GHepParticle * TargetNucleus(void) const
Definition: GHepRecord.cxx:323
void TransportHadrons(GHepRecord *ev) const
#define pINFO
Definition: Messenger.h:53
double GenerateStep(GHepRecord *ev, GHepParticle *p) const
Misc GENIE control constants.
p
Definition: test.py:228
static const double A
Definition: Units.h:82
double KinE(bool mass_from_pdg=false) const
Get kinetic energy.
bool IsIon(int pdgc)
Definition: PDGUtils.cxx:53
TLorentzVector * X4(void) const
Definition: GHepParticle.h:80
void SetStatus(GHepStatus_t s)
Definition: GHepParticle.h:125
A registry. Provides the container for algorithm configuration parameters.
Definition: Registry.h:66
bool NeedsRescattering(const GHepParticle *p) const
virtual void ProcessEventRecord(GHepRecord *event_rec) const
bool IsPseudoParticle(int pdgc)
Definition: PDGUtils.cxx:38
GEvGenMode_t fGMode
event generation mode (lepton+A, hadron+A, ...)
bool fAltOset
NuWro&#39;s table-based implementation (not recommended)
int fRemnZ
remnant nucleus Z
Definition: Intranuke2015.h:99
const int kPdgPiM
Definition: PDGCodes.h:133
TLorentzVector fRemnP4
P4 of remnant system.
virtual void AddParticle(const GHepParticle &p)
Definition: GHepRecord.cxx:526
const int kPdgProton
Definition: PDGCodes.h:62
int A(void) const
#define pNOTICE
Definition: Messenger.h:52
void SetTrackingRadius(const GHepParticle *p) const
TLorentzVector * P4(void) const
Definition: GHepParticle.h:79
double fDelRNucleon
factor by which Nucleon Compton wavelength gets multiplied to become nuclear size enhancement ...
int fRemnA
remnant nucleus A
Definition: Intranuke2015.h:98
const int kPdgNeutron
Definition: PDGCodes.h:64
GENIE&#39;s GHEP MC event record.
Definition: GHepRecord.h:46
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.
Definition: GHepParticle.h:40
double fHadStep
step size for intranuclear hadron transport
virtual int TargetNucleusPosition(void) const
Definition: GHepRecord.cxx:398
Root of GENIE utility namespaces.
double fDelRPion
factor by which Pion Compton wavelength gets multiplied to become nuclear size enhancement ...
#define pDEBUG
Definition: Messenger.h:54