Advertisement
Guest User

randMC.cpp

a guest
Dec 16th, 2019
196
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.56 KB | None | 0 0
  1. #define _USE_MATH_DEFINES
  2. #include <cmath>
  3. #include "RandMC.h"
  4. #include "random.h"
  5. #include "material.h"
  6. #include "AtomicData.h"
  7. #include "Spectrum.h"
  8. #include <iostream>
  9.  
  10.  
  11. cRandMC::cRandMC()
  12. {
  13. pRand = NULL;
  14. minEnergy = 1; // in keV ;
  15. maxEnergy = 1000; // in keV
  16. noOfEnergySteps = 100;
  17. }
  18.  
  19.  
  20. cRandMC::~cRandMC()
  21. {
  22. }
  23.  
  24. void cRandMC::setRandBase(cRandKiss &rand) {
  25. pRand = &rand;
  26. }
  27.  
  28. void cRandMC::prepare(cMaterial &mat, double tubeVoltage) {
  29. cAtomicData data;
  30. data.prepare();
  31.  
  32. if (pRand == NULL) {
  33. throw runtime_error("pRand is null");
  34. }
  35. else {
  36. preparePhotonEnergy(tubeVoltage);
  37. prepareFreePath(mat);
  38. prepareInteractingElement(mat);
  39.  
  40. for (unsigned i = 0; i < mat.getNoOfElements(); i++) {
  41.  
  42. prepareInteraction(mat.getAtomicNumber(i));
  43. prepareSubShellCS(mat.getAtomicNumber(i));
  44. prepareAugerChar(mat.getAtomicNumber(i));
  45. prepareComptonPolar(mat.getAtomicNumber(i));
  46. prepareRayleighPolar(mat.getAtomicNumber(i));
  47. }
  48. }
  49. }
  50. double cRandMC::getPhotonEnergy() {
  51. return randPhotonEnergy.rand();
  52. }
  53. double cRandMC::getIsotropicPolar() {
  54.  
  55. return acos(1 - 2 * pRand->randU());
  56. }
  57. double cRandMC::getIsotropicPolar(double thetaMax) {
  58.  
  59. return acos(1 -(1 - cos(thetaMax)) * pRand->randU());
  60. }
  61. void cRandMC::getIsotropicAzimuth(double u[3]) {
  62.  
  63. double azimuth; // new azimuthal angle
  64. double a ; // length on xy−plane
  65. azimuth = 2 * M_PI * pRand->randU ();
  66. a = sqrt (1 - u[2] * u[2] ) ;
  67. u[0] = a * sin (azimuth );
  68. u[1] = a * cos (azimuth );
  69.  
  70. }
  71. double cRandMC::getFreePath(double energy) {
  72.  
  73. unsigned i = 0; // index for mfp
  74. unsigned step; // actual step size
  75. // find index i
  76. for (step = step0Mfp; step; step >>= 1) {
  77. if ((i | step) < noOfEnergySteps && energy > meanFreePath[0][i|step]) {
  78. i |= step;
  79. }
  80.  
  81. // apply linear interpolation
  82. return (meanFreePath[1][i] + (meanFreePath[1][i + 1] - meanFreePath[1][i]) *(energy - meanFreePath[0][i]) / (meanFreePath[0][i + 1] - meanFreePath[0][i])) * randExp.rand();
  83. }
  84.  
  85. }
  86. unsigned cRandMC::getInteractingElement(double energy) {
  87.  
  88. return (unsigned)randChooseElement.rand(energy);
  89. }
  90. unsigned cRandMC::getInteraction(unsigned Z, double energy) {
  91.  
  92. return (unsigned)randInteraction[Z-1].rand(energy);
  93. }
  94. unsigned cRandMC::getPhotoSubshell(unsigned Z, double energy) {
  95.  
  96. if (Z <= 2) {
  97. return 1;
  98. }
  99. else {
  100. return (unsigned)randSubshell[Z-1].rand(energy);
  101. }
  102.  
  103. }
  104. double cRandMC::getAugerChar(unsigned Z, unsigned vacancy, unsigned &newVac1, unsigned &newVac2) {
  105.  
  106. cAtomicData data;
  107. unsigned randVal;
  108.  
  109. if (randAugerChar[Z - 1]->isPrepared()) {
  110. randVal = (unsigned)randAugerChar[Z-1][vacancy -1].rand();
  111. newVac1 = randVal & 0x3F;
  112. newVac2 = randVal >> 6;
  113.  
  114. return data.getBindingEnergy(Z, vacancy) - data.getBindingEnergy(Z, newVac1) - data.getBindingEnergy(Z, newVac2);
  115. }
  116. else {
  117. newVac1 = 0;
  118. newVac2 = 0;
  119. return data.getBindingEnergy(Z, vacancy);
  120. }
  121. }
  122. double cRandMC::getComptonPolar(unsigned Z, double energy) {
  123.  
  124. return randComPolAngle[Z-1].rand(energy);
  125. }
  126. double cRandMC::getRayleighPolar(unsigned Z, double energy) {
  127.  
  128. return randRayPolAngle[Z-1].rand(energy);
  129. }
  130. void cRandMC::preparePhotonEnergy(double tubeVoltage) {
  131.  
  132. double minEnergy;
  133. string spectrumName;
  134. cSpectrum spectrum;
  135. spectrum.readSpectrum("SRO33100ROT350.dat", tubeVoltage, minEnergy, spectrumName);
  136.  
  137.  
  138. randPhotonEnergy.reset();
  139. randPhotonEnergy.setRandomBase(*pRand);
  140.  
  141. double step = (tubeVoltage - minEnergy) / spectrum.size();
  142.  
  143. for (unsigned i = 0; i < spectrum.size(); i++) {
  144. randPhotonEnergy.addDistPoint(i * step, spectrum[i]);
  145. }
  146. randPhotonEnergy.addDistPoint(tubeVoltage, 0);
  147. randPhotonEnergy.prepare();
  148.  
  149. }
  150. void cRandMC::prepareFreePath(cMaterial &mat) {
  151.  
  152. meanFreePath[0].resize(noOfEnergySteps + 1);
  153. meanFreePath[1].resize(noOfEnergySteps + 1);
  154.  
  155. for (unsigned k = 0; k <= noOfEnergySteps; k++) {
  156.  
  157. meanFreePath[0][k] = minEnergy * exp(k * log(maxEnergy / minEnergy) / noOfEnergySteps);
  158.  
  159. meanFreePath[1][k] = 1/ mat.getAttCoeff(minEnergy);
  160. }
  161.  
  162. randExp.reset();
  163. randExp.setRandomBase(*pRand);
  164.  
  165. for (step0Mfp = 1 << 31; !(step0Mfp & (noOfEnergySteps -1)); step0Mfp >>= 1);
  166.  
  167. }
  168. void cRandMC::prepareInteractingElement(cMaterial &mat) {
  169.  
  170. vector<double> dist;
  171. dist.resize(mat.getNoOfElements());
  172.  
  173. for (unsigned i = 0; i < mat.getNoOfElements(); i++) {
  174.  
  175. dist[i] = mat.getAtomicNumber(i) + 0.5;
  176. }
  177.  
  178. randChooseElement.reset();
  179. randChooseElement.setRandomBase(*pRand);
  180. randChooseElement.setRandomValues(dist);
  181.  
  182. double energy;
  183.  
  184. for (unsigned k = 0; k <= noOfEnergySteps; k++) {
  185.  
  186. energy = minEnergy * exp(k * log(maxEnergy / minEnergy) / noOfEnergySteps);
  187.  
  188. for (unsigned m = 0; m < mat.getNoOfElements(); m++) {
  189.  
  190. dist[m] = (mat.getAttCoeff(energy) * mat.getFraction(m));
  191.  
  192. randChooseElement.addProbabilities(dist, energy);
  193. }
  194. }
  195.  
  196. randChooseElement.prepare();
  197. }
  198. void cRandMC::prepareInteraction(unsigned Z) {
  199.  
  200. cAtomicData data;
  201. vector<double> dist(3);
  202. randInteraction[Z-1].reset();
  203. randInteraction[Z-1].setRandomBase(*pRand);
  204.  
  205. dist[0] = 1.5;
  206. dist[1] = 2.5;
  207. dist[2] = 3.5;
  208.  
  209. randInteraction->setRandomValues(dist);
  210.  
  211. double energy;
  212.  
  213. for (unsigned k = 0; k <= noOfEnergySteps; k++) {
  214.  
  215. energy = minEnergy * exp(k * log(maxEnergy / minEnergy) / noOfEnergySteps);
  216.  
  217. dist[0] = data.getPhotoTotal(Z, energy);
  218. dist[1] = data.getComptonTotal(Z, energy);
  219. dist[2] = data.getRayleighTotal(Z, energy);
  220.  
  221. randInteraction[Z - 1].addProbabilities(dist, energy);
  222. }
  223. randInteraction->prepare();
  224. }
  225. void cRandMC::prepareSubShellCS(unsigned Z) {
  226.  
  227. vector<unsigned> subshell;
  228. vector<double> dist;
  229.  
  230. if (Z > 2) {
  231.  
  232. randSubshell[Z-1].reset();
  233. randSubshell[Z-1].setRandomBase(*pRand);
  234.  
  235. cAtomicData data;
  236. data.prepare();
  237. data.getPhotoSubshells(Z, subshell);
  238. dist.resize(subshell.size());
  239.  
  240. for (unsigned i = 0; i < subshell.size(); i++) {
  241. dist[i] = subshell[i] + 0.5;
  242. }
  243. randSubshell[Z - 1].setRandomValues(dist);
  244. double energy;
  245.  
  246. for (unsigned k = 0; k <= noOfEnergySteps; k++) {
  247.  
  248. energy = minEnergy * exp(k * log(maxEnergy / minEnergy) / noOfEnergySteps);
  249.  
  250. for (unsigned m = 0; m < subshell.size(); m++) {
  251.  
  252. dist[m] = data.getTotalCrossSection(subshell[m], energy);
  253. }
  254. randSubshell[Z - 1].addProbabilities(dist, energy);
  255.  
  256. }
  257. randSubshell[Z - 1].prepare();
  258. }
  259.  
  260. }
  261. void cRandMC::prepareAugerChar(unsigned Z) {
  262.  
  263. vector<unsigned> subshell;
  264. vector<cAtomicData::tAugerEm> augerEm;
  265. vector<cAtomicData::tCharEm> charEm;
  266.  
  267. cAtomicData data;
  268. data.getPhotoSubshells(Z, subshell);
  269.  
  270. for (unsigned k = 0; k < subshell.size(); k++) {
  271.  
  272. if (data.getBindingEnergy(Z, subshell[k]) > minEnergy) {
  273.  
  274. data.getAugerEmissionTable(Z, subshell[k], augerEm);
  275. data.getCharEmissionTable(Z, subshell[k], charEm);
  276.  
  277. randAugerChar[Z -1][subshell[k] -1].reset();
  278. randAugerChar[Z-1][subshell[k]-1].setRandomBase(*pRand);
  279.  
  280. for (unsigned j = 0; j < augerEm.size(); j++) {
  281.  
  282. randAugerChar[Z - 1][subshell[k] - 1].addDistPoint(augerEm[j].vacancy1 + (augerEm[j].vacancy2 << 6) + 0.5, augerEm[j].prob);
  283. }
  284.  
  285. for (unsigned m = 0; m < charEm.size(); m++) {
  286. randAugerChar[Z - 1][subshell[k] - 1].addDistPoint(charEm[m].vacancy + 0.5, charEm[m].prob);
  287. }
  288. randAugerChar[Z - 1][subshell[k] - 1].prepare();
  289. }
  290.  
  291. }
  292. }
  293. void cRandMC::prepareComptonPolar(unsigned Z) {
  294.  
  295. double energy;
  296. double theta;
  297. double prob;
  298. cAtomicData data;
  299. randComPolAngle[Z-1].reset();
  300. randComPolAngle[Z-1].setRandomBase(*pRand);
  301.  
  302. for (unsigned k = 0; k <= noOfEnergySteps; k++) {
  303.  
  304. energy = minEnergy * exp(k * log(maxEnergy / minEnergy) / noOfEnergySteps);
  305.  
  306. randComPolAngle[Z - 1].add(0, 0, energy);
  307.  
  308. for (unsigned m = 1; m < 179; m++) {
  309.  
  310. theta = m * M_PI / 180;
  311.  
  312. prob = sin(theta) * data.getComptonDiff(Z, energy, theta);
  313.  
  314. randComPolAngle[Z-1].add(theta, prob, energy);
  315. }
  316. }
  317.  
  318. randComPolAngle[Z-1].add(M_PI, 0, energy);
  319. randComPolAngle[Z - 1].prepare();
  320. }
  321. void cRandMC::prepareRayleighPolar(unsigned Z) {
  322.  
  323. double energy;
  324. double theta;
  325. double prob;
  326. cAtomicData data;
  327. randRayPolAngle[Z-1].reset();
  328. randRayPolAngle[Z-1].setRandomBase(*pRand);
  329.  
  330. for (unsigned k = 0; k <= noOfEnergySteps; k++) {
  331.  
  332. energy = minEnergy * exp(k * log(maxEnergy / minEnergy) / noOfEnergySteps);
  333. randRayPolAngle[Z - 1].add(0, 0, energy);
  334.  
  335. for (unsigned m = 1; m < 179; m++) {
  336.  
  337. theta = m * M_PI / 180;
  338. prob = sin(theta) * data.getComptonDiff(Z, energy, theta);
  339.  
  340. randRayPolAngle[Z - 1].add(theta, prob, energy);
  341. }
  342. randRayPolAngle[Z - 1].add(M_PI, 0, energy);
  343. }
  344. randRayPolAngle[Z - 1].prepare();
  345. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement