1
0
Fork 0
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:
Gordon McCann 2021-09-06 16:18:49 -04:00
parent 170cc7afb0
commit e96b29accf
31 changed files with 1490 additions and 1484 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -171,4 +171,5 @@ private:
}; };
#endif #endif

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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----------

View File

@ -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;
} }

View File

@ -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;
}
} }
} }

View File

@ -49,6 +49,7 @@
*/ */
#include "SabreDetector.h" #include "SabreDetector.h"
SabreDetector::SabreDetector() : SabreDetector::SabreDetector() :

View File

@ -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

View File

@ -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;
} }

View File

@ -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;
}

View File

@ -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]);
} }

View File

@ -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;
} }

View File

@ -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;
}
};

View File

@ -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;
}
} }
} }

View File

@ -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);
}
}
};

View File

@ -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;
} }
}; };

View File

@ -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];
} }

View File

@ -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);
}
};

View File

@ -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();
}
};

View File

@ -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();