GENIEGenerator
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
LocalFGM.cxx
Go to the documentation of this file.
1 //____________________________________________________________________________
2 /*
3  Copyright (c) 2003-2024, The GENIE Collaboration
4  For the full text of the license visit http://copyright.genie-mc.org
5 
6 
7  Author: Joe Johnston, University of Pittsburgh (Advisor Steven Dytman)
8 
9  For the class documentation see the corresponding header file.
10 
11 */
12 //____________________________________________________________________________
13 
14 #include <sstream>
15 #include <cstdlib>
16 #include <TMath.h>
17 
19 #include "Framework/Conventions/GBuild.h"
28 
29 using std::ostringstream;
30 using namespace genie;
31 using namespace genie::constants;
32 using namespace genie::utils;
33 
34 //____________________________________________________________________________
36 NuclearModelI("genie::LocalFGM")
37 {
38 
39 }
40 //____________________________________________________________________________
41 LocalFGM::LocalFGM(string config) :
42 NuclearModelI("genie::LocalFGM", config)
43 {
44 
45 }
46 //____________________________________________________________________________
48 {
49 
50 }
51 //____________________________________________________________________________
52 bool LocalFGM::GenerateNucleon(const Target & target,
53  double hitNucleonRadius) const
54 {
55  assert(target.HitNucIsSet());
56 
57  fCurrRemovalEnergy = -99999.0;
58  fCurrMomentum.SetXYZ(0,0,0);
59 
60  //-- set fermi momentum vector
61  //
62  TH1D * prob = this->ProbDistro(target,hitNucleonRadius);
63  if(!prob) {
64  LOG("LocalFGM", pNOTICE)
65  << "Null nucleon momentum probability distribution";
66  exit(1);
67  }
68 
70 
71  double costheta = -1. + 2. * rnd->RndGen().Rndm();
72  double sintheta = TMath::Sqrt(1.-costheta*costheta);
73  double fi = 2 * kPi * rnd->RndGen().Rndm();
74  double cosfi = TMath::Cos(fi);
75  double sinfi = TMath::Sin(fi);
76 
77  double px;
78  double py;
79  double pz;
80 
81  int Z = target.Z();
82  map<int,double>::const_iterator it = fNucRmvE.find(Z);
83 
84  double p;
85 
86  bool doThrow = 1;
87 
88  while(doThrow){
89  p = prob->GetRandom();
90 
91  LOG("LocalFGM", pINFO) << "|p,nucleon| = " << p;
92 
93  px = p*sintheta*cosfi;
94  py = p*sintheta*sinfi;
95  pz = p*costheta;
96 
97  fCurrMomentum.SetXYZ(px,py,pz);
98 
99  if (fMomDepErmv) {
100  // hit nucleon mass
101  double nucl_mass = target.HitNucMass();
102  // get the local Fermi momentum
103  double KF = LocalFermiMomentum( target, target.HitNucPdg(), hitNucleonRadius);
104 
105  //initial nucleon kinetic energy at the Fermi surface
106  double T_F = TMath::Sqrt(TMath::Power(nucl_mass,2)+TMath::Power(KF,2)) - nucl_mass;
107 
108  //the minimum removal energy to keep nucleons bound is equal to
109  //the nucleon kinetic energy at the Fermi surface
110  double localEb = T_F;
111 
112  //initial state nucleon kinetic energy (already present and contributing to its escape from the nucleus)
113  double T_nucl = TMath::Sqrt(TMath::Power(fCurrMomentum.Mag(),2)+TMath::Power(nucl_mass,2))- nucl_mass;
114 
115  //set the Qvalue (separation energy) to the RFG removal energy in the CommonParams file
116  double q_val_offset;
117  if(it != fNucRmvE.end()) q_val_offset = it->second;
118  else q_val_offset = nuclear::BindEnergyPerNucleon(target);
119 
120  //set the removal energy to be the sum of the removal energy at the Fermi surface
121  //and the Q value offset, minus the nucleon kinetic energy
122  fCurrRemovalEnergy = localEb + q_val_offset - T_nucl;
123 
124 
125  }
126  else {
127  //else, use already existing treatment, i.e. set removal energy to RFG value from table or use
128  //Wapstra's semi-empirical formula
129  if(it != fNucRmvE.end()) fCurrRemovalEnergy = it->second;
130  else fCurrRemovalEnergy = nuclear::BindEnergyPerNucleon(target);
131  }
132 
133  //decide whether to rethrow event if removal energy is negative
134 
135  if (fForcePositiveErmv){
136  if(fCurrRemovalEnergy<0) doThrow=true;
137  else doThrow = false;
138  }
139  else doThrow=false;
140  }
141 
142  delete prob;
143 
144  return true;
145 }
146 //____________________________________________________________________________
147 double LocalFGM::Prob(double p, double w, const Target & target,
148  double hitNucleonRadius) const
149 {
150  if(w<0) {
151  TH1D * prob = this->ProbDistro(target, hitNucleonRadius);
152  int bin = prob->FindBin(p);
153  double y = prob->GetBinContent(bin);
154  double dx = prob->GetBinWidth(bin);
155  double pr = y*dx;
156  delete prob;
157  return pr;
158  }
159  return 1;
160 }
161 //____________________________________________________________________________
162 // *** The TH1D object must be deleted after it is used ***
163 TH1D * LocalFGM::ProbDistro(const Target & target, double r) const
164 {
165  LOG("LocalFGM", pNOTICE)
166  << "Computing P = f(p_nucleon) for: " << target.AsString()
167  << ", Nucleon Radius = " << r;
168  LOG("LocalFGM", pNOTICE)
169  << ", P(max) = " << fPMax;
170 
171  assert(target.HitNucIsSet());
172 
173  //-- get information for the nuclear target
174  int nucleon_pdgc = target.HitNucPdg();
175  assert(pdg::IsProton(nucleon_pdgc) || pdg::IsNeutron(nucleon_pdgc));
176 
177  // bool is_p = pdg::IsProton(nucleon_pdgc);
178  // double numNuc = (is_p) ? (double)target.Z():(double)target.N();
179 
180  // Calculate Fermi Momentum using Local FG equations
181  double KF = LocalFermiMomentum( target, nucleon_pdgc, r ) ;
182 
183  LOG("LocalFGM",pNOTICE) << "KF = " << KF;
184 
185  //double a = 2.0;
186  //double C = 4. * kPi * TMath::Power(KF,3) / 3.;
187 
188  // Do not include nucleon correlation tail
189  //double R = 1. / (1.- KF/4.);
190 //#ifdef __GENIE_LOW_LEVEL_MESG_ENABLED__
191  //LOG("LocalFGM", pDEBUG) << "a = " << a;
192  //LOG("LocalFGM", pDEBUG) << "C = " << C;
193  //LOG("LocalFGM", pDEBUG) << "R = " << R;
194 //#endif
195 
196  //-- create the probability distribution
197 
198  int npbins = (int) (1000*fPMax);
199  TH1D * prob = new TH1D("", "", npbins, 0, fPMax);
200  prob->SetDirectory(0);
201 
202  double dp = fPMax / (npbins-1);
203 // double iC = (C>0) ? 1./C : 0.; // unused variables
204 // double kfa_pi_2 = TMath::Power(KF*a/kPi,2); // unused variables
205 
206  for(int i = 0; i < npbins; i++) {
207  double p = i * dp;
208  double p2 = TMath::Power(p,2);
209 
210  // use expression with fSRC_Fraction to allow the possibility of
211  // using the Correlated Fermi Gas Model with a high momentum tail
212 
213  // calculate |phi(p)|^2
214  double phi2 = 0;
215  if (p <= KF){
216  phi2 = (1./(4*kPi)) * (3/TMath::Power(KF,3.)) * ( 1 - fSRC_Fraction );
217  }else if( p > KF && p < fPCutOff ){
218  phi2 = (1./(4*kPi)) * ( fSRC_Fraction / (1./KF - 1./fPCutOff) ) / TMath::Power(p,4.);
219  }
220 
221  // calculate probability density : dProbability/dp
222  double dP_dp = 4*kPi * p2 * phi2;
223 #ifdef __GENIE_LOW_LEVEL_MESG_ENABLED__
224  LOG("LocalFGM", pDEBUG) << "p = " << p << ", dP/dp = " << dP_dp;
225 #endif
226  prob->Fill(p, dP_dp);
227  }
228 
229  double normfactor = prob->Integral("width");
230 
231  //-- normalize the probability distribution
232  if (normfactor > 0) prob->Scale(1/normfactor);
233 
234  return prob;
235 }
236 //____________________________________________________________________________
237 double LocalFGM::LocalFermiMomentum( const Target & t, int nucleon_pdg, double radius ) const {
238 
239  assert(pdg::IsProton(nucleon_pdg) || pdg::IsNeutron(nucleon_pdg)) ;
240 
241  bool is_p = pdg::IsProton(nucleon_pdg);
242  double numNuc = (double) ( (is_p) ? t.Z() : t.N() );
243 
244  // double hbarc = kLightSpeed*kPlankConstant/genie::units::fermi;
245 
246  double kF = TMath::Power( 3*kPi2*numNuc*genie::utils::nuclear::Density( radius, t.A() ),
247  1.0/3.0 )
249 
250  return kF ;
251 }
252 //____________________________________________________________________________
253 void LocalFGM::Configure(const Registry & config)
254 {
255  Algorithm::Configure(config);
256  this->LoadConfig();
257 }
258 //____________________________________________________________________________
259 void LocalFGM::Configure(string param_set)
260 {
261  Algorithm::Configure(param_set);
262  this->LoadConfig();
263 }
264 //____________________________________________________________________________
266 {
267 
269 
270  this->GetParamDef("LFG-MomentumMax", fPMax, 1.0);
271  assert(fPMax > 0);
272 
273  this->GetParamDef("SRC-Fraction", fSRC_Fraction, 0.0);
274  this->GetParam("LFG-MomentumCutOff", fPCutOff);
275  this->GetParam("LFG-MomentumDependentErmv", fMomDepErmv);
276  this->GetParam("LFG-ForcePositiveErmv", fForcePositiveErmv);
277 
278  if (fPCutOff > fPMax) {
279  LOG("LocalFGM", pFATAL) << "Momentum CutOff greater than Momentum Max";
280  exit(78);
281  }
282 
283 
284  // Load removal energy for specific nuclei from either the algorithm's
285  // configuration file or the UserPhysicsOptions file.
286  // If none is used use Wapstra's semi-empirical formula.
287  //
288 
289  for(int Z=1; Z<140; Z++) {
290  for(int A=Z; A<3*Z; A++) {
291  ostringstream key ;
292  int pdgc = pdg::IonPdgCode(A,Z);
293  key << "RFG-NucRemovalE@Pdg=" << pdgc;
294  RgKey rgkey = key.str();
295  double eb ;
296  if ( GetParam( rgkey, eb, false ) ) {
297  eb = TMath::Max(eb, 0.);
298  LOG("LocalFGM", pINFO) << "Nucleus: " << pdgc << " -> using Eb = " << eb << " GeV";
299  fNucRmvE.insert(map<int,double>::value_type(Z,eb));
300  }
301  }
302  }
303 }
304 //____________________________________________________________________________
string AsString(void) const
Definition: Target.cxx:383
static RandomGen * Instance()
Access instance.
Definition: RandomGen.cxx:71
int HitNucPdg(void) const
Definition: Target.cxx:304
double Density(double r, int A, double ring=0.)
int A(void) const
Definition: Target.h:70
double HitNucMass(void) const
Definition: Target.cxx:233
#define pFATAL
Definition: Messenger.h:56
bool fMomDepErmv
Definition: LocalFGM.h:78
double Prob(double p, double w, const Target &t, double hitNucleonRadius) const
Definition: LocalFGM.cxx:147
Pure abstract base class. Defines the NuclearModelI interface to be implemented by any physics model ...
Definition: NuclearModelI.h:46
A singleton holding random number generator classes. All random number generation in GENIE should tak...
Definition: RandomGen.h:29
bool IsNeutron(int pdgc)
Definition: PDGUtils.cxx:341
double BindEnergyPerNucleon(const Target &target)
bool IsProton(int pdgc)
Definition: PDGUtils.cxx:336
map< int, double > fNucRmvE
Definition: LocalFGM.h:75
#define LOG(stream, priority)
A macro that returns the requested log4cpp::Category appending a string (using the FILE...
Definition: Messenger.h:96
static constexpr double A
Definition: Units.h:74
void LoadConfig(void)
Definition: LocalFGM.cxx:265
A Neutrino Interaction Target. Is a transparent encapsulation of quite different physical systems suc...
Definition: Target.h:40
virtual void Configure(const Registry &config)
Definition: Algorithm.cxx:62
double fSRC_Fraction
Definition: LocalFGM.h:82
double fPCutOff
Definition: LocalFGM.h:83
bool GenerateNucleon(const Target &t, double hitNucleonRadius) const
Definition: LocalFGM.cxx:52
int Z(void) const
Definition: Target.h:68
#define pINFO
Definition: Messenger.h:62
double fPMax
Definition: LocalFGM.h:77
virtual void LoadConfig()
TH1D * ProbDistro(const Target &t, double r) const
Definition: LocalFGM.cxx:163
int N(void) const
Definition: Target.h:69
bool HitNucIsSet(void) const
Definition: Target.cxx:283
string RgKey
A registry. Provides the container for algorithm configuration parameters.
Definition: Registry.h:65
virtual ~LocalFGM()
Definition: LocalFGM.cxx:47
TRandom3 & RndGen(void) const
rnd number generator for generic usage
Definition: RandomGen.h:80
int IonPdgCode(int A, int Z)
Definition: PDGUtils.cxx:71
virtual double LocalFermiMomentum(const Target &t, int nucleon_pdg, double radius) const
Definition: LocalFGM.cxx:237
static constexpr double fermi
Definition: Units.h:55
void Configure(const Registry &config)
Definition: LocalFGM.cxx:253
#define pNOTICE
Definition: Messenger.h:61
bool GetParamDef(const RgKey &name, T &p, const T &def) const
bool GetParam(const RgKey &name, T &p, bool is_top_call=true) const
Most commonly used PDG codes. A set of utility functions to handle PDG codes is provided in PDGUtils...
#define pDEBUG
Definition: Messenger.h:63
bool fForcePositiveErmv
Definition: LocalFGM.h:79