mirror of
https://github.com/gwm17/Mask.git
synced 2024-11-26 12:08:52 -05:00
Fixed some stylistic incosistencies. Incorporated all classes used for Mask into the Mask namespace. Updated some comments.
This commit is contained in:
parent
170cc7afb0
commit
e96b29accf
|
@ -5,35 +5,39 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <random>
|
#include <random>
|
||||||
|
|
||||||
class AngularDistribution {
|
namespace Mask {
|
||||||
public:
|
|
||||||
AngularDistribution();
|
|
||||||
AngularDistribution(const std::string& file);
|
|
||||||
~AngularDistribution();
|
|
||||||
void ReadDistributionFile(const std::string& file);
|
|
||||||
void AttachRandomNumberGenerator(std::mt19937* random) { generator = random; };
|
|
||||||
double GetRandomCosTheta();
|
|
||||||
int GetL() { return L; };
|
|
||||||
double GetBranchingRatio() { return branchingRatio; };
|
|
||||||
|
|
||||||
private:
|
class AngularDistribution {
|
||||||
bool IsIsotropic();
|
public:
|
||||||
bool IsGeneratorSet() {
|
AngularDistribution();
|
||||||
if(generator) {
|
AngularDistribution(const std::string& file);
|
||||||
return true;
|
~AngularDistribution();
|
||||||
} else {
|
void ReadDistributionFile(const std::string& file);
|
||||||
return false;
|
inline void AttachRandomNumberGenerator(std::mt19937* random) { generator = random; }
|
||||||
|
double GetRandomCosTheta();
|
||||||
|
inline int GetL() { return L; }
|
||||||
|
inline double GetBranchingRatio() { return branchingRatio; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
inline bool IsIsotropic() { return isoFlag; }
|
||||||
|
inline bool IsGeneratorSet() {
|
||||||
|
if(generator) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
std::mt19937* generator; //NOT OWNED BY ANGULAR DISTRIBUTION
|
std::mt19937* generator; //NOT OWNED BY ANGULAR DISTRIBUTION
|
||||||
std::uniform_real_distribution<double> uniform_cosine_dist;
|
std::uniform_real_distribution<double> uniform_cosine_dist;
|
||||||
std::uniform_real_distribution<double> uniform_prob_dist;
|
std::uniform_real_distribution<double> uniform_prob_dist;
|
||||||
|
|
||||||
double branchingRatio;
|
double branchingRatio;
|
||||||
int L;
|
int L;
|
||||||
std::vector<double> constants;
|
std::vector<double> constants;
|
||||||
bool isoFlag;
|
bool isoFlag;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -1,130 +1,133 @@
|
||||||
#ifndef ELOSS_TABLES_H
|
#ifndef ELOSS_TABLES_H
|
||||||
#define ELOSS_TABLES_H
|
#define ELOSS_TABLES_H
|
||||||
|
|
||||||
#define MAX_Z 93 //Maximum number of elements for which we have hydrogen coefficients
|
namespace Mask {
|
||||||
|
|
||||||
/*Atomic Masses for elements H through U. Taken from ELAST data*/
|
#define MAX_Z 93 //Maximum number of elements for which we have hydrogen coefficients
|
||||||
static double NATURAL_MASS[MAX_Z] =
|
|
||||||
{0,
|
|
||||||
1.00797, 4.0026, 6.939, 9.0122, 10.818,
|
|
||||||
12.01115, 14.0067, 15.9994, 18.99984, 20.183,
|
|
||||||
22.9898, 24.312, 26.9815, 28.086, 30.9738,
|
|
||||||
32.064, 35.453, 39.948, 39.102, 40.08,
|
|
||||||
44.956, 47.90, 50.942, 51.996, 54.938,
|
|
||||||
55.847, 58.933, 58.71, 63.54, 65.37,
|
|
||||||
69.72, 72.59, 74.922, 78.96, 79.909,
|
|
||||||
83.80, 85.47, 87.62, 88.909, 91.22,
|
|
||||||
92.906, 95.94, 98., 101.07, 102.905,
|
|
||||||
106.4, 107.87, 112.4, 114.82, 118.69,
|
|
||||||
121.75, 127.60, 126.904, 131.3, 132.905,
|
|
||||||
137.34, 138.91, 140.12, 140.907, 144.24,
|
|
||||||
146., 150.35, 151.96, 157.25, 158.924,
|
|
||||||
162.50, 164.93, 167.26, 168.934, 173.04,
|
|
||||||
174.97, 178.49, 180.948, 183.85, 186.2,
|
|
||||||
190.2, 192.2, 195.09, 196.967, 200.59,
|
|
||||||
204.37, 207.19, 208.98, 209., 210.,
|
|
||||||
222., 223., 226., 227., 232.038,
|
|
||||||
231., 238.03 };
|
|
||||||
|
|
||||||
/*Stopping power coefficients for hydrogen into Z
|
/*Atomic Masses for elements H through U. Taken from ELAST data*/
|
||||||
*Taken from Ziegler, Hydrogen Stopping Powers and Ranges in All Elements, Volume 3 of
|
static double NATURAL_MASS[MAX_Z] =
|
||||||
*The Stopping and Ranges of Ions in Matter, 1977, Pergamon Press Inc.
|
{0,
|
||||||
*Expanded table for method given in O.G. Spanc
|
1.00797, 4.0026, 6.939, 9.0122, 10.818,
|
||||||
*Note: some elements represent extrapolations when there was no data to fit
|
12.01115, 14.0067, 15.9994, 18.99984, 20.183,
|
||||||
*/
|
22.9898, 24.312, 26.9815, 28.086, 30.9738,
|
||||||
static double HYDROGEN_COEFF[MAX_Z][12] = {
|
32.064, 35.453, 39.948, 39.102, 40.08,
|
||||||
/*Blank*/{0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.},
|
44.956, 47.90, 50.942, 51.996, 54.938,
|
||||||
/*H*/{1.262,1.44,242.6,1.2E4,0.1159,0.0005099,5.436E4,-5.052,2.049,-0.3044,0.01966,-0.0004659},
|
55.847, 58.933, 58.71, 63.54, 65.37,
|
||||||
/*He*/{1.229,1.397,484.5,5873,0.05225,0.00102,2.451E4,-2.158,0.8278,-0.1172,0.007259,-0.000166},
|
69.72, 72.59, 74.922, 78.96, 79.909,
|
||||||
/*Li*/{1.411,1.6,725.6,3013,0.04578,0.00153,2.147E4,-0.5831,0.562,-0.1183,0.009298,-0.0002498},
|
83.80, 85.47, 87.62, 88.909, 91.22,
|
||||||
/*Be*/{2.248,2.59,966,153.8,0.03475,0.002039,1.63E4,0.2779,0.1745,-0.05684,0.005155,-0.0001488},
|
92.906, 95.94, 98., 101.07, 102.905,
|
||||||
/*B*/{2.474,2.815,1206,1060,0.02855,0.002549,1.345E4,-2.445,1.283,-0.2205,0.0156,-0.000393},
|
106.4, 107.87, 112.4, 114.82, 118.69,
|
||||||
/*C*/{2.631,2.989,1445,957.2,0.02819,0.003059,1.322E4,-4.38,2.044,-0.3283,0.02221,-0.0005417},
|
121.75, 127.60, 126.904, 131.3, 132.905,
|
||||||
/*N*/{2.954,3.35,1683,1900,0.02513,0.003569,1.179E4,-5.054,2.325,-0.3713,0.02506,-0.0006109},
|
137.34, 138.91, 140.12, 140.907, 144.24,
|
||||||
/*O*/{2.652,3,1920,2000,0.0223,0.004079,1.046E4,-6.734,3.019,-0.4748,0.03171,-0.0007669},
|
146., 150.35, 151.96, 157.25, 158.924,
|
||||||
/*F*/{2.085,2.352,2157,2634,0.01816,0.004589,8517,-5.571,2.449,-0.3781,0.02483,-0.0005919},
|
162.50, 164.93, 167.26, 168.934, 173.04,
|
||||||
/*Ne*/{1.951,2.199,2393,2699,0.01568,0.005099,7353,-4.408,1.879,-0.2814,0.01796,-0.0004168},
|
174.97, 178.49, 180.948, 183.85, 186.2,
|
||||||
/*Na*/{2.542,2.869,2628,1854,0.01472,0.005609,6905,-4.959,2.073,-0.3054,0.01921,-0.0004403},
|
190.2, 192.2, 195.09, 196.967, 200.59,
|
||||||
/*Mg*/{3.792,4.293,2862,1009,0.01397,0.006118,6551,-5.51,2.266,-0.3295,0.02047,-0.0004637},
|
204.37, 207.19, 208.98, 209., 210.,
|
||||||
/*Al*/{4.154,4.739,2766,164.5,0.02023,0.006628,6309,-6.061,2.46,-0.3535,0.02173,-0.0004871},
|
222., 223., 226., 227., 232.038,
|
||||||
/*Si*/{4.15,4.7,3329,550,0.01321,0.007138,6194,-6.294,2.538,-0.3628,0.0222,-0.0004956},
|
231., 238.03 };
|
||||||
/*P*/{3.232,3.647,3561,1560,0.01267,0.007648,5942,-6.527,2.616,-0.3721,0.02267,-0.000504},
|
|
||||||
/*S*/{3.447,3.891,3792,1219,0.01211,0.008158,5678,-6.761,2.694,-0.3814,0.02314,-0.0005125},
|
/*Stopping power coefficients for hydrogen into Z
|
||||||
/*Cl*/{5.047,5.714,4023,878.6,0.01178,0.008668,5524,-6.994,2.773,-0.3907,0.02361,-0.0005209},
|
*Taken from Ziegler, Hydrogen Stopping Powers and Ranges in All Elements, Volume 3 of
|
||||||
/*Ar*/{5.731,6.5,4253,530,0.01123,0.009178,5268,-7.227,2.851,-0.4,0.02407,-0.0005294},
|
*The Stopping and Ranges of Ions in Matter, 1977, Pergamon Press Inc.
|
||||||
/*K*/{5.151,5.833,4482,545.7,0.01129,0.009687,5295,-7.44,2.923,-0.4094,0.02462,-0.0005411},
|
*Expanded table for method given in O.G. Spanc
|
||||||
/*Ca*/{5.521,6.252,4710,553.3,0.01112,0.0102,5214,-7.653,2.995,-0.4187,0.02516,-0.0005529},
|
*Note: some elements represent extrapolations when there was no data to fit
|
||||||
/*Sc*/{5.201,5.884,4938,560.9,0.009995,0.01071,4688,-8.012,3.123,-0.435,0.02605,-0.0005707},
|
*/
|
||||||
/*Ti*/{4.862,5.496,5165,568.5,0.009474,0.01122,4443,-8.371,3.251,-0.4513,0.02694,-0.0005886},
|
static double HYDROGEN_COEFF[MAX_Z][12] = {
|
||||||
/*V*/{4.48,5.055,5391,952.3,0.009117,0.01173,4276,-8.731,3.379,-0.4676,0.02783,-0.0006064},
|
/*Blank*/{0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.},
|
||||||
/*Cr*/{3.983,4.489,5616,1336,0.008413,0.01224,3946,-9.09,3.507,-0.4838,0.02872,-0.0006243},
|
/*H*/{1.262,1.44,242.6,1.2E4,0.1159,0.0005099,5.436E4,-5.052,2.049,-0.3044,0.01966,-0.0004659},
|
||||||
/*Mn*/{3.469,3.907,5725,1461,0.008829,0.01275,3785,-9.449,3.635,-0.5001,0.02961,-0.0006421},
|
/*He*/{1.229,1.397,484.5,5873,0.05225,0.00102,2.451E4,-2.158,0.8278,-0.1172,0.007259,-0.000166},
|
||||||
/*Fe*/{3.519,3.963,6065,1243,0.007782,0.01326,3650,-9.809,3.763,-0.5164,0.0305,-0.00066},
|
/*Li*/{1.411,1.6,725.6,3013,0.04578,0.00153,2.147E4,-0.5831,0.562,-0.1183,0.009298,-0.0002498},
|
||||||
/*Co*/{3.14,3.535,6288,1372,0.007361,0.01377,3453,-10.17,3.891,-0.5327,0.03139,-0.0006779},
|
/*Be*/{2.248,2.59,966,153.8,0.03475,0.002039,1.63E4,0.2779,0.1745,-0.05684,0.005155,-0.0001488},
|
||||||
/*Ni*/{3.553,4.004,6205,555.1,0.008763,0.01428,3297,-10.53,4.019,-0.549,0.03229,-0.0006957},
|
/*B*/{2.474,2.815,1206,1060,0.02855,0.002549,1.345E4,-2.445,1.283,-0.2205,0.0156,-0.000393},
|
||||||
/*Cu*/{3.696,4.175,4673,387.8,0.02188,0.01479,3174,-11.18,4.252,-0.5791,0.03399,-0.0007314},
|
/*C*/{2.631,2.989,1445,957.2,0.02819,0.003059,1.322E4,-4.38,2.044,-0.3283,0.02221,-0.0005417},
|
||||||
/*Zn*/{4.21,4.75,6953,295.2,0.006809,0.0153,3194,-11.57,4.394,-0.598,0.03506,-0.0007537},
|
/*N*/{2.954,3.35,1683,1900,0.02513,0.003569,1.179E4,-5.054,2.325,-0.3713,0.02506,-0.0006109},
|
||||||
/*Ga*/{5.041,5.697,7173,202.6,0.006725,0.01581,3154,-11.95,4.537,-0.6169,0.03613,-0.0007759},
|
/*O*/{2.652,3,1920,2000,0.0223,0.004079,1.046E4,-6.734,3.019,-0.4748,0.03171,-0.0007669},
|
||||||
/*Ge*/{5.554,6.3,6496,110,0.009689,0.01632,3097,-12.34,4.68,-0.6358,0.03721,-0.0007981},
|
/*F*/{2.085,2.352,2157,2634,0.01816,0.004589,8517,-5.571,2.449,-0.3781,0.02483,-0.0005919},
|
||||||
/*As*/{5.323,6.012,7611,292.5,0.006447,0.01683,3024,-12.72,4.823,-0.6547,0.03828,-0.0008203},
|
/*Ne*/{1.951,2.199,2393,2699,0.01568,0.005099,7353,-4.408,1.879,-0.2814,0.01796,-0.0004168},
|
||||||
/*Se*/{5.874,6.656,7395,117.5,0.007684,0.01734,3006,-13.11,4.965,-0.6735,0.03935,-0.0008425},
|
/*Na*/{2.542,2.869,2628,1854,0.01472,0.005609,6905,-4.959,2.073,-0.3054,0.01921,-0.0004403},
|
||||||
/*Br*/{5.611,6.335,8046,365.2,0.006244,0.01785,2928,-13.4,5.083,-0.6906,0.04042,-0.0008675},
|
/*Mg*/{3.792,4.293,2862,1009,0.01397,0.006118,6551,-5.51,2.266,-0.3295,0.02047,-0.0004637},
|
||||||
/*Kr*/{6.411,7.25,8262,220,0.006087,0.01836,2855,-13.69,5.2,-0.7076,0.0415,-0.0008925},
|
/*Al*/{4.154,4.739,2766,164.5,0.02023,0.006628,6309,-6.061,2.46,-0.3535,0.02173,-0.0004871},
|
||||||
/*Rb*/{5.694,6.429,8478,292.9,0.006087,0.01886,2855,-13.92,5.266,-0.714,0.04173,-0.0008943},
|
/*Si*/{4.15,4.7,3329,550,0.01321,0.007138,6194,-6.294,2.538,-0.3628,0.0222,-0.0004956},
|
||||||
/*Sr*/{6.339,7.159,8693,330.3,0.006003,0.01937,2815,-14.14,5.331,-0.7205,0.04196,-0.0008962},
|
/*P*/{3.232,3.647,3561,1560,0.01267,0.007648,5942,-6.527,2.616,-0.3721,0.02267,-0.000504},
|
||||||
/*Y*/{6.407,7.234,8907,367.8,0.005889,0.01988,2762,-14.36,5.397,-0.7269,0.04219,-0.000898},
|
/*S*/{3.447,3.891,3792,1219,0.01211,0.008158,5678,-6.761,2.694,-0.3814,0.02314,-0.0005125},
|
||||||
/*Zr*/{6.734,7.603,9120,405.2,0.005765,0.02039,2704,-14.59,5.463,-0.7333,0.04242,-0.0008998},
|
/*Cl*/{5.047,5.714,4023,878.6,0.01178,0.008668,5524,-6.994,2.773,-0.3907,0.02361,-0.0005209},
|
||||||
/*Nb*/{6.902,7.791,9333,442.7,0.005587,0.0209,2621,-16.22,6.094,-0.8225,0.04791,-0.001024},
|
/*Ar*/{5.731,6.5,4253,530,0.01123,0.009178,5268,-7.227,2.851,-0.4,0.02407,-0.0005294},
|
||||||
/*Mo*/{6.425,7.248,9545,480.2,0.005367,0.02141,2517,-17.85,6.725,-0.9116,0.05339,-0.001148},
|
/*K*/{5.151,5.833,4482,545.7,0.01129,0.009687,5295,-7.44,2.923,-0.4094,0.02462,-0.0005411},
|
||||||
/*Tc*/{6.799,7.671,9756,517.6,0.005315,0.02192,2493,-17.96,6.752,-0.9135,0.05341,-0.001147},
|
/*Ca*/{5.521,6.252,4710,553.3,0.01112,0.0102,5214,-7.653,2.995,-0.4187,0.02516,-0.0005529},
|
||||||
/*Ru*/{6.108,6.887,9966,555.1,0.005151,0.02243,2416,-18.07,6.779,-0.9154,0.05342,-0.001145},
|
/*Sc*/{5.201,5.884,4938,560.9,0.009995,0.01071,4688,-8.012,3.123,-0.435,0.02605,-0.0005707},
|
||||||
/*Rh*/{5.924,6.677,1.018E4,592.5,0.004919,0.02294,2307,-18.18,6.806,-0.9173,0.05343,-0.001143},
|
/*Ti*/{4.862,5.496,5165,568.5,0.009474,0.01122,4443,-8.371,3.251,-0.4513,0.02694,-0.0005886},
|
||||||
/*Pd*/{5.238,5.9,1.038E4,630,0.004758,0.02345,2231,-18.28,6.833,-0.9192,0.05345,-0.001142},
|
/*V*/{4.48,5.055,5391,952.3,0.009117,0.01173,4276,-8.731,3.379,-0.4676,0.02783,-0.0006064},
|
||||||
/*Ag*/{5.623,6.354,7160,337.6,0.01394,0.02396,2193,-18.39,6.86,-0.9211,0.05346,-0.00114},
|
/*Cr*/{3.983,4.489,5616,1336,0.008413,0.01224,3946,-9.09,3.507,-0.4838,0.02872,-0.0006243},
|
||||||
/*Cd*/{5.814,6.554,1.08E4,355.5,0.004626,0.02447,2170,-18.62,6.915,-0.9243,0.0534,-0.001134},
|
/*Mn*/{3.469,3.907,5725,1461,0.008829,0.01275,3785,-9.449,3.635,-0.5001,0.02961,-0.0006421},
|
||||||
/*In*/{6.23,7.024,1.101E4,370.9,0.00454,0.02498,2129,-18.85,6.969,-0.9275,0.05335,-0.001127},
|
/*Fe*/{3.519,3.963,6065,1243,0.007782,0.01326,3650,-9.809,3.763,-0.5164,0.0305,-0.00066},
|
||||||
/*Sn*/{6.41,7.227,1.121E4,386.4,0.004474,0.02549,2099,-19.07,7.024,-0.9308,0.05329,-0.001121},
|
/*Co*/{3.14,3.535,6288,1372,0.007361,0.01377,3453,-10.17,3.891,-0.5327,0.03139,-0.0006779},
|
||||||
/*Sb*/{7.5,8.48,8608,348,0.009074,0.026,2069,-19.57,7.225,-0.9603,0.05518,-0.001165},
|
/*Ni*/{3.553,4.004,6205,555.1,0.008763,0.01428,3297,-10.53,4.019,-0.549,0.03229,-0.0006957},
|
||||||
/*Te*/{6.979,7.871,1.162E4,392.4,0.004402,0.02651,2065,-20.07,7.426,-0.9899,0.05707,-0.001209},
|
/*Cu*/{3.696,4.175,4673,387.8,0.02188,0.01479,3174,-11.18,4.252,-0.5791,0.03399,-0.0007314},
|
||||||
/*I*/{7.725,8.716,1.183E4,394.8,0.004376,0.02702,2052,-20.56,7.627,-1.019,0.05896,-0.001254},
|
/*Zn*/{4.21,4.75,6953,295.2,0.006809,0.0153,3194,-11.57,4.394,-0.598,0.03506,-0.0007537},
|
||||||
/*Xe*/{8.231,9.289,1.203E4,397.3,0.004384,0.02753,2056,-21.06,7.828,-1.049,0.06085,-0.001298},
|
/*Ga*/{5.041,5.697,7173,202.6,0.006725,0.01581,3154,-11.95,4.537,-0.6169,0.03613,-0.0007759},
|
||||||
/*Cs*/{7.287,8.218,1.223E4,399.7,0.004447,0.02804,2086,-20.4,7.54,-1.004,0.05782,-0.001224},
|
/*Ge*/{5.554,6.3,6496,110,0.009689,0.01632,3097,-12.34,4.68,-0.6358,0.03721,-0.0007981},
|
||||||
/*Ba*/{7.899,8.911,1.243E4,402.1,0.004511,0.02855,2116,-19.74,7.252,-0.9588,0.05479,-0.001151},
|
/*As*/{5.323,6.012,7611,292.5,0.006447,0.01683,3024,-12.72,4.823,-0.6547,0.03828,-0.0008203},
|
||||||
/*La*/{8.041,9.071,1.263E4,404.5,0.00454,0.02906,2129,-19.08,6.964,-0.9136,0.05176,-0.001077},
|
/*Se*/{5.874,6.656,7395,117.5,0.007684,0.01734,3006,-13.11,4.965,-0.6735,0.03935,-0.0008425},
|
||||||
/*Ce*/{7.489,8.444,1.283E4,406.9,0.00442,0.02957,2073,-18.43,6.677,-0.8684,0.04872,-0.001003},
|
/*Br*/{5.611,6.335,8046,365.2,0.006244,0.01785,2928,-13.4,5.083,-0.6906,0.04042,-0.0008675},
|
||||||
/*Pr*/{7.291,8.219,1.303E4,409.3,0.004298,0.03008,2016,-17.77,6.389,-0.8233,0.04569,-0.0009292},
|
/*Kr*/{6.411,7.25,8262,220,0.006087,0.01836,2855,-13.69,5.2,-0.7076,0.0415,-0.0008925},
|
||||||
/*Nd*/{7.098,8,1.323E4,411.8,0.004182,0.03059,1962,-17.11,6.101,-0.7781,0.04266,-0.0008553},
|
/*Rb*/{5.694,6.429,8478,292.9,0.006087,0.01886,2855,-13.92,5.266,-0.714,0.04173,-0.0008943},
|
||||||
/*Pm*/{6.91,7.786,1.343E4,414.2,0.00405,0.0311,1903,-16.45,5.813,-0.733,0.03963,-0.0007815},
|
/*Sr*/{6.339,7.159,8693,330.3,0.006003,0.01937,2815,-14.14,5.331,-0.7205,0.04196,-0.0008962},
|
||||||
/*Sm*/{6.728,7.58,1.362E4,416.6,0.003976,0.03161,1865,-15.79,5.526,-0.6878,0.0366,-0.0007077},
|
/*Y*/{6.407,7.234,8907,367.8,0.005889,0.01988,2762,-14.36,5.397,-0.7269,0.04219,-0.000898},
|
||||||
/*Eu*/{6.551,7.38,1.382E4,419,0.003877,0.03212,1819,-15.13,5.238,-0.6426,0.03357,-0.0006339},
|
/*Zr*/{6.734,7.603,9120,405.2,0.005765,0.02039,2704,-14.59,5.463,-0.7333,0.04242,-0.0008998},
|
||||||
/*Gd*/{6.739,7.592,1.402E4,421.4,0.003863,0.03263,1812,-14.47,4.95,-0.5975,0.03053,-0.0005601},
|
/*Nb*/{6.902,7.791,9333,442.7,0.005587,0.0209,2621,-16.22,6.094,-0.8225,0.04791,-0.001024},
|
||||||
/*Tb*/{6.212,6.996,1.421E4,423.9,0.003725,0.03314,1747,-14.56,4.984,-0.6022,0.03082,-0.0005668},
|
/*Mo*/{6.425,7.248,9545,480.2,0.005367,0.02141,2517,-17.85,6.725,-0.9116,0.05339,-0.001148},
|
||||||
/*Dy*/{5.517,6.21,1.44E4,426.3,0.003632,0.03365,1703,-14.65,5.018,-0.6069,0.03111,-0.0005734},
|
/*Tc*/{6.799,7.671,9756,517.6,0.005315,0.02192,2493,-17.96,6.752,-0.9135,0.05341,-0.001147},
|
||||||
/*Ho*/{5.219,5.874,1.46E4,428.7,0.003498,0.03416,1640,-14.74,5.051,-0.6117,0.03141,-0.0005801},
|
/*Ru*/{6.108,6.887,9966,555.1,0.005151,0.02243,2416,-18.07,6.779,-0.9154,0.05342,-0.001145},
|
||||||
/*Er*/{5.071,5.706,1.479E4,433,0.003405,0.03467,1597,-14.83,5.085,-0.6164,0.0317,-0.0005867},
|
/*Rh*/{5.924,6.677,1.018E4,592.5,0.004919,0.02294,2307,-18.18,6.806,-0.9173,0.05343,-0.001143},
|
||||||
/*Tm*/{4.926,5.542,1.498E4,433.5,0.003342,0.03518,1567,-14.91,5.119,-0.6211,0.03199,-0.0005933},
|
/*Pd*/{5.238,5.9,1.038E4,630,0.004758,0.02345,2231,-18.28,6.833,-0.9192,0.05345,-0.001142},
|
||||||
/*Yb*/{4.787, 5.386,1.517E4,435.9,0.003292,0.03569,1544,-15,5.153,-0.6258,0.03228,-0.0006},
|
/*Ag*/{5.623,6.354,7160,337.6,0.01394,0.02396,2193,-18.39,6.86,-0.9211,0.05346,-0.00114},
|
||||||
/*Lu*/{4.893, 5.505,1.536E4,438.4,0.003243,0.0362,1521,-15.09,5.186,-0.6305,0.03257,-0.0006066},
|
/*Cd*/{5.814,6.554,1.08E4,355.5,0.004626,0.02447,2170,-18.62,6.915,-0.9243,0.0534,-0.001134},
|
||||||
/*Hf*/{5.028, 5.657,1.555E4,440.8,0.003195,0.03671,1499,-15.18,5.22,-0.6353,0.03286,-0.0006133},
|
/*In*/{6.23,7.024,1.101E4,370.9,0.00454,0.02498,2129,-18.85,6.969,-0.9275,0.05335,-0.001127},
|
||||||
/*Ta*/{4.738, 5.329,1.574E4,443.2,0.003186,0.03722,1494,-15.27,5.254,-0.64,0.03315,-0.0006199},
|
/*Sn*/{6.41,7.227,1.121E4,386.4,0.004474,0.02549,2099,-19.07,7.024,-0.9308,0.05329,-0.001121},
|
||||||
/*W*/{4.574, 5.144,1.593E4,442.4,0.003144,0.03773,1475,-15.67,5.392,-0.6577,0.03418,-0.0006426},
|
/*Sb*/{7.5,8.48,8608,348,0.009074,0.026,2069,-19.57,7.225,-0.9603,0.05518,-0.001165},
|
||||||
/*Re*/{5.2, 5.851,1.612E4,441.6,0.003122,0.03824,1464,-16.07,5.529,-0.6755,0.03521,-0.0006654},
|
/*Te*/{6.979,7.871,1.162E4,392.4,0.004402,0.02651,2065,-20.07,7.426,-0.9899,0.05707,-0.001209},
|
||||||
/*Os*/{5.07, 5.704,1.63E4,440.9,0.003082,0.03875,1446,-16.47,5.667,-0.6932,0.03624,-0.0006881},
|
/*I*/{7.725,8.716,1.183E4,394.8,0.004376,0.02702,2052,-20.56,7.627,-1.019,0.05896,-0.001254},
|
||||||
/*Ir*/{4.945, 5.563,1.649E4,440.1,0.002965,0.03926,1390,-16.88,5.804,-0.711,0.03727,-0.0007109},
|
/*Xe*/{8.231,9.289,1.203E4,397.3,0.004384,0.02753,2056,-21.06,7.828,-1.049,0.06085,-0.001298},
|
||||||
/*Pt*/{4.476, 5.034,1.667E4,439.3,0.002871,0.03977,1347,-17.28,5.942,-0.7287,0.0383,-0.0007336},
|
/*Cs*/{7.287,8.218,1.223E4,399.7,0.004447,0.02804,2086,-20.4,7.54,-1.004,0.05782,-0.001224},
|
||||||
/*Au*/{4.856, 5.46,1.832E4,438.5,0.002542,0.04028,1354,-17.02,5.846,-0.7149,0.0374,-0.0007114},
|
/*Ba*/{7.899,8.911,1.243E4,402.1,0.004511,0.02855,2116,-19.74,7.252,-0.9588,0.05479,-0.001151},
|
||||||
/*Hg*/{4.308, 4.843,1.704E4,487.8,0.002882,0.04079,1352,-17.84,6.183,-0.7659,0.04076,-0.0007925},
|
/*La*/{8.041,9.071,1.263E4,404.5,0.00454,0.02906,2129,-19.08,6.964,-0.9136,0.05176,-0.001077},
|
||||||
/*Tl*/{4.723, 5.311,1.722E4,537,0.002913,0.0413,1366,-18.66,6.52,-0.8169,0.04411,-0.0008737},
|
/*Ce*/{7.489,8.444,1.283E4,406.9,0.00442,0.02957,2073,-18.43,6.677,-0.8684,0.04872,-0.001003},
|
||||||
/*Pb*/{5.319, 5.982,1.74E4,586.3,0.002871,0.04181,1347,-19.48,6.857,-0.8678,0.04747,-0.0009548},
|
/*Pr*/{7.291,8.219,1.303E4,409.3,0.004298,0.03008,2016,-17.77,6.389,-0.8233,0.04569,-0.0009292},
|
||||||
/*Bi*/{5.956, 6.7,1.78E4,677,0.00266,0.04232,1336,-19.55,6.871,-0.8686,0.04748,-0.0009544},
|
/*Nd*/{7.098,8,1.323E4,411.8,0.004182,0.03059,1962,-17.11,6.101,-0.7781,0.04266,-0.0008553},
|
||||||
/*Po*/{6.158, 6.928,1.777E4,586.3,0.002812,0.04283,1319,-19.62,6.884,-0.8694,0.04748,-0.000954},
|
/*Pm*/{6.91,7.786,1.343E4,414.2,0.00405,0.0311,1903,-16.45,5.813,-0.733,0.03963,-0.0007815},
|
||||||
/*At*/{6.204, 6.979,1.795E4,586.3,0.002776,0.04334,1302,-19.69,6.898,-0.8702,0.04749,-0.0009536},
|
/*Sm*/{6.728,7.58,1.362E4,416.6,0.003976,0.03161,1865,-15.79,5.526,-0.6878,0.0366,-0.0007077},
|
||||||
/*Rn*/{6.181, 6.954,1.812E4,586.3,0.002748,0.04385,1289,-19.76,6.912,-0.871,0.04749,-0.0009532},
|
/*Eu*/{6.551,7.38,1.382E4,419,0.003877,0.03212,1819,-15.13,5.238,-0.6426,0.03357,-0.0006339},
|
||||||
/*Fr*/{6.949, 7.82,1.83E4,586.3,0.002737,0.04436,1284,-19.83,6.926,-0.8718,0.0475,-0.0009528},
|
/*Gd*/{6.739,7.592,1.402E4,421.4,0.003863,0.03263,1812,-14.47,4.95,-0.5975,0.03053,-0.0005601},
|
||||||
/*Ra*/{7.506, 8.448,1.848E4,586.3,0.002727,0.04487,1279,-19.9,6.94,-0.8726,0.04751,-0.0009524},
|
/*Tb*/{6.212,6.996,1.421E4,423.9,0.003725,0.03314,1747,-14.56,4.984,-0.6022,0.03082,-0.0005668},
|
||||||
/*Ac*/{7.649, 8.609,1.866E4,586.3,0.002697,0.04538,1265,-19.97,6.953,-0.8733,0.04751,-0.000952},
|
/*Dy*/{5.517,6.21,1.44E4,426.3,0.003632,0.03365,1703,-14.65,5.018,-0.6069,0.03111,-0.0005734},
|
||||||
/*Th*/{7.71, 8.679,1.883E4,586.3,0.002641,0.04589,1239,-20.04,6.967,-0.8741,0.04752,-0.0009516},
|
/*Ho*/{5.219,5.874,1.46E4,428.7,0.003498,0.03416,1640,-14.74,5.051,-0.6117,0.03141,-0.0005801},
|
||||||
/*Pa*/{7.407, 8.336,1.901E4,586.3,0.002603,0.0464,1221,-20.11,6.981,-0.8749,0.04752,-0.0009512},
|
/*Er*/{5.071,5.706,1.479E4,433,0.003405,0.03467,1597,-14.83,5.085,-0.6164,0.0317,-0.0005867},
|
||||||
/*U*/{7.29, 8.204,1.918E4,586.3,0.002573,0.04691,1207,-20.18,6.995,-0.8757,0.04753,-0.0009508}
|
/*Tm*/{4.926,5.542,1.498E4,433.5,0.003342,0.03518,1567,-14.91,5.119,-0.6211,0.03199,-0.0005933},
|
||||||
};
|
/*Yb*/{4.787, 5.386,1.517E4,435.9,0.003292,0.03569,1544,-15,5.153,-0.6258,0.03228,-0.0006},
|
||||||
|
/*Lu*/{4.893, 5.505,1.536E4,438.4,0.003243,0.0362,1521,-15.09,5.186,-0.6305,0.03257,-0.0006066},
|
||||||
|
/*Hf*/{5.028, 5.657,1.555E4,440.8,0.003195,0.03671,1499,-15.18,5.22,-0.6353,0.03286,-0.0006133},
|
||||||
|
/*Ta*/{4.738, 5.329,1.574E4,443.2,0.003186,0.03722,1494,-15.27,5.254,-0.64,0.03315,-0.0006199},
|
||||||
|
/*W*/{4.574, 5.144,1.593E4,442.4,0.003144,0.03773,1475,-15.67,5.392,-0.6577,0.03418,-0.0006426},
|
||||||
|
/*Re*/{5.2, 5.851,1.612E4,441.6,0.003122,0.03824,1464,-16.07,5.529,-0.6755,0.03521,-0.0006654},
|
||||||
|
/*Os*/{5.07, 5.704,1.63E4,440.9,0.003082,0.03875,1446,-16.47,5.667,-0.6932,0.03624,-0.0006881},
|
||||||
|
/*Ir*/{4.945, 5.563,1.649E4,440.1,0.002965,0.03926,1390,-16.88,5.804,-0.711,0.03727,-0.0007109},
|
||||||
|
/*Pt*/{4.476, 5.034,1.667E4,439.3,0.002871,0.03977,1347,-17.28,5.942,-0.7287,0.0383,-0.0007336},
|
||||||
|
/*Au*/{4.856, 5.46,1.832E4,438.5,0.002542,0.04028,1354,-17.02,5.846,-0.7149,0.0374,-0.0007114},
|
||||||
|
/*Hg*/{4.308, 4.843,1.704E4,487.8,0.002882,0.04079,1352,-17.84,6.183,-0.7659,0.04076,-0.0007925},
|
||||||
|
/*Tl*/{4.723, 5.311,1.722E4,537,0.002913,0.0413,1366,-18.66,6.52,-0.8169,0.04411,-0.0008737},
|
||||||
|
/*Pb*/{5.319, 5.982,1.74E4,586.3,0.002871,0.04181,1347,-19.48,6.857,-0.8678,0.04747,-0.0009548},
|
||||||
|
/*Bi*/{5.956, 6.7,1.78E4,677,0.00266,0.04232,1336,-19.55,6.871,-0.8686,0.04748,-0.0009544},
|
||||||
|
/*Po*/{6.158, 6.928,1.777E4,586.3,0.002812,0.04283,1319,-19.62,6.884,-0.8694,0.04748,-0.000954},
|
||||||
|
/*At*/{6.204, 6.979,1.795E4,586.3,0.002776,0.04334,1302,-19.69,6.898,-0.8702,0.04749,-0.0009536},
|
||||||
|
/*Rn*/{6.181, 6.954,1.812E4,586.3,0.002748,0.04385,1289,-19.76,6.912,-0.871,0.04749,-0.0009532},
|
||||||
|
/*Fr*/{6.949, 7.82,1.83E4,586.3,0.002737,0.04436,1284,-19.83,6.926,-0.8718,0.0475,-0.0009528},
|
||||||
|
/*Ra*/{7.506, 8.448,1.848E4,586.3,0.002727,0.04487,1279,-19.9,6.94,-0.8726,0.04751,-0.0009524},
|
||||||
|
/*Ac*/{7.649, 8.609,1.866E4,586.3,0.002697,0.04538,1265,-19.97,6.953,-0.8733,0.04751,-0.000952},
|
||||||
|
/*Th*/{7.71, 8.679,1.883E4,586.3,0.002641,0.04589,1239,-20.04,6.967,-0.8741,0.04752,-0.0009516},
|
||||||
|
/*Pa*/{7.407, 8.336,1.901E4,586.3,0.002603,0.0464,1221,-20.11,6.981,-0.8749,0.04752,-0.0009512},
|
||||||
|
/*U*/{7.29, 8.204,1.918E4,586.3,0.002573,0.04691,1207,-20.18,6.995,-0.8757,0.04753,-0.0009508}
|
||||||
|
};
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -19,39 +19,40 @@ Written by G.W. McCann Aug. 2020
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include "MassLookup.h"
|
#include "MassLookup.h"
|
||||||
|
|
||||||
class EnergyLoss {
|
namespace Mask {
|
||||||
|
class EnergyLoss {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
EnergyLoss();
|
EnergyLoss();
|
||||||
~EnergyLoss();
|
~EnergyLoss();
|
||||||
double GetEnergyLoss(int zp, int ap, double e_initial, double thickness);
|
double GetEnergyLoss(int zp, int ap, double e_initial, double thickness);
|
||||||
double GetReverseEnergyLoss(int zp, int ap, double e_final, double thickness);
|
double GetReverseEnergyLoss(int zp, int ap, double e_final, double thickness);
|
||||||
double GetRange(double energy);
|
double GetRange(double energy);
|
||||||
void SetTargetComponents(std::vector<int>& Zt, std::vector<int>& At, std::vector<int>& Stoich);
|
void SetTargetComponents(std::vector<int>& Zt, std::vector<int>& At, std::vector<int>& Stoich);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
double GetElectronicStoppingPower(double energy);
|
double GetElectronicStoppingPower(double energy);
|
||||||
double GetNuclearStoppingPower(double energy);
|
double GetNuclearStoppingPower(double energy);
|
||||||
double GetTotalStoppingPower(double energy);
|
double GetTotalStoppingPower(double energy);
|
||||||
double Hydrogen_dEdx_Low(double e_per_u, int z);
|
double Hydrogen_dEdx_Low(double e_per_u, int z);
|
||||||
double Hydrogen_dEdx_Med(double e_per_u, int z);
|
double Hydrogen_dEdx_Med(double e_per_u, int z);
|
||||||
double Hydrogen_dEdx_High(double e_per_u, double energy, int z);
|
double Hydrogen_dEdx_High(double e_per_u, double energy, int z);
|
||||||
double CalculateEffectiveChargeRatio(double e_per_u, int z);
|
double CalculateEffectiveChargeRatio(double e_per_u, int z);
|
||||||
|
|
||||||
int ZP, AP;
|
int ZP, AP;
|
||||||
double MP; //units of u, isotopic
|
double MP; //units of u, isotopic
|
||||||
double comp_denom;
|
double comp_denom;
|
||||||
std::vector<int> ZT, AT;
|
std::vector<int> ZT, AT;
|
||||||
std::vector<double> targ_composition;
|
std::vector<double> targ_composition;
|
||||||
|
|
||||||
//constants for calculations
|
//constants for calculations
|
||||||
static constexpr double MAX_FRACTIONAL_STEP = 0.001;
|
static constexpr double MAX_FRACTIONAL_STEP = 0.001;
|
||||||
static constexpr double MAX_DEPTH = 50;
|
static constexpr double MAX_DEPTH = 50;
|
||||||
static constexpr double MAX_H_E_PER_U = 100000.0;
|
static constexpr double MAX_H_E_PER_U = 100000.0;
|
||||||
static constexpr double AVOGADRO = 0.60221367; //N_A times 10^(-24) for converting
|
static constexpr double AVOGADRO = 0.60221367; //N_A times 10^(-24) for converting
|
||||||
static constexpr double MEV2U = 1.0/931.4940954;
|
static constexpr double MEV2U = 1.0/931.4940954;
|
||||||
static constexpr double PI = 3.14159265358979323846;
|
static constexpr double H_RESTMASS = 938.27231; //MeV, for beta calc
|
||||||
static constexpr double H_RESTMASS = 938.27231; //MeV, for beta calc
|
};
|
||||||
};
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
|
|
||||||
LayeredTarget.h
|
LayeredTarget.h
|
||||||
Functional unit for targets in the SPANCRedux environment. Contains a
|
Functional unit for targets in the Mask environment. Contains a
|
||||||
set (read: vector) of Targets for use in reaction calculations. In this
|
set (read: vector) of Targets for use in reaction calculations. In this
|
||||||
way handles situations such as carbon backed targets
|
way handles situations such as carbon backed targets
|
||||||
|
|
||||||
|
@ -15,27 +15,30 @@ Written by G.W. McCann Aug. 2020
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <iostream>
|
|
||||||
#include "Target.h"
|
#include "Target.h"
|
||||||
|
|
||||||
class LayeredTarget {
|
namespace Mask {
|
||||||
|
|
||||||
public:
|
class LayeredTarget {
|
||||||
LayeredTarget();
|
|
||||||
~LayeredTarget();
|
|
||||||
void AddLayer(std::vector<int>& Z, std::vector<int>& A, std::vector<int>& stoich, double thickness);
|
|
||||||
double GetProjectileEnergyLoss(int zp, int ap, double startEnergy, int rxnLayer, double angle);
|
|
||||||
double GetEjectileEnergyLoss(int ze, int ae, double startEnergy, int rxnLayer, double angle);
|
|
||||||
double GetEjectileReverseEnergyLoss(int ze, int ae, double startEnergy, int rxnLayer, double angle);
|
|
||||||
int GetNumberOfLayers();
|
|
||||||
int FindLayerContaining(int Z, int A);
|
|
||||||
void SetName(std::string& n);
|
|
||||||
Target& GetLayerInfo(int index);
|
|
||||||
std::string& GetName();
|
|
||||||
|
|
||||||
private:
|
public:
|
||||||
std::vector<Target> layers;
|
LayeredTarget();
|
||||||
std::string name;
|
~LayeredTarget();
|
||||||
};
|
void AddLayer(std::vector<int>& Z, std::vector<int>& A, std::vector<int>& stoich, double thickness);
|
||||||
|
double GetProjectileEnergyLoss(int zp, int ap, double startEnergy, int rxnLayer, double angle);
|
||||||
|
double GetEjectileEnergyLoss(int ze, int ae, double startEnergy, int rxnLayer, double angle);
|
||||||
|
double GetEjectileReverseEnergyLoss(int ze, int ae, double startEnergy, int rxnLayer, double angle);
|
||||||
|
int FindLayerContaining(int Z, int A);
|
||||||
|
inline int GetNumberOfLayers() { return layers.size(); }
|
||||||
|
inline void SetName(std::string& n) { name = n; }
|
||||||
|
inline const Target& GetLayerInfo(int index) { return layers[index]; }
|
||||||
|
inline const std::string& GetName() { return name; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<Target> layers;
|
||||||
|
std::string name;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,12 +1,16 @@
|
||||||
#ifndef LEGENDREPOLY_H
|
#ifndef LEGENDREPOLY_H
|
||||||
#define LEGENDREPOLY_H
|
#define LEGENDREPOLY_H
|
||||||
|
|
||||||
double P_l(int l, double x);
|
namespace Mask {
|
||||||
double P_l_ROOT(double* x, double* pars);
|
|
||||||
double Normed_P_l_sq(int l, double x);
|
|
||||||
|
|
||||||
double P_0(double x);
|
double P_l(int l, double x);
|
||||||
double P_1(double x);
|
double P_l_ROOT(double* x, double* pars);
|
||||||
double P_2(double x);
|
double Normed_P_l_sq(int l, double x);
|
||||||
|
|
||||||
|
double P_0(double x);
|
||||||
|
double P_1(double x);
|
||||||
|
double P_2(double x);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -12,36 +12,38 @@ Converted to true singleton to simplify usage -- Aug. 2021 GWM
|
||||||
#ifndef MASS_LOOKUP_H
|
#ifndef MASS_LOOKUP_H
|
||||||
#define MASS_LOOKUP_H
|
#define MASS_LOOKUP_H
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <stdexcept>
|
|
||||||
|
|
||||||
class MassLookup {
|
namespace Mask {
|
||||||
|
|
||||||
public:
|
class MassLookup {
|
||||||
~MassLookup();
|
public:
|
||||||
double FindMass(int Z, int A);
|
~MassLookup();
|
||||||
std::string FindSymbol(int Z, int A);
|
double FindMass(int Z, int A);
|
||||||
static MassLookup* GetInstance() {
|
std::string FindSymbol(int Z, int A);
|
||||||
if(s_instance == nullptr) {
|
|
||||||
s_instance = new MassLookup();
|
|
||||||
}
|
|
||||||
return s_instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
static MassLookup* GetInstance() {
|
||||||
MassLookup();
|
if(s_instance == nullptr) {
|
||||||
std::unordered_map<std::string, double> massTable;
|
s_instance = new MassLookup();
|
||||||
std::unordered_map<int, std::string> elementTable;
|
}
|
||||||
|
return s_instance;
|
||||||
|
}
|
||||||
|
|
||||||
static MassLookup* s_instance;
|
private:
|
||||||
|
MassLookup();
|
||||||
|
std::unordered_map<std::string, double> massTable;
|
||||||
|
std::unordered_map<int, std::string> elementTable;
|
||||||
|
|
||||||
//constants
|
static MassLookup* s_instance;
|
||||||
static constexpr double u_to_mev = 931.4940954;
|
|
||||||
static constexpr double electron_mass = 0.000548579909;
|
|
||||||
|
|
||||||
};
|
//constants
|
||||||
|
static constexpr double u_to_mev = 931.4940954;
|
||||||
|
static constexpr double electron_mass = 0.000548579909;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -14,66 +14,65 @@
|
||||||
|
|
||||||
namespace Mask {
|
namespace Mask {
|
||||||
|
|
||||||
class Reaction {
|
class Reaction {
|
||||||
public:
|
public:
|
||||||
Reaction();
|
Reaction();
|
||||||
Reaction(int zt, int at, int zp, int ap, int ze, int ae);
|
Reaction(int zt, int at, int zp, int ap, int ze, int ae);
|
||||||
~Reaction();
|
~Reaction();
|
||||||
bool Calculate();
|
bool Calculate();
|
||||||
void SetNuclei(int zt, int at, int zp, int ap, int ze, int ae);
|
void SetNuclei(int zt, int at, int zp, int ap, int ze, int ae);
|
||||||
void SetNuclei(const Nucleus* nucs);
|
void SetNuclei(const Nucleus* nucs);
|
||||||
void SetBeamKE(double bke);
|
void SetBeamKE(double bke);
|
||||||
void SetEjectileThetaType(int type);
|
void SetEjectileThetaType(int type);
|
||||||
|
|
||||||
/*Setters and getters*/
|
inline void SetLayeredTarget(LayeredTarget* targ) { target = targ; };
|
||||||
inline void SetLayeredTarget(LayeredTarget* targ) { target = targ; };
|
inline void SetPolarRxnAngle(double theta) { m_theta = theta; };
|
||||||
inline void SetPolarRxnAngle(double theta) { m_theta = theta; };
|
inline void SetAzimRxnAngle(double phi) { m_phi = phi; };
|
||||||
inline void SetAzimRxnAngle(double phi) { m_phi = phi; };
|
inline void SetExcitation(double ex) { m_ex = ex; };
|
||||||
inline void SetExcitation(double ex) { m_ex = ex; };
|
inline void SetTarget(const Nucleus& nuc) { reactants[0] = nuc; };
|
||||||
inline void SetTarget(const Nucleus& nuc) { reactants[0] = nuc; };
|
inline void SetTarget(int z, int a) { reactants[0] = Nucleus(z, a); };
|
||||||
inline void SetTarget(int z, int a) { reactants[0] = Nucleus(z, a); };
|
inline void SetProjectile(const Nucleus& nuc) { reactants[1] = nuc; };
|
||||||
inline void SetProjectile(const Nucleus& nuc) { reactants[1] = nuc; };
|
inline void SetProjectile(int z, int a) { reactants[1] = Nucleus(z, a); };
|
||||||
inline void SetProjectile(int z, int a) { reactants[1] = Nucleus(z, a); };
|
inline void SetEjectile(const Nucleus& nuc) { reactants[2] = nuc; };
|
||||||
inline void SetEjectile(const Nucleus& nuc) { reactants[2] = nuc; };
|
inline void SetEjectile(int z, int a) { reactants[2] = Nucleus(z, a); };
|
||||||
inline void SetEjectile(int z, int a) { reactants[2] = Nucleus(z, a); };
|
inline void SetResidual(const Nucleus& nuc) { reactants[3] = nuc; };
|
||||||
inline void SetResidual(const Nucleus& nuc) { reactants[3] = nuc; };
|
inline void SetResidual(int z, int a) { reactants[3] = Nucleus(z, a); };
|
||||||
inline void SetResidual(int z, int a) { reactants[3] = Nucleus(z, a); };
|
inline void SetRxnLayer(int layer) { rxnLayer = layer; };
|
||||||
inline void SetRxnLayer(int layer) { rxnLayer = layer; };
|
inline void TurnOffResidualEloss() { resid_elossFlag = false; };
|
||||||
inline void TurnOffResidualEloss() { resid_elossFlag = false; };
|
inline void TurnOnResidualEloss() { resid_elossFlag = true; };
|
||||||
inline void TurnOnResidualEloss() { resid_elossFlag = true; };
|
inline bool IsDecay() { return decayFlag; };
|
||||||
inline bool IsDecay() { return decayFlag; };
|
inline const Nucleus* GetNuclei() const { return &(reactants[0]); };
|
||||||
inline const Nucleus* GetNuclei() const { return &(reactants[0]); };
|
inline const Nucleus& GetProjectile() const { return reactants[1]; };
|
||||||
inline const Nucleus& GetProjectile() const { return reactants[1]; };
|
inline const Nucleus& GetTarget() const { return reactants[0]; };
|
||||||
inline const Nucleus& GetTarget() const { return reactants[0]; };
|
inline const Nucleus& GetEjectile() const { return reactants[2]; };
|
||||||
inline const Nucleus& GetEjectile() const { return reactants[2]; };
|
inline const Nucleus& GetResidual() const { return reactants[3]; };
|
||||||
inline const Nucleus& GetResidual() const { return reactants[3]; };
|
inline int GetRxnLayer() { return rxnLayer; };
|
||||||
inline void ResetTarget() { reactants[0].SetVectorCartesian(0,0,0,0); };
|
inline void ResetTarget() { reactants[0].SetVectorCartesian(0,0,0, reactants[0].GetGroundStateMass()); }
|
||||||
inline void ResetProjectile() { reactants[1].SetVectorCartesian(0,0,0,0); };
|
inline void ResetProjectile() { reactants[1].SetVectorCartesian(0,0,0, reactants[1].GetGroundStateMass()); }
|
||||||
inline void ResetEjectile() { reactants[2].SetVectorCartesian(0,0,0,0); };
|
inline void ResetEjectile() { reactants[2].SetVectorCartesian(0,0,0, reactants[2].GetGroundStateMass()); }
|
||||||
inline void ResetResidual() { reactants[3].SetVectorCartesian(0,0,0,0); };
|
inline void ResetResidual() { reactants[3].SetVectorCartesian(0,0,0, reactants[3].GetGroundStateMass()); }
|
||||||
inline int GetRxnLayer() { return rxnLayer; };
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void CalculateReaction(); //target + project -> eject + resid
|
void CalculateDecay(); //target -> light_decay (eject) + heavy_decay(resid)
|
||||||
void CalculateReactionThetaLab();
|
void CalculateReaction(); //target + project -> eject + resid
|
||||||
void CalculateReactionThetaCM();
|
void CalculateReactionThetaLab();
|
||||||
void CalculateDecay(); //target -> light_decay (eject) + heavy_decay(resid)
|
void CalculateReactionThetaCM();
|
||||||
|
|
||||||
Nucleus reactants[4]; //0=target, 1=projectile, 2=ejectile, 3=residual
|
Nucleus reactants[4]; //0=target, 1=projectile, 2=ejectile, 3=residual
|
||||||
LayeredTarget* target; //not owned by Reaction
|
LayeredTarget* target; //not owned by Reaction
|
||||||
|
|
||||||
double m_bke, m_theta, m_phi, m_ex;
|
double m_bke, m_theta, m_phi, m_ex;
|
||||||
|
|
||||||
int rxnLayer;
|
int rxnLayer;
|
||||||
int m_eject_theta_type;
|
int m_eject_theta_type;
|
||||||
|
|
||||||
bool decayFlag, nuc_initFlag, resid_elossFlag;
|
bool decayFlag, nuc_initFlag, resid_elossFlag;
|
||||||
|
|
||||||
static constexpr int lab = 0;
|
static constexpr int lab = 0;
|
||||||
static constexpr int center_of_mass = 1;
|
static constexpr int center_of_mass = 1;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -10,69 +10,69 @@
|
||||||
|
|
||||||
namespace Mask {
|
namespace Mask {
|
||||||
|
|
||||||
class XRotation {
|
class XRotation {
|
||||||
public:
|
public:
|
||||||
XRotation();
|
XRotation();
|
||||||
XRotation(double ang);
|
XRotation(double ang);
|
||||||
~XRotation();
|
~XRotation();
|
||||||
Vec3 Rotate(const Vec3& vector);
|
Vec3 Rotate(const Vec3& vector);
|
||||||
inline void SetAngle(double ang) { m_angle = ang; GenerateMatrix(); };
|
inline void SetAngle(double ang) { m_angle = ang; GenerateMatrix(); }
|
||||||
inline XRotation GetInverse() { return XRotation(-m_angle); };
|
inline XRotation GetInverse() { return XRotation(-m_angle); }
|
||||||
inline Vec3 operator*(const Vec3& vector) {
|
inline Vec3 operator*(const Vec3& vector) {
|
||||||
double x = m_matrix[0][0]*vector[0] + m_matrix[0][1]*vector[1] + m_matrix[0][2]*vector[2];
|
double x = m_matrix[0][0]*vector[0] + m_matrix[0][1]*vector[1] + m_matrix[0][2]*vector[2];
|
||||||
double y = m_matrix[1][0]*vector[0] + m_matrix[1][1]*vector[1] + m_matrix[1][2]*vector[2];
|
double y = m_matrix[1][0]*vector[0] + m_matrix[1][1]*vector[1] + m_matrix[1][2]*vector[2];
|
||||||
double z = m_matrix[2][0]*vector[0] + m_matrix[2][1]*vector[1] + m_matrix[2][2]*vector[2];
|
double z = m_matrix[2][0]*vector[0] + m_matrix[2][1]*vector[1] + m_matrix[2][2]*vector[2];
|
||||||
return Vec3(x, y, z);
|
return Vec3(x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void GenerateMatrix();
|
||||||
|
double m_angle;
|
||||||
|
double m_matrix[3][3];
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
class YRotation {
|
||||||
void GenerateMatrix();
|
public:
|
||||||
double m_angle;
|
YRotation();
|
||||||
double m_matrix[3][3];
|
YRotation(double ang);
|
||||||
};
|
~YRotation();
|
||||||
|
Vec3 Rotate(const Vec3& vector);
|
||||||
|
inline void SetAngle(double ang) { m_angle = ang; GenerateMatrix(); }
|
||||||
|
inline YRotation GetInverse() { return YRotation(-m_angle); }
|
||||||
|
inline Vec3 operator*(const Vec3& vector) {
|
||||||
|
double x = m_matrix[0][0]*vector[0] + m_matrix[0][1]*vector[1] + m_matrix[0][2]*vector[2];
|
||||||
|
double y = m_matrix[1][0]*vector[0] + m_matrix[1][1]*vector[1] + m_matrix[1][2]*vector[2];
|
||||||
|
double z = m_matrix[2][0]*vector[0] + m_matrix[2][1]*vector[1] + m_matrix[2][2]*vector[2];
|
||||||
|
return Vec3(x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
class YRotation {
|
private:
|
||||||
public:
|
void GenerateMatrix();
|
||||||
YRotation();
|
double m_angle;
|
||||||
YRotation(double ang);
|
double m_matrix[3][3];
|
||||||
~YRotation();
|
|
||||||
Vec3 Rotate(const Vec3& vector);
|
|
||||||
inline void SetAngle(double ang) { m_angle = ang; GenerateMatrix(); };
|
|
||||||
inline YRotation GetInverse() { return YRotation(-m_angle); };
|
|
||||||
inline Vec3 operator*(const Vec3& vector) {
|
|
||||||
double x = m_matrix[0][0]*vector[0] + m_matrix[0][1]*vector[1] + m_matrix[0][2]*vector[2];
|
|
||||||
double y = m_matrix[1][0]*vector[0] + m_matrix[1][1]*vector[1] + m_matrix[1][2]*vector[2];
|
|
||||||
double z = m_matrix[2][0]*vector[0] + m_matrix[2][1]*vector[1] + m_matrix[2][2]*vector[2];
|
|
||||||
return Vec3(x, y, z);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
class ZRotation {
|
||||||
void GenerateMatrix();
|
public:
|
||||||
double m_angle;
|
ZRotation();
|
||||||
double m_matrix[3][3];
|
ZRotation(double ang);
|
||||||
};
|
~ZRotation();
|
||||||
|
Vec3 Rotate(const Vec3& vector);
|
||||||
|
inline void SetAngle(double ang) { m_angle = ang; GenerateMatrix(); }
|
||||||
|
inline ZRotation GetInverse() { return ZRotation(-m_angle); }
|
||||||
|
inline Vec3 operator*(const Vec3& vector) {
|
||||||
|
double x = m_matrix[0][0]*vector[0] + m_matrix[0][1]*vector[1] + m_matrix[0][2]*vector[2];
|
||||||
|
double y = m_matrix[1][0]*vector[0] + m_matrix[1][1]*vector[1] + m_matrix[1][2]*vector[2];
|
||||||
|
double z = m_matrix[2][0]*vector[0] + m_matrix[2][1]*vector[1] + m_matrix[2][2]*vector[2];
|
||||||
|
return Vec3(x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
class ZRotation {
|
private:
|
||||||
public:
|
void GenerateMatrix();
|
||||||
ZRotation();
|
double m_angle;
|
||||||
ZRotation(double ang);
|
double m_matrix[3][3];
|
||||||
~ZRotation();
|
|
||||||
Vec3 Rotate(const Vec3& vector);
|
|
||||||
inline void SetAngle(double ang) { m_angle = ang; GenerateMatrix();};
|
|
||||||
inline ZRotation GetInverse() { return ZRotation(-m_angle); };
|
|
||||||
inline Vec3 operator*(const Vec3& vector) {
|
|
||||||
double x = m_matrix[0][0]*vector[0] + m_matrix[0][1]*vector[1] + m_matrix[0][2]*vector[2];
|
|
||||||
double y = m_matrix[1][0]*vector[0] + m_matrix[1][1]*vector[1] + m_matrix[1][2]*vector[2];
|
|
||||||
double z = m_matrix[2][0]*vector[0] + m_matrix[2][1]*vector[1] + m_matrix[2][2]*vector[2];
|
|
||||||
return Vec3(x, y, z);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
}
|
||||||
void GenerateMatrix();
|
|
||||||
double m_angle;
|
|
||||||
double m_matrix[3][3];
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -171,4 +171,5 @@ private:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -21,8 +21,8 @@ private:
|
||||||
|
|
||||||
std::vector<SabreDetector> detectors;
|
std::vector<SabreDetector> detectors;
|
||||||
|
|
||||||
Target deadlayer;
|
Mask::Target deadlayer;
|
||||||
Target sabre_eloss;
|
Mask::Target sabre_eloss;
|
||||||
DeadChannelMap dmap;
|
DeadChannelMap dmap;
|
||||||
|
|
||||||
//Sabre constants
|
//Sabre constants
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
|
|
||||||
Target.h
|
Target.h
|
||||||
A basic target unit for use in the SPANCRedux environment. A target
|
A basic target unit for use in the Mask environment. A target
|
||||||
is defined as a single compound with elements Z,A of a given stoichiometry
|
is defined as a single compound with elements Z,A of a given stoichiometry
|
||||||
Holds an energy loss class
|
Holds an energy loss class
|
||||||
|
|
||||||
|
@ -15,32 +15,35 @@ Written by G.W. McCann Aug. 2020
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <cmath>
|
||||||
#include "EnergyLoss.h"
|
#include "EnergyLoss.h"
|
||||||
|
|
||||||
class Target {
|
namespace Mask {
|
||||||
|
|
||||||
public:
|
class Target {
|
||||||
Target(double thick);
|
|
||||||
~Target();
|
|
||||||
void SetElements(std::vector<int>& z, std::vector<int>& a, std::vector<int>& stoich);
|
|
||||||
bool ContainsElement(int z, int a);
|
|
||||||
double getEnergyLossTotal(int zp, int ap, double startEnergy, double angle);
|
|
||||||
double getEnergyLossHalf(int zp, int ap, double startEnergy, double angle);
|
|
||||||
double getReverseEnergyLossTotal(int zp, int ap, double finalEnergy, double angle);
|
|
||||||
double getReverseEnergyLossHalf(int zp, int ap, double finalEnergy, double angle);
|
|
||||||
double& GetThickness();
|
|
||||||
int GetNumberOfElements();
|
|
||||||
int GetElementZ(int index);
|
|
||||||
int GetElementA(int index);
|
|
||||||
int GetElementStoich(int index);
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
Target(double thick);
|
||||||
|
~Target();
|
||||||
|
void SetElements(std::vector<int>& z, std::vector<int>& a, std::vector<int>& stoich);
|
||||||
|
bool ContainsElement(int z, int a);
|
||||||
|
double getEnergyLossTotal(int zp, int ap, double startEnergy, double angle);
|
||||||
|
double getEnergyLossHalf(int zp, int ap, double startEnergy, double angle);
|
||||||
|
double getReverseEnergyLossTotal(int zp, int ap, double finalEnergy, double angle);
|
||||||
|
double getReverseEnergyLossHalf(int zp, int ap, double finalEnergy, double angle);
|
||||||
|
inline const double& GetThickness() { return thickness; }
|
||||||
|
inline int GetNumberOfElements() { return Z.size(); }
|
||||||
|
inline int GetElementZ(int index) { return Z[index]; }
|
||||||
|
inline int GetElementA(int index) { return A[index]; }
|
||||||
|
inline int GetElementStoich(int index) { return Stoich[index]; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
EnergyLoss eloss;
|
EnergyLoss eloss;
|
||||||
double thickness;
|
double thickness;
|
||||||
std::vector<int> Z, A, Stoich;
|
std::vector<int> Z, A, Stoich;
|
||||||
static constexpr double PI = 3.14159265358979323846;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -11,51 +11,51 @@
|
||||||
|
|
||||||
namespace Mask {
|
namespace Mask {
|
||||||
|
|
||||||
class Vec3 {
|
class Vec3 {
|
||||||
public:
|
public:
|
||||||
Vec3();
|
Vec3();
|
||||||
Vec3(double x, double y, double z);
|
Vec3(double x, double y, double z);
|
||||||
~Vec3();
|
~Vec3();
|
||||||
|
|
||||||
|
void SetVectorCartesian(double x, double y, double z);
|
||||||
|
void SetVectorSpherical(double r, double theta, double phi);
|
||||||
|
inline double GetX() const { return m_data[0]; }
|
||||||
|
inline double GetY() const { return m_data[1]; }
|
||||||
|
inline double GetZ() const { return m_data[2]; }
|
||||||
|
inline double GetRho() const { return std::sqrt(std::pow(m_data[0], 2.0) + std::pow(m_data[1], 2.0)); }
|
||||||
|
inline double GetR() const { return std::sqrt(std::pow(m_data[0], 2.0) + std::pow(m_data[1], 2.0) + std::pow(m_data[2], 2.0)); }
|
||||||
|
inline double GetTheta() const { return Atan2(GetRho(), GetZ()); }
|
||||||
|
inline double GetPhi() const {
|
||||||
|
double phi = Atan2(GetY(), GetX());
|
||||||
|
if(phi < 0) phi += M_PI*2.0;
|
||||||
|
return phi;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const double operator[](int index) const { return index>2 || index<0 ? 0.0 : m_data[index]; }
|
||||||
|
inline Vec3& operator=(const Vec3& rhs) { SetVectorCartesian(rhs.GetX(), rhs.GetY(), rhs.GetZ()); return *this; }
|
||||||
|
inline Vec3 operator+(const Vec3& rhs) const { return Vec3(this->GetX()+rhs.GetX(), this->GetY()+rhs.GetY(), this->GetZ()+rhs.GetZ()); }
|
||||||
|
inline Vec3 operator-(const Vec3& rhs) const { return Vec3(this->GetX()-rhs.GetX(), this->GetY()-rhs.GetY(), this->GetZ()-rhs.GetZ()); }
|
||||||
|
|
||||||
|
|
||||||
|
double Dot(const Vec3& rhs) const;
|
||||||
|
Vec3 Cross(const Vec3& rhs) const;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
//Use instead of std::atan2. Better control over values close to x=0
|
||||||
|
inline double Atan2(double y, double x) const {
|
||||||
|
if(x != 0.0) return std::atan2(y, x);
|
||||||
|
else if(y > 0.0) return M_PI/2.0;
|
||||||
|
else if(y < 0.0) return -M_PI/2.0;
|
||||||
|
else return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
double m_data[3];
|
||||||
|
|
||||||
void SetVectorCartesian(double x, double y, double z);
|
|
||||||
void SetVectorSpherical(double r, double theta, double phi);
|
|
||||||
inline double GetX() const { return m_data[0]; };
|
|
||||||
inline double GetY() const { return m_data[1]; };
|
|
||||||
inline double GetZ() const { return m_data[2]; };
|
|
||||||
inline double GetRho() const { return std::sqrt(std::pow(m_data[0], 2.0) + std::pow(m_data[1], 2.0)); };
|
|
||||||
inline double GetR() const { return std::sqrt(std::pow(m_data[0], 2.0) + std::pow(m_data[1], 2.0) + std::pow(m_data[2], 2.0)); }
|
|
||||||
inline double GetTheta() const { return Atan2(GetRho(), GetZ()); };
|
|
||||||
inline double GetPhi() const {
|
|
||||||
double phi = Atan2(GetY(), GetX());
|
|
||||||
if(phi < 0) phi += M_PI*2.0;
|
|
||||||
return phi;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline const double operator[](int index) const { return index>2 || index<0 ? 0.0 : m_data[index]; };
|
}
|
||||||
inline Vec3& operator=(const Vec3& rhs) { SetVectorCartesian(rhs.GetX(), rhs.GetY(), rhs.GetZ()); return *this; };
|
|
||||||
inline Vec3 operator+(const Vec3& rhs) const { return Vec3(this->GetX()+rhs.GetX(), this->GetY()+rhs.GetY(), this->GetZ()+rhs.GetZ()); };
|
|
||||||
inline Vec3 operator-(const Vec3& rhs) const { return Vec3(this->GetX()-rhs.GetX(), this->GetY()-rhs.GetY(), this->GetZ()-rhs.GetZ()); };
|
|
||||||
|
|
||||||
|
|
||||||
double Dot(const Vec3& rhs) const;
|
|
||||||
Vec3 Cross(const Vec3& rhs) const;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
//Use instead of std::atan2. Better control over values close to x=0
|
|
||||||
inline double Atan2(double y, double x) const {
|
|
||||||
if(x != 0.0) return std::atan2(y, x);
|
|
||||||
else if(y > 0.0) return M_PI/2.0;
|
|
||||||
else if(y < 0.0) return -M_PI/2.0;
|
|
||||||
else return 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
double m_data[3];
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
#endif
|
102
include/Vec4.h
102
include/Vec4.h
|
@ -11,59 +11,59 @@
|
||||||
|
|
||||||
namespace Mask {
|
namespace Mask {
|
||||||
|
|
||||||
class Vec4 {
|
class Vec4 {
|
||||||
public:
|
public:
|
||||||
Vec4();
|
Vec4();
|
||||||
Vec4(double px, double py, double pz, double E);
|
Vec4(double px, double py, double pz, double E);
|
||||||
virtual ~Vec4();
|
virtual ~Vec4();
|
||||||
void SetVectorCartesian(double px, double py, double pz, double E);
|
void SetVectorCartesian(double px, double py, double pz, double E);
|
||||||
void SetVectorSpherical(double theta, double phi, double p, double E);
|
void SetVectorSpherical(double theta, double phi, double p, double E);
|
||||||
|
|
||||||
|
inline double GetE() const { return m_data[3]; }
|
||||||
|
inline double GetPx() const { return m_data[0]; }
|
||||||
|
inline double GetPy() const { return m_data[1]; }
|
||||||
|
inline double GetPz() const { return m_data[2]; }
|
||||||
|
inline double GetP() const { return std::sqrt(m_data[0]*m_data[0] + m_data[1]*m_data[1] + m_data[2]*m_data[2]); }
|
||||||
|
inline double GetPxy() const { return std::sqrt(m_data[0]*m_data[0] + m_data[1]*m_data[1]); }
|
||||||
|
inline double GetTheta() const { return GetPxy() == 0.0 && GetPz() == 0.0 ? 0.0 : Atan2(GetPxy(), GetPz()); }
|
||||||
|
inline double GetPhi() const {
|
||||||
|
double phi = Atan2(GetPy(), GetPx());
|
||||||
|
if(phi<0) phi += 2.0*M_PI;
|
||||||
|
return GetPx() == 0.0 && GetPy() == 0.0 ? 0.0 : phi;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline double GetInvMass() const { return std::sqrt(GetE()*GetE() - GetP()*GetP()); }
|
||||||
|
inline double GetKE() const { return GetE() - GetInvMass(); }
|
||||||
|
inline const double* GetBoost() const { return &m_boost[0]; }
|
||||||
|
|
||||||
|
void ApplyBoost(const double* boost);
|
||||||
|
|
||||||
|
//Only intended for use in looping access!
|
||||||
|
inline const double operator[] (int index) const { return index>3 || index < 0 ? 0.0 : m_data[index]; }
|
||||||
|
|
||||||
|
inline Vec4& operator=(const Vec4& rhs) { SetVectorCartesian(rhs.GetPx(), rhs.GetPy(), rhs.GetPz(), rhs.GetE()); return *this; }
|
||||||
|
inline Vec4 operator+(const Vec4& rhs) const { return Vec4(rhs.GetPx()+GetPx(), rhs.GetPy()+GetPy(), rhs.GetPz()+GetPz(), rhs.GetE()+GetE()); }
|
||||||
|
inline Vec4 operator-(const Vec4& rhs) const { return Vec4(rhs.GetPx()-GetPx(), rhs.GetPy()-GetPy(), rhs.GetPz()-GetPz(), rhs.GetE()-GetE()); }
|
||||||
|
|
||||||
|
double Dot(const Vec4& rhs) const;
|
||||||
|
Vec4 Cross(const Vec4& rhs) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void CalcBoostToCM();
|
||||||
|
|
||||||
|
//use instead of std::atan2. Better controll over x=0
|
||||||
|
inline double Atan2(double y, double x) const {
|
||||||
|
if(x != 0) return std::atan2(y, x);
|
||||||
|
else if( y > 0 ) return M_PI/2.0;
|
||||||
|
else if( y < 0 ) return -M_PI/2.0;
|
||||||
|
else return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
double m_data[4];
|
||||||
|
double m_boost[3];
|
||||||
|
|
||||||
inline double GetE() const {return m_data[3];};
|
|
||||||
inline double GetPx() const {return m_data[0];};
|
|
||||||
inline double GetPy() const {return m_data[1];};
|
|
||||||
inline double GetPz() const {return m_data[2];};
|
|
||||||
inline double GetP() const {return std::sqrt(m_data[0]*m_data[0] + m_data[1]*m_data[1] + m_data[2]*m_data[2]);};
|
|
||||||
inline double GetPxy() const {return std::sqrt(m_data[0]*m_data[0] + m_data[1]*m_data[1]); };
|
|
||||||
inline double GetTheta() const {return GetPxy() == 0.0 && GetPz() == 0.0 ? 0.0 : Atan2(GetPxy(), GetPz());};
|
|
||||||
inline double GetPhi() const {
|
|
||||||
double phi = Atan2(GetPy(), GetPx());
|
|
||||||
if(phi<0) phi += 2.0*M_PI;
|
|
||||||
return GetPx() == 0.0 && GetPy() == 0.0 ? 0.0 : phi;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline double GetInvMass() const {return std::sqrt(GetE()*GetE() - GetP()*GetP());};
|
}
|
||||||
inline double GetKE() const {return GetE() - GetInvMass();};
|
|
||||||
inline const double* GetBoost() const {return &m_boost[0];};
|
|
||||||
|
|
||||||
void ApplyBoost(const double* boost);
|
|
||||||
|
|
||||||
//Only intended for use in looping access!
|
|
||||||
inline const double operator[] (int index) const {return index>3 || index < 0 ? 0.0 : m_data[index];};
|
|
||||||
|
|
||||||
inline Vec4& operator=(const Vec4& rhs) {SetVectorCartesian(rhs.GetPx(), rhs.GetPy(), rhs.GetPz(), rhs.GetE()); return *this;};
|
|
||||||
inline Vec4 operator+(const Vec4& rhs) const {return Vec4(rhs.GetPx()+GetPx(), rhs.GetPy()+GetPy(), rhs.GetPz()+GetPz(), rhs.GetE()+GetE());};
|
|
||||||
inline Vec4 operator-(const Vec4& rhs) const {return Vec4(rhs.GetPx()-GetPx(), rhs.GetPy()-GetPy(), rhs.GetPz()-GetPz(), rhs.GetE()-GetE());};
|
|
||||||
|
|
||||||
double Dot(const Vec4& rhs) const;
|
|
||||||
Vec4 Cross(const Vec4& rhs) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void CalcBoostToCM();
|
|
||||||
|
|
||||||
//use instead of std::atan2. Better controll over x=0
|
|
||||||
inline double Atan2(double y, double x) const {
|
|
||||||
if(x != 0) return std::atan2(y, x);
|
|
||||||
else if( y > 0 ) return M_PI/2.0;
|
|
||||||
else if( y < 0 ) return -M_PI/2.0;
|
|
||||||
else return 0.0;
|
|
||||||
};
|
|
||||||
|
|
||||||
double m_data[4];
|
|
||||||
double m_boost[3];
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -1,5 +1,5 @@
|
||||||
----------Data Information----------
|
----------Data Information----------
|
||||||
OutputFile: /data1/gwm17/mask_tests/7Bedp_600keV_beam_centered_target_targetgap_BackQQQ_rndmCM_test.mask
|
OutputFile: test/7Bedp_600keV_beam_centered_target_targetgap_BackQQQ_rndmCM_test.mask
|
||||||
SaveTree: yes
|
SaveTree: yes
|
||||||
SavePlots: yes
|
SavePlots: yes
|
||||||
----------Reaction Information----------
|
----------Reaction Information----------
|
||||||
|
|
|
@ -4,101 +4,105 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include "LegendrePoly.h"
|
#include "LegendrePoly.h"
|
||||||
|
|
||||||
AngularDistribution::AngularDistribution() :
|
namespace Mask {
|
||||||
generator(nullptr), uniform_cosine_dist(-1.0, 1.0), uniform_prob_dist(0.0, 1.0), branchingRatio(1.0), L(0), isoFlag(true)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
AngularDistribution::AngularDistribution(const std::string& file) :
|
AngularDistribution::AngularDistribution() :
|
||||||
generator(nullptr), branchingRatio(1.0), L(0), isoFlag(true)
|
generator(nullptr), uniform_cosine_dist(-1.0, 1.0), uniform_prob_dist(0.0, 1.0), branchingRatio(1.0), L(0), isoFlag(true)
|
||||||
{
|
{
|
||||||
ReadDistributionFile(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
AngularDistribution::~AngularDistribution() {}
|
|
||||||
|
|
||||||
void AngularDistribution::ReadDistributionFile(const std::string& file) {
|
|
||||||
|
|
||||||
if(file == "none" || file == "") {
|
|
||||||
L=0;
|
|
||||||
branchingRatio=1.0;
|
|
||||||
constants.clear();
|
|
||||||
constants.push_back(0.5);
|
|
||||||
isoFlag = true;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ifstream input(file);
|
AngularDistribution::AngularDistribution(const std::string& file) :
|
||||||
std::string junk;
|
generator(nullptr), branchingRatio(1.0), L(0), isoFlag(true)
|
||||||
int l;
|
{
|
||||||
double par;
|
ReadDistributionFile(file);
|
||||||
|
|
||||||
if(!input.is_open()) {
|
|
||||||
std::cerr<<"Unable to open distribution file. All values reset to default."<<std::endl;
|
|
||||||
L=0;
|
|
||||||
branchingRatio=1.0;
|
|
||||||
constants.clear();
|
|
||||||
constants.push_back(0.5);
|
|
||||||
isoFlag = true;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
input>>junk>>l;
|
AngularDistribution::~AngularDistribution() {}
|
||||||
while(input>>junk) {
|
|
||||||
input>>par;
|
void AngularDistribution::ReadDistributionFile(const std::string& file) {
|
||||||
constants.push_back(par);
|
|
||||||
}
|
if(file == "none" || file == "") {
|
||||||
input.close();
|
L=0;
|
||||||
|
branchingRatio=1.0;
|
||||||
|
constants.clear();
|
||||||
|
constants.push_back(0.5);
|
||||||
|
isoFlag = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ifstream input(file);
|
||||||
|
std::string junk;
|
||||||
|
int l;
|
||||||
|
double par;
|
||||||
|
|
||||||
|
if(!input.is_open()) {
|
||||||
|
std::cerr<<"Unable to open distribution file. All values reset to default."<<std::endl;
|
||||||
|
L=0;
|
||||||
|
branchingRatio=1.0;
|
||||||
|
constants.clear();
|
||||||
|
constants.push_back(0.5);
|
||||||
|
isoFlag = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
input>>junk>>l;
|
||||||
|
while(input>>junk) {
|
||||||
|
input>>par;
|
||||||
|
constants.push_back(par);
|
||||||
|
}
|
||||||
|
input.close();
|
||||||
|
|
||||||
|
if(constants.size() != ((unsigned int) l+1)) {
|
||||||
|
std::cerr<<"Unexpected number of constants for given angular momentum! Expected "<<l+1<<" and given "<<constants.size()<<std::endl;
|
||||||
|
std::cerr<<"Setting all values to default."<<std::endl;
|
||||||
|
branchingRatio=1.0;
|
||||||
|
constants.clear();
|
||||||
|
constants.push_back(0.5);
|
||||||
|
isoFlag = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Total branching ratio
|
||||||
|
branchingRatio = constants[0]*2.0;
|
||||||
|
L = l;
|
||||||
|
|
||||||
|
//Renormalize distribution such that total prob is 1.0.
|
||||||
|
//Test branching ratio to see if we "make" a decay particle,
|
||||||
|
//then use re-normalized distribution to pick an angle.
|
||||||
|
if(constants[0] < 0.5) {
|
||||||
|
double norm = 0.5/constants[0];
|
||||||
|
for(auto& value : constants)
|
||||||
|
value *= norm;
|
||||||
|
}
|
||||||
|
|
||||||
|
isoFlag = false;
|
||||||
|
|
||||||
if(constants.size() != ((unsigned int) l+1)) {
|
|
||||||
std::cerr<<"Unexpected number of constants for given angular momentum! Expected "<<l+1<<" and given "<<constants.size()<<std::endl;
|
|
||||||
std::cerr<<"Setting all values to default."<<std::endl;
|
|
||||||
branchingRatio=1.0;
|
|
||||||
constants.clear();
|
|
||||||
constants.push_back(0.5);
|
|
||||||
isoFlag = true;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Total branching ratio
|
double AngularDistribution::GetRandomCosTheta() {
|
||||||
branchingRatio = constants[0]*2.0;
|
|
||||||
L = l;
|
|
||||||
|
|
||||||
//Renormalize distribution such that total prob is 1.0.
|
if(!IsGeneratorSet()) {
|
||||||
//Test branching ratio to see if we "make" a decay particle,
|
std::cerr<<"Random number generator is not set in AngularDistribution! Returning default value of 0"<<std::endl;
|
||||||
//then use re-normalized distribution to pick an angle.
|
return 0.0;
|
||||||
if(constants[0] < 0.5) {
|
}
|
||||||
double norm = 0.5/constants[0];
|
|
||||||
for(auto& value : constants)
|
|
||||||
value *= norm;
|
|
||||||
}
|
|
||||||
|
|
||||||
isoFlag = false;
|
if(isoFlag) return uniform_cosine_dist(*generator);
|
||||||
|
|
||||||
}
|
double test, probability;
|
||||||
|
double costheta;
|
||||||
|
|
||||||
double AngularDistribution::GetRandomCosTheta() {
|
|
||||||
|
|
||||||
if(!IsGeneratorSet()) {
|
|
||||||
std::cerr<<"Random number generator is not set in AngularDistribution! Returning default value of 0"<<std::endl;
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(isoFlag) return uniform_cosine_dist(*generator);
|
|
||||||
|
|
||||||
double test, probability;
|
|
||||||
double costheta;
|
|
||||||
|
|
||||||
test = uniform_prob_dist(*generator);
|
|
||||||
if(test > branchingRatio) return -10;
|
|
||||||
|
|
||||||
do {
|
|
||||||
probability = 0.0;
|
|
||||||
costheta = uniform_cosine_dist(*generator);
|
|
||||||
test = uniform_prob_dist(*generator);
|
test = uniform_prob_dist(*generator);
|
||||||
for(unsigned int i=0; i<constants.size(); i++)
|
if(test > branchingRatio) return -10;
|
||||||
probability += constants[i]*P_l(i*2, costheta);
|
|
||||||
} while(test > probability);
|
do {
|
||||||
|
probability = 0.0;
|
||||||
|
costheta = uniform_cosine_dist(*generator);
|
||||||
|
test = uniform_prob_dist(*generator);
|
||||||
|
for(unsigned int i=0; i<constants.size(); i++)
|
||||||
|
probability += constants[i]*P_l(i*2, costheta);
|
||||||
|
} while(test > probability);
|
||||||
|
|
||||||
|
return costheta;
|
||||||
|
}
|
||||||
|
|
||||||
return costheta;
|
|
||||||
}
|
}
|
|
@ -59,17 +59,14 @@ namespace Mask {
|
||||||
LinkTarget();
|
LinkTarget();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(step1.IsDecay()) {
|
double rxnTheta = std::acos(decay1dist.GetRandomCosTheta());
|
||||||
double rxnTheta = std::acos(decay1dist.GetRandomCosTheta());
|
double rxnPhi = (*m_phi1Range)(*generator);
|
||||||
double rxnPhi = (*m_phi1Range)(*generator);
|
step1.SetPolarRxnAngle(rxnTheta);
|
||||||
step1.SetPolarRxnAngle(rxnTheta);
|
step1.SetAzimRxnAngle(rxnPhi);
|
||||||
step1.SetAzimRxnAngle(rxnPhi);
|
|
||||||
|
step1.TurnOnResidualEloss();
|
||||||
|
step1.Calculate();
|
||||||
|
|
||||||
step1.TurnOnResidualEloss();
|
|
||||||
step1.Calculate();
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -49,6 +49,7 @@
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "SabreDetector.h"
|
#include "SabreDetector.h"
|
||||||
|
|
||||||
SabreDetector::SabreDetector() :
|
SabreDetector::SabreDetector() :
|
||||||
|
|
|
@ -14,231 +14,230 @@ Written by G.W. McCann Aug. 2020
|
||||||
#include "KinematicsExceptions.h"
|
#include "KinematicsExceptions.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
EnergyLoss::EnergyLoss() {
|
namespace Mask {
|
||||||
comp_denom = 0;
|
|
||||||
ZP = -1;
|
EnergyLoss::EnergyLoss() :
|
||||||
|
ZP(-1), AP(-1), MP(-1.0), comp_denom(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
EnergyLoss::~EnergyLoss() {}
|
||||||
|
|
||||||
|
/*Targets are defined by their atomic number, total number of nucleons, and their stoichiometry within the target compound*/
|
||||||
|
void EnergyLoss::SetTargetComponents(std::vector<int>& Zt, std::vector<int>& At, std::vector<int>& Stoich) {
|
||||||
|
comp_denom = 0;
|
||||||
|
ZT = Zt;
|
||||||
|
AT = At;
|
||||||
|
for(unsigned int i=0; i<Stoich.size(); i++) {
|
||||||
|
comp_denom += Stoich[i];
|
||||||
|
if(ZT[i] > MAX_Z)
|
||||||
|
throw ELossException("Maximum allowed target Z exceeded");
|
||||||
|
}
|
||||||
|
targ_composition.resize(Stoich.size());
|
||||||
|
|
||||||
|
for(unsigned int i=0; i<Stoich.size(); i++)
|
||||||
|
targ_composition[i] = Stoich[i]/comp_denom;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Returns units of MeV; thickness in ug/cm^2; e_initial in units of MeV
|
||||||
|
Energy loss going through the target
|
||||||
|
*/
|
||||||
|
double EnergyLoss::GetEnergyLoss(int zp, int ap, double e_initial, double thickness) {
|
||||||
|
if( ZP != zp) {
|
||||||
|
ZP = zp;
|
||||||
|
AP = ap;
|
||||||
|
MP = MassLookup::GetInstance()->FindMass(ZP, AP)*MEV2U;
|
||||||
|
}
|
||||||
|
|
||||||
|
double e_final = e_initial;
|
||||||
|
double x_traversed = 0;
|
||||||
|
double x_step = 0.25*thickness; //initial step in x
|
||||||
|
double e_step = GetTotalStoppingPower(e_final)*x_step/1000.0; //initial step in e
|
||||||
|
double e_threshold = 0.05*e_initial;
|
||||||
|
|
||||||
|
int depth=0;
|
||||||
|
|
||||||
|
|
||||||
|
if(thickness == 0.0 || e_initial == 0.0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
bool go = true;
|
||||||
|
while(go) {
|
||||||
|
//If intial guess of step size is too large, shrink until in range
|
||||||
|
if(e_step/e_final > MAX_FRACTIONAL_STEP && depth < MAX_DEPTH) {
|
||||||
|
depth++;
|
||||||
|
x_step *= 0.5;
|
||||||
|
e_step = GetTotalStoppingPower(e_final)*x_step/1000.0;
|
||||||
|
} else if((x_step + x_traversed) >= thickness) { //last chunk
|
||||||
|
go = false;
|
||||||
|
x_step = thickness - x_traversed; //get valid portion of last chunk
|
||||||
|
e_final -= GetTotalStoppingPower(e_final)*x_step/1000.0;
|
||||||
|
if(e_final <= e_threshold)
|
||||||
|
return e_initial;
|
||||||
|
} else if(depth == MAX_DEPTH) {
|
||||||
|
return e_initial;
|
||||||
|
} else {
|
||||||
|
x_traversed += x_step;
|
||||||
|
e_step = GetTotalStoppingPower(e_final)*x_step/1000.0;
|
||||||
|
e_final -= e_step;
|
||||||
|
if(e_final <= e_threshold)
|
||||||
|
return e_initial;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return e_initial - e_final;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Returns units of MeV; thickness in ug/cm^2; e_final in units of MeV
|
||||||
|
Energy loss going through the target using energy of particle after traversal
|
||||||
|
*/
|
||||||
|
double EnergyLoss::GetReverseEnergyLoss(int zp, int ap, double e_final, double thickness) {
|
||||||
|
if( ZP != zp) {
|
||||||
|
ZP = zp;
|
||||||
|
AP = ap;
|
||||||
|
MP = MassLookup::GetInstance()->FindMass(ZP, AP)*MEV2U;
|
||||||
|
}
|
||||||
|
|
||||||
|
double e_initial = e_final;
|
||||||
|
double x_traversed = 0.0;
|
||||||
|
double x_step = 0.25*thickness; //initial step in x
|
||||||
|
double e_step = GetTotalStoppingPower(e_initial)*x_step/1000.0; //initial step in E
|
||||||
|
|
||||||
|
bool go = true;
|
||||||
|
while(go) {
|
||||||
|
if(e_step/e_initial > MAX_FRACTIONAL_STEP) {
|
||||||
|
x_step *= 0.5;
|
||||||
|
e_step = GetTotalStoppingPower(e_initial)*x_step/1000.0;
|
||||||
|
} else if (x_traversed+x_step > thickness) {
|
||||||
|
go = false;
|
||||||
|
x_step = thickness - x_traversed;
|
||||||
|
e_initial += GetTotalStoppingPower(e_initial)*x_step/1000.0;
|
||||||
|
} else {
|
||||||
|
x_traversed += x_step;
|
||||||
|
e_step = GetTotalStoppingPower(e_initial)*x_step/1000.0;
|
||||||
|
e_initial += e_step;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return e_initial-e_final;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Returns units of keV/(ug/cm^2)
|
||||||
|
Calculates Electronic stopping power by first calculating SE for hydrogen through the target and then using
|
||||||
|
corrections to calculate SE for projectile of interest
|
||||||
|
*/
|
||||||
|
double EnergyLoss::GetElectronicStoppingPower(double energy) {
|
||||||
|
//Wants in units of keV
|
||||||
|
energy *= 1000.0;
|
||||||
|
double e_per_u = energy/MP;
|
||||||
|
std::vector<double> values;
|
||||||
|
if(e_per_u > MAX_H_E_PER_U) {
|
||||||
|
throw ELossException("Exceeded maximum allowed energy per nucleon");
|
||||||
|
} else if (e_per_u > 1000.0) {
|
||||||
|
for(auto& z: ZT)
|
||||||
|
values.push_back(Hydrogen_dEdx_High(e_per_u, energy, z));
|
||||||
|
} else if (e_per_u > 10.0) {
|
||||||
|
for(auto& z: ZT)
|
||||||
|
values.push_back(Hydrogen_dEdx_Med(e_per_u, z));
|
||||||
|
} else if (e_per_u > 0.0) {
|
||||||
|
for(auto& z: ZT)
|
||||||
|
values.push_back(Hydrogen_dEdx_Low(e_per_u, z));
|
||||||
|
} else {
|
||||||
|
throw ELossException("Negative energy per nucleon");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(values.size() == 0)
|
||||||
|
throw ELossException("Size of value array is 0. Unable to iterate over target components");
|
||||||
|
|
||||||
|
if(ZP > 1) { //not hydrogen, need to account for effective charge
|
||||||
|
for(unsigned int i=0; i<values.size(); i++)
|
||||||
|
values[i] *= CalculateEffectiveChargeRatio(e_per_u, ZT[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
double stopping_total = 0;
|
||||||
|
double conversion_factor = 0;
|
||||||
|
for(unsigned int i=0; i<ZT.size(); i++) {
|
||||||
|
conversion_factor += targ_composition[i]*NATURAL_MASS[ZT[i]];
|
||||||
|
stopping_total += values[i]*targ_composition[i];
|
||||||
|
}
|
||||||
|
stopping_total *= AVOGADRO/conversion_factor;
|
||||||
|
|
||||||
|
return stopping_total;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Returns units of keV/(ug/cm^2)
|
||||||
|
double EnergyLoss::GetNuclearStoppingPower(double energy) {
|
||||||
|
energy *= 1000.0;
|
||||||
|
double stopping_total = 0.0;
|
||||||
|
double sn, x, epsilon, conversion_factor;
|
||||||
|
for(unsigned int i=0; i<ZT.size(); i++) {
|
||||||
|
x = (MP + NATURAL_MASS[ZT[i]]) * std::sqrt(std::pow(ZP, 2.0/3.0) + std::pow(ZT[i], 2.0/3.0));
|
||||||
|
epsilon = 32.53*NATURAL_MASS[ZT[i]]*energy/(ZP*ZT[i]*x);
|
||||||
|
sn = 8.462*(0.5*std::log(1.0+epsilon)/(epsilon+0.10718*std::pow(epsilon, 0.37544)))*ZP*ZT[i]*MP/x;
|
||||||
|
conversion_factor = AVOGADRO/NATURAL_MASS[ZT[i]];
|
||||||
|
stopping_total += sn*conversion_factor*targ_composition[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return stopping_total;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*Wrapper function for aquiring total stopping (elec + nuc)*/
|
||||||
|
double EnergyLoss::GetTotalStoppingPower(double energy) {
|
||||||
|
if(ZP == 0)
|
||||||
|
return GetNuclearStoppingPower(energy);
|
||||||
|
|
||||||
|
return GetElectronicStoppingPower(energy)+GetNuclearStoppingPower(energy);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*Charge rel to H*/
|
||||||
|
double EnergyLoss::CalculateEffectiveChargeRatio(double e_per_u, int z) {
|
||||||
|
double z_ratio;
|
||||||
|
if(ZP == 2) {
|
||||||
|
double ln_epu = std::log(e_per_u);
|
||||||
|
double gamma = 1.0+(0.007+0.00005*z)*std::exp(-std::pow(7.6-ln_epu,2.0));
|
||||||
|
double alpha = 0.7446 + 0.1429*ln_epu + 0.01562*std::pow(ln_epu, 2.0) - 0.00267*std::pow(ln_epu,3.0)
|
||||||
|
+ 1.338E-6*std::pow(ln_epu,8.0);
|
||||||
|
z_ratio = gamma*(1.0-std::exp(-alpha))*2.0;
|
||||||
|
} else if (ZP == 3) {
|
||||||
|
double ln_epu = std::log(e_per_u);
|
||||||
|
double gamma = 1.0+(0.007+0.00005*z)*std::exp(-std::pow(7.6-ln_epu,2.0));
|
||||||
|
double alpha = 0.7138+0.002797*e_per_u+1.348E-6*std::pow(e_per_u, 2.0);
|
||||||
|
z_ratio = gamma*(1-std::exp(-alpha))*3.0;
|
||||||
|
} else {
|
||||||
|
double B = 0.886*std::pow(e_per_u/25.0, 0.5)/std::pow(ZP, 2.0/3.0);
|
||||||
|
double A = B + 0.0378*std::sin(M_PI/2.0*B);
|
||||||
|
z_ratio = 1.0 - std::exp(-A)*(1.034-0.1777*std::exp(-0.08114*ZP))*z;
|
||||||
|
}
|
||||||
|
return z_ratio*z_ratio; //for stopping power uses ratio sq.
|
||||||
|
}
|
||||||
|
|
||||||
|
double EnergyLoss::Hydrogen_dEdx_Low(double e_per_u, int z) {
|
||||||
|
return std::sqrt(e_per_u)*HYDROGEN_COEFF[z][0];
|
||||||
|
}
|
||||||
|
|
||||||
|
double EnergyLoss::Hydrogen_dEdx_Med(double e_per_u, int z) {
|
||||||
|
double x = HYDROGEN_COEFF[z][1]*std::pow(e_per_u, 0.45);
|
||||||
|
double y = HYDROGEN_COEFF[z][2]/e_per_u * std::log(1.0+HYDROGEN_COEFF[z][3]/e_per_u+HYDROGEN_COEFF[z][4]*e_per_u);
|
||||||
|
return x*y/(x+y);
|
||||||
|
}
|
||||||
|
|
||||||
|
double EnergyLoss::Hydrogen_dEdx_High(double e_per_u, double energy, int z) {
|
||||||
|
energy /= 1000.0; //back to MeV for ease of beta calc
|
||||||
|
double beta_sq = energy * (energy+2.0*MP/MEV2U)/std::pow(energy+MP/MEV2U, 2.0);
|
||||||
|
double alpha = HYDROGEN_COEFF[z][5]/beta_sq;
|
||||||
|
double epsilon = HYDROGEN_COEFF[z][6]*beta_sq/(1.0-beta_sq) - beta_sq - HYDROGEN_COEFF[z][7];
|
||||||
|
for(int i=1; i<5; i++)
|
||||||
|
epsilon += HYDROGEN_COEFF[z][7+i]*std::pow(std::log(e_per_u), i);
|
||||||
|
|
||||||
|
return alpha * std::log(epsilon);
|
||||||
|
}
|
||||||
|
|
||||||
|
//unimplemented
|
||||||
|
double EnergyLoss::GetRange(double energy) {
|
||||||
|
std::cerr<<"EnergyLoss::GetRange is not implemented! Returning 0.0"<<std::endl;
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EnergyLoss::~EnergyLoss() {}
|
|
||||||
|
|
||||||
/*Targets are defined by their atomic number, total number of nucleons, and their stoichiometry within the target compound*/
|
|
||||||
void EnergyLoss::SetTargetComponents(std::vector<int>& Zt, std::vector<int>& At, std::vector<int>& Stoich) {
|
|
||||||
comp_denom = 0;
|
|
||||||
ZT = Zt;
|
|
||||||
AT = At;
|
|
||||||
for(unsigned int i=0; i<Stoich.size(); i++) {
|
|
||||||
comp_denom += Stoich[i];
|
|
||||||
if(ZT[i] > MAX_Z) {
|
|
||||||
throw ELossException("Maximum allowed target Z exceeded");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
targ_composition.resize(Stoich.size());
|
|
||||||
for(unsigned int i=0; i<Stoich.size(); i++) {
|
|
||||||
targ_composition[i] = Stoich[i]/comp_denom;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Returns units of MeV; thickness in ug/cm^2; e_initial in units of MeV
|
|
||||||
Energy loss going through the target
|
|
||||||
*/
|
|
||||||
double EnergyLoss::GetEnergyLoss(int zp, int ap, double e_initial, double thickness) {
|
|
||||||
if( ZP != zp) {
|
|
||||||
ZP = zp;
|
|
||||||
AP = ap;
|
|
||||||
MP = MassLookup::GetInstance()->FindMass(ZP, AP)*MEV2U;
|
|
||||||
}
|
|
||||||
|
|
||||||
double e_final = e_initial;
|
|
||||||
double x_traversed = 0;
|
|
||||||
double x_step = 0.25*thickness; //initial step in x
|
|
||||||
double e_step = GetTotalStoppingPower(e_final)*x_step/1000.0; //initial step in e
|
|
||||||
double e_threshold = 0.05*e_initial;
|
|
||||||
|
|
||||||
int depth=0;
|
|
||||||
|
|
||||||
|
|
||||||
if(thickness == 0.0) return 0;
|
|
||||||
else if(e_initial == 0.0) return 0;
|
|
||||||
|
|
||||||
bool go = true;
|
|
||||||
while(go) {
|
|
||||||
//If intial guess of step size is too large, shrink until in range
|
|
||||||
if(e_step/e_final > MAX_FRACTIONAL_STEP && depth < MAX_DEPTH) {
|
|
||||||
depth++;
|
|
||||||
x_step *= 0.5;
|
|
||||||
e_step = GetTotalStoppingPower(e_final)*x_step/1000.0;
|
|
||||||
} else if((x_step + x_traversed) >= thickness) { //last chunk
|
|
||||||
go = false;
|
|
||||||
x_step = thickness - x_traversed; //get valid portion of last chunk
|
|
||||||
e_final -= GetTotalStoppingPower(e_final)*x_step/1000.0;
|
|
||||||
if(depth > 20)std::cout<<"depth: "<<depth<<std::endl;
|
|
||||||
if(e_final <= e_threshold) {
|
|
||||||
return e_initial;
|
|
||||||
}
|
|
||||||
} else if(depth == MAX_DEPTH) {
|
|
||||||
return e_initial;
|
|
||||||
} else {
|
|
||||||
x_traversed += x_step;
|
|
||||||
e_step = GetTotalStoppingPower(e_final)*x_step/1000.0;
|
|
||||||
e_final -= e_step;
|
|
||||||
if(e_final <= e_threshold) {
|
|
||||||
return e_initial;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return e_initial - e_final;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Returns units of MeV; thickness in ug/cm^2; e_final in units of MeV
|
|
||||||
Energy loss going through the target using energy of particle after traversal
|
|
||||||
*/
|
|
||||||
double EnergyLoss::GetReverseEnergyLoss(int zp, int ap, double e_final, double thickness) {
|
|
||||||
if( ZP != zp) {
|
|
||||||
ZP = zp;
|
|
||||||
AP = ap;
|
|
||||||
MP = MassLookup::GetInstance()->FindMass(ZP, AP)*MEV2U;
|
|
||||||
}
|
|
||||||
|
|
||||||
double e_initial = e_final;
|
|
||||||
double x_traversed = 0.0;
|
|
||||||
double x_step = 0.25*thickness; //initial step in x
|
|
||||||
double e_step = GetTotalStoppingPower(e_initial)*x_step/1000.0; //initial step in E
|
|
||||||
|
|
||||||
bool go = true;
|
|
||||||
while(go) {
|
|
||||||
if(e_step/e_initial > MAX_FRACTIONAL_STEP) {
|
|
||||||
x_step *= 0.5;
|
|
||||||
e_step = GetTotalStoppingPower(e_initial)*x_step/1000.0;
|
|
||||||
} else if (x_traversed+x_step > thickness) {
|
|
||||||
go = false;
|
|
||||||
x_step = thickness - x_traversed;
|
|
||||||
e_initial += GetTotalStoppingPower(e_initial)*x_step/1000.0;
|
|
||||||
} else {
|
|
||||||
x_traversed += x_step;
|
|
||||||
e_step = GetTotalStoppingPower(e_initial)*x_step/1000.0;
|
|
||||||
e_initial += e_step;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return e_initial-e_final;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Returns units of keV/(ug/cm^2)
|
|
||||||
Calculates Electronic stopping power by first calculating SE for hydrogen through the target and then using
|
|
||||||
corrections to calculate SE for projectile of interest
|
|
||||||
*/
|
|
||||||
double EnergyLoss::GetElectronicStoppingPower(double energy) {
|
|
||||||
//Wants in units of keV
|
|
||||||
energy *= 1000.0;
|
|
||||||
double e_per_u = energy/MP;
|
|
||||||
std::vector<double> values;
|
|
||||||
if(e_per_u > MAX_H_E_PER_U) {
|
|
||||||
throw ELossException("Exceeded maximum allowed energy per nucleon");
|
|
||||||
} else if (e_per_u > 1000.0) {
|
|
||||||
for(auto& z: ZT) {
|
|
||||||
values.push_back(Hydrogen_dEdx_High(e_per_u, energy, z));
|
|
||||||
}
|
|
||||||
} else if (e_per_u > 10.0) {
|
|
||||||
for(auto& z: ZT) {
|
|
||||||
values.push_back(Hydrogen_dEdx_Med(e_per_u, z));
|
|
||||||
}
|
|
||||||
} else if (e_per_u > 0.0) {
|
|
||||||
for(auto& z: ZT) {
|
|
||||||
values.push_back(Hydrogen_dEdx_Low(e_per_u, z));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw ELossException("Negative energy per nucleon");
|
|
||||||
}
|
|
||||||
|
|
||||||
if(values.size() == 0) {
|
|
||||||
throw ELossException("Size of value array is 0. Unable to iterate over target components");
|
|
||||||
}
|
|
||||||
|
|
||||||
if(ZP > 1) { //not hydrogen, need to account for effective charge
|
|
||||||
for(unsigned int i=0; i<values.size(); i++) {
|
|
||||||
values[i] *= CalculateEffectiveChargeRatio(e_per_u, ZT[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
double stopping_total = 0;
|
|
||||||
double conversion_factor = 0;
|
|
||||||
for(unsigned int i=0; i<ZT.size(); i++) {
|
|
||||||
conversion_factor += targ_composition[i]*NATURAL_MASS[ZT[i]];
|
|
||||||
stopping_total += values[i]*targ_composition[i];
|
|
||||||
}
|
|
||||||
stopping_total *= AVOGADRO/conversion_factor;
|
|
||||||
|
|
||||||
return stopping_total;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Returns units of keV/(ug/cm^2)
|
|
||||||
double EnergyLoss::GetNuclearStoppingPower(double energy) {
|
|
||||||
energy *= 1000.0;
|
|
||||||
double stopping_total = 0.0;
|
|
||||||
double sn, x, epsilon, conversion_factor;
|
|
||||||
for(unsigned int i=0; i<ZT.size(); i++) {
|
|
||||||
x = (MP + NATURAL_MASS[ZT[i]]) * std::sqrt(std::pow(ZP, 2.0/3.0) + std::pow(ZT[i], 2.0/3.0));
|
|
||||||
epsilon = 32.53*NATURAL_MASS[ZT[i]]*energy/(ZP*ZT[i]*x);
|
|
||||||
sn = 8.462*(0.5*std::log(1.0+epsilon)/(epsilon+0.10718*std::pow(epsilon, 0.37544)))*ZP*ZT[i]*MP/x;
|
|
||||||
conversion_factor = AVOGADRO/NATURAL_MASS[ZT[i]];
|
|
||||||
stopping_total += sn*conversion_factor*targ_composition[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
return stopping_total;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*Wrapper function for aquiring total stopping (elec + nuc)*/
|
|
||||||
double EnergyLoss::GetTotalStoppingPower(double energy) {
|
|
||||||
if(ZP == 0) {
|
|
||||||
return GetNuclearStoppingPower(energy);
|
|
||||||
}
|
|
||||||
return GetElectronicStoppingPower(energy)+GetNuclearStoppingPower(energy);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*Charge rel to H*/
|
|
||||||
double EnergyLoss::CalculateEffectiveChargeRatio(double e_per_u, int z) {
|
|
||||||
double z_ratio;
|
|
||||||
if(ZP == 2) {
|
|
||||||
double ln_epu = std::log(e_per_u);
|
|
||||||
double gamma = 1.0+(0.007+0.00005*z)*std::exp(-std::pow(7.6-ln_epu,2.0));
|
|
||||||
double alpha = 0.7446 + 0.1429*ln_epu + 0.01562*std::pow(ln_epu, 2.0) - 0.00267*std::pow(ln_epu,3.0)
|
|
||||||
+ 1.338E-6*std::pow(ln_epu,8.0);
|
|
||||||
z_ratio = gamma*(1.0-std::exp(-alpha))*2.0; //test this; SPANC has factor of 2. mult
|
|
||||||
} else if (ZP == 3) {
|
|
||||||
double ln_epu = std::log(e_per_u);
|
|
||||||
double gamma = 1.0+(0.007+0.00005*z)*std::exp(-std::pow(7.6-ln_epu,2.0));
|
|
||||||
double alpha = 0.7138+0.002797*e_per_u+1.348E-6*std::pow(e_per_u, 2.0);
|
|
||||||
z_ratio = gamma*(1-std::exp(-alpha))*3.0; //test this; SPANC has factor of 3. mult
|
|
||||||
} else {
|
|
||||||
double B = 0.886*std::pow(e_per_u/25.0, 0.5)/std::pow(ZP, 2.0/3.0);
|
|
||||||
double A = B + 0.0378*std::sin(PI/2.0*B);
|
|
||||||
z_ratio = 1.0 - std::exp(-A)*(1.034-0.1777*std::exp(-0.08114*ZP))*z; //test this; SPANC has factor of ZT[i] mult
|
|
||||||
}
|
|
||||||
return z_ratio*z_ratio; //for stopping power uses ratio sq.
|
|
||||||
}
|
|
||||||
|
|
||||||
double EnergyLoss::Hydrogen_dEdx_Low(double e_per_u, int z) {
|
|
||||||
return std::sqrt(e_per_u)*HYDROGEN_COEFF[z][0];
|
|
||||||
}
|
|
||||||
|
|
||||||
double EnergyLoss::Hydrogen_dEdx_Med(double e_per_u, int z) {
|
|
||||||
double x = HYDROGEN_COEFF[z][1]*std::pow(e_per_u, 0.45);
|
|
||||||
double y = HYDROGEN_COEFF[z][2]/e_per_u * std::log(1.0+HYDROGEN_COEFF[z][3]/e_per_u+HYDROGEN_COEFF[z][4]*e_per_u);
|
|
||||||
return x*y/(x+y);
|
|
||||||
}
|
|
||||||
|
|
||||||
double EnergyLoss::Hydrogen_dEdx_High(double e_per_u, double energy, int z) {
|
|
||||||
energy /= 1000.0; //back to MeV for ease of beta calc
|
|
||||||
double beta_sq = energy * (energy+2.0*MP/MEV2U)/std::pow(energy+MP/MEV2U, 2.0);
|
|
||||||
double alpha = HYDROGEN_COEFF[z][5]/beta_sq;
|
|
||||||
double epsilon = HYDROGEN_COEFF[z][6]*beta_sq/(1.0-beta_sq) - beta_sq - HYDROGEN_COEFF[z][7];
|
|
||||||
for(int i=1; i<5; i++) {
|
|
||||||
epsilon += HYDROGEN_COEFF[z][7+i]*std::pow(std::log(e_per_u), i);
|
|
||||||
}
|
|
||||||
return alpha * std::log(epsilon);
|
|
||||||
}
|
|
||||||
|
|
||||||
double EnergyLoss::GetRange(double energy) {return 0.0;} //unimplemented
|
|
||||||
|
|
|
@ -24,7 +24,6 @@ namespace Mask {
|
||||||
|
|
||||||
std::ifstream input(filename);
|
std::ifstream input(filename);
|
||||||
if(!input.is_open()) {
|
if(!input.is_open()) {
|
||||||
std::cerr<<"Unable to load configuration in "<<filename<<", check that it exists"<<std::endl;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
|
|
||||||
LayeredTarget.h
|
LayeredTarget.h
|
||||||
Functional unit for targets in the SPANCRedux environment. Contains a
|
Functional unit for targets in the Mask environment. Contains a
|
||||||
set (read: vector) of Targets for use in reaction calculations. In this
|
set (read: vector) of Targets for use in reaction calculations. In this
|
||||||
way handles situations such as carbon backed targets
|
way handles situations such as carbon backed targets
|
||||||
|
|
||||||
|
@ -11,117 +11,108 @@ Written by G.W. McCann Aug. 2020
|
||||||
|
|
||||||
*/
|
*/
|
||||||
#include "LayeredTarget.h"
|
#include "LayeredTarget.h"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
LayeredTarget::LayeredTarget() {}
|
namespace Mask {
|
||||||
|
|
||||||
|
LayeredTarget::LayeredTarget() :
|
||||||
|
name("")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
LayeredTarget::~LayeredTarget() {}
|
||||||
|
|
||||||
|
/*Add in a Target made of a compound defined by a set of Zs, As, Ss, and a thickness*/
|
||||||
|
void LayeredTarget::AddLayer(std::vector<int>& Z, std::vector<int>& A, std::vector<int>& stoich, double thickness) {
|
||||||
|
Target t(thickness);
|
||||||
|
t.SetElements(Z, A, stoich);
|
||||||
|
layers.push_back(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Here projectile refers to the incoming reactant particle (i.e. the beam)
|
||||||
|
Calculates energy loss assuming that the reaction occurs in the middle of the target
|
||||||
|
Note that the layer order can matter!
|
||||||
|
*/
|
||||||
|
double LayeredTarget::GetProjectileEnergyLoss(int zp, int ap, double startEnergy, int rxnLayer, double angle) {
|
||||||
|
|
||||||
|
if(rxnLayer < 0 || ((unsigned int) rxnLayer) > layers.size()) {
|
||||||
|
std::cerr<<"Reaction layer in eloss calculation is not in range! Returning 0"<<std::endl;
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
double eloss = 0.0;
|
||||||
|
double newEnergy = startEnergy;
|
||||||
|
for(int i=0; i<=rxnLayer; i++) {
|
||||||
|
if(i == rxnLayer) {
|
||||||
|
eloss += layers[i].getEnergyLossHalf(zp, ap, newEnergy, angle);
|
||||||
|
newEnergy = startEnergy - eloss;
|
||||||
|
} else {
|
||||||
|
eloss += layers[i].getEnergyLossTotal(zp, ap, newEnergy, angle);
|
||||||
|
newEnergy = startEnergy-eloss;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return eloss;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Here ejectile refers to the outgoing reactant particle
|
||||||
|
Calculates energy loss assuming that the reaction occurs in the middle of the target
|
||||||
|
Note that the layer order can matter!
|
||||||
|
*/
|
||||||
|
double LayeredTarget::GetEjectileEnergyLoss(int ze, int ae, double startEnergy, int rxnLayer, double angle) {
|
||||||
|
|
||||||
|
if(rxnLayer < 0 || ((unsigned int) rxnLayer) > layers.size()) {
|
||||||
|
std::cerr<<"Reaction layer in eloss calculation is not in range! Returning 0"<<std::endl;
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
double eloss = 0.0;
|
||||||
|
double newEnergy = startEnergy;
|
||||||
|
for(unsigned int i=rxnLayer; i<layers.size(); i++) {
|
||||||
|
if(i == ((unsigned int)rxnLayer)) {
|
||||||
|
eloss += layers[i].getEnergyLossHalf(ze, ae, newEnergy, angle);
|
||||||
|
newEnergy = startEnergy - eloss;
|
||||||
|
} else {
|
||||||
|
eloss += layers[i].getEnergyLossTotal(ze, ae, newEnergy, angle);
|
||||||
|
newEnergy = startEnergy - eloss;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return eloss;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*ReverseEnergyLoss version of GetEjectileEnergyLoss*/
|
||||||
|
double LayeredTarget::GetEjectileReverseEnergyLoss(int ze, int ae, double startEnergy, int rxnLayer, double angle) {
|
||||||
|
|
||||||
|
if(rxnLayer < 0 || ((unsigned int) rxnLayer) > layers.size()) {
|
||||||
|
std::cerr<<"Reaction layer in eloss calculation is not in range! Returning 0"<<std::endl;
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
double eloss = 0.0;
|
||||||
|
double newEnergy = startEnergy;
|
||||||
|
for(int i=(layers.size()-1); i>=rxnLayer; i--) {
|
||||||
|
if(i == rxnLayer) {
|
||||||
|
eloss += layers[i].getReverseEnergyLossHalf(ze, ae, newEnergy, angle);
|
||||||
|
newEnergy = startEnergy + eloss;
|
||||||
|
} else {
|
||||||
|
eloss += layers[i].getReverseEnergyLossTotal(ze, ae, newEnergy, angle);
|
||||||
|
newEnergy = startEnergy + eloss;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return eloss;
|
||||||
|
}
|
||||||
|
|
||||||
|
int LayeredTarget::FindLayerContaining(int Z, int A) {
|
||||||
|
for(unsigned int i=0; i<layers.size(); i++)
|
||||||
|
if(layers[i].ContainsElement(Z, A))
|
||||||
|
return i;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
LayeredTarget::~LayeredTarget() {}
|
|
||||||
|
|
||||||
/*Add in a Target made of a compound defined by a set of Zs, As, Ss, and a thickness*/
|
|
||||||
void LayeredTarget::AddLayer(std::vector<int>& Z, std::vector<int>& A, std::vector<int>& stoich, double thickness) {
|
|
||||||
Target t(thickness);
|
|
||||||
t.SetElements(Z, A, stoich);
|
|
||||||
layers.push_back(t);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
Here projectile refers to the incoming reactant particle (i.e. the beam)
|
|
||||||
Calculates energy loss assuming that the reaction occurs in the middle of the target
|
|
||||||
Note that the layer order can matter!
|
|
||||||
*/
|
|
||||||
double LayeredTarget::GetProjectileEnergyLoss(int zp, int ap, double startEnergy, int rxnLayer, double angle) {
|
|
||||||
|
|
||||||
if(rxnLayer < 0 || ((unsigned int) rxnLayer) > layers.size()) {
|
|
||||||
std::cerr<<"Reaction layer in eloss calculation is not in range! Returning 0"<<std::endl;
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
double eloss = 0.0;
|
|
||||||
double newEnergy = startEnergy;
|
|
||||||
for(int i=0; i<=rxnLayer; i++) {
|
|
||||||
if(i == rxnLayer) {
|
|
||||||
eloss += layers[i].getEnergyLossHalf(zp, ap, newEnergy, angle);
|
|
||||||
newEnergy = startEnergy - eloss;
|
|
||||||
} else {
|
|
||||||
eloss += layers[i].getEnergyLossTotal(zp, ap, newEnergy, angle);
|
|
||||||
newEnergy = startEnergy-eloss;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return eloss;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Here ejectile refers to the outgoing reactant particle
|
|
||||||
Calculates energy loss assuming that the reaction occurs in the middle of the target
|
|
||||||
Note that the layer order can matter!
|
|
||||||
*/
|
|
||||||
double LayeredTarget::GetEjectileEnergyLoss(int ze, int ae, double startEnergy, int rxnLayer, double angle) {
|
|
||||||
|
|
||||||
if(rxnLayer < 0 || ((unsigned int) rxnLayer) > layers.size()) {
|
|
||||||
std::cerr<<"Reaction layer in eloss calculation is not in range! Returning 0"<<std::endl;
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
double eloss = 0.0;
|
|
||||||
double newEnergy = startEnergy;
|
|
||||||
for(unsigned int i=rxnLayer; i<layers.size(); i++) {
|
|
||||||
if(i == ((unsigned int)rxnLayer)) {
|
|
||||||
eloss += layers[i].getEnergyLossHalf(ze, ae, newEnergy, angle);
|
|
||||||
newEnergy = startEnergy - eloss;
|
|
||||||
} else {
|
|
||||||
eloss += layers[i].getEnergyLossTotal(ze, ae, newEnergy, angle);
|
|
||||||
newEnergy = startEnergy - eloss;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return eloss;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*ReverseEnergyLoss version of GetEjectileEnergyLoss*/
|
|
||||||
double LayeredTarget::GetEjectileReverseEnergyLoss(int ze, int ae, double startEnergy, int rxnLayer, double angle) {
|
|
||||||
|
|
||||||
if(rxnLayer < 0 || ((unsigned int) rxnLayer) > layers.size()) {
|
|
||||||
std::cerr<<"Reaction layer in eloss calculation is not in range! Returning 0"<<std::endl;
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
double eloss = 0.0;
|
|
||||||
double newEnergy = startEnergy;
|
|
||||||
for(int i=(layers.size()-1); i>=rxnLayer; i--) {
|
|
||||||
if(i == rxnLayer) {
|
|
||||||
eloss += layers[i].getReverseEnergyLossHalf(ze, ae, newEnergy, angle);
|
|
||||||
newEnergy = startEnergy + eloss;
|
|
||||||
} else {
|
|
||||||
eloss += layers[i].getReverseEnergyLossTotal(ze, ae, newEnergy, angle);
|
|
||||||
newEnergy = startEnergy + eloss;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return eloss;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*Getters and Setters*/
|
|
||||||
|
|
||||||
int LayeredTarget::GetNumberOfLayers() {
|
|
||||||
return layers.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
int LayeredTarget::FindLayerContaining(int Z, int A) {
|
|
||||||
for(unsigned int i=0; i<layers.size(); i++) {
|
|
||||||
if(layers[i].ContainsElement(Z, A)) return i;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LayeredTarget::SetName(std::string& n) {
|
|
||||||
name = n;
|
|
||||||
}
|
|
||||||
|
|
||||||
Target& LayeredTarget::GetLayerInfo(int index) {
|
|
||||||
return layers[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string& LayeredTarget::GetName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -1,32 +1,36 @@
|
||||||
#include "LegendrePoly.h"
|
#include "LegendrePoly.h"
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
double P_l(int l, double x) {
|
namespace Mask {
|
||||||
if(l == 0) {
|
|
||||||
return 1.0;
|
double P_l(int l, double x) {
|
||||||
} else if (l == 1) {
|
if(l == 0) {
|
||||||
return x;
|
return 1.0;
|
||||||
} else {
|
} else if (l == 1) {
|
||||||
return (2.0*l - 1.0)/l*x*P_l(l-1, x) - (l-1.0)/l*P_l(l-2, x);
|
return x;
|
||||||
|
} else {
|
||||||
|
return (2.0*l - 1.0)/l*x*P_l(l-1, x) - (l-1.0)/l*P_l(l-2, x);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
double Normed_P_l_sq(int l, double x) {
|
double Normed_P_l_sq(int l, double x) {
|
||||||
return (2.0*l+1.0)/2.0*std::pow(P_l(l, x), 2.0);
|
return (2.0*l+1.0)/2.0*std::pow(P_l(l, x), 2.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
double P_0(double x) {
|
double P_0(double x) {
|
||||||
return 1.0;
|
return 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
double P_1(double x) {
|
double P_1(double x) {
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
double P_2(double x) {
|
double P_2(double x) {
|
||||||
return 0.5*(3.0*x*x -1.0);
|
return 0.5*(3.0*x*x -1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double P_l_ROOT(double* x, double* pars) {
|
||||||
|
return P_l(pars[0], x[0]);
|
||||||
|
}
|
||||||
|
|
||||||
double P_l_ROOT(double* x, double* pars) {
|
|
||||||
return P_l(pars[0], x[0]);
|
|
||||||
}
|
}
|
|
@ -11,52 +11,51 @@ Written by G.W. McCann Aug. 2020
|
||||||
#include "MassLookup.h"
|
#include "MassLookup.h"
|
||||||
#include "KinematicsExceptions.h"
|
#include "KinematicsExceptions.h"
|
||||||
|
|
||||||
|
namespace Mask {
|
||||||
|
|
||||||
/*
|
MassLookup* MassLookup::s_instance = nullptr;
|
||||||
Read in AMDC mass file, preformated to remove excess info. Here assumes that by default
|
|
||||||
the file is in a local directory etc/
|
|
||||||
*/
|
|
||||||
|
|
||||||
MassLookup* MassLookup::s_instance = nullptr;
|
MassLookup::MassLookup() {
|
||||||
|
|
||||||
MassLookup::MassLookup() {
|
std::ifstream massfile("etc/mass.txt");
|
||||||
std::ifstream massfile("./etc/mass.txt");
|
if(massfile.is_open()) {
|
||||||
if(massfile.is_open()) {
|
std::string junk, A, element;
|
||||||
std::string junk, A, element;
|
int Z;
|
||||||
int Z;
|
double atomicMassBig, atomicMassSmall, isotopicMass;
|
||||||
double atomicMassBig, atomicMassSmall, isotopicMass;
|
getline(massfile,junk);
|
||||||
getline(massfile,junk);
|
getline(massfile,junk);
|
||||||
getline(massfile,junk);
|
while(massfile>>junk) {
|
||||||
while(massfile>>junk) {
|
massfile>>Z>>A>>element>>atomicMassBig>>atomicMassSmall;
|
||||||
massfile>>Z>>A>>element>>atomicMassBig>>atomicMassSmall;
|
isotopicMass = (atomicMassBig + atomicMassSmall*1e-6 - Z*electron_mass)*u_to_mev;
|
||||||
isotopicMass = (atomicMassBig + atomicMassSmall*1e-6 - Z*electron_mass)*u_to_mev;
|
std::string key = "("+std::to_string(Z)+","+A+")";
|
||||||
std::string key = "("+std::to_string(Z)+","+A+")";
|
massTable[key] = isotopicMass;
|
||||||
massTable[key] = isotopicMass;
|
elementTable[Z] = element;
|
||||||
elementTable[Z] = element;
|
}
|
||||||
|
} else {
|
||||||
|
throw MassFileException();
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
throw MassFileException();
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
MassLookup::~MassLookup() {}
|
MassLookup::~MassLookup() {}
|
||||||
|
|
||||||
//Returns nuclear mass in MeV
|
//Returns nuclear mass in MeV
|
||||||
double MassLookup::FindMass(int Z, int A) {
|
double MassLookup::FindMass(int Z, int A) {
|
||||||
std::string key = "("+std::to_string(Z)+","+std::to_string(A)+")";
|
std::string key = "("+std::to_string(Z)+","+std::to_string(A)+")";
|
||||||
auto data = massTable.find(key);
|
auto data = massTable.find(key);
|
||||||
if(data == massTable.end()) {
|
if(data == massTable.end())
|
||||||
throw MassException();
|
throw MassException();
|
||||||
}
|
|
||||||
return data->second;
|
return data->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//returns element symbol
|
||||||
|
std::string MassLookup::FindSymbol(int Z, int A) {
|
||||||
|
auto data = elementTable.find(Z);
|
||||||
|
if(data == elementTable.end())
|
||||||
|
throw MassException();
|
||||||
|
|
||||||
|
std::string fullsymbol = std::to_string(A) + data->second;
|
||||||
|
return fullsymbol;
|
||||||
|
}
|
||||||
|
|
||||||
//returns element symbol
|
|
||||||
std::string MassLookup::FindSymbol(int Z, int A) {
|
|
||||||
auto data = elementTable.find(Z);
|
|
||||||
if(data == elementTable.end()) {
|
|
||||||
throw MassException();
|
|
||||||
}
|
|
||||||
std::string fullsymbol = std::to_string(A) + data->second;
|
|
||||||
return fullsymbol;
|
|
||||||
}
|
}
|
|
@ -11,37 +11,37 @@
|
||||||
|
|
||||||
namespace Mask {
|
namespace Mask {
|
||||||
|
|
||||||
Nucleus::Nucleus () :
|
Nucleus::Nucleus () :
|
||||||
Vec4(), m_z(0), m_a(0), m_gs_mass(0), m_theta_cm(0), m_symbol(""), m_detectFlag(false)
|
Vec4(), m_z(0), m_a(0), m_gs_mass(0), m_theta_cm(0), m_symbol(""), m_detectFlag(false)
|
||||||
{
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Nucleus::Nucleus(int Z, int A) :
|
||||||
|
Vec4(), m_z(Z), m_a(A), m_theta_cm(0), m_detectFlag(false)
|
||||||
|
{
|
||||||
|
m_gs_mass = MassLookup::GetInstance()->FindMass(Z, A);
|
||||||
|
m_symbol = MassLookup::GetInstance()->FindSymbol(Z, A);
|
||||||
|
SetVectorCartesian(0,0,0,m_gs_mass); //by defualt a nucleus has mass given by the g.s.
|
||||||
|
}
|
||||||
|
|
||||||
|
Nucleus::Nucleus(int Z, int A, double px, double py, double pz, double E) :
|
||||||
|
Vec4(px, py, pz, E), m_z(Z), m_a(A)
|
||||||
|
{
|
||||||
|
m_gs_mass = MassLookup::GetInstance()->FindMass(Z, A);
|
||||||
|
m_symbol = MassLookup::GetInstance()->FindSymbol(Z, A);
|
||||||
|
}
|
||||||
|
|
||||||
|
Nucleus::~Nucleus() {}
|
||||||
|
|
||||||
|
bool Nucleus::SetIsotope(int Z, int A) {
|
||||||
|
if(Z>A) return false;
|
||||||
|
|
||||||
|
m_z = Z;
|
||||||
|
m_a = A;
|
||||||
|
m_gs_mass = MassLookup::GetInstance()->FindMass(Z, A);
|
||||||
|
m_symbol = MassLookup::GetInstance()->FindSymbol(Z, A);
|
||||||
|
SetVectorCartesian(0,0,0,m_gs_mass);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Nucleus::Nucleus(int Z, int A) :
|
|
||||||
Vec4(), m_z(Z), m_a(A), m_theta_cm(0), m_detectFlag(false)
|
|
||||||
{
|
|
||||||
m_gs_mass = MassLookup::GetInstance()->FindMass(Z, A);
|
|
||||||
m_symbol = MassLookup::GetInstance()->FindSymbol(Z, A);
|
|
||||||
SetVectorCartesian(0,0,0,m_gs_mass); //by defualt a nucleus has mass given by the g.s.
|
|
||||||
}
|
|
||||||
|
|
||||||
Nucleus::Nucleus(int Z, int A, double px, double py, double pz, double E) :
|
|
||||||
Vec4(px, py, pz, E), m_z(Z), m_a(A)
|
|
||||||
{
|
|
||||||
m_gs_mass = MassLookup::GetInstance()->FindMass(Z, A);
|
|
||||||
m_symbol = MassLookup::GetInstance()->FindSymbol(Z, A);
|
|
||||||
}
|
|
||||||
|
|
||||||
Nucleus::~Nucleus() {}
|
|
||||||
|
|
||||||
bool Nucleus::SetIsotope(int Z, int A) {
|
|
||||||
if(Z>A) return false;
|
|
||||||
|
|
||||||
m_z = Z;
|
|
||||||
m_a = A;
|
|
||||||
m_gs_mass = MassLookup::GetInstance()->FindMass(Z, A);
|
|
||||||
m_symbol = MassLookup::GetInstance()->FindSymbol(Z, A);
|
|
||||||
SetVectorCartesian(0,0,0,m_gs_mass);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
|
@ -55,23 +55,19 @@ namespace Mask {
|
||||||
LinkTarget();
|
LinkTarget();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!step1.IsDecay()) {
|
//Sample parameters
|
||||||
//Sample parameters
|
double bke = (*m_beamDist)(*generator);
|
||||||
double bke = (*m_beamDist)(*generator);
|
double rxnTheta = std::acos((*m_theta1Range)(*generator));
|
||||||
double rxnTheta = std::acos((*m_theta1Range)(*generator));
|
double rxnPhi = (*m_phi1Range)(*generator);
|
||||||
double rxnPhi = (*m_phi1Range)(*generator);
|
double residEx = (*m_exDist)(*generator);
|
||||||
double residEx = (*m_exDist)(*generator);
|
|
||||||
|
|
||||||
step1.SetBeamKE(bke);
|
step1.SetBeamKE(bke);
|
||||||
step1.SetPolarRxnAngle(rxnTheta);
|
step1.SetPolarRxnAngle(rxnTheta);
|
||||||
step1.SetAzimRxnAngle(rxnPhi);
|
step1.SetAzimRxnAngle(rxnPhi);
|
||||||
step1.SetExcitation(residEx);
|
step1.SetExcitation(residEx);
|
||||||
|
|
||||||
step1.TurnOnResidualEloss();
|
step1.TurnOnResidualEloss();
|
||||||
step1.Calculate();
|
step1.Calculate();
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
440
src/Reaction.cpp
440
src/Reaction.cpp
|
@ -11,234 +11,236 @@
|
||||||
|
|
||||||
namespace Mask {
|
namespace Mask {
|
||||||
|
|
||||||
Reaction::Reaction() :
|
Reaction::Reaction() :
|
||||||
target(nullptr), m_bke(0), m_theta(0), m_phi(0), m_ex(0), rxnLayer(0), m_eject_theta_type(lab), nuc_initFlag(false), resid_elossFlag(false)
|
target(nullptr), m_bke(0), m_theta(0), m_phi(0), m_ex(0), rxnLayer(0), m_eject_theta_type(lab), nuc_initFlag(false), resid_elossFlag(false)
|
||||||
{
|
{
|
||||||
}
|
|
||||||
|
|
||||||
Reaction::Reaction(int zt, int at, int zp, int ap, int ze, int ae) :
|
|
||||||
target(nullptr), m_bke(0), m_theta(0), m_phi(0), m_ex(0), rxnLayer(0), m_eject_theta_type(lab), resid_elossFlag(false)
|
|
||||||
{
|
|
||||||
SetNuclei(zt, at, zp, ap, ze, ae);
|
|
||||||
}
|
|
||||||
|
|
||||||
Reaction::~Reaction()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Reaction::Calculate() {
|
|
||||||
|
|
||||||
if(!nuc_initFlag) return false;
|
|
||||||
|
|
||||||
if(decayFlag) {
|
|
||||||
CalculateDecay();
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
CalculateReaction();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Deep copy of nucleus array
|
|
||||||
void Reaction::SetNuclei(const Nucleus* nucs) {
|
|
||||||
reactants[0] = nucs[0];
|
|
||||||
reactants[1] = nucs[1];
|
|
||||||
reactants[2] = nucs[2];
|
|
||||||
reactants[3] = nucs[3];
|
|
||||||
nuc_initFlag = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Reaction::SetNuclei(int zt, int at, int zp, int ap, int ze, int ae) {
|
|
||||||
int zr, ar;
|
|
||||||
reactants[0] = Nucleus(zt, at);
|
|
||||||
reactants[2] = Nucleus(ze, ae);
|
|
||||||
if(ap == 0) {
|
|
||||||
decayFlag = true;
|
|
||||||
zr = zt - ze;
|
|
||||||
ar = at - ae;
|
|
||||||
} else {
|
|
||||||
reactants[1] = Nucleus(zp, ap);
|
|
||||||
decayFlag = false;
|
|
||||||
zr = zt + zp - ze;
|
|
||||||
ar = at + ap - ae;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(zr < 0 || ar <= 0) {
|
Reaction::Reaction(int zt, int at, int zp, int ap, int ze, int ae) :
|
||||||
nuc_initFlag = false;
|
target(nullptr), m_bke(0), m_theta(0), m_phi(0), m_ex(0), rxnLayer(0), m_eject_theta_type(lab), resid_elossFlag(false)
|
||||||
} else {
|
{
|
||||||
reactants[3] = Nucleus(zr, ar);
|
SetNuclei(zt, at, zp, ap, ze, ae);
|
||||||
|
}
|
||||||
|
|
||||||
|
Reaction::~Reaction()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Reaction::Calculate() {
|
||||||
|
|
||||||
|
if(!nuc_initFlag)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if(decayFlag) {
|
||||||
|
CalculateDecay();
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
CalculateReaction();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Deep copy of nucleus array
|
||||||
|
void Reaction::SetNuclei(const Nucleus* nucs) {
|
||||||
|
reactants[0] = nucs[0];
|
||||||
|
reactants[1] = nucs[1];
|
||||||
|
reactants[2] = nucs[2];
|
||||||
|
reactants[3] = nucs[3];
|
||||||
nuc_initFlag = true;
|
nuc_initFlag = true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void Reaction::SetBeamKE(double bke) {
|
void Reaction::SetNuclei(int zt, int at, int zp, int ap, int ze, int ae) {
|
||||||
if(!nuc_initFlag) return;
|
int zr, ar;
|
||||||
else if(decayFlag) return;
|
reactants[0] = Nucleus(zt, at);
|
||||||
m_bke = bke - target->GetProjectileEnergyLoss(reactants[1].GetZ(), reactants[1].GetA(), bke, rxnLayer, 0);
|
reactants[2] = Nucleus(ze, ae);
|
||||||
};
|
if(ap == 0) {
|
||||||
|
decayFlag = true;
|
||||||
void Reaction::SetEjectileThetaType(int type) {
|
zr = zt - ze;
|
||||||
if(decayFlag) return;
|
ar = at - ae;
|
||||||
if(type != center_of_mass && type != lab) return;
|
} else {
|
||||||
|
reactants[1] = Nucleus(zp, ap);
|
||||||
m_eject_theta_type = type;
|
decayFlag = false;
|
||||||
}
|
zr = zt + zp - ze;
|
||||||
|
ar = at + ap - ae;
|
||||||
//Methods given by Iliadis in Nuclear Physics of Stars, Appendix C
|
|
||||||
//For use with lab frame restricted angles. May not give appropriate disribution for ejectile
|
|
||||||
void Reaction::CalculateReactionThetaLab() {
|
|
||||||
reactants[0].SetVectorCartesian(0.,0.,0.,reactants[0].GetGroundStateMass());
|
|
||||||
double beam_pz = std::sqrt(m_bke*(m_bke + 2.0 * reactants[1].GetGroundStateMass()));
|
|
||||||
double beam_E = m_bke + reactants[1].GetGroundStateMass();
|
|
||||||
reactants[1].SetVectorCartesian(0.,0.,beam_pz,beam_E);
|
|
||||||
|
|
||||||
double Q = reactants[0].GetGroundStateMass() + reactants[1].GetGroundStateMass() - (reactants[2].GetGroundStateMass() + reactants[3].GetGroundStateMass() + m_ex);
|
|
||||||
|
|
||||||
double Ethresh = -Q*(reactants[2].GetGroundStateMass()+reactants[3].GetGroundStateMass())/(reactants[2].GetGroundStateMass() + reactants[3].GetGroundStateMass() - reactants[1].GetGroundStateMass());
|
|
||||||
if(m_bke < Ethresh) {
|
|
||||||
throw EnergyThresholdException();
|
|
||||||
}
|
|
||||||
|
|
||||||
double term1 = sqrt(reactants[1].GetGroundStateMass()*reactants[2].GetGroundStateMass()*m_bke)/(reactants[2].GetGroundStateMass()+reactants[3].GetGroundStateMass())*cos(m_theta);
|
|
||||||
double term2 = (m_bke*(reactants[3].GetGroundStateMass() - reactants[1].GetGroundStateMass()) + reactants[3].GetGroundStateMass()*Q)/(reactants[3].GetGroundStateMass() + reactants[2].GetGroundStateMass());
|
|
||||||
double sqrt_pos_ejectKE = term1 + sqrt(term1*term1 + term2);
|
|
||||||
double sqrt_neg_ejectKE = term1 - sqrt(term1*term1 + term2);
|
|
||||||
double ejectKE;
|
|
||||||
if(sqrt_pos_ejectKE > 0) {
|
|
||||||
ejectKE = sqrt_pos_ejectKE*sqrt_pos_ejectKE;
|
|
||||||
} else {
|
|
||||||
ejectKE = sqrt_neg_ejectKE*sqrt_neg_ejectKE;
|
|
||||||
}
|
|
||||||
double ejectP = std::sqrt(ejectKE*(ejectKE + 2.0 * reactants[2].GetGroundStateMass()));
|
|
||||||
double ejectE = ejectKE + reactants[2].GetGroundStateMass();
|
|
||||||
|
|
||||||
reactants[2].SetVectorSpherical(m_theta, m_phi, ejectP, ejectE);
|
|
||||||
|
|
||||||
reactants[3] = reactants[0] + reactants[1] - reactants[2];
|
|
||||||
|
|
||||||
ejectKE -= target->GetEjectileEnergyLoss(reactants[2].GetZ(), reactants[2].GetA(), ejectKE, rxnLayer, m_theta);
|
|
||||||
ejectP = std::sqrt(ejectKE*(ejectKE + 2.0 * reactants[2].GetGroundStateMass()));
|
|
||||||
ejectE = ejectKE + reactants[2].GetGroundStateMass();
|
|
||||||
reactants[2].SetVectorSpherical(m_theta, m_phi, ejectP, ejectE);
|
|
||||||
|
|
||||||
if(resid_elossFlag) {
|
|
||||||
double residKE = reactants[3].GetKE() - target->GetEjectileEnergyLoss(reactants[3].GetZ(), reactants[3].GetA(), reactants[3].GetKE(), rxnLayer, reactants[3].GetTheta());
|
|
||||||
double residP = std::sqrt(residKE*(residKE + 2.0*reactants[3].GetInvMass()));
|
|
||||||
double residE = residKE + reactants[3].GetInvMass();
|
|
||||||
reactants[3].SetVectorSpherical(reactants[3].GetTheta(), reactants[3].GetPhi(), residP, residE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Methods from original ANASEN. Gives proper distribution for inverse kinematics.
|
|
||||||
void Reaction::CalculateReactionThetaCM() {
|
|
||||||
//Target assumed at rest, with 0 excitation energy
|
|
||||||
reactants[0].SetVectorCartesian(0.,0.,0.,reactants[0].GetGroundStateMass());
|
|
||||||
double beam_pz = std::sqrt(m_bke*(m_bke + 2.0 * reactants[1].GetGroundStateMass()));
|
|
||||||
double beam_E = m_bke + reactants[1].GetGroundStateMass();
|
|
||||||
reactants[1].SetVectorCartesian(0.,0.,beam_pz,beam_E);
|
|
||||||
|
|
||||||
|
|
||||||
double Q = reactants[0].GetGroundStateMass() + reactants[1].GetGroundStateMass() - (reactants[2].GetGroundStateMass() + reactants[3].GetGroundStateMass() + m_ex);
|
|
||||||
|
|
||||||
double Ethresh = -Q*(reactants[2].GetGroundStateMass()+reactants[3].GetGroundStateMass())/(reactants[2].GetGroundStateMass() + reactants[3].GetGroundStateMass() - reactants[1].GetGroundStateMass());
|
|
||||||
if(m_bke < Ethresh) {
|
|
||||||
throw EnergyThresholdException();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto parent = reactants[0] + reactants[1];
|
|
||||||
double boost2lab[3];
|
|
||||||
double boost2cm[3];
|
|
||||||
const double* boost = parent.GetBoost();
|
|
||||||
for(int i=0; i<3; i++) {
|
|
||||||
boost2lab[i] = boost[i];
|
|
||||||
boost2cm[i] = boost[i]*(-1.0);
|
|
||||||
}
|
|
||||||
parent.ApplyBoost(boost2cm);
|
|
||||||
double ejectE_cm = (std::pow(reactants[2].GetGroundStateMass(), 2.0) - std::pow(reactants[3].GetGroundStateMass() + m_ex, 2.0) + std::pow(parent.GetE(),2.0))/(2.0*parent.GetE());
|
|
||||||
double ejectP_cm = std::sqrt(ejectE_cm*ejectE_cm - std::pow(reactants[2].GetGroundStateMass(), 2.0));
|
|
||||||
reactants[2].SetVectorSpherical(m_theta, m_phi, ejectP_cm, ejectE_cm);
|
|
||||||
reactants[2].ApplyBoost(boost2lab);
|
|
||||||
reactants[3] = reactants[0] + reactants[1] - reactants[2];
|
|
||||||
|
|
||||||
double ejectKE = reactants[2].GetKE();
|
|
||||||
double ejectP = reactants[2].GetP();
|
|
||||||
double ejectE = reactants[2].GetE();
|
|
||||||
//energy loss for ejectile (after reaction!)
|
|
||||||
ejectKE -= target->GetEjectileEnergyLoss(reactants[2].GetZ(), reactants[2].GetA(), ejectKE, rxnLayer, reactants[2].GetTheta());
|
|
||||||
ejectP = std::sqrt(ejectKE*(ejectKE + 2.0 * reactants[2].GetGroundStateMass()));
|
|
||||||
ejectE = ejectKE + reactants[2].GetGroundStateMass();
|
|
||||||
reactants[2].SetVectorSpherical(reactants[2].GetTheta(), reactants[2].GetPhi(), ejectP, ejectE);
|
|
||||||
|
|
||||||
//if on, get eloss for residual (after reaction!)
|
|
||||||
if(resid_elossFlag) {
|
|
||||||
double residKE = reactants[3].GetKE() - target->GetEjectileEnergyLoss(reactants[3].GetZ(), reactants[3].GetA(), reactants[3].GetKE(), rxnLayer, reactants[3].GetTheta());
|
|
||||||
double residP = std::sqrt(residKE*(residKE + 2.0*reactants[3].GetInvMass()));
|
|
||||||
double residE = residKE + reactants[3].GetInvMass();
|
|
||||||
reactants[3].SetVectorSpherical(reactants[3].GetTheta(), reactants[3].GetPhi(), residP, residE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Reaction::CalculateReaction() {
|
|
||||||
switch(m_eject_theta_type) {
|
|
||||||
case center_of_mass:
|
|
||||||
{
|
|
||||||
CalculateReactionThetaCM();
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case lab:
|
|
||||||
{
|
if(zr < 0 || ar <= 0) {
|
||||||
CalculateReactionThetaLab();
|
nuc_initFlag = false;
|
||||||
break;
|
} else {
|
||||||
|
reactants[3] = Nucleus(zr, ar);
|
||||||
|
nuc_initFlag = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Reaction::SetBeamKE(double bke) {
|
||||||
|
if(!nuc_initFlag || decayFlag)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_bke = bke - target->GetProjectileEnergyLoss(reactants[1].GetZ(), reactants[1].GetA(), bke, rxnLayer, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Reaction::SetEjectileThetaType(int type) {
|
||||||
|
if(decayFlag) return;
|
||||||
|
if(type != center_of_mass && type != lab) return;
|
||||||
|
|
||||||
|
m_eject_theta_type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Methods given by Iliadis in Nuclear Physics of Stars, Appendix C
|
||||||
|
//For use with lab frame restricted angles. May not give appropriate disribution for ejectile
|
||||||
|
void Reaction::CalculateReactionThetaLab() {
|
||||||
|
reactants[0].SetVectorCartesian(0.,0.,0.,reactants[0].GetGroundStateMass());
|
||||||
|
double beam_pz = std::sqrt(m_bke*(m_bke + 2.0 * reactants[1].GetGroundStateMass()));
|
||||||
|
double beam_E = m_bke + reactants[1].GetGroundStateMass();
|
||||||
|
reactants[1].SetVectorCartesian(0.,0.,beam_pz,beam_E);
|
||||||
|
|
||||||
|
double Q = reactants[0].GetGroundStateMass() + reactants[1].GetGroundStateMass() - (reactants[2].GetGroundStateMass() + reactants[3].GetGroundStateMass() + m_ex);
|
||||||
|
|
||||||
|
double Ethresh = -Q*(reactants[2].GetGroundStateMass()+reactants[3].GetGroundStateMass())/(reactants[2].GetGroundStateMass() + reactants[3].GetGroundStateMass() - reactants[1].GetGroundStateMass());
|
||||||
|
if(m_bke < Ethresh) {
|
||||||
|
throw EnergyThresholdException();
|
||||||
|
}
|
||||||
|
|
||||||
|
double term1 = sqrt(reactants[1].GetGroundStateMass()*reactants[2].GetGroundStateMass()*m_bke)/(reactants[2].GetGroundStateMass()+reactants[3].GetGroundStateMass())*cos(m_theta);
|
||||||
|
double term2 = (m_bke*(reactants[3].GetGroundStateMass() - reactants[1].GetGroundStateMass()) + reactants[3].GetGroundStateMass()*Q)/(reactants[3].GetGroundStateMass() + reactants[2].GetGroundStateMass());
|
||||||
|
double sqrt_pos_ejectKE = term1 + sqrt(term1*term1 + term2);
|
||||||
|
double sqrt_neg_ejectKE = term1 - sqrt(term1*term1 + term2);
|
||||||
|
double ejectKE;
|
||||||
|
if(sqrt_pos_ejectKE > 0) {
|
||||||
|
ejectKE = sqrt_pos_ejectKE*sqrt_pos_ejectKE;
|
||||||
|
} else {
|
||||||
|
ejectKE = sqrt_neg_ejectKE*sqrt_neg_ejectKE;
|
||||||
|
}
|
||||||
|
double ejectP = std::sqrt(ejectKE*(ejectKE + 2.0 * reactants[2].GetGroundStateMass()));
|
||||||
|
double ejectE = ejectKE + reactants[2].GetGroundStateMass();
|
||||||
|
|
||||||
|
reactants[2].SetVectorSpherical(m_theta, m_phi, ejectP, ejectE);
|
||||||
|
|
||||||
|
reactants[3] = reactants[0] + reactants[1] - reactants[2];
|
||||||
|
|
||||||
|
ejectKE -= target->GetEjectileEnergyLoss(reactants[2].GetZ(), reactants[2].GetA(), ejectKE, rxnLayer, m_theta);
|
||||||
|
ejectP = std::sqrt(ejectKE*(ejectKE + 2.0 * reactants[2].GetGroundStateMass()));
|
||||||
|
ejectE = ejectKE + reactants[2].GetGroundStateMass();
|
||||||
|
reactants[2].SetVectorSpherical(m_theta, m_phi, ejectP, ejectE);
|
||||||
|
|
||||||
|
if(resid_elossFlag) {
|
||||||
|
double residKE = reactants[3].GetKE() - target->GetEjectileEnergyLoss(reactants[3].GetZ(), reactants[3].GetA(), reactants[3].GetKE(), rxnLayer, reactants[3].GetTheta());
|
||||||
|
double residP = std::sqrt(residKE*(residKE + 2.0*reactants[3].GetInvMass()));
|
||||||
|
double residE = residKE + reactants[3].GetInvMass();
|
||||||
|
reactants[3].SetVectorSpherical(reactants[3].GetTheta(), reactants[3].GetPhi(), residP, residE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Methods from original ANASEN. Gives proper distribution for inverse kinematics.
|
||||||
|
void Reaction::CalculateReactionThetaCM() {
|
||||||
|
//Target assumed at rest, with 0 excitation energy
|
||||||
|
reactants[0].SetVectorCartesian(0.,0.,0.,reactants[0].GetGroundStateMass());
|
||||||
|
double beam_pz = std::sqrt(m_bke*(m_bke + 2.0 * reactants[1].GetGroundStateMass()));
|
||||||
|
double beam_E = m_bke + reactants[1].GetGroundStateMass();
|
||||||
|
reactants[1].SetVectorCartesian(0.,0.,beam_pz,beam_E);
|
||||||
|
|
||||||
|
|
||||||
|
double Q = reactants[0].GetGroundStateMass() + reactants[1].GetGroundStateMass() - (reactants[2].GetGroundStateMass() + reactants[3].GetGroundStateMass() + m_ex);
|
||||||
|
|
||||||
|
double Ethresh = -Q*(reactants[2].GetGroundStateMass()+reactants[3].GetGroundStateMass())/(reactants[2].GetGroundStateMass() + reactants[3].GetGroundStateMass() - reactants[1].GetGroundStateMass());
|
||||||
|
if(m_bke < Ethresh) {
|
||||||
|
throw EnergyThresholdException();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto parent = reactants[0] + reactants[1];
|
||||||
|
double boost2lab[3];
|
||||||
|
double boost2cm[3];
|
||||||
|
const double* boost = parent.GetBoost();
|
||||||
|
for(int i=0; i<3; i++) {
|
||||||
|
boost2lab[i] = boost[i];
|
||||||
|
boost2cm[i] = boost[i]*(-1.0);
|
||||||
|
}
|
||||||
|
parent.ApplyBoost(boost2cm);
|
||||||
|
double ejectE_cm = (std::pow(reactants[2].GetGroundStateMass(), 2.0) - std::pow(reactants[3].GetGroundStateMass() + m_ex, 2.0) + std::pow(parent.GetE(),2.0))/(2.0*parent.GetE());
|
||||||
|
double ejectP_cm = std::sqrt(ejectE_cm*ejectE_cm - std::pow(reactants[2].GetGroundStateMass(), 2.0));
|
||||||
|
reactants[2].SetVectorSpherical(m_theta, m_phi, ejectP_cm, ejectE_cm);
|
||||||
|
reactants[2].ApplyBoost(boost2lab);
|
||||||
|
reactants[3] = reactants[0] + reactants[1] - reactants[2];
|
||||||
|
|
||||||
|
double ejectKE = reactants[2].GetKE();
|
||||||
|
double ejectP = reactants[2].GetP();
|
||||||
|
double ejectE = reactants[2].GetE();
|
||||||
|
//energy loss for ejectile (after reaction!)
|
||||||
|
ejectKE -= target->GetEjectileEnergyLoss(reactants[2].GetZ(), reactants[2].GetA(), ejectKE, rxnLayer, reactants[2].GetTheta());
|
||||||
|
ejectP = std::sqrt(ejectKE*(ejectKE + 2.0 * reactants[2].GetGroundStateMass()));
|
||||||
|
ejectE = ejectKE + reactants[2].GetGroundStateMass();
|
||||||
|
reactants[2].SetVectorSpherical(reactants[2].GetTheta(), reactants[2].GetPhi(), ejectP, ejectE);
|
||||||
|
|
||||||
|
//if on, get eloss for residual (after reaction!)
|
||||||
|
if(resid_elossFlag) {
|
||||||
|
double residKE = reactants[3].GetKE() - target->GetEjectileEnergyLoss(reactants[3].GetZ(), reactants[3].GetA(), reactants[3].GetKE(), rxnLayer, reactants[3].GetTheta());
|
||||||
|
double residP = std::sqrt(residKE*(residKE + 2.0*reactants[3].GetInvMass()));
|
||||||
|
double residE = residKE + reactants[3].GetInvMass();
|
||||||
|
reactants[3].SetVectorSpherical(reactants[3].GetTheta(), reactants[3].GetPhi(), residP, residE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Reaction::CalculateReaction() {
|
||||||
|
switch(m_eject_theta_type) {
|
||||||
|
case center_of_mass:
|
||||||
|
{
|
||||||
|
CalculateReactionThetaCM();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case lab:
|
||||||
|
{
|
||||||
|
CalculateReactionThetaLab();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Calculate in CM, where decay is isotropic
|
||||||
|
void Reaction::CalculateDecay() {
|
||||||
|
|
||||||
|
double Q = reactants[0].GetInvMass() - reactants[2].GetGroundStateMass() - reactants[3].GetGroundStateMass();
|
||||||
|
if(Q < 0) {
|
||||||
|
throw QValueException();
|
||||||
|
}
|
||||||
|
|
||||||
|
const double* boost = reactants[0].GetBoost();
|
||||||
|
double boost2cm[3];
|
||||||
|
double boost2lab[3];
|
||||||
|
for(int i=0; i<3; i++) {
|
||||||
|
boost2lab[i] = boost[i];
|
||||||
|
boost2cm[i] = boost[i]*(-1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
reactants[0].ApplyBoost(&(boost2cm[0]));
|
||||||
|
double ejectE_cm = (reactants[2].GetGroundStateMass()*reactants[2].GetGroundStateMass() - reactants[3].GetGroundStateMass()*reactants[3].GetGroundStateMass() + reactants[0].GetE()*reactants[0].GetE())/
|
||||||
|
(2.0*reactants[0].GetE());
|
||||||
|
double ejectP_cm = std::sqrt(ejectE_cm*ejectE_cm - reactants[2].GetGroundStateMass()*reactants[2].GetGroundStateMass());
|
||||||
|
|
||||||
|
reactants[2].SetVectorSpherical(m_theta, m_phi, ejectP_cm, ejectE_cm);
|
||||||
|
reactants[2].SetThetaCM(m_theta);
|
||||||
|
|
||||||
|
reactants[0].ApplyBoost(boost2lab);
|
||||||
|
reactants[2].ApplyBoost(boost2lab);
|
||||||
|
|
||||||
|
reactants[3] = reactants[0] - reactants[2];
|
||||||
|
|
||||||
|
//energy loss for the *light* break up nucleus
|
||||||
|
double ejectKE = reactants[2].GetKE() - target->GetEjectileEnergyLoss(reactants[2].GetZ(), reactants[2].GetA(), reactants[2].GetKE(), rxnLayer, reactants[2].GetTheta());
|
||||||
|
double ejectP = std::sqrt(ejectKE*(ejectKE + 2.0*reactants[2].GetGroundStateMass()));
|
||||||
|
double ejectE = ejectKE + reactants[2].GetGroundStateMass();
|
||||||
|
reactants[2].SetVectorSpherical(reactants[2].GetTheta(), reactants[2].GetPhi(), ejectP, ejectE);
|
||||||
|
|
||||||
|
//if on, get eloss for *heavy* break up nucleus
|
||||||
|
if(resid_elossFlag) {
|
||||||
|
|
||||||
|
double residKE = reactants[3].GetKE() - target->GetEjectileEnergyLoss(reactants[3].GetZ(), reactants[3].GetA(), reactants[3].GetKE(), rxnLayer, reactants[3].GetTheta());
|
||||||
|
double residP = std::sqrt(residKE*(residKE + 2.0*reactants[3].GetInvMass()));
|
||||||
|
double residE = residKE + reactants[3].GetInvMass();
|
||||||
|
reactants[3].SetVectorSpherical(reactants[3].GetTheta(), reactants[3].GetPhi(), residP, residE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Calculate in CM, where decay is isotropic
|
|
||||||
void Reaction::CalculateDecay() {
|
|
||||||
|
|
||||||
double Q = reactants[0].GetInvMass() - reactants[2].GetGroundStateMass() - reactants[3].GetGroundStateMass();
|
|
||||||
if(Q < 0) {
|
|
||||||
throw QValueException();
|
|
||||||
}
|
|
||||||
|
|
||||||
const double* boost = reactants[0].GetBoost();
|
|
||||||
double boost2cm[3];
|
|
||||||
double boost2lab[3];
|
|
||||||
for(int i=0; i<3; i++) {
|
|
||||||
boost2lab[i] = boost[i];
|
|
||||||
boost2cm[i] = boost[i]*(-1.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
reactants[0].ApplyBoost(&(boost2cm[0]));
|
|
||||||
double ejectE_cm = (reactants[2].GetGroundStateMass()*reactants[2].GetGroundStateMass() - reactants[3].GetGroundStateMass()*reactants[3].GetGroundStateMass() + reactants[0].GetE()*reactants[0].GetE())/
|
|
||||||
(2.0*reactants[0].GetE());
|
|
||||||
double ejectP_cm = std::sqrt(ejectE_cm*ejectE_cm - reactants[2].GetGroundStateMass()*reactants[2].GetGroundStateMass());
|
|
||||||
|
|
||||||
reactants[2].SetVectorSpherical(m_theta, m_phi, ejectP_cm, ejectE_cm);
|
|
||||||
reactants[2].SetThetaCM(m_theta);
|
|
||||||
|
|
||||||
reactants[0].ApplyBoost(boost2lab);
|
|
||||||
reactants[2].ApplyBoost(boost2lab);
|
|
||||||
|
|
||||||
reactants[3] = reactants[0] - reactants[2];
|
|
||||||
|
|
||||||
//energy loss for the *light* break up nucleus
|
|
||||||
double ejectKE = reactants[2].GetKE() - target->GetEjectileEnergyLoss(reactants[2].GetZ(), reactants[2].GetA(), reactants[2].GetKE(), rxnLayer, reactants[2].GetTheta());
|
|
||||||
double ejectP = std::sqrt(ejectKE*(ejectKE + 2.0*reactants[2].GetGroundStateMass()));
|
|
||||||
double ejectE = ejectKE + reactants[2].GetGroundStateMass();
|
|
||||||
reactants[2].SetVectorSpherical(reactants[2].GetTheta(), reactants[2].GetPhi(), ejectP, ejectE);
|
|
||||||
|
|
||||||
//if on, get eloss for *heavy* break up nucleus
|
|
||||||
if(resid_elossFlag) {
|
|
||||||
|
|
||||||
double residKE = reactants[3].GetKE() - target->GetEjectileEnergyLoss(reactants[3].GetZ(), reactants[3].GetA(), reactants[3].GetKE(), rxnLayer, reactants[3].GetTheta());
|
|
||||||
double residP = std::sqrt(residKE*(residKE + 2.0*reactants[3].GetInvMass()));
|
|
||||||
double residE = residKE + reactants[3].GetInvMass();
|
|
||||||
reactants[3].SetVectorSpherical(reactants[3].GetTheta(), reactants[3].GetPhi(), residP, residE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -7,65 +7,65 @@
|
||||||
|
|
||||||
namespace Mask {
|
namespace Mask {
|
||||||
|
|
||||||
XRotation::XRotation() :
|
XRotation::XRotation() :
|
||||||
m_angle(0)
|
m_angle(0)
|
||||||
{
|
{
|
||||||
GenerateMatrix();
|
GenerateMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
XRotation::XRotation(double angle) :
|
XRotation::XRotation(double angle) :
|
||||||
m_angle(angle)
|
m_angle(angle)
|
||||||
{
|
{
|
||||||
GenerateMatrix();
|
GenerateMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
XRotation::~XRotation() {}
|
XRotation::~XRotation() {}
|
||||||
|
|
||||||
void XRotation::GenerateMatrix() {
|
void XRotation::GenerateMatrix() {
|
||||||
m_matrix[0][0] = 1.0; m_matrix[0][1] = 0.0; m_matrix[0][2] = 0.0;
|
m_matrix[0][0] = 1.0; m_matrix[0][1] = 0.0; m_matrix[0][2] = 0.0;
|
||||||
m_matrix[1][0] = 0.0; m_matrix[1][1] = std::cos(m_angle); m_matrix[1][2] = -std::sin(m_angle);
|
m_matrix[1][0] = 0.0; m_matrix[1][1] = std::cos(m_angle); m_matrix[1][2] = -std::sin(m_angle);
|
||||||
m_matrix[2][0] = 0.0; m_matrix[2][1] = std::sin(m_angle); m_matrix[2][2] = std::cos(m_angle);
|
m_matrix[2][0] = 0.0; m_matrix[2][1] = std::sin(m_angle); m_matrix[2][2] = std::cos(m_angle);
|
||||||
}
|
}
|
||||||
|
|
||||||
YRotation::YRotation() :
|
YRotation::YRotation() :
|
||||||
m_angle(0)
|
m_angle(0)
|
||||||
{
|
{
|
||||||
GenerateMatrix();
|
GenerateMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
YRotation::YRotation(double angle) :
|
YRotation::YRotation(double angle) :
|
||||||
m_angle(angle)
|
m_angle(angle)
|
||||||
{
|
{
|
||||||
GenerateMatrix();
|
GenerateMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
YRotation::~YRotation() {}
|
YRotation::~YRotation() {}
|
||||||
|
|
||||||
void YRotation::GenerateMatrix() {
|
void YRotation::GenerateMatrix() {
|
||||||
m_matrix[0][0] = std::cos(m_angle); m_matrix[0][1] = 0.0; m_matrix[0][2] = -std::sin(m_angle);
|
m_matrix[0][0] = std::cos(m_angle); m_matrix[0][1] = 0.0; m_matrix[0][2] = -std::sin(m_angle);
|
||||||
m_matrix[1][0] = 0.0; m_matrix[1][1] = 1.0; m_matrix[1][2] = 0.0;
|
m_matrix[1][0] = 0.0; m_matrix[1][1] = 1.0; m_matrix[1][2] = 0.0;
|
||||||
m_matrix[2][0] = std::sin(m_angle); m_matrix[2][1] = 0.0; m_matrix[2][2] = std::cos(m_angle);
|
m_matrix[2][0] = std::sin(m_angle); m_matrix[2][1] = 0.0; m_matrix[2][2] = std::cos(m_angle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ZRotation::ZRotation() :
|
ZRotation::ZRotation() :
|
||||||
m_angle(0)
|
m_angle(0)
|
||||||
{
|
{
|
||||||
GenerateMatrix();
|
GenerateMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
ZRotation::ZRotation(double angle) :
|
ZRotation::ZRotation(double angle) :
|
||||||
m_angle(angle)
|
m_angle(angle)
|
||||||
{
|
{
|
||||||
GenerateMatrix();
|
GenerateMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
ZRotation::~ZRotation() {}
|
ZRotation::~ZRotation() {}
|
||||||
|
|
||||||
void ZRotation::GenerateMatrix() {
|
void ZRotation::GenerateMatrix() {
|
||||||
m_matrix[0][0] = std::cos(m_angle); m_matrix[0][1] = -std::sin(m_angle); m_matrix[0][2] = 0.0;
|
m_matrix[0][0] = std::cos(m_angle); m_matrix[0][1] = -std::sin(m_angle); m_matrix[0][2] = 0.0;
|
||||||
m_matrix[1][0] = std::sin(m_angle); m_matrix[1][1] = std::cos(m_angle); m_matrix[1][2] = 0.0;
|
m_matrix[1][0] = std::sin(m_angle); m_matrix[1][1] = std::cos(m_angle); m_matrix[1][2] = 0.0;
|
||||||
m_matrix[2][0] = 0.0; m_matrix[2][1] = 0.0; m_matrix[2][2] = 1.0;
|
m_matrix[2][0] = 0.0; m_matrix[2][1] = 0.0; m_matrix[2][2] = 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
139
src/Target.cpp
139
src/Target.cpp
|
@ -12,77 +12,70 @@ Written by G.W. McCann Aug. 2020
|
||||||
*/
|
*/
|
||||||
#include "Target.h"
|
#include "Target.h"
|
||||||
|
|
||||||
/*Targets must be of known thickness*/
|
namespace Mask {
|
||||||
Target::Target(double thick) {
|
|
||||||
thickness = thick;
|
/*Targets must be of known thickness*/
|
||||||
}
|
Target::Target(double thick) {
|
||||||
|
thickness = thick;
|
||||||
Target::~Target() {
|
}
|
||||||
}
|
|
||||||
|
Target::~Target() {}
|
||||||
/*Set target elements of given Z, A, S*/
|
|
||||||
void Target::SetElements(std::vector<int>& z, std::vector<int>& a, std::vector<int>& stoich) {
|
/*Set target elements of given Z, A, S*/
|
||||||
Z = z;
|
void Target::SetElements(std::vector<int>& z, std::vector<int>& a, std::vector<int>& stoich) {
|
||||||
A = a;
|
Z = z;
|
||||||
Stoich = stoich;
|
A = a;
|
||||||
|
Stoich = stoich;
|
||||||
eloss.SetTargetComponents(Z, A, Stoich);
|
|
||||||
}
|
eloss.SetTargetComponents(Z, A, Stoich);
|
||||||
|
}
|
||||||
/*Element verification*/
|
|
||||||
bool Target::ContainsElement(int z, int a) {
|
/*Element verification*/
|
||||||
for(unsigned int i=0; i<Z.size(); i++) {
|
bool Target::ContainsElement(int z, int a) {
|
||||||
if( z == Z[i] && a == A[i]) return true;
|
for(unsigned int i=0; i<Z.size(); i++)
|
||||||
}
|
if( z == Z[i] && a == A[i])
|
||||||
return false;
|
return true;
|
||||||
}
|
return false;
|
||||||
|
}
|
||||||
/*Calculates energy loss for travelling all the way through the target*/
|
|
||||||
double Target::getEnergyLossTotal(int zp, int ap, double startEnergy, double theta) {
|
/*Calculates energy loss for travelling all the way through the target*/
|
||||||
if(theta == PI/2.) return startEnergy;
|
double Target::getEnergyLossTotal(int zp, int ap, double startEnergy, double theta) {
|
||||||
else if (theta > PI/2.) theta = PI - theta;
|
if(theta == M_PI/2.)
|
||||||
return eloss.GetEnergyLoss(zp, ap, startEnergy, thickness/fabs(cos(theta)));
|
return startEnergy;
|
||||||
}
|
else if (theta > M_PI/2.)
|
||||||
|
theta = M_PI - theta;
|
||||||
/*Calculates energy loss for travelling halfway through the target*/
|
|
||||||
double Target::getEnergyLossHalf(int zp, int ap, double startEnergy, double theta) {
|
return eloss.GetEnergyLoss(zp, ap, startEnergy, thickness/fabs(cos(theta)));
|
||||||
if(theta == PI/2.) return startEnergy;
|
}
|
||||||
else if (theta > PI/2.) theta = PI - theta;
|
|
||||||
return eloss.GetEnergyLoss(zp, ap, startEnergy, thickness/(2.0*fabs(cos(theta))));
|
/*Calculates energy loss for travelling halfway through the target*/
|
||||||
}
|
double Target::getEnergyLossHalf(int zp, int ap, double startEnergy, double theta) {
|
||||||
|
if(theta == M_PI/2.)
|
||||||
/*Calculates reverse energy loss for travelling all the way through the target*/
|
return startEnergy;
|
||||||
double Target::getReverseEnergyLossTotal(int zp, int ap, double finalEnergy, double theta) {
|
else if (theta > M_PI/2.)
|
||||||
if(theta == PI/2.) return finalEnergy;
|
theta = M_PI - theta;
|
||||||
else if (theta > PI/2.) theta = PI - theta;
|
|
||||||
return eloss.GetReverseEnergyLoss(zp, ap, finalEnergy, thickness/fabs(cos(theta)));
|
return eloss.GetEnergyLoss(zp, ap, startEnergy, thickness/(2.0*fabs(cos(theta))));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*Calculates reverse energy loss for travelling half way through the target*/
|
/*Calculates reverse energy loss for travelling all the way through the target*/
|
||||||
double Target::getReverseEnergyLossHalf(int zp, int ap, double finalEnergy, double theta) {
|
double Target::getReverseEnergyLossTotal(int zp, int ap, double finalEnergy, double theta) {
|
||||||
if(theta == PI/2.) return finalEnergy;
|
if(theta == M_PI/2.)
|
||||||
else if (theta > PI/2.) theta = PI - theta;
|
return finalEnergy;
|
||||||
return eloss.GetReverseEnergyLoss(zp, ap, finalEnergy, thickness/(2.0*fabs(cos(theta))));
|
else if (theta > M_PI/2.)
|
||||||
}
|
theta = M_PI - theta;
|
||||||
|
|
||||||
/*Getter functions*/
|
return eloss.GetReverseEnergyLoss(zp, ap, finalEnergy, thickness/fabs(cos(theta)));
|
||||||
|
}
|
||||||
double& Target::GetThickness() {
|
|
||||||
return thickness;
|
/*Calculates reverse energy loss for travelling half way through the target*/
|
||||||
}
|
double Target::getReverseEnergyLossHalf(int zp, int ap, double finalEnergy, double theta) {
|
||||||
|
if(theta == M_PI/2.)
|
||||||
int Target::GetNumberOfElements() {
|
return finalEnergy;
|
||||||
return Z.size();
|
else if (theta > M_PI/2.)
|
||||||
}
|
theta = M_PI - theta;
|
||||||
|
|
||||||
int Target::GetElementZ(int index) {
|
return eloss.GetReverseEnergyLoss(zp, ap, finalEnergy, thickness/(2.0*fabs(cos(theta))));
|
||||||
return Z[index];
|
}
|
||||||
}
|
|
||||||
|
|
||||||
int Target::GetElementA(int index) {
|
|
||||||
return A[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
int Target::GetElementStoich(int index) {
|
|
||||||
return Stoich[index];
|
|
||||||
}
|
}
|
||||||
|
|
74
src/Vec3.cpp
74
src/Vec3.cpp
|
@ -8,41 +8,41 @@
|
||||||
|
|
||||||
namespace Mask {
|
namespace Mask {
|
||||||
|
|
||||||
Vec3::Vec3() {
|
Vec3::Vec3() {
|
||||||
m_data[0] = 0.;
|
m_data[0] = 0.;
|
||||||
m_data[1] = 0.;
|
m_data[1] = 0.;
|
||||||
m_data[2] = 0.;
|
m_data[2] = 0.;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec3::Vec3(double x, double y, double z) {
|
||||||
|
m_data[0] = x;
|
||||||
|
m_data[1] = y;
|
||||||
|
m_data[2] = z;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec3::~Vec3() {}
|
||||||
|
|
||||||
|
void Vec3::SetVectorCartesian(double x, double y, double z) {
|
||||||
|
m_data[0] = x;
|
||||||
|
m_data[1] = y;
|
||||||
|
m_data[2] = z;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Vec3::SetVectorSpherical(double r, double theta, double phi) {
|
||||||
|
m_data[0] = r*std::cos(phi)*std::sin(theta);
|
||||||
|
m_data[1] = r*std::sin(phi)*std::sin(theta);
|
||||||
|
m_data[2] = r*std::cos(theta);
|
||||||
|
}
|
||||||
|
|
||||||
|
double Vec3::Dot(const Vec3& rhs) const {
|
||||||
|
return GetX()*rhs.GetX() + GetY()*rhs.GetY() + GetZ()*rhs.GetZ();
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec3 Vec3::Cross(const Vec3& rhs) const {
|
||||||
|
double x = GetY()*rhs.GetZ() - GetZ()*rhs.GetY();
|
||||||
|
double y = GetZ()*rhs.GetX() - GetX()*rhs.GetZ();
|
||||||
|
double z = GetX()*rhs.GetY() - GetY()*rhs.GetX();
|
||||||
|
return Vec3(x,y,z);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec3::Vec3(double x, double y, double z) {
|
|
||||||
m_data[0] = x;
|
|
||||||
m_data[1] = y;
|
|
||||||
m_data[2] = z;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vec3::~Vec3() {}
|
|
||||||
|
|
||||||
void Vec3::SetVectorCartesian(double x, double y, double z) {
|
|
||||||
m_data[0] = x;
|
|
||||||
m_data[1] = y;
|
|
||||||
m_data[2] = z;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Vec3::SetVectorSpherical(double r, double theta, double phi) {
|
|
||||||
m_data[0] = r*std::cos(phi)*std::sin(theta);
|
|
||||||
m_data[1] = r*std::sin(phi)*std::sin(theta);
|
|
||||||
m_data[2] = r*std::cos(theta);
|
|
||||||
}
|
|
||||||
|
|
||||||
double Vec3::Dot(const Vec3& rhs) const {
|
|
||||||
return GetX()*rhs.GetX() + GetY()*rhs.GetY() + GetZ()*rhs.GetZ();
|
|
||||||
}
|
|
||||||
|
|
||||||
Vec3 Vec3::Cross(const Vec3& rhs) const {
|
|
||||||
double x = GetY()*rhs.GetZ() - GetZ()*rhs.GetY();
|
|
||||||
double y = GetZ()*rhs.GetX() - GetX()*rhs.GetZ();
|
|
||||||
double z = GetX()*rhs.GetY() - GetY()*rhs.GetX();
|
|
||||||
return Vec3(x,y,z);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
120
src/Vec4.cpp
120
src/Vec4.cpp
|
@ -10,64 +10,64 @@
|
||||||
|
|
||||||
namespace Mask {
|
namespace Mask {
|
||||||
|
|
||||||
Vec4::Vec4() {
|
Vec4::Vec4() {
|
||||||
for(auto& val: m_data)
|
for(auto& val: m_data)
|
||||||
val = 0.0;
|
val = 0.0;
|
||||||
for(auto& val: m_boost)
|
for(auto& val: m_boost)
|
||||||
val = 0.0;
|
val = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec4::Vec4(double px, double py, double pz, double E) {
|
||||||
|
m_data[0] = px;
|
||||||
|
m_data[1] = py;
|
||||||
|
m_data[2] = pz;
|
||||||
|
m_data[3] = E;
|
||||||
|
CalcBoostToCM();
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec4::~Vec4() {}
|
||||||
|
|
||||||
|
void Vec4::SetVectorCartesian(double px, double py, double pz, double E) {
|
||||||
|
m_data[0] = px;
|
||||||
|
m_data[1] = py;
|
||||||
|
m_data[2] = pz;
|
||||||
|
m_data[3] = E;
|
||||||
|
|
||||||
|
CalcBoostToCM();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Vec4::SetVectorSpherical(double theta, double phi, double p, double E) {
|
||||||
|
m_data[0] = p*cos(phi)*sin(theta);
|
||||||
|
m_data[1] = p*sin(phi)*sin(theta);
|
||||||
|
m_data[2] = p*cos(theta);
|
||||||
|
m_data[3] = E;
|
||||||
|
CalcBoostToCM();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Vec4::CalcBoostToCM() {
|
||||||
|
m_boost[0] = m_data[0]/m_data[3];
|
||||||
|
m_boost[1] = m_data[1]/m_data[3];
|
||||||
|
m_boost[2] = m_data[2]/m_data[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
void Vec4::ApplyBoost(const double* beta) {
|
||||||
|
double beta2 = beta[0]*beta[0] + beta[1]*beta[1] + beta[2]*beta[2];
|
||||||
|
double gamma = 1.0/std::sqrt(1.0 - beta2);
|
||||||
|
double bdotp = beta[0]*m_data[0] + beta[1]*m_data[1] + beta[2]*m_data[2];
|
||||||
|
double gfactor = beta2>0.0 ? (gamma - 1.0)/beta2 : 0.0;
|
||||||
|
|
||||||
|
SetVectorCartesian(GetPx()+gfactor*bdotp*beta[0]+gamma*beta[0]*GetE(),
|
||||||
|
GetPy()+gfactor*bdotp*beta[1]+gamma*beta[1]*GetE(),
|
||||||
|
GetPz()+gfactor*bdotp*beta[2]+gamma*beta[2]*GetE(),
|
||||||
|
gamma*(GetE() + bdotp));
|
||||||
|
}
|
||||||
|
|
||||||
|
double Vec4::Dot(const Vec4& rhs) const {
|
||||||
|
return GetE()*rhs.GetE() - GetPx()*rhs.GetPx() - GetPy()*rhs.GetPy() - GetPz()*rhs.GetPz();
|
||||||
|
}
|
||||||
|
|
||||||
|
Vec4 Vec4::Cross(const Vec4& rhs) const {
|
||||||
|
return Vec4();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec4::Vec4(double px, double py, double pz, double E) {
|
|
||||||
m_data[0] = px;
|
|
||||||
m_data[1] = py;
|
|
||||||
m_data[2] = pz;
|
|
||||||
m_data[3] = E;
|
|
||||||
CalcBoostToCM();
|
|
||||||
}
|
|
||||||
|
|
||||||
Vec4::~Vec4() {}
|
|
||||||
|
|
||||||
void Vec4::SetVectorCartesian(double px, double py, double pz, double E) {
|
|
||||||
m_data[0] = px;
|
|
||||||
m_data[1] = py;
|
|
||||||
m_data[2] = pz;
|
|
||||||
m_data[3] = E;
|
|
||||||
|
|
||||||
CalcBoostToCM();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Vec4::SetVectorSpherical(double theta, double phi, double p, double E) {
|
|
||||||
m_data[0] = p*cos(phi)*sin(theta);
|
|
||||||
m_data[1] = p*sin(phi)*sin(theta);
|
|
||||||
m_data[2] = p*cos(theta);
|
|
||||||
m_data[3] = E;
|
|
||||||
CalcBoostToCM();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Vec4::CalcBoostToCM() {
|
|
||||||
m_boost[0] = m_data[0]/m_data[3];
|
|
||||||
m_boost[1] = m_data[1]/m_data[3];
|
|
||||||
m_boost[2] = m_data[2]/m_data[3];
|
|
||||||
}
|
|
||||||
|
|
||||||
void Vec4::ApplyBoost(const double* beta) {
|
|
||||||
double beta2 = beta[0]*beta[0] + beta[1]*beta[1] + beta[2]*beta[2];
|
|
||||||
double gamma = 1.0/std::sqrt(1.0 - beta2);
|
|
||||||
double bdotp = beta[0]*m_data[0] + beta[1]*m_data[1] + beta[2]*m_data[2];
|
|
||||||
double gfactor = beta2>0.0 ? (gamma - 1.0)/beta2 : 0.0;
|
|
||||||
|
|
||||||
SetVectorCartesian(GetPx()+gfactor*bdotp*beta[0]+gamma*beta[0]*GetE(),
|
|
||||||
GetPy()+gfactor*bdotp*beta[1]+gamma*beta[1]*GetE(),
|
|
||||||
GetPz()+gfactor*bdotp*beta[2]+gamma*beta[2]*GetE(),
|
|
||||||
gamma*(GetE() + bdotp));
|
|
||||||
}
|
|
||||||
|
|
||||||
double Vec4::Dot(const Vec4& rhs) const {
|
|
||||||
return GetE()*rhs.GetE() - GetPx()*rhs.GetPx() - GetPy()*rhs.GetPy() - GetPz()*rhs.GetPz();
|
|
||||||
}
|
|
||||||
|
|
||||||
Vec4 Vec4::Cross(const Vec4& rhs) const {
|
|
||||||
return Vec4();
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
|
@ -17,6 +17,7 @@ int main(int argc, char** argv) {
|
||||||
sw.Start();
|
sw.Start();
|
||||||
try {
|
try {
|
||||||
if(!calculator.LoadConfig(argv[1])) {
|
if(!calculator.LoadConfig(argv[1])) {
|
||||||
|
std::cerr<<"Unable to read input file!"<<std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
calculator.Run();
|
calculator.Run();
|
||||||
|
|
Binary file not shown.
Loading…
Reference in New Issue
Block a user