Berkeley Nuclear Data Software
NSDPhysicsCalcs.h
Go to the documentation of this file.
1 #ifndef _NSD_PHYSICS_CALCS_
2 #define _NSD_PHYSICS_CALCS_
3 
4 #include <cmath>
5 #include <vector>
6 #include <numeric>
7 
8 namespace NSDPhysicsCalcs
9 {
10  //physics constants used in calculations
11  constexpr double CcmPerNs = 29.979245800;
12  constexpr double MnMeV = 939.56542052;
13  constexpr double electronRestEnergy = 0.510998950; // MeV
14 
19 {
20 public:
21  // Computes and returns recoil gamma ray energy from Compton
22  // scattering kinematics
23  inline static double recoilGammaEnergy(double a_incidentEnergy,
24  double a_scatteringAngle);
25 
26  // Computes and returns recoil electron energy from Compton
27  // scattering kinematics
28  inline static double recoilElectronEnergy(double a_incidentEnergy,
29  double a_scatteringAngle);
30 
31  // Computes and returns scattering angle (degrees) of recoil gamma ray
32  // from electron energy deposited in detector volume assuming electron is
33  // fully stopped
34  inline static double scatteringAngleFromED(double a_incidentEnergy, // MeV
35  double a_electronEnergyDep); // MeV
36 
37 };
39 
40 
45 class NTOFCalcs
46 {
47 public:
48  NTOFCalcs();
51  inline static double gT(double a_L
52  );
56  inline static double Nen(double a_L,
57  double a_t
58  );
60  inline static double NTOF(double a_L,
61  double a_nEn
62  );
64  inline static std::vector<double> GenEnBins(double a_L,
65  double a_maxT,
66  double a_minT,
67  double a_dt
68  );
69 };
70 
74 {
75 public:
76  // GenExtraCalcs();
78  inline static double levelThreshold(double A,
79  double a_Ex
80  );
81 
85  inline static double scintSigma(double a_E,
86  double a_A,
87  double a_B,
88  double a_C
89  );
90 
94  inline static double biExponential(double a_t,
95  double a_tau1,
96  double a_tau2
97  );
98 
102  inline static double triExponential(double a_t,
103  double a_tau1,
104  double a_tau2,
105  double a_tau3,
106  double a_lambda
107  );
108  //Added by Ananya on 2/15/24 for CLYC WF fitting
109  inline static double ErfEnvExponential(double a_t,
110  double a_tau1,
111  double a_tau2
112  );
113 
117  inline static double cloverResol(const std::vector<double>& a_coeffs,
118  double a_val
119  );
120 
123  inline static double polyEval(const std::vector<double>& a_coeffs,
124  double a_val
125  );
128  inline static double getNormIntegral(double a_mu,
129  double a_sigma,
130  double a_start,
131  double a_stop
132  );
133 
136  inline static std::vector<double> getNormVector(std::vector<double> a_pntA,
137  std::vector<double> a_pntB,
138  std::vector<double> a_pntC
139  );
140 
143  inline static std::vector<double> getVector(double a_x1,
144  double a_y1,
145  double a_z1,
146  double a_x2,
147  double a_y2,
148  double a_z2);
149  inline static std::vector<double> getVector(std::vector<double> a_v1,
150  std::vector<double> a_v2);
152  inline static double magnitude(std::vector<double> a_v);
153 
157  inline static double calcAngle(std::vector<double> a_v1,
158  std::vector<double> a_v2);
161  inline static double calcAngle(double a_x1,
162  double a_y1,
163  double a_z1,
164  double a_x2,
165  double a_y2,
166  double a_z2
167  );
172  inline static double getGaussArea(double a_norm,
173  double a_sig,
174  double a_binWidth,
175  double a_dNorm,
176  double a_dSig,
177  double* a_dArea
178  );
179 
180  inline static unsigned long upper_power_of_two(unsigned long v);
181 
182 };
183 //~~~~~~~~~~~~~~~~~~implementation for inlines~~~~~~~~~~~~~~~~~~~~~~~~
184 // McGuire, 2023
185 
186 // Calculates recoil gamma ray energy according to compton scattering kinematics
187 double ComptonCalcs::recoilGammaEnergy(double a_incidentEnergy, // MeV
188  double a_scatteringAngle) // radians
189 {
190  double A = 1.0;
191  A *= a_incidentEnergy;
192  double B = 1.0;
193  B += (a_incidentEnergy/electronRestEnergy) * (1 - cos(a_scatteringAngle));
194  double recoilGammaEnergy = A / B; // MeV
195  return recoilGammaEnergy;
196 }
197 
198 // Calculates recoil electron energy according to compton scattering kinematics
199 // and conservation of energy
200 double ComptonCalcs::recoilElectronEnergy(double a_incidentEnergy, // MeV
201  double a_scatteringAngle) // radians
202 {
203  double recoilGammaRayEnergy = recoilGammaEnergy(a_incidentEnergy,
204  a_scatteringAngle); // MeV
205  double recoilElectronEnergy = a_incidentEnergy - recoilGammaRayEnergy; // MeV
206  return recoilElectronEnergy;
207 }
208 
209 // Computes and returns scattering angle (degrees) of recoil gamma ray from
210 // electron energy deposited in detector volume assuming electron is fully
211 // stopped
212 // "this is a sligtly dangerous way to calculate the scatter angle
213 // what if the electron left the volume before depositing it's full energy?" -JB
214 double ComptonCalcs::scatteringAngleFromED(double a_incidentEnergy, // MeV
215  double a_electronEnergyDep) // MeV
216 {
217  double A = 1.0;
218  double B = 1.0;
219  B *= ((a_incidentEnergy / (a_incidentEnergy - a_electronEnergyDep)) - 1);
220  B *= electronRestEnergy/a_incidentEnergy;
221  A -= B;
222  double theta = acos(A) * (180. / M_PI);; // degrees
223  return theta; // degrees
224 }
225 
226 
227 double NTOFCalcs::gT(double a_L)
228 {
229  return a_L/CcmPerNs;
230 }
231 double NTOFCalcs::Nen(double a_L,
232  double a_t
233  )
234 {
236  double gTime = gT(a_L);
237  if(a_t>=gTime)
238  {
239  double beta = (a_L*a_L)/(a_t*a_t*CcmPerNs*CcmPerNs);
240  double gamma = 1.0/sqrt(1-beta);
241  return MnMeV*(gamma -1.0);
242  }
243  //implicit else due to return if the flight time is faster than a gamma
244  //this isn't a valid neutron time of flight return -100 for the energy
245  return -100;
246 }
248 double NTOFCalcs::NTOF(double a_L,
249  double a_nEn
250  )
251 {
252  double numerator = a_L * (a_nEn+MnMeV);
253  double denominator = CcmPerNs * sqrt(a_nEn*a_nEn+2.0*MnMeV*a_nEn);
254  return numerator/denominator;
255 }
257 std::vector<double> NTOFCalcs::GenEnBins(double a_L,
258  double a_maxT,
259  double a_minT,
260  double a_dt
261  )
262 {
263  std::vector<double> res;
264  for(double t = a_maxT;t>a_minT;t-=a_dt)
265  {
266  res.push_back(Nen(a_L,t));
267  }
268  res.push_back(Nen(a_L,a_minT));
269  return res;
270 }
271 
272 
275  double a_Ex
276  )
277 {
278  return a_Ex*(A+1)/A ;
279 }
280 
281 double GenExtraCalcs::cloverResol(const std::vector<double>& a_coeffs,
282  double a_val
283  )
284 {
285  return (a_coeffs[0]*a_val+a_coeffs[1])/(1+0.221*log(a_val)-1.07) \
286  + (0.221*log(a_val)-1.07)/(1+0.221*log(a_val)-1.07)*(a_coeffs[2]*a_val+2*a_coeffs[1]);
287 }
288 
289 double GenExtraCalcs::polyEval(const std::vector<double>& a_coeffs,
290  double a_val
291  )
292 {
293  int a_coeffsSize = a_coeffs.size();
294  if(a_coeffsSize>0)
295  {
296  double result = a_coeffs[0];
297  // for(auto& coeff : a_coeffs)
298  for(int a_i=1; a_i<a_coeffsSize; a_i++)
299  {
300  result = result*a_val + a_coeffs[a_i];
301  }
302  return result;
303  }
304  else
305  {
306  return 0;
307  }
308 }
312 double GenExtraCalcs::scintSigma(double a_E,
313  double a_A,
314  double a_B,
315  double a_C
316  )
317 {
318  return a_A+a_B*sqrt(a_E)+a_C*a_E;
319 }
320 
325  double a_tau1,
326  double a_tau2
327  )
328 {
329  if(a_t>0)
330  {
331  return std::exp(-1.0 * a_t / a_tau2) * (1. - std::exp(-1.0 * a_t / a_tau1)) /
332  a_tau2 / a_tau2 * (a_tau1 + a_tau2);
333  }
334  return 0;
335 }
336 
338  double a_tau1,
339  double a_tau2
340  )
341 {
342  if(a_t>0)
343  {
344  return std::exp(-1.0 * a_t / a_tau2) * std::erf(a_t / a_tau1);
345  }
346  return 0;
347 }
348 
353  double a_tau1,
354  double a_tau2,
355  double a_tau3,
356  double a_lambda
357  )
358 {
359  if(a_t>0)
360  {
361  return (a_lambda*std::exp(-1.0 * a_t / a_tau3)+std::exp(-1.0 * a_t / a_tau2)) *
362  (1. - std::exp(-1.0 * a_t / a_tau1)) *(a_tau2+a_tau3)*(a_tau1*a_tau2
363  + a_tau1*a_tau3 + a_tau2*a_tau3)/((a_tau2*a_tau3)*(a_tau2*a_tau3));
364  }
365  return 0;
366 }
367 
374  double a_sigma,
375  double a_start,
376  double a_stop
377  )
378 {
379  double erfDenom = a_sigma*sqrt(2);
380  double upperErfArg = (a_stop-a_mu)/erfDenom;
381  double lowerErfArg = (a_start-a_mu)/erfDenom;
382  return 0.5*(erf(upperErfArg)-erf(lowerErfArg));
383 }
384 
389 inline std::vector<double> GenExtraCalcs::
390  getNormVector(std::vector<double> a_pntA,
391  std::vector<double> a_pntB,
392  std::vector<double> a_pntC
393  )
394 {
395  //vector from a to b
396  std::vector<double> vecAB;
397  vecAB.push_back(a_pntB[0]-a_pntA[0]);
398  vecAB.push_back(a_pntB[1]-a_pntA[1]);
399  vecAB.push_back(a_pntB[2]-a_pntA[2]);
400  std::vector<double> vecAC;
401  //vector from a to c
402  vecAC.push_back(a_pntC[0]-a_pntA[0]);
403  vecAC.push_back(a_pntC[1]-a_pntA[1]);
404  vecAC.push_back(a_pntC[2]-a_pntA[2]);
405  //orthogonal vector is the cross product of the two resultant vectors
406  std::vector<double> orthVector;
407  orthVector.push_back(vecAB[1]*vecAC[2]-vecAB[2]*vecAC[1]);
408  orthVector.push_back(vecAB[2]*vecAC[0]-vecAB[0]*vecAC[2]);
409  orthVector.push_back(vecAB[0]*vecAC[1]-vecAB[1]*vecAC[0]);
410  double vecNorm = sqrt(orthVector[0]*orthVector[0]+
411  orthVector[1]*orthVector[1]+
412  orthVector[2]*orthVector[2]
413  );
414  orthVector[0]/=vecNorm;
415  orthVector[1]/=vecNorm;
416  orthVector[2]/=vecNorm;
417  return orthVector;
418 }
419 
420 inline std::vector<double> GenExtraCalcs::getVector(double a_x1,
421  double a_y1,
422  double a_z1,
423  double a_x2,
424  double a_y2,
425  double a_z2)
426 {
427  double x = a_x2 - a_x1;
428  double y = a_y2 - a_y1;
429  double z = a_z2 - a_z1;
430  std::vector<double> rtnVec = {x , y, z};
431  return rtnVec;
432 }
433 
434 inline std::vector<double> GenExtraCalcs::getVector(std::vector<double> a_v1,
435  std::vector<double> a_v2)
436 {
437  return getVector(a_v1[0], a_v1[1], a_v1[2], a_v2[0], a_v2[1], a_v2[2]);
438 }
439 
440 // WARING: Assumes vector is length 3
441 inline double GenExtraCalcs::magnitude(std::vector<double> a_v)
442 {
443  return (std::sqrt(a_v[0]*a_v[0] + a_v[1]*a_v[1] + a_v[2]*a_v[2]));
444 }
445 
446 inline double GenExtraCalcs::calcAngle(std::vector<double> a_v1,
447  std::vector<double> a_v2)
448 {
449  //this needs to be completed
450  double numerator = std::inner_product(a_v1.begin(),
451  a_v1.end(), a_v2.begin(), 0.);
452  // another method below
453  //double numnerator = a_v1[0]*a_v2[0] + a_v1[1]*a_v2[1] + a_v1[2]*a_v2[2];
454  double denominator = magnitude(a_v1) * magnitude(a_v2);
455  double cosTheta = numerator / denominator;
456  double theta = acos(cosTheta); // radians
457  //prefer radians as builtins all use radians
458  return theta;
459 }
462 inline double GenExtraCalcs::calcAngle(double a_x1,
463  double a_y1,
464  double a_z1,
465  double a_x2,
466  double a_y2,
467  double a_z2
468  )
469 {
470  double dot = a_x1*a_x2+a_y1*a_y2+a_z1*a_z2;
471  double mag1 = sqrt(a_x1*a_x1+a_y1*a_y1+a_z1*a_z1);
472  double mag2 = sqrt(a_x2*a_x2+a_y2*a_y2+a_z2*a_z2);
473  return acos(dot/(mag1*mag2)); // radians
474 }
475 //this functon returns the area under a fitted gaussian and it's associated
476  //area when fitting binned data with a gaussian distribution
477 inline double GenExtraCalcs::
478  getGaussArea(double a_norm,
479  double a_sig,
480  double a_binWidth,
481  double a_dNorm,
482  double a_dSig,
483  double* a_dArea
484  )
485 {
486  double area = a_norm*a_sig*sqrt(2.*M_PI)/a_binWidth;
487  if(a_dArea!=nullptr)
488  {
489  double percDSig = a_dSig/a_sig;
490  double percDNorm = a_dNorm/a_norm;
491  *a_dArea = area * sqrt(percDNorm*percDNorm + percDSig*percDSig);
492  }
493  return area;
494 }
495 
496 unsigned long GenExtraCalcs::upper_power_of_two(unsigned long v)
497 {
498  v--;
499  v |= v >> 1;
500  v |= v >> 2;
501  v |= v >> 4;
502  v |= v >> 8;
503  v |= v >> 16;
504  v++;
505  return v;
506 }
507 }//end of namespace
508 
509 #endif
Definition: NSDPhysicsCalcs.h:19
static double recoilElectronEnergy(double a_incidentEnergy, double a_scatteringAngle)
Definition: NSDPhysicsCalcs.h:200
static double scatteringAngleFromED(double a_incidentEnergy, double a_electronEnergyDep)
Definition: NSDPhysicsCalcs.h:214
static double recoilGammaEnergy(double a_incidentEnergy, double a_scatteringAngle)
Definition: NSDPhysicsCalcs.h:187
Definition: NSDPhysicsCalcs.h:74
static double magnitude(std::vector< double > a_v)
this function returns the magnitude of a vector
Definition: NSDPhysicsCalcs.h:441
static double ErfEnvExponential(double a_t, double a_tau1, double a_tau2)
Definition: NSDPhysicsCalcs.h:337
static std::vector< double > getVector(double a_x1, double a_y1, double a_z1, double a_x2, double a_y2, double a_z2)
Definition: NSDPhysicsCalcs.h:420
static double getNormIntegral(double a_mu, double a_sigma, double a_start, double a_stop)
Definition: NSDPhysicsCalcs.h:373
static double getGaussArea(double a_norm, double a_sig, double a_binWidth, double a_dNorm, double a_dSig, double *a_dArea)
Definition: NSDPhysicsCalcs.h:478
static double cloverResol(const std::vector< double > &a_coeffs, double a_val)
Definition: NSDPhysicsCalcs.h:281
static double scintSigma(double a_E, double a_A, double a_B, double a_C)
Definition: NSDPhysicsCalcs.h:312
static double levelThreshold(double A, double a_Ex)
this function calculates level energy thresholds for given mass number A
Definition: NSDPhysicsCalcs.h:274
static double biExponential(double a_t, double a_tau1, double a_tau2)
Definition: NSDPhysicsCalcs.h:324
static std::vector< double > getNormVector(std::vector< double > a_pntA, std::vector< double > a_pntB, std::vector< double > a_pntC)
Definition: NSDPhysicsCalcs.h:390
static double triExponential(double a_t, double a_tau1, double a_tau2, double a_tau3, double a_lambda)
Definition: NSDPhysicsCalcs.h:352
static unsigned long upper_power_of_two(unsigned long v)
Definition: NSDPhysicsCalcs.h:496
static double polyEval(const std::vector< double > &a_coeffs, double a_val)
Definition: NSDPhysicsCalcs.h:289
static double calcAngle(std::vector< double > a_v1, std::vector< double > a_v2)
Definition: NSDPhysicsCalcs.h:446
McGuire, 2023.
Definition: NSDPhysicsCalcs.h:46
static double gT(double a_L)
Definition: NSDPhysicsCalcs.h:227
static double NTOF(double a_L, double a_nEn)
this function calculates the time of flight in ns for a neutron
Definition: NSDPhysicsCalcs.h:248
static std::vector< double > GenEnBins(double a_L, double a_maxT, double a_minT, double a_dt)
this function calculates the time of flight in ns for a neutron
Definition: NSDPhysicsCalcs.h:257
NTOFCalcs()
Definition: NSDPhysicsCalcs.cpp:4
static double Nen(double a_L, double a_t)
Definition: NSDPhysicsCalcs.h:231
Definition: NSDPhysicsCalcs.h:9
constexpr double CcmPerNs
Definition: NSDPhysicsCalcs.h:11
constexpr double electronRestEnergy
Definition: NSDPhysicsCalcs.h:13
constexpr double MnMeV
Definition: NSDPhysicsCalcs.h:12