Intranuke2014.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("HNIntranuke2014", 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("Intranuke2014", 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("Intranuke2014", 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("Intranuke2014", pNOTICE)
281  << "Propagating hadrons within nucleus found in position = " << inucl;
282  GHepParticle * nucl = evrec->Particle(inucl);
283  if(!nucl) {
284  LOG("Intranuke2014", pERROR)
285  << "No nucleus found in position = " << inucl;
286  LOG("Intranuke2014", pERROR)
287  << *evrec;
288  return;
289  }
290 
291  fRemnA = nucl->A();
292  fRemnZ = nucl->Z();
293 
294  LOG("Intranuke2014", 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("Intranuke2014", 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("Intranuke2014", 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  if(has_interacted && fRemnA>0) {
349  // the particle interacts - simulate the hadronic interaction
350  LOG("Intranuke2014", pNOTICE)
351  << "Particle has interacted at location: "
352  << sp->X4()->Vect().Mag() << " / nucl rad= " << fTrackingRadius;
353  this->SimulateHadronicFinalState(evrec,sp);
354  } else if(has_interacted && fRemnA<=0) {
355  // nothing left to interact with!
356  LOG("Intranuke2014", pNOTICE)
357  << "*** Nothing left to interact with, escaping.";
359  evrec->AddParticle(*sp);
360  evrec->Particle(sp->FirstMother())->SetRescatterCode(1);
361  } else {
362  // the exits the nucleus without interacting - Done with it!
363  LOG("Intranuke2014", pNOTICE)
364  << "*** Hadron escaped the nucleus! Done with it.";
366  evrec->AddParticle(*sp);
367  evrec->Particle(sp->FirstMother())->SetRescatterCode(1);
368  }
369  delete sp;
370 
371  // Current snapshot
372  //LOG("Intranuke2014", pINFO) << "Current event record snapshot: " << *evrec;
373 
374  }// GHEP entries
375 
376  // Add remnant nucleus - that 'hadronic blob' has all the remaining hadronic
377  // 4p not put explicitly into the simulated particles
378  TLorentzVector v4(0.,0.,0.,0.);
379  GHepParticle remnant_nucleus(
381  evrec->AddParticle(remnant_nucleus);
382  // Mark the initial remnant nucleus as an intermediate state
383  // Don't do that in the hadron/photon-nucleus scatterig mode since the initial
384  // remnant nucleus and the target nucleus coincide.
385  if(fGMode != kGMdHadronNucleus &&
387  evrec->Particle(inucl)->SetStatus(kIStIntermediateState);
388  }
389 }
390 //___________________________________________________________________________
392 {
393 // Generate a step (in fermis) for particle p in the input event.
394 // Computes the mean free path L and generate an 'interaction' distance d
395 // from an exp(-d/L) distribution
396 
397  RandomGen * rnd = RandomGen::Instance();
398 
399  double L = utils::intranuke2014::MeanFreePath(p->Pdg(), *p->X4(), *p->P4(), fRemnA,
401  double d = -1.*L * TMath::Log(rnd->RndFsi().Rndm());
402 
403  LOG("Intranuke2014", pDEBUG)
404  << "Mean free path = " << L << " fm / "
405  << "Generated path length = " << d << " fm";
406  return d;
407 }
408 //___________________________________________________________________________
410 {
411  Algorithm::Configure(config);
412  this->LoadConfig();
413 }
414 //___________________________________________________________________________
415 void Intranuke2014::Configure(string param_set)
416 {
417  Algorithm::Configure(param_set);
418  this->LoadConfig();
419 }
420 //___________________________________________________________________________
void GenerateVertex(GHepRecord *ev) const
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
#define pERROR
Definition: Messenger.h:50
double fNR
param multiplying the nuclear radius, determining how far to track hadrons beyond the "nuclear bounda...
static RandomGen * Instance()
Access instance.
Definition: RandomGen.cxx:79
Defines the EventRecordVisitorI interface. Concrete implementations of this interface use the &#39;Visito...
const int kPdgHadronicBlob
Definition: PDGCodes.h:182
virtual int RemnantNucleusPosition(void) const
Definition: GHepRecord.cxx:424
string Vec3AsString(const TVector3 *vec)
double fR0
effective nuclear size param
int fRemnZ
remnant nucleus Z
Definition: Intranuke2014.h:97
bool IsInNucleus(const GHepParticle *p) const
void TransportHadrons(GHepRecord *ev) const
A singleton holding random number generator classes. All random number generation in GENIE should tak...
Definition: RandomGen.h:30
void StepParticle(GHepParticle *p, double step, double nuclear_radius=-1.)
Step particle.
GHepStatus_t Status(void) const
Definition: GHepParticle.h:65
double GenerateStep(GHepRecord *ev, GHepParticle *p) const
virtual void ProcessEventRecord(GHepRecord *event_rec) const
double fTrackingRadius
tracking radius for the nucleus in the current event
Definition: Intranuke2014.h:91
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
string Name(void) const
Name that corresponds to the PDG code.
int fRemnA
remnant nucleus A
Definition: Intranuke2014.h:96
double y
double fDelRPion
factor by which Pion Compton wavelength gets multiplied to become nuclear size enhancement ...
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
double MeanFreePath(int pdgc, const TLorentzVector &x4, const TLorentzVector &p4, double A, double Z, double nRpi=0.5, double nRnuc=1.0)
Mean free path (pions, nucleons)
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
const int kPdgPi0
Definition: PDGCodes.h:134
virtual GHepParticle * TargetNucleus(void) const
Definition: GHepRecord.cxx:323
#define pINFO
Definition: Messenger.h:53
bool CanRescatter(const GHepParticle *p) const
Misc GENIE control constants.
p
Definition: test.py:228
static const double A
Definition: Units.h:82
bool NeedsRescattering(const GHepParticle *p) const
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 IsPseudoParticle(int pdgc)
Definition: PDGUtils.cxx:38
GEvGenMode_t fGMode
event generation mode (lepton+A, hadron+A, ...)
Definition: Intranuke2014.h:99
void SetTrackingRadius(const GHepParticle *p) const
const int kPdgPiM
Definition: PDGCodes.h:133
virtual void LoadConfig(void)=0
virtual void AddParticle(const GHepParticle &p)
Definition: GHepRecord.cxx:526
void Configure(const Registry &config)
Configure the algorithm.
double fDelRNucleon
factor by which Nucleon Compton wavelength gets multiplied to become nuclear size enhancement ...
const int kPdgProton
Definition: PDGCodes.h:62
int A(void) const
#define pNOTICE
Definition: Messenger.h:52
TLorentzVector * P4(void) const
Definition: GHepParticle.h:79
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
TLorentzVector fRemnP4
P4 of remnant system.
Definition: Intranuke2014.h:98
virtual int TargetNucleusPosition(void) const
Definition: GHepRecord.cxx:398
Root of GENIE utility namespaces.
#define pDEBUG
Definition: Messenger.h:54