GENIEGenerator
Loading...
Searching...
No Matches
SmithMonizUtils.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 Igor Kakorin <kakorin@jinr.ru>
7 Joint Institute for Nuclear Research
8
9 adapted from fortran code provided by:
10
11 Konstantin Kuzmin <kkuzmin@theor.jinr.ru>
12 Joint Institute for Nuclear Research
13
14 Vladimir Lyubushkin
15 Joint Institute for Nuclear Research
16
17 Vadim Naumov <vnaumov@theor.jinr.ru>
18 Joint Institute for Nuclear Research
19
20 based on code of:
21 Costas Andreopoulos <c.andreopoulos \at cern.ch>
22 University of Liverpool
23*/
24//____________________________________________________________________________
25#include <TMath.h>
26#include <Math/IFunction.h>
27#include <Math/RootFinder.h>
28
29#include "Framework/Conventions/GBuild.h"
40
41using namespace genie;
42using namespace genie::constants;
43using std::ostringstream;
44
45//____________________________________________________________________________
47Algorithm("genie::SmithMonizUtils")
48{
49
50}
51//____________________________________________________________________________
53Algorithm("genie::SmithMonizUtils", config)
54{
55
56}
57//____________________________________________________________________________
62//____________________________________________________________________________
64{
66 this->LoadConfig();
67}
68//____________________________________________________________________________
69void SmithMonizUtils::Configure(string config)
70{
72 this->LoadConfig();
73}
74//____________________________________________________________________________
76{
77
78
79 GetParam( "FermiMomentumTable", fKFTable);
80 GetParam( "RFG-UseParametrization", fUseParametrization);
81
82
83 // load removal energy for specific nuclei from either the algorithm's
84 // configuration file or the UserPhysicsOptions file.
85 // if none is used use Wapstra's semi-empirical formula.
86 const std::string keyStart = "RFG-NucRemovalE@Pdg=";
87
88 RgIMap entries = GetConfig().GetItemMap();
89
90 for(RgIMap::const_iterator it = entries.begin(); it != entries.end(); ++it)
91 {
92 const std::string& key = it->first;
93 int pdg = 0;
94 int Z = 0;
95 if (0 == key.compare(0, keyStart.size(), keyStart.c_str()))
96 {
97 pdg = atoi(key.c_str() + keyStart.size());
99 }
100 if (0 != pdg && 0 != Z)
101 {
102 ostringstream key_ss ;
103 key_ss << keyStart << pdg;
104 RgKey rgkey = key_ss.str();
105 double eb;
106 GetParam( rgkey, eb ) ;
107 eb = TMath::Max(eb, 0.);
108 fNucRmvE.insert(map<int,double>::value_type(Z,eb));
109 }
110 }
111
112
113}
114//____________________________________________________________________________
115// Set the variables necessary for further calculations
117{
118
119 fInteraction = interaction;
120 // get kinematics & init-state parameters
121 const InitialState & init_state = interaction -> InitState();
122 const Target & target = init_state.Tgt();
123 PDGLibrary * pdglib = PDGLibrary::Instance();
124
125 // neutrino energy (GeV)
126 E_nu = interaction->InitState().ProbeE(kRfLab);
127
128 assert(target.HitNucIsSet());
129 // get lepton&nuclear masses (init & final state nucleus)
130
131 // mass of final charged lepton (GeV)
132 m_lep = interaction->FSPrimLepton()->Mass();
133 mm_lep = TMath::Power(m_lep, 2);
134 int nucl_pdg_ini = target.HitNucPdg();
135 m_ini = target.HitNucMass();
136 mm_ini = TMath::Power(m_ini, 2);
137 int nucl_pdg_fin = genie::pdg::SwitchProtonNeutron(nucl_pdg_ini);
138 TParticlePDG * nucl_fin = pdglib->Find( nucl_pdg_fin );
139 // mass of final hadron or hadron system (GeV)
140 m_fin = nucl_fin -> Mass();
141 mm_fin = TMath::Power(m_fin, 2);
142 // mass of target nucleus (GeV)
143 m_tar = target.Mass();
144 mm_tar = TMath::Power(m_tar, 2);
145
146 // RFG is not applied for A<4
147 if (target.A()<4)
148 {
149 E_BIN = P_Fermi = m_rnu = mm_rnu = 0;
150 return;
151 }
152
153 bool is_p = pdg::IsProton(nucl_pdg_ini);
154 int Zi = target.Z();
155 int Ai = target.A();
156 int Zf = (is_p) ? Zi-1 : Zi;
157 int Af = Ai-1;
158 TParticlePDG * nucl_f = pdglib->Find( pdg::IonPdgCode(Af, Zf) );
159 if(!nucl_f)
160 {
161 LOG("SmithMoniz", pFATAL)
162 << "Unknwown nuclear target! No target with code: "
163 << pdg::IonPdgCode(Af, Zf) << " in PDGLibrary!";
164 exit(1);
165 }
166 // mass of residual nucleus (GeV)
167 m_rnu = nucl_f -> Mass();
168 mm_rnu = TMath::Power(m_rnu, 2);
169
170 int Z = target.Z();
171 int A = target.A();
172 int N = A-Z;
173
174
175 // maximum value of Fermi momentum of target nucleon (GeV)
176 if (A < 6 || !fUseParametrization)
177 {
178 // look up the Fermi momentum for this Target
180 const FermiMomentumTable * kft = kftp->GetTable(fKFTable);
181 P_Fermi = kft->FindClosestKF(pdg::IonPdgCode(A, Z), nucl_pdg_ini);
182 }
183 else
184 {
185 // define the Fermi momentum for this Target
186 //
188 // correct the Fermi momentum for the struck nucleon
189 if(is_p) P_Fermi *= TMath::Power( 2.*Z/A, 1./3);
190 else
191 P_Fermi *= TMath::Power( 2.*N/A, 1./3);
192 }
193
194 // neutrino binding energy (GeV)
195 if (target.A() < 6 || !fUseParametrization)
196 {
197 map<int,double>::const_iterator it = fNucRmvE.find(Z);
198 if(it != fNucRmvE.end()) E_BIN = it->second;
200 }
201 else
203
204
205
206
207}
208//____________________________________________________________________________
209// Get the neutrino energy threshold
211{
212
214
215 // maximum of function call
216 const int MFC = 10000;
217 const double EPSABS = 0.;
218 const double EPSREL = 1.0e-08;
219
220 // Energy threshold of scattering on nucleus (Eq. (1) of Ref. 3)
221 double E_min = ((m_lep + m_rnu + m_fin)*(m_lep + m_rnu + m_fin) - mm_tar)/2/m_tar;
222
223 // Energy threshold of scattering on bound nucleon (Eq. (2) of Ref. 3)
224 double E_min2 = ((m_lep + m_fin)*(m_lep + m_fin)-mm_ini-E_BIN*E_BIN+2*E_BIN*TMath::Sqrt(mm_ini+P_Fermi*P_Fermi))/2/(TMath::Sqrt(mm_ini+P_Fermi*P_Fermi)-E_BIN+P_Fermi);
225
226 E_min = TMath::Max(E_min, E_min2);
227
228 // if nu_1>nu_max at E_min then we try to find energy in range (E_min, 50.) where nu_1=nu_max and put E_min equal to it.
229 // nu_1 -- minimal energy transfer for bound nucleon (see Eqs. (11) of Ref. 3),
230 // nu_max -- maximal energy transfer on nucleus (see Eq. (9) of Ref.3)
231 if (QEL_EnuMin_SM(E_min) > 0)
232 {
233 // C++ analog of fortran function Enu_rf= DZEROX(E_min,Enu_2,EPS,MFC,QEL_EnuMin_SM,1)
234 ROOT::Math::RootFinder rfgb(ROOT::Math::RootFinder::kGSL_BRENT);
235 //convergence is reached using tolerance = 2 *( epsrel * abs(x) + epsabs)
236 if ( rfgb.Solve(QEL_EnuMin_SM_, E_min, 50., MFC, EPSABS, EPSREL) )
237 {
238 E_min = rfgb.Root();
239 }
240 }
241 E_min = TMath::Max(E_min, 0.);
242 return E_min;
243
244}
245//____________________________________________________________________________
246// The auxiliary function for determining energy threshold
247double SmithMonizUtils::QEL_EnuMin_SM(double Enu) const
248{
249 // return the minimum of nu_1-nu_max as function of Q2 in range ( Q2_lim1(Enu), Q2_lim2(Enu) )
250 const double EPS = 1.0e-06;
251 const double Delta= 1.0e-14;
252 const double Precision = std::numeric_limits<double>::epsilon();
253 double s = 2*Enu*m_tar+mm_tar;
254 double W2 = (m_rnu+m_fin)*(m_rnu+m_fin);
255 // neutrino energy in CMS (see Eq. (4) of Ref.3)
256 double E_nu_CM = (s-mm_tar)/2/TMath::Sqrt(s);
257 // final lepton energy and momentum at W2_min (see Eqs. (5) and (6) of Ref.3)
258 double E_l_CM = (s+mm_lep-W2)/2/TMath::Sqrt(s);
259 double P_l_CM = E_l_CM>m_lep?TMath::Sqrt(E_l_CM*E_l_CM-mm_lep):Precision;
260 // minimal and maximal allowed Q2 for scattering on nucleus (see Eqs. (3) of Ref.3)
261 double Q2_lim1 = 2*E_nu_CM*(E_l_CM-P_l_CM)-mm_lep;
262 double Q2_lim2 = 2*E_nu_CM*(E_l_CM+P_l_CM)-mm_lep;
263 // C++ analog of fortran function DMINFC(Q2lim1_SM,Q2_lim1,Q2_lim2,EPS,Delta,Q2_0,F_MIN,LLM)
265 double Q2_0,F_MIN;
266 bool LLM;
267 // find minimum of nu_1-nu_max as function of Q2 in range (Q2_lim1,Q2_lim2)
268 DMINFC(Q2lim1_SM_,Q2_lim1,Q2_lim2,EPS,Delta,Q2_0,F_MIN,LLM);
269 return F_MIN;
270}
271//____________________________________________________________________________
272// The auxiliary function for determining Q2-range
273double SmithMonizUtils::Q2lim1_SM(double Q2, double Enu) const
274{
275 // maximal energy transfer (see Eq. (9) of Ref.3)
276 double nu_max = Enu*Q2/(Q2+mm_lep)-(Q2+mm_lep)/4/Enu;
277
278 double E = sqrt(P_Fermi*P_Fermi+mm_ini);
279 double b = (E-E_BIN)*(E-E_BIN)-P_Fermi*P_Fermi;
280 double a = 0.5*(Q2+mm_fin-b);
281 // minimal energy transfer for bound nucleon (see Eqs. (11) of Ref. 3),
282 double nu_1 = (a*(E-E_BIN)-P_Fermi*TMath::Sqrt(a*a+Q2*b))/b;
283 return nu_1-nu_max;
284
285}
286//____________________________________________________________________________
287// The auxiliary function for determining Q2-range
288double SmithMonizUtils::Q2lim2_SM(double Q2) const
289{
290 // minimal energy transfer for scattering on nucleus (see Eq. (7) of Ref.3)
291 double nu_min = ((m_rnu+m_fin)*(m_rnu+m_fin)+Q2-mm_tar)/(2*m_tar);
292
293 double E = sqrt(P_Fermi*P_Fermi+mm_ini);
294 double b = (E-E_BIN)*(E-E_BIN)-P_Fermi*P_Fermi;
295 double a = (Q2+mm_fin-b)*0.5;
296 // maximal energy transfer for bound nucleon (see Eqs. (11) of Ref. 3)
297 double nu_2 = (a*(E-E_BIN)+P_Fermi*TMath::Sqrt(a*a+Q2*b))/b;
298 return nu_min-nu_2;
299
300}
301//____________________________________________________________________________
302// Return allowed Q2-range
304{
305
306 // here we find Q2_min and Q2_max such that
307 // 0. Q2_min>=0
308 // 1. nu_1(Q2_min)<=nu_max(Q2_min)
309 // 2. nu_1(Q2_max)<=nu_max(Q2_max)
310 // 3. nu_min(Q2_min)<=nu_2(Q2_min)
311 // 4. Q2_min>=the value of minimal Q2 defined for scattering on nucleus
312 // 5. Q2_max<=the value of maximal Q2 defined for scattering on nucleus (see Eqs. (3) of Ref.3)
313 // nu_1 -- minimal energy transfer for bound nucleon (see Eqs. (11) of Ref. 3),
314 // nu_max -- maximal energy transfer on nucleus (see Eq. (9) of Ref.3),
315 // nu_2 -- maximal energy transfer for bound nucleon (see Eqs. (11) of Ref. 3),
316 // nu_min -- minimal energy transfer on nucleus (see Eq. (7) of Ref.3)
317
318 // maximum of function call
319 const int MFC = 1000;
320 const double EPS = 1.0e-08;
321 const double Delta= 1.0e-14;
322 const double EPSABS = 0;
323 const double EPSREL = 1.0e-08;
324 const double Precision = std::numeric_limits<double>::epsilon();
325 // if the nucleus mass is less than 4 then this is a special case
326 if (E_BIN == 0 && P_Fermi == 0)
327 {
328 double s = 2*E_nu*m_ini+mm_ini;
329 // minimal W2 for scattering on nucleus (see Eq. (6) of Ref.3)
330 double W2 = mm_fin;
331 // neutrino energy in CMS (see Eq. (4) of Ref.3)
332 double E_nu_CM = (s-mm_ini)/2/TMath::Sqrt(s);
333 // final lepton energy and momentum at W2_min (see Eqs. (5) of Ref.3)
334 double E_l_CM = (s+mm_lep-W2)/2/TMath::Sqrt(s);
335 double P_l_CM = E_l_CM>m_lep?TMath::Sqrt(E_l_CM*E_l_CM-mm_lep):Precision;
336 // minimal and maximal allowed Q2 for scattering on nucleus (see Eqs. (3) of Ref.3)
337 double Q2_min = 2*E_nu_CM*(E_l_CM-P_l_CM)-mm_lep;
338 double Q2_max = 2*E_nu_CM*(E_l_CM+P_l_CM)-mm_lep;
339 Q2_min= TMath::Max(Q2_min,0.0);
340 Range1D_t R(Q2_min,Q2_max);
341 return R;
342 }
343 double s = 2*E_nu*m_tar+mm_tar;
344 // minimal W2 for scattering on nucleus (see Eq. (6) of Ref.3)
345 double W2 = (m_rnu+m_fin)*(m_rnu+m_fin);
346 // neutrino energy in CMS (see Eq. (4) of Ref.3)
347 double E_nu_CM = (s-mm_tar)/2/TMath::Sqrt(s);
348 // final lepton energy and momentum at W2_min (see Eqs. (5) of Ref.3)
349 double E_l_CM = (s+mm_lep-W2)/2/TMath::Sqrt(s);
350 double P_l_CM = E_l_CM>m_lep?TMath::Sqrt(E_l_CM*E_l_CM-mm_lep):Precision;
351 // minimal and maximal allowed Q2 for scattering on nucleus (see Eqs. (3) of Ref.3)
352 double Q2_min = 2*E_nu_CM*(E_l_CM-P_l_CM)-mm_lep;
353 double Q2_max = 2*E_nu_CM*(E_l_CM+P_l_CM)-mm_lep;
354 double F_MIN, Q2_0;
355 bool LLM;
356 // C++ analog of fortran function DMINFC(Q2lim1_SM,Q2_min,Q2_max,EPS,Delta,Q2_0,F_MIN,LLM)
358 // if minimum of nu_1-nu_max>0 then exit with error, because it's impossible
359 DMINFC(Q2lim1_SM_,Q2_min,Q2_max,EPS,Delta,Q2_0,F_MIN,LLM);
360 if (F_MIN>0)
361 {
362 LOG("SmithMoniz", pFATAL)
363 << "No overlapped area for energy " << E_nu << "\n" <<
364 "Q2_min=" << Q2_min << " Q2_max=" << Q2_max << "\n" <<
365 "Q2_0=" << Q2_0 << " F_MIN=" << F_MIN;
366 exit(1);
367 }
368 // at Q2_0 here we have: nu_1(Q2_0)-nu_max(Q2_0)<0
369 // if nu_1(Q2_min)-nu_max(Q2_min)>0 we find corrected Q2_min_cor>Q2_min where nu_1(Q2_min_cor)-nu_max(Q2_min_cor)=0
370 // (it is always possible because of above conditions)
371 if (Q2lim1_SM(Q2_min, E_nu)>0)
372 {
373 //C++ analog of fortran function Q2_RF=DZEROX(Q2_min,Q2_0,EPS,MFC,Q2lim1_SM,1)
374 ROOT::Math::RootFinder rfgb(ROOT::Math::RootFinder::kGSL_BRENT);
375 // convergence is reached using tolerance = 2 *( epsrel * abs(x) + epsabs)
376 if (rfgb.Solve(Q2lim1_SM_, Q2_min, Q2_0, MFC, EPSABS, EPSREL))
377 {
378 Q2_min= rfgb.Root();
379 }
380 }
381 // if nu_1(Q2_max)-nu_max(Q2_max)>0 we find Q2_max_cor<Q2_max where nu_1(Q2_max_cor)-nu_max(Q2_max_cor)=0
382 // (it is always possible because of above conditions)
383 if(Q2lim1_SM(Q2_max, E_nu)>0)
384 {
385 // C++ analog of fortran function Q2_RF=DZEROX(Q2_0,Q2_max,Eps,MFC,Q2lim1_SM,1)
386 ROOT::Math::RootFinder rfgb(ROOT::Math::RootFinder::kGSL_BRENT);
387 //convergence is reached using tolerance = 2 *( epsrel * abs(x) + epsabs)
388 if (rfgb.Solve(Q2lim1_SM_, Q2_0, Q2_max, MFC, EPSABS, EPSREL))
389 {
390 Q2_max= rfgb.Root();
391 }
392 }
394 // if nu_min(Q2_min)-nu_2(Q2_min)>0 and nu_min(Q2_max)-nu_2(Q2_max)>0 then set Q2_min=Q2_max (it makes xsec equal to zero).
395 if (Q2lim2_SM(Q2_min)>0)
396 {
397 if(Q2lim2_SM(Q2_max)>0)
398 {
399 LOG("SmithMoniz", pWARN) << "The RFG model is not applicable! The cross section is set zero!";
400 Q2_min = Q2_max;
401 }
402 // here we have nu_min(Q2_min)-nu_2(Q2_min)>0 and nu_min(Q2_max)-nu_2(Q2_max)<0 or vice versa
403 // so we always can find Q2_min_cor where nu_min(Q2_min_cor)-nu_2(Q2_min_cor)=0
404 else
405 {
406 // C++ analog of fortran function Q2_RF = DZEROX(Q2_min,Q2_max,Eps,MFC,Q2lim2_SM,1)
407 ROOT::Math::RootFinder rfgb(ROOT::Math::RootFinder::kGSL_BRENT);
408 // convergence is reached using tolerance = 2 *( epsrel * abs(x) + epsabs)
409 if (rfgb.Solve(Q2lim2_SM_, Q2_min,Q2_max, MFC, EPSABS, EPSREL))
410 {
411 Q2_min= rfgb.Root();
412 }
413 }
414 }
415 Q2_min = TMath::Max(Q2_min,0.0);
416
417 Range1D_t R(Q2_min,Q2_max);
418 return R;
419
420}
421//____________________________________________________________________________
422// Return allowed v-range for given Q2
424{
425
426 // minimal energy transfer for scattering on nucleus (see Eq. (7) of Ref.3)
427 double nu_min= ((m_rnu+m_fin)*(m_rnu+m_fin)+Q2-mm_tar)/2/m_tar;
428
429 // if the target is nucleon then nu_min=nu_max=(m_fin^2+Q^2-m_ini^2)/(2*m_ini)
430 if (E_BIN == 0 && P_Fermi == 0)
431 return Range1D_t(nu_min, nu_min);
432
433 // maximal energy transfer (see Eq. (9) of Ref.3)
434 double nu_max = E_nu*Q2/(Q2+mm_lep)-(Q2+mm_lep)/4/E_nu;
435
436 // now we find limits for bound nucleon
437 double E = TMath::Sqrt(P_Fermi*P_Fermi+mm_ini);
438 double b = (E-E_BIN)*(E-E_BIN)-P_Fermi*P_Fermi;
439 double a = (Q2+mm_fin-b)*0.5;
440 double tmp1 = a*(E-E_BIN);
441 double tmp2 = P_Fermi*TMath::Sqrt(a*a+Q2*b);
442 // minimal and maximal energy transfer for bound nucleon (see Eqs. (11) of Ref. 3)
443 double nu_1 = (tmp1-tmp2)/b;
444 double nu_2 = (tmp1+tmp2)/b;
445 // for minimal energy transfer we take maximum of corresponding values on nucleus and bound nucleon
446 nu_min= TMath::Max(nu_min,nu_1);
447 // for maximal energy transfer we take minimum of corresponding values on nucleus and bound nucleon
448 nu_max= TMath::Min(nu_max,nu_2);
449
450 if (nu_min<=nu_max)
451 return Range1D_t(nu_min,nu_max);
452 else
453 // to avoid machine precision errors
454 return Range1D_t(0.5*(nu_min+nu_max),0.5*(nu_min+nu_max));
455
456}
457//____________________________________________________________________________
458// Return minimum of low edge of v-range for given neutrino energy
459double SmithMonizUtils::vQES_SM_min(double Q2_min, double Q2_max) const
460{
461 // maximum of function call
462 const double EPS = 1.0e-08;
463 const double Delta= 1.0e-14;
464
465 if (E_BIN == 0 && P_Fermi == 0)
466 return vQES_SM_lim(Q2_min).min;
467
468 double F_MIN, Q2_0;
469 bool LLM;
470 // C++ analog of fortran function DMINFC(Q2lim1_SM,Q2_min,Q2_max,EPS,Delta,Q2_0,F_MIN,LLM)
472 DMINFC(vlim1_SM_,Q2_min,Q2_max,EPS,Delta,Q2_0,F_MIN,LLM);
473
474 return F_MIN;
475
476}
477//____________________________________________________________________________
478// Return maximum of low edge of v-range for given neutrino energy
479double SmithMonizUtils::vQES_SM_max(double Q2_min, double Q2_max) const
480{
481 // maximum of function call
482 const double EPS = 1.0e-08;
483 const double Delta= 1.0e-14;
484
485 if (E_BIN == 0 && P_Fermi == 0)
486 return vQES_SM_lim(Q2_max).min;
487
488 double F_MIN, Q2_0;
489 bool LLM;
490 // C++ analog of fortran function DMINFC(Q2lim1_SM,Q2_min,Q2_max,EPS,Delta,Q2_0,F_MIN,LLM)
492 DMINFC(vlim2_SM_,Q2_min,Q2_max,EPS,Delta,Q2_0,F_MIN,LLM);
493
494 return -F_MIN;
495
496}
497//____________________________________________________________________________
498// The auxiliary function for determining minimum of low edge of v-range
499double SmithMonizUtils::vlim1_SM(double Q2) const
500{
501 // minimal energy transfer for scattering on nucleus (see Eq. (7) of Ref.3)
502 double nu_min = ((m_rnu+m_fin)*(m_rnu+m_fin)+Q2-mm_tar)/(2*m_tar);
503
504 double E = sqrt(P_Fermi*P_Fermi+mm_ini);
505 double b = (E-E_BIN)*(E-E_BIN)-P_Fermi*P_Fermi;
506 double a = (Q2+mm_fin-b)*0.5;
507 // minimal energy transfer for bound nucleon (see Eqs. (11) of Ref. 3)
508 double nu_1 = (a*(E-E_BIN)-P_Fermi*TMath::Sqrt(a*a+Q2*b))/b;
509 nu_min= TMath::Max(nu_min,nu_1);
510 return nu_min;
511}
512//____________________________________________________________________________
513// The auxiliary function for determining maximum of up edge of v-range
514double SmithMonizUtils::vlim2_SM(double Q2) const
515{
516 // maximal energy transfer (see Eq. (9) of Ref.3)
517 double nu_max = E_nu*Q2/(Q2+mm_lep)-(Q2+mm_lep)/4/E_nu;
518
519 double E = sqrt(P_Fermi*P_Fermi+mm_ini);
520 double b = (E-E_BIN)*(E-E_BIN)-P_Fermi*P_Fermi;
521 double a = 0.5*(Q2+mm_fin-b);
522 // maximal energy transfer for bound nucleon (see Eqs. (11) of Ref. 3)
523 double nu_2 = (a*(E-E_BIN)+P_Fermi*TMath::Sqrt(a*a+Q2*b))/b;
524 nu_max= TMath::Min(nu_max,nu_2);
525 return -nu_max;
526}
527//____________________________________________________________________________
528// Return allowed Fermi momentum range for given Q2 and v
529Range1D_t SmithMonizUtils::kFQES_SM_lim(double Q2, double nu) const
530{
531 double qv = TMath::Sqrt(nu*nu+Q2);
532 double c_f = (nu-E_BIN)/qv;
533 double d_f = (E_BIN*E_BIN-2*nu*E_BIN-Q2+mm_ini-mm_fin)/(2*qv*m_ini);
534 // minimal energy of initial nucleon (see Eq. (13) of Ref.3)
535 double Ef_min= TMath::Max(m_ini*(c_f*d_f+TMath::Sqrt(1.0-c_f*c_f+d_f*d_f))/(1.0-c_f*c_f), TMath::Sqrt(P_Fermi*P_Fermi+mm_ini)-nu);
536 double kF_min= P_Fermi!=0?TMath::Sqrt(TMath::Max(Ef_min*Ef_min-mm_ini,0.0)):0.;
537 double kF_max= P_Fermi;
538 Range1D_t R;
539 if (kF_min<=kF_max)
540 R = Range1D_t(kF_min,kF_max);
541 else
542 R = Range1D_t(0.5*(kF_min+kF_max),0.5*(kF_min+kF_max));
543 return R;
544
545}
546//____________________________________________________________________________
547// C++ implementation of DMINC function from CERN library
548void SmithMonizUtils::DMINFC(Functor1D &F, double A,double B, double EPS, double DELTA, double &X, double &Y, bool &LLM) const
549{
550 const double W5 = TMath::Sqrt(5);
551 const double HV = (3-W5)/2;
552 const double HW = (W5-1)/2;
553 const double R1 = 1.0;
554 const double HF = R1/2;
555
556 int N = -1;
557 if(A!=B) N = TMath::Nint(2.08*TMath::Log(TMath::Abs((A-B)/EPS)));
558 double C = A;
559 double D = B;
560 if(A>B)
561 {
562 C = B;
563 D = A;
564 }
565 bool LLT = true;
566 bool LGE = true;
567 double V, FV, W, FW, H;
568 while(true)
569 {
570 H = D-C;
571 if(N<0)
572 {
573 X = HF*(C+D);
574 Y = F(X);
575 LLM = TMath::Abs(X-A)>DELTA && TMath::Abs(X-B)>DELTA;
576 return;
577 }
578 if(LLT)
579 {
580 V = C+HV*H;
581 FV = F(V);
582 }
583 if(LGE)
584 {
585 W = C+HW*H;
586 FW = F(W);
587 }
588 if(FV<FW)
589 {
590 LLT = true;
591 LGE = false;
592 D = W;
593 W = V;
594 FW = FV;
595 }
596 else
597 {
598 LLT = false;
599 LGE = true;
600 C = V;
601 V = W;
602 FV = FW;
603 }
604 N = N-1;
605 }
606}
607//____________________________________________________________________________
608// Density of Fermi gas, for case T_Fermi=0 is a step functio, which is blurred at T_Fermi!=0
609double SmithMonizUtils::rho(double P_Fermi, double T_Fermi, double p)
610{
611
612 if (T_Fermi==0)
613 {
614 //Pure Fermi gaz with T_Fermi=0
615 if(p<=P_Fermi)
616 return 1.0;
617 else
618 return 0.0;
619 }
620 else
621 {
622 //Fermi-Dirac distribution
623 return 1.0/(1.0 + TMath::Exp(-(P_Fermi-p)/T_Fermi));
624 }
625
626
627}
628//____________________________________________________________________________
630{
631 return E_BIN;
632}
633//____________________________________________________________________________
635{
636 return P_Fermi;
637}
638//____________________________________________________________________________
639double SmithMonizUtils::GetTheta_k(double v, double qv) const
640{
641 return TMath::ACos((v + (mm_lep-v*v+qv*qv)/2/E_nu)/qv);
642}
643//____________________________________________________________________________
644double SmithMonizUtils::GetTheta_p(double pv, double v, double qv, double &E_p) const
645{
646 E_p = TMath::Sqrt(mm_ini+pv*pv)-E_BIN;
647 if (pv != 0)
648 return TMath::ACos(((v-E_BIN)*(2*E_p+v+E_BIN)-qv*qv+mm_ini-mm_fin)/(2*pv*qv));
649 else
650 return 0;
651}
652//____________________________________________________________________________
654{
655 double vol = 0.0;
656 if (ps == kPSQ2fE)
657 {
658 Range1D_t rQ2 = Q2QES_SM_lim();
659 vol = rQ2.max - rQ2.min;
660 return vol;
661 }
662 else if (ps == kPSQ2vpfE)
663 {
664 const int kNQ2 = 101;
665 const int kNv = 101;
666 Range1D_t rQ2 = Q2QES_SM_lim();
667 double dQ2 = (rQ2.max-rQ2.min)/(kNQ2-1);
668 for(int iq2=0; iq2<kNQ2-1; iq2++)
669 {
670 double Q2 = rQ2.min + iq2*dQ2;
671 Range1D_t rv = vQES_SM_lim(Q2);
672 double dv = (rv.max-rv.min)/(kNv-1);
673 for(int iv=0; iv<kNv-1; iv++)
674 {
675 double v = rv.min + iv*dv;
676 Range1D_t rkF = kFQES_SM_lim(Q2,v);
677 double dkF = (rkF.max-rkF.min);
678 vol += (dQ2*dv*dkF);
679 }
680 }
681 return vol;
682 }
683 else
684 return 0;
685}
#define pFATAL
Definition Messenger.h:56
#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
string RgKey
virtual const Registry & GetConfig(void) const
bool GetParam(const RgKey &name, T &p, bool is_top_call=true) const
virtual void Configure(const Registry &config)
Definition Algorithm.cxx:62
Singleton class to load & serve tables of Fermi momentum constants.
const FermiMomentumTable * GetTable(string name)
static FermiMomentumTablePool * Instance(void)
A table of Fermi momentum constants.
double FindClosestKF(int target_pdgc, int nucleon_pdgc) const
Initial State information.
const Target & Tgt(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
Singleton class to load & serve a TDatabasePDG.
Definition PDGLibrary.h:36
static PDGLibrary * Instance(void)
TParticlePDG * Find(int pdgc, bool must_exist=true)
A simple [min,max] interval for doubles.
Definition Range1.h:43
A registry. Provides the container for algorithm configuration parameters.
Definition Registry.h:65
const RgIMap & GetItemMap(void) const
Definition Registry.h:161
double m_fin
Mass of final hadron or hadron system (GeV)
double vlim2_SM(double Q2) const
double mm_tar
Squared mass of target nucleus (GeV)
Range1D_t Q2QES_SM_lim(void) const
double E_nu
Neutrino energy (GeV)
double m_rnu
Mass of residual nucleus (GeV)
double GetTheta_p(double pv, double v, double qv, double &E_p) const
void Configure(const Registry &config)
double mm_ini
Sqared mass of initial hadron or hadron system (GeV)
void DMINFC(Functor1D &F, double A, double B, double EPS, double DELTA, double &X, double &Y, bool &LLM) const
double P_Fermi
Maximum value of Fermi momentum of target nucleon (GeV)
static double rho(double P_Fermi, double T_Fermi, double p)
double E_nu_thr_SM(void) const
double mm_fin
Squared mass of final hadron or hadron system (GeV)
double E_BIN
Binding energy (GeV)
void SetInteraction(const Interaction *i)
const Interaction * fInteraction
double PhaseSpaceVolume(KinePhaseSpace_t ps) const
Range1D_t vQES_SM_lim(double Q2) const
double Q2lim1_SM(double Q2, double Enu) const
map< int, double > fNucRmvE
double mm_lep
Squared mass of final charged lepton (GeV)
double m_tar
Mass of target nucleus (GeV)
double QEL_EnuMin_SM(double E_nu) const
double m_lep
Mass of final charged lepton (GeV)
double m_ini
Mass of initial hadron or hadron system (GeV)
double GetTheta_k(double v, double qv) const
double GetBindingEnergy(void) const
double mm_rnu
Squared mass of residual nucleus (GeV)
Range1D_t kFQES_SM_lim(double nu, double Q2) const
double vlim1_SM(double Q2) const
double Q2lim2_SM(double Q2) const
double vQES_SM_min(double Q2min, double Q2max) const
double GetFermiMomentum(void) const
double vQES_SM_max(double Q2min, double Q2max) const
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
int Z(void) const
Definition Target.h:68
int A(void) const
Definition Target.h:70
double Mass(void) const
Definition Target.cxx:224
double HitNucMass(void) const
Definition Target.cxx:233
bool HitNucIsSet(void) const
Definition Target.cxx:283
const double a
Basic constants.
Utilities for improving the code readability when using PDG codes.
int IonPdgCode(int A, int Z)
Definition PDGUtils.cxx:71
bool IsProton(int pdgc)
Definition PDGUtils.cxx:336
int SwitchProtonNeutron(int pdgc)
Definition PDGUtils.cxx:356
int IonPdgCodeToZ(int pdgc)
Definition PDGUtils.cxx:55
double FermiMomentumForIsoscalarNucleonParametrization(const Target &target)
double BindEnergyPerNucleon(const Target &target)
double BindEnergyPerNucleonParametrization(const Target &target)
THE MAIN GENIE PROJECT NAMESPACE
Definition AlgCmp.h:25
map< RgKey, RegistryItemI * > RgIMap
Definition Registry.h:45
enum genie::EKinePhaseSpace KinePhaseSpace_t
@ kRfLab
Definition RefFrame.h:26