52 #define S_STREAM std::istringstream
55 #define S_STREAM std::istrstream
67 getSampledAverage(e,de);
90 sprintf(buf,
"monoenergetic %g MeV",E);
94 EGS_Float expectedAverage()
const {
97 EGS_Float maxEnergy()
const {
112 static bool have_x =
false;
113 static EGS_Float the_x;
118 EGS_Float r = sqrt(-2*log(1-rndm->
getUniform()));
119 EGS_Float cphi, sphi;
154 if (Eo <= 0)
egsFatal(
"EGS_GaussianSpectrum: attempt to construct "
155 "a spectrum with a negative mean energy (%g)\n",Eo);
157 sigma = -sigma*0.4246609;
161 sprintf(buf,
"Gaussian spectrum with Eo = %g and sigma = %g",Eo,sigma);
163 if (Eo - 5*sigma > 0) {
171 EGS_Float expectedAverage()
const {
174 EGS_Float maxEnergy()
const {
181 E = Eo + sigma*getGaussianRN(rndm);
183 while (E <= 0 || E > Emax);
231 sleft(sig_left), sright(sig_right) {
233 sleft = -sleft*0.4246609;
236 sright= -sright*0.4246609;
238 Emax = Eo + 4*sright;
239 if (Eo - 4*sleft < 0)
egsWarning(
"EGS_DoubleGaussianSpectrum: "
240 "for Eo=%g, sigma=%g there will be negative energy sampled\n");
241 p = sleft/(sleft + sright);
243 sprintf(buf,
"Double Gaussian spectrum with Eo = %g sig(left) = %g"
244 " and sig(right) = %g",Eo,sleft,sright);
248 EGS_Float maxEnergy()
const {
251 EGS_Float expectedAverage()
const {
252 return Eo + sqrt(2/M_PI)*(sright-sleft);
268 E = Eo-sleft*fabs(getGaussianRN(rndm));
274 E = Eo+sright*fabs(getGaussianRN(rndm));
307 Emin(emin), Emax(emax), de(emax - emin) {
309 sprintf(buf,
"Uniform spectrum with Emin = %g Emax = %g",Emin,Emax);
313 EGS_Float maxEnergy()
const {
316 EGS_Float expectedAverage()
const {
317 return (Emin+Emax)/2;
410 EGS_Float maxEnergy()
const {
411 return table->getMaximum();
413 EGS_Float expectedAverage()
const {
414 return table->getAverage();
420 void setType(
int Type,
const char *fname) {
422 type =
"tabulated line spectrum";
424 else if (Type == 1) {
425 type =
"tabulated histogram spectrum";
428 type =
"tabulated spectrum";
431 type +=
" defined in ";
435 type +=
" defined inline";
440 return table->
sample(rndm);
466 vector<BetaRecordLeaf *> myBetas = decays->getBetaRecords();
468 for (vector<BetaRecordLeaf *>::iterator beta = myBetas.begin();
469 beta != myBetas.end(); beta++) {
472 if ((*beta)->getCharge() == 1 &&
473 (*beta)->getPositronIntensity() == 0) {
477 unsigned short int daughterZ = (*beta)->getZ();
480 "Energy, Z, A, forbidden: %f %d %d %d\n",
481 (*beta)->getFinalEnergy(), daughterZ,
482 (*beta)->getAtomicWeight(), (*beta)->getForbidden()
486 EGS_Float *e =
new EGS_Float [nbin];
487 EGS_Float *spec =
new EGS_Float [nbin];
488 EGS_Float *spec_y =
new EGS_Float [nbin];
490 double de, s_y, factor, se_y;
496 emax = (*beta)->getFinalEnergy();
497 zzz[0] = (double)daughterZ;
498 rmass = (*beta)->getAtomicWeight();
505 if (daughterZ == 18 && (*beta)->getCharge() == -1) {
510 else if (daughterZ == 54 && emax < 0.154 && emax > 0.150) {
515 else if (daughterZ == 56 && emax > 1.173 && emax < 1.177) {
520 else if (daughterZ == 82) {
525 else if (daughterZ == 84) {
529 lamda[0] = (*beta)->getForbidden();
534 if ((*beta)->getCharge() == 1) {
547 de=((int)(etop[0]*10.0+1)/10.)/nbin;
551 for (
int ib=0; ib<nbin; ib++) {
558 for (
int ib=0; ib<nbin; ib++) {
561 sp(e[ib],spec_y[ib],factor);
568 se_y=se_y+spec_y[ib]*e[ib];
571 for (
int ib=0; ib<nbin; ib++) {
572 spec[ib]=1/de*(spec_y[ib]/s_y);
577 (*beta)->setSpectrum(bspec);
580 if (outputBetaSpectra ==
"yes") {
583 ostr << decays->radionuclide <<
"_" << emax <<
".spec";
585 egsInformation(
"EGS_RadionuclideBetaSpectrum: Outputting beta spectrum to file: %s\n", ostr.str().c_str());
588 specStream.open(ostr.str().c_str());
589 for (
int ib=0; ib<nbin; ib++) {
590 spec[ib]=1/de*(spec_y[ib]/s_y);
591 specStream << e[ib] <<
" " << spec[ib] << endl;
600 complex<double> cgamma(complex<double> z) {
602 static const int g=7;
603 static const double pi = 3.1415926535897932384626433832795028841972;
604 static const double p[g+2] = {0.99999999999980993, 676.5203681218851,
609 -0.13857109526572012,
610 9.9843695780195716e-6,
611 1.5056327351493116e-7
615 return pi / (sin(pi*z)*cgamma(
double(1.0)-z));
619 complex<double> x=p[0];
620 for (
int i=1; i<g+2; i++) {
621 x += p[i]/(z+complex<double>(i,0));
623 complex<double> t = z + (g + double(0.5));
625 return double(sqrt(2.*pi)) * pow(t,z+
double(0.5)) * exp(-t) * x;
628 complex<double> clgamma(complex<double> z) {
629 complex<double> u, v, h, p, r;
631 static const double pi = 3.1415926535897932384626433832795028841972;
632 static const double c1 = 9.189385332046727e-1;
633 static const double c2 = 1.144729885849400;
634 static const double c[10] = {8.333333333333333e-2,
635 -2.777777777777777e-3,
636 7.936507936507936e-4,
637 -5.952380952380952e-4,
638 8.417508417508417e-4,
639 -1.917526917526917e-3,
640 6.410256410256410e-3,
641 -2.955065359477124e-2,
642 1.796443723688305e-1,
646 static const double hf = 0.5;
652 if (y == 0 && -abs(x) ==
int(x)) {
658 u = double(1.) - complex<double>(x, ya);
661 u = complex<double>(x, ya);
671 for (
int i=1; i<=6-int(ur); i++) {
673 u = complex<double>(ur, ui);
675 a = a + atan2(ui, ur);
677 h = complex<double>(hf * log(pow(real(h),2) + pow(imag(h),2)),
683 r = double(1.) / pow(u,2);
686 for (
int i=8; i>=1; i--) {
690 h = c1 + (u-hf)*log(u) - u + (c[0]+p) / u - h;
693 ur = double(
int(x)) - 1.;
696 double t = exp(-x-x);
698 t = x + hf * log(t*pow(a,2)+pow(hf*(1.-t),2));
699 a = atan2(cos(ui)*tanh(x),a) - ur*pi;
700 h = c2 - complex<double>(t,a) - h;
710 void slfact(
double p,
double z,
double radf,
double xl[4]) {
713 double dfac[4]= {1.0, 3.0, 15.0, 105.0};
714 double pi,c137,az,w,rad,pr,y,x1,gk,bb,cc,dd,x2;
726 for (
int k=1; k<=4; k++) {
728 gk = sqrt(k*k-az*az);
729 x1 = pow((pow(p,k-1)/dfac[k-1]), 2);
731 aa = clgamma(complex<double>(gk,y));
732 double aa_real = real(aa);
734 bb=lgamma((
double)k);
735 cc=lgamma(2.0*k +1.0);
736 dd=lgamma(2.0*gk+1.0);
739 pow(2.0*pr, 2.0*(gk-k)) *
740 exp(pi*y+2.0*(aa_real+cc-bb-dd)) *
745 az*pr*(2.0*w*(2.0*k+1.0)/(p*k*(2.0*gk+1.0)) -
746 2.0*p*gk/(w*k*(2.0*gk+1.0))) -
747 2.0*k*pr*pr/((2.0*k+1.0)*(k+gk));
748 xl[k-1] = x1*ff[k-1]/ff[0]*x2;
754 void bsp(
double e,
double &bspec,
double &factor) {
777 double pi,c137,zab,v,z,x,w,psq,p,y,qsq,g,cab,f,radf;
792 v = 1.13*pow(zab,1.333)/pow(c137,2);
802 psq = w*w-double(1.0);
806 qsq = 3.83*pow(emax-e,2);
811 g = qsq*2.0*pi*pow(z,(2.0*x-1.0));
815 a = complex<double>(x,y);
818 f = pow(psq,x-1.0)*exp(pi*y)*pow(cab,2);
828 radf = 1.2*pow(rmass,0.333);
829 slfact(p,zz,radf,xl);
832 bspec = g*(qsq*xl[0]+9.0*xl[1]);
836 bspec = g*(pow(qsq,2)*xl[0]+30.0*qsq*xl[1]+225.0*xl[2]);
840 bspec = g*(pow(qsq,3.0)*xl[0]+63.0*pow(qsq,2)*xl[1]+
841 1575.0*qsq*xl[2] + 11025.0*xl[3]);
851 bspec = bspec*(qsq*xl[0]+20.07*xl[1]);
856 bspec = bspec*(psq+10.0*qsq);
861 bspec = bspec*(qsq*xl[0]+0.045*xl[1]);
866 bspec = bspec*(1.0-1.677*e+ 2.77*e*e);
871 bspec = bspec*(1.78-2.35*e+e*e);
879 void sp(
double e,
double &spec,
double &factor) {
884 for (
int icomp=0; icomp<ncomps; icomp++) {
889 spec= spec+bspec*rel[icomp]/area[icomp];
895 double zz,emax,rmass;
896 double zzz[9],etop[9],rel[9],area[9],lamda[9];
1025 const EGS_Float relativeActivity,
const string relaxType,
const string outputBetaSpectra,
const bool scoreAlphasLocally,
const bool allowMultiTransition) :
1036 decays =
new EGS_Ensdf(nuclide, ensdf_file, relaxType, allowMultiTransition, verbose);
1039 decays->normalizeIntensities();
1045 myBetas = decays->getBetaRecords();
1046 myAlphas = decays->getAlphaRecords();
1047 myGammas = decays->getGammaRecords();
1048 myMetastableGammas = decays->getMetastableGammaRecords();
1049 myUncorrelatedGammas = decays->getUncorrelatedGammaRecords();
1050 myLevels = decays->getLevelRecords();
1051 xrayIntensities = decays->getXRayIntensities();
1052 xrayEnergies = decays->getXRayEnergies();
1053 augerIntensities = decays->getAugerIntensities();
1054 augerEnergies = decays->getAugerEnergies();
1061 totalGammaEnergy = 0;
1062 relaxationType = relaxType;
1063 scoreAlphasLocal = scoreAlphasLocally;
1066 for (vector<BetaRecordLeaf *>::iterator beta = myBetas.begin();
1067 beta != myBetas.end(); beta++) {
1069 double energy = (*beta)->getFinalEnergy();
1070 if (Emax < energy) {
1074 for (vector<AlphaRecord *>::iterator alpha = myAlphas.begin();
1075 alpha != myAlphas.end(); alpha++) {
1077 double energy = (*alpha)->getFinalEnergy();
1078 if (Emax < energy) {
1082 for (vector<GammaRecord *>::iterator gamma = myGammas.begin();
1083 gamma != myGammas.end(); gamma++) {
1085 double energy = (*gamma)->getDecayEnergy();
1086 if (Emax < energy) {
1090 for (vector<GammaRecord *>::iterator gamma = myUncorrelatedGammas.begin();
1091 gamma != myUncorrelatedGammas.end(); gamma++) {
1093 double energy = (*gamma)->getDecayEnergy();
1094 if (Emax < energy) {
1098 for (
unsigned int i=0; i < xrayEnergies.size(); ++i) {
1099 numSampledXRay.push_back(0);
1100 if (Emax < xrayEnergies[i]) {
1101 Emax = xrayEnergies[i];
1104 for (
unsigned int i=0; i < augerEnergies.size(); ++i) {
1105 numSampledAuger.push_back(0);
1106 if (Emax < augerEnergies[i]) {
1107 Emax = augerEnergies[i];
1112 spectrumWeight = relativeActivity;
1116 egsInformation(
"EGS_RadionuclideSpectrum: Relative activity: %f\n",relativeActivity);
1166 return spectrumWeight;
1171 spectrumWeight = newWeight;
1193 return emissionType;
1200 egsInformation(
"\nSampled %s emissions:\n", decays->radionuclide.c_str());
1204 egsWarning(
"EGS_RadionuclideSpectrum::printSampledEmissions: Warning: The number of disintegrations (tracked by `ishower`) is less than 1.\n");
1208 egsInformation(
"Energy | Intensity per 100 decays (adjusted by %f)\n", decays->decayDiscrepancy);
1209 if (myBetas.size() > 0) {
1212 for (vector<BetaRecordLeaf *>::iterator beta = myBetas.begin();
1213 beta != myBetas.end(); beta++) {
1216 ((EGS_Float)(*beta)->getNumSampled()/(ishower+1))*100);
1218 if (myAlphas.size() > 0) {
1221 for (vector<AlphaRecord *>::iterator alpha = myAlphas.begin();
1222 alpha != myAlphas.end(); alpha++) {
1225 ((EGS_Float)(*alpha)->getNumSampled()/(ishower+1))*100);
1227 if (myGammas.size() > 0) {
1230 EGS_I64 totalNumSampled = 0;
1231 for (vector<GammaRecord *>::iterator gamma = myGammas.begin();
1232 gamma != myGammas.end(); gamma++) {
1234 totalNumSampled += (*gamma)->getGammaSampled();
1236 ((EGS_Float)(*gamma)->getGammaSampled()/(ishower+1))*100,
1237 ((EGS_Float)(*gamma)->getICSampled()/(ishower+1))*100,
1238 ((EGS_Float)(*gamma)->getIPSampled()/(ishower+1))*100
1241 if (myGammas.size() > 0) {
1242 if (totalNumSampled > 0) {
1244 totalGammaEnergy / totalNumSampled);
1250 if (myUncorrelatedGammas.size() > 0) {
1251 egsInformation(
"Uncorrelated gamma records (E,Igamma,Ice,Ipp):\n");
1253 for (vector<GammaRecord *>::iterator gamma = myUncorrelatedGammas.begin();
1254 gamma != myUncorrelatedGammas.end(); gamma++) {
1257 ((EGS_Float)(*gamma)->getGammaSampled()/(ishower+1))*100,
1258 ((EGS_Float)(*gamma)->getICSampled()/(ishower+1))*100,
1259 ((EGS_Float)(*gamma)->getIPSampled()/(ishower+1))*100
1262 if (xrayEnergies.size() > 0) {
1265 for (
unsigned int i=0; i < xrayEnergies.size(); ++i) {
1267 ((EGS_Float)numSampledXRay[i]/(ishower+1))*100);
1269 if (augerEnergies.size() > 0) {
1272 for (
unsigned int i=0; i < augerEnergies.size(); ++i) {
1274 ((EGS_Float)numSampledAuger[i]/(ishower+1))*100);
1279 bool storeState(ostream &data)
const {
1283 bool setState(istream &data) {
1287 void resetCounter() {
1291 totalGammaEnergy = 0;
1309 if (relaxParticles.size() > 0) {
1326 if (currentLevel && currentLevel->levelCanDecay() && currentLevel->getEnergy() >
epsilon) {
1328 for (vector<GammaRecord *>::iterator gamma = myGammas.begin();
1329 gamma != myGammas.end(); gamma++) {
1331 if ((*gamma)->getLevelRecord() == currentLevel) {
1333 if (u < (*gamma)->getTransitionIntensity()) {
1338 if ((*gamma)->getGammaIntensity() < 1) {
1345 double hl = currentLevel->getHalfLife();
1347 currentTime = -hl * log(1.-rndm->
getUniform()) /
1348 0.693147180559945309417232121458176568075500134360255254120680009493393;
1352 if (rndm->
getUniform() < (*gamma)->getMultiTransitionProb()) {
1353 multiTransitions.push_back(currentLevel);
1357 currentLevel = (*gamma)->getFinalLevel();
1360 if (u2 < (*gamma)->getGammaIntensity()) {
1362 (*gamma)->incrGammaSampled();
1364 currentQ = (*gamma)->getCharge();
1366 E = (*gamma)->getDecayEnergy();
1368 totalGammaEnergy += E;
1375 else if (u2 < (*gamma)->getICIntensity()) {
1376 (*gamma)->incrICSampled();
1380 if ((*gamma)->icIntensity.size()) {
1386 for (
unsigned int i=0; i<(*gamma)->icIntensity.size(); ++i) {
1387 if (u3 < (*gamma)->icIntensity[i]) {
1389 E = (*gamma)->getDecayEnergy() - (*gamma)->getBindingEnergy(i);
1394 if (relaxationType ==
"eadl") {
1398 (*gamma)->relax(i,app->getEcut()-app->getRM(),app->getPcut(),rndm,edep,relaxParticles);
1409 (*gamma)->incrIPSampled();
1435 if (multiTransitions.size() > 0) {
1436 currentLevel = multiTransitions.back();
1437 multiTransitions.pop_back();
1447 for (vector<BetaRecordLeaf *>::iterator beta = myBetas.begin();
1448 beta != myBetas.end(); beta++) {
1449 if (u < (*beta)->getBetaIntensity()) {
1455 (*beta)->incrNumSampled();
1456 currentQ = (*beta)->getCharge();
1459 currentLevel = (*beta)->getLevelRecord();
1463 if (currentQ == 1) {
1465 if ((*beta)->getPositronIntensity() >
epsilon && rndm->
getUniform() < (*beta)->getPositronIntensity()) {
1470 if (relaxationType ==
"eadl" && (*beta)->ecShellIntensity.size()) {
1475 for (
unsigned int i=0; i<(*beta)->ecShellIntensity.size(); ++i) {
1476 if (u3 < (*beta)->ecShellIntensity[i]) {
1480 (*beta)->relax(i,app->getEcut()-app->getRM(),app->getPcut(),rndm,edep,relaxParticles);
1502 E = (*beta)->getSpectrum()->sample(rndm);
1509 for (vector<AlphaRecord *>::iterator alpha = myAlphas.begin();
1510 alpha != myAlphas.end(); alpha++) {
1511 if (u < (*alpha)->getAlphaIntensity()) {
1517 (*alpha)->incrNumSampled();
1518 currentQ = (*alpha)->getCharge();
1521 currentLevel = (*alpha)->getLevelRecord();
1526 if (scoreAlphasLocal) {
1527 edep += (*alpha)->getFinalEnergy();
1539 for (vector<GammaRecord *>::iterator gamma = myMetastableGammas.begin();
1540 gamma != myMetastableGammas.end(); gamma++) {
1541 if (u < (*gamma)->getTransitionIntensity()) {
1548 currentLevel = (*gamma)->getLevelRecord();
1558 for (vector<GammaRecord *>::iterator gamma = myUncorrelatedGammas.begin();
1559 gamma != myUncorrelatedGammas.end(); gamma++) {
1560 if (u < (*gamma)->getTransitionIntensity()) {
1565 if ((*gamma)->getGammaIntensity() < 1) {
1570 if (u2 < (*gamma)->getGammaIntensity()) {
1572 (*gamma)->incrGammaSampled();
1574 currentQ = (*gamma)->getCharge();
1576 E = (*gamma)->getDecayEnergy();
1578 totalGammaEnergy += E;
1585 else if (u2 < (*gamma)->getICIntensity()) {
1586 (*gamma)->incrICSampled();
1590 if ((*gamma)->icIntensity.size()) {
1596 for (
unsigned int i=0; i<(*gamma)->icIntensity.size(); ++i) {
1597 if (u3 < (*gamma)->icIntensity[i]) {
1599 E = (*gamma)->getDecayEnergy() - (*gamma)->getBindingEnergy(i);
1602 if (relaxationType ==
"eadl") {
1606 (*gamma)->relax(i,app->getEcut()-app->getRM(),app->getPcut(),rndm,edep,relaxParticles);
1617 (*gamma)->incrIPSampled();
1636 for (
unsigned int i=0; i < xrayIntensities.size(); ++i) {
1637 if (u < xrayIntensities[i]) {
1639 numSampledXRay[i]++;
1642 E = xrayEnergies[i];
1651 for (
unsigned int i=0; i < augerIntensities.size(); ++i) {
1652 if (u < augerIntensities[i]) {
1654 numSampledAuger[i]++;
1657 E = augerEnergies[i];
1680 vector<BetaRecordLeaf *> myBetas;
1681 vector<AlphaRecord *> myAlphas;
1682 vector<GammaRecord *> myGammas,
1684 myUncorrelatedGammas;
1685 vector<LevelRecord *> myLevels;
1686 vector<double> xrayIntensities,
1690 vector<EGS_I64> numSampledXRay,
1692 vector<const LevelRecord *> multiTransitions;
1696 unsigned int emissionType;
1697 EGS_Float currentTime,
1703 string relaxationType;
1704 bool scoreAlphasLocal;
1716 istream &skipsep(istream &in) {
1718 for (EGS_I64 loopCount=0; loopCount<=
loopMax; ++loopCount) {
1720 egsFatal(
"skipsep: Too many iterations were required! Input may be invalid, or consider increasing loopMax.");
1724 if (in.eof() || in.fail() || !in.good()) {
1738 static char spec_msg1[] =
"EGS_BaseSpectrum::createSpectrum:";
1742 egsWarning(
"%s got null input?\n",spec_msg1);
1746 bool delete_it =
false;
1747 if (!input->
isA(
"spectrum")) {
1750 egsWarning(
"%s no 'spectrum' input!\n",spec_msg1);
1756 int err = inp->
getInput(
"type",stype);
1758 egsWarning(
"%s wrong/missing 'type' input\n",spec_msg1);
1765 if (inp->
compare(stype,
"monoenergetic")) {
1768 if (err)
egsWarning(
"%s wrong/missing 'energy' input for a "
1769 "monoenergetic spectrum\n",spec_msg1);
1774 else if (inp->
compare(stype,
"Gaussian")) {
1775 EGS_Float Eo, sig, fwhm;
1776 int err1 = inp->
getInput(
"mean energy",Eo);
1777 int err2 = inp->
getInput(
"sigma",sig);
1778 int err3 = inp->
getInput(
"fwhm",fwhm);
1779 if (err1 || (err2 && err3)) {
1780 if (err1)
egsWarning(
"%s wrong/missing 'mean energy' input"
1781 " for a Gaussian spectrum\n",spec_msg1);
1782 else egsWarning(
"%s wrong/missing 'sigma' and 'FWHM' input for a "
1783 "Gaussian spectrum\n",spec_msg1);
1787 if (Eo <= 0)
egsWarning(
"%s mean energy must be positive but your"
1788 " input was %g\n",Eo);
1791 if (sig <= 0)
egsWarning(
"%s sigma must be positive"
1792 " but your input was %g\n",spec_msg1,sig);
1798 if (fwhm <= 0)
egsWarning(
"%s FWHM must be positive"
1799 " but your input was %g\n",spec_msg1,fwhm);
1807 else if (inp->
compare(stype,
"Double Gaussian")) {
1809 vector<EGS_Float> sig, fwhm;
1810 int err1 = inp->
getInput(
"mean energy",Eo);
1811 int err2 = inp->
getInput(
"sigma",sig);
1812 int err3 = inp->
getInput(
"fwhm",fwhm);
1813 if (!err1 && Eo <= 0) {
1816 if (!err2 && sig.size() != 2) {
1819 if (!err2 && (sig[0] <= 0 || sig[1] <= 0)) {
1822 if (!err3 && fwhm.size() != 2) {
1825 if (!err3 && (fwhm[0] <= 0 || fwhm[1] <= 0)) {
1828 if (err1 || (err2 && err3)) {
1829 if (err1)
egsWarning(
"%s wrong/missing 'mean energy' input"
1830 " for a Double Gaussian spectrum\n",spec_msg1);
1831 if (err2 && err3)
egsWarning(
"%s wrong/missing 'sigma' and 'FWHM'"
1832 " input for a Double Gaussian spectrum\n",spec_msg1);
1835 if (!err2 && !err3)
egsWarning(
"%s found 'sigma' and 'FWHM' "
1836 "input, using 'sigma'\n",spec_msg1);
1845 else if (inp->
compare(stype,
"uniform")) {
1846 vector<EGS_Float> range;
1847 EGS_Float Emin, Emax;
1848 int err1 = inp->
getInput(
"range",range);
1849 int err2 = inp->
getInput(
"minimum energy",Emin);
1850 int err3 = inp->
getInput(
"maximum energy",Emax);
1851 if (!err2 && !err3 && Emin > Emax) {
1852 egsWarning(
"%s Emin (%g) is greater than Emax (%g)?\n",
1853 spec_msg1,Emin,Emax);
1857 if (err1 && err2 && err3)
egsWarning(
"%s wrong/missing 'range' and"
1858 " 'minimum/maximum energy' input\n",spec_msg1);
1860 if (!err2 && !err3) {
1864 if (range[0] < range[1]) {
1873 else if (inp->
compare(stype,
"tabulated spectrum")) {
1875 err = inp->
getInput(
"spectrum file",spec_file);
1879 ifstream sdata(spec_file.c_str());
1880 if (!sdata)
egsWarning(
"%s failed to open spectrum file %s\n",
1881 spec_msg1,spec_file.c_str());
1884 sdata.getline(title,1023);
1885 if (sdata.eof() || sdata.fail() || !sdata.good()) {
1886 egsWarning(
"%s error while reading title of spectrum file"
1887 "%s\n",spec_msg1,spec_file.c_str());
1893 if (sdata.eof() || sdata.fail() || !sdata.good()) {
1894 egsWarning(
"%s error while reading spectrum type and "
1895 "number of bins in spectrum file %s\n",
1896 spec_msg1,spec_file.c_str());
1904 sdata >> nbin >> skipsep >> dum >> skipsep >> mode;
1905 if (sdata.eof() || sdata.fail() || !sdata.good()) {
1906 egsWarning(
"%s error while reading spectrum type and "
1907 "number of bins in spectrum file %s\n",
1908 spec_msg1,spec_file.c_str());
1915 egsWarning(
"%s nbin in a spectrum must be at least 2\n"
1916 " you have %d in the spectrum file %s\n",
1917 spec_msg1,nbin,spec_file.c_str());
1923 if (mode < 0 || mode > 3) {
1924 egsWarning(
"%s unknown spectrum type %d in spectrum file"
1925 " %s\n",spec_msg1,mode,spec_file.c_str());
1931 EGS_Float *en_array, *f_array;
1933 f_array =
new EGS_Float [nbin];
1934 if (mode == 0 || mode == 1) {
1935 en_array =
new EGS_Float [nbin+1];
1940 en_array =
new EGS_Float [nbin];
1943 for (
int j=0; j<nbin; j++) {
1944 sdata >> en_array[ibin++] >> skipsep >> f_array[j];
1945 if (sdata.eof() || sdata.fail() || !sdata.good()) {
1946 egsWarning(
"%s error on line %d in spectrum file %s\n",
1947 spec_msg1,j+2,spec_file.c_str());
1955 if (mode != 2 && ibin > 1) {
1956 if (en_array[ibin-1] <= en_array[ibin-2]) {
1957 egsWarning(
"%s energies must be in increasing "
1958 "order.\n This is not the case for input on "
1959 "lines %d,%d in spectrum file %s\n",
1960 spec_msg1,j+2,j+1,spec_file.c_str());
1968 f_array[j]/=(en_array[ibin-1]-en_array[ibin-2]);
1975 else if (mode == 3) {
1978 int nb = itype == 1 ? nbin+1 : nbin;
1986 vector<EGS_Float> eners, probs;
1988 int err1 = inp->
getInput(
"energies",eners);
1989 int err2 = inp->
getInput(
"probabilities",probs);
1990 int err3 = inp->
getInput(
"spectrum mode",mode);
1992 err3 = inp->
getInput(
"spectrum type",mode);
1995 egsWarning(
"%s wrong/missing 'spectrum mode' input\n",spec_msg1);
2002 if (mode < 0 || mode > 3) {
2004 " %s\n",spec_msg1,mode,spec_file.c_str());
2013 else if (mode == 3) {
2018 if (err1)
egsWarning(
"%s wrong/missing 'energies' input\n",
2020 if (err2)
egsWarning(
"%s wrong/missing 'probabilities' "
2021 "input\n",spec_msg1);
2024 if (itype == 1 && probs.size() != eners.size()-1)
2025 egsWarning(
"%s for spectrum type 1 the number of energies"
2026 " must be the number of probabilities + 1\n",
2028 else if ((itype == 0 || itype == 2) &&
2029 probs.size() != eners.size())
2030 egsWarning(
"%s for spectrum types 0 and 2 the number of "
2031 "energies must be equal to the number of probabilities\n",
2034 int nbin = eners.size();
2035 int nbin1 = itype == 1 ? nbin-1 : nbin;
2036 EGS_Float *x =
new EGS_Float [nbin],
2037 *f =
new EGS_Float [nbin1];
2043 for (
int j=0; j<nbin1; j++) {
2044 x[ibin] = eners[ibin];
2046 f[j] = mode == 0 ? probs[j]/(eners[ibin-1]-eners[ibin-2]) : probs[j];
2047 if (itype != 0 && ibin > 1) {
2048 if (x[ibin-1] <= x[ibin-2]) {
2050 "increasing order\n This is not the case"
2051 " for inputs %d and %d (%g,%g) %d\n",
2052 spec_msg1,ibin-2,ibin-1,x[ibin-2],x[ibin-1],
2070 else if (inp->
compare(stype,
"radionuclide")) {
2071 egsInformation(
"EGS_BaseSpectrum::createSpectrum: Initializing radionuclide spectrum...\n");
2074 err = inp->
getInput(
"nuclide",nuclide);
2076 err = inp->
getInput(
"isotope",nuclide);
2078 err = inp->
getInput(
"radionuclide",nuclide);
2080 egsWarning(
"%s wrong/missing 'nuclide' input\n",spec_msg1);
2086 EGS_Float relativeActivity;
2087 err = inp->
getInput(
"relative activity",relativeActivity);
2089 relativeActivity = 1;
2094 string tmp_relaxType, relaxType;
2095 err = inp->
getInput(
"atomic relaxations", tmp_relaxType);
2097 relaxType = tmp_relaxType;
2102 if (inp->
compare(relaxType,
"ensdf")) {
2103 relaxType =
"ensdf";
2104 egsInformation(
"EGS_BaseSpectrum::createSpectrum: Fluorescence and auger from the ensdf file will be used.\n");
2106 else if (inp->
compare(relaxType,
"eadl")) {
2108 egsInformation(
"EGS_BaseSpectrum::createSpectrum: Fluorescence and auger from the ensdf file will be ignored. EADL relaxations will be used.\n");
2110 else if (inp->
compare(relaxType,
"none") || inp->
compare(relaxType,
"off") || inp->
compare(relaxType,
"no")) {
2112 egsInformation(
"EGS_BaseSpectrum::createSpectrum: Fluorescence and auger from the ensdf file will be ignored. No relaxations following radionuclide disintegrations will be modelled.\n");
2115 egsFatal(
"EGS_BaseSpectrum::createSpectrum: Error: Invalid selection for 'atomic relaxations'. Use 'eadl' (default), 'ensdf' or 'off'.\n");
2120 string tmp_outputBetaSpectra, outputBetaSpectra;
2121 err = inp->
getInput(
"output beta spectra", tmp_outputBetaSpectra);
2123 outputBetaSpectra = tmp_outputBetaSpectra;
2125 if (inp->
compare(outputBetaSpectra,
"yes")) {
2126 egsInformation(
"EGS_BaseSpectrum::createSpectrum: Beta energy spectra will be output to files.\n");
2128 else if (inp->
compare(outputBetaSpectra,
"no")) {
2129 egsInformation(
"EGS_BaseSpectrum::createSpectrum: Beta energy spectra will not be output to files.\n");
2132 egsFatal(
"EGS_BaseSpectrum::createSpectrum: Error: Invalid selection for 'output beta spectra'. Use 'no' (default) or 'yes'.\n");
2136 outputBetaSpectra =
"no";
2141 string tmp_alphaScoring;
2142 bool scoreAlphasLocally =
false;
2143 err = inp->
getInput(
"alpha scoring", tmp_alphaScoring);
2145 if (inp->
compare(tmp_alphaScoring,
"local")) {
2146 scoreAlphasLocally =
true;
2147 egsInformation(
"EGS_BaseSpectrum::createSpectrum: Alpha particles will deposit energy locally, in the same region as creation.\n");
2149 else if (inp->
compare(tmp_alphaScoring,
"discard")) {
2150 scoreAlphasLocally =
false;
2151 egsInformation(
"EGS_BaseSpectrum::createSpectrum: Alpha particles will be discarded (no transport or energy deposition).\n");
2154 egsFatal(
"EGS_BaseSpectrum::createSpectrum: Error: Invalid selection for 'alpha scoring'. Use 'discard' (default) or 'local'.\n");
2160 string tmp_allowMultiTransition;
2161 bool allowMultiTransition =
false;
2162 err = inp->
getInput(
"extra transition approximation", tmp_allowMultiTransition);
2164 if (inp->
compare(tmp_allowMultiTransition,
"on")) {
2165 allowMultiTransition =
true;
2166 egsInformation(
"EGS_BaseSpectrum::createSpectrum: Extra transition approximation is on. If the intensity away from a level in a radionuclide daughter is larger than the intensity feeding the level (e.g. decays to that level), then additional transitions away from that level will be sampled. They will not be correlated with decays, but the spectrum will produce emission rates to match both the decay intensities and the internal transition intensities from the ensdf file.\n");
2168 else if (inp->
compare(tmp_allowMultiTransition,
"off")) {
2169 allowMultiTransition =
false;
2170 egsInformation(
"EGS_BaseSpectrum::createSpectrum: Extra transition approximation is off.\n");
2173 egsFatal(
"EGS_BaseSpectrum::createSpectrum: Error: Invalid selection for 'extra transition approximation'. Use 'off' (default) or 'on'.\n");
2179 err = inp->
getInput(
"ensdf file",ensdf_file);
2188 ensdf_file =
egsJoinPath(ensdf_file.c_str(),
"lnhb");
2189 ensdf_file =
egsJoinPath(ensdf_file.c_str(),
"ensdf");
2192 char *hen_house = getenv(
"HEN_HOUSE");
2195 egsWarning(
"EGS_BaseSpectrum::createSpectrum: "
2196 "No active application and HEN_HOUSE not defined.\n"
2197 "Assuming local directory for spectra\n");
2202 ensdf_file =
egsJoinPath(ensdf_file.c_str(),
"lnhb");
2203 ensdf_file =
egsJoinPath(ensdf_file.c_str(),
"ensdf");
2206 ensdf_file =
egsJoinPath(ensdf_file.c_str(),nuclide.append(
".txt"));
2211 ensdf_fh.open(ensdf_file.c_str(),ios::in);
2212 if (!ensdf_fh.is_open()) {
2213 egsWarning(
"EGS_BaseSpectrum::createSpectrum: failed to open ensdf file %s"
2214 " for reading\n",ensdf_file.c_str());
2220 spec =
new EGS_RadionuclideSpectrum(nuclide, ensdf_file, relativeActivity, relaxType, outputBetaSpectra, scoreAlphasLocally, allowMultiTransition);
2223 egsWarning(
"%s unknown spectrum type %s\n",spec_msg1,stype.c_str());
~EGS_RadionuclideSpectrum()
Destructor.
#define EGS_EXPORT
Export symbols from the egspp library.
const EGS_I64 loopMax
The maximum number of iterations for near-infinite loops.
bool EGS_EXPORT egsGetI64(istream &data, EGS_I64 &n)
Reads a 64 bit integer from the stream data and assigns it to n. Returns true on success, false on failure.
EGS_AliasTable class header file.
void setSpectrumWeight(EGS_Float newWeight)
Set the relative weight assigned to this spectrum.
A class for sampling random values from a given probability distribution using the alias table techni...
EGS_BaseSource class header file.
EGS_Float expectedAverage() const
Not implemented - returns 0.
void reportAverageEnergy() const
Report the average energy (expected and actually sampled).
EGS_TabulatedSpectrum(int N, const EGS_Float *x, const EGS_Float *f, int Type=1, const char *fname=0)
Construct a tabulated spectrum from the energies x and the probabilities f.
A monoenergetic particle spectrum.
bool EGS_EXPORT egsStoreI64(ostream &data, EGS_I64 n)
Writes the 64 bit integer n to the output stream data and returns true on success, false on failure.
EGS_DoubleGaussianSpectrum(EGS_Float mean_energy, EGS_Float sig_left, EGS_Float sig_right)
Construct a double-Gaussian spectrum with mean energy mean_energy and widths sig_left and sig_right...
string egsJoinPath(const string &first, const string &second)
Join two path variables (or a path and a file name) using the platform specific directory separator a...
void getAzimuth(EGS_Float &cphi, EGS_Float &sphi)
Sets cphi and sphi to the cosine and sine of a random angle uniformely distributed between 0 and ...
EGS_Float sample(EGS_RandomGenerator *rndm) const
Get a random point from this table using the RNG rndm.
EGS_Float sigma
The Gaussian width.
EGS_Float Emax
The maximum energy.
EGS_AdvancedApplication class header file.
EGS_Float Emax
The maximum energy.
The ensdf library header file.
EGS_I64 getShowerIndex() const
Get the shower index of the most recent emission.
double getTime() const
Get the emission time of the most recent emission.
unsigned int getEmissionType() const
Get the emission type of the most recent source particle.
static EGS_BaseSpectrum * createSpectrum(EGS_Input *inp)
Create and return a pointer to a spectrum object from the information pointed to by inp...
int q
charge (0-photon, -1=electron)
EGS_Float getSpectrumWeight() const
Get the relative weight assigned to this spectrum.
Base random number generator class. All random number generators should be derived from this class...
EGS_InfoFunction EGS_EXPORT egsFatal
Always use this function for reporting fatal errors.
The ensdf class for reading ensdf format data files.
string egsExpandPath(const string &aname)
Expands first environment variable found in a file name.
EGS_RandomGenerator class header file.
EGS_InfoFunction EGS_EXPORT egsInformation
Always use this function for reporting the progress of a simulation and any other type of information...
static EGS_Application * activeApplication()
Get the active application.
Attempts to fix broken math header files.
EGS_Float getUniform()
Returns a random number uniformly distributed between zero (inclusive) and 1 (exclusive).
void printSampledEmissions()
Print the sampled emission intensities.
EGS_RadionuclideSpectrum(const string nuclide, const string ensdf_file, const EGS_Float relativeActivity, const string relaxType, const string outputBetaSpectra, const bool scoreAlphasLocally, const bool allowMultiTransition)
Construct a radionuclide spectrum.
const EGS_Float epsilon
The epsilon constant for floating point comparisons.
EGS_Float sright
The width of the spectrum right of Eo.
const string & getHenHouse() const
Returns the HEN_HOUSE directory.
EGS_RadionuclideBetaSpectrum(EGS_Ensdf *decays, const string outputBetaSpectra)
Construct beta spectra for a radionuclide.
A double-Gaussian spectrum.
EGS_Float sleft
The width of the spectrum left of Eo.
Base class for energy spectra. All energy spectra in the EGSnrc C++ class library are derived from th...
Beta spectrum generation for EGS_RadionuclideSpectrum.
EGS_MonoEnergy(EGS_Float energy)
Construct a monoenergetic spectrum with energy energy.
EGS_GaussianSpectrum(EGS_Float mean_energy, EGS_Float Sigma)
Construct a Gaussian spectrum with mean energy mean_energy and width Sigma.
EGS_Float getEdep() const
Get energy that should be deposited locally from relaxations/alphas.
EGS_Application class header file.
EGS_Float maxEnergy() const
Returns the maximum energy that may be emitted.
Base class for advanced EGSnrc C++ applications.
EGS_Float sample(EGS_RandomGenerator *rndm)
Sample an event from the spectrum, returns the energy of the emitted particle.
int getCharge() const
Get the charge of the most recent emission.
EGS_InfoFunction EGS_EXPORT egsWarning
Always use this function for reporting warnings.