42 #include "estar_formulaCalcs.h"
43 #include "estar_dataParser.h"
44 #include "estar_dataTables.h"
54 class compFormulaPreprocess {
56 struct RestructureCompound {
58 string finalElemArray[100];
59 float finalNumAtoms[100];
69 RestructureCompound compRes(
string *inputElemArray,
float *inputNumAtomArray,
int NEP) {
72 int perTableLength = 100;
73 int elemPresent[perTableLength];
75 float numAtomsArray[perTableLength];
77 string tempElemArray[perTableLength];
78 while (j < perTableLength) {
84 vector<int> atomicNumArray(NEP);
87 auto it = atomic_number.find(inputElemArray[i]);
88 if (it == atomic_number.end()) {
89 egsFatal(
"estar::compRes: Unrecognised element symbol '%s' at index %d.\n"
90 "Check the formula input.\n", inputElemArray[i].c_str(), i);
92 atomicNumArray[i] = it->second;
100 zIndex = atomicNumArray[i] - 1;
102 if (zIndex < 0 || zIndex >= perTableLength) {
103 egsFatal(
"estar::compRes: Atomic number index %d is out of bounds [0, %d).\n"
104 "Element '%s' may not be in the periodic table.\n",
105 zIndex, perTableLength, inputElemArray[i].c_str());
108 if (elemPresent[zIndex] == 0) {
109 elemPresent[zIndex] = 1;
110 numAtomsArray[zIndex] = inputNumAtomArray[i];
111 tempElemArray[zIndex] = inputElemArray[i];
112 numDiffAtoms = numDiffAtoms + 1;
116 numAtomsArray[zIndex] = numAtomsArray[zIndex] + inputNumAtomArray[i];
121 RestructureCompound compForm;
122 compForm.finalNumOfElems = numDiffAtoms;
123 for (
int m=0; m < perTableLength; ++m) {
124 if (elemPresent[m] == 1) {
125 compForm.finalElemArray[k] = tempElemArray[m];
126 compForm.finalNumAtoms[k] = numAtomsArray[m];
135 string getCompFormula(
string *elementArray,
float *numOfAtoms,
int NEP,
int mediaNum) {
136 vector<int> numberOfAtoms(NEP);
137 vector<string> numberOfAtomsStr(NEP);
138 string compoundFormula =
"";
139 for (
int i=0; i < NEP; ++i) {
140 numberOfAtoms[i] =
static_cast<int>(numOfAtoms[i]);
141 numberOfAtomsStr[i] = to_string(numberOfAtoms[i]);
145 for (
int i=0; i < NEP; ++i) {
146 compoundFormula = compoundFormula + elementArray[i] + numberOfAtomsStr[i];
149 egsInformation(
"\nestar::getCompFormula: Medium %d is a compound of %d elements with formula: %s\n", mediaNum, NEP, compoundFormula.c_str());
151 return compoundFormula;
161 formula_calc getDataFromFormulae(
int knmat,
double rho,
string *elementArray,
double *massFraction,
float *numOfAtoms,
int NEP,
int mediaNum) {
164 string formulaCompound;
166 formula = elementArray[0];
167 fc = fcalc(knmat, rho, formula);
169 egsInformation(
"\nestar::getDataFromFormulae: Medium %d treated as element.\n", mediaNum);
173 else if (knmat == 1) {
174 compFormulaPreprocess compObject;
175 compFormulaPreprocess::RestructureCompound rc = compObject.compRes(elementArray, numOfAtoms, NEP);
176 string compFormula = compObject.getCompFormula(rc.finalElemArray, rc.finalNumAtoms, rc.finalNumOfElems, mediaNum);
177 fc = fcalc(knmat, rho, compFormula);
179 egsInformation(
"\nestar::getDataFromFormulae: Medium %d treated as compound.\n", mediaNum);
184 fc = mixtureCalculation(rho, elementArray, massFraction, NEP);
186 egsInformation(
"\nestar::getDataFromFormulae: Medium %d treated as mixture.\n", mediaNum);
201 int atom_num(
string elem_name) {
202 auto it = atomic_number.find(elem_name);
203 if (it == atomic_number.end()) {
204 egsFatal(
"estar::atom_num: Unrecognised element symbol '%s'.\n"
205 "Check the formula input, they must be characters not integers.\n", elem_name.c_str());
218 formula_calc fcalc(
int knmat,
double rho,
string elemName) {
219 int numElemsPerTable = 100;
226 int mmax = pf.elem_types;
228 if (mmax > numElemsPerTable) {
229 egsFatal(
"estar::fcalc: Parsed element type count %d exceeds maximum of %d.\n"
230 "Formula '%s' may be malformed.\n",
231 mmax, numElemsPerTable, elemName.c_str());
234 int atomic_number_element;
235 fc.mmax = pf.elem_types;
236 double nz[numElemsPerTable];
239 fc.jz[i] = atom_num(pf.str_arr[i]);
240 atomic_number_element = fc.jz[i];
247 nz[i] = pf.num_arr[i];
262 asum = asum+atb[jm-1]*nz[m];
267 egsFatal(
"estar::fcalc: Total atomic mass sum is zero for formula '%s'.\n"
268 "Check that atom counts are non-zero.\n", elemName.c_str());
282 fc.wt[m] = atb[jm-1]*(nz[m]/asum);
292 const double rhocut = 0.1;
299 za = fc.jz[m]/atb[jm-1];
300 fc.zav = fc.zav + fc.wt[m]*za;
311 potm = 1.13*poth[jm-1];
336 egsFatal(
"estar::fcalc: I-value potm=%g is non-positive for Z=%d.\n"
337 "Cannot take log. Check poth/potgas/potcon tables.\n", potm, jm);
340 potl = potl + fc.wt[m]*za*log(potm);
346 egsFatal(
"estar::fcalc: Mean Z/A (zav) is zero for formula '%s'.\n"
347 "Cannot compute I-value.\n", elemName.c_str());
349 fc.pot = exp(potl/fc.zav);
355 mixtureData getEgsMediaData(
string *elementArray,
double *massFraction,
int NEP) {
360 egsFatal(
"estar::getEgsMediaData: Number of components must be > 0, got %d.\n", ncomp);
362 for (
int i=0; i < ncomp; ++i) {
363 md.frm[i] = elementArray[i];
367 for (
int i=0; i < ncomp; ++i) {
368 if (massFraction[i] <= 0) {
369 egsFatal(
"estar::getEgsMediaData: Mass fraction for component %d is %g.\n"
370 "Mass fractions must be > 0.\n", i, massFraction[i]);
372 md.frac[i] = massFraction[i];
373 sumf = sumf + md.frac[i];
376 for (
int i=0; i < ncomp; ++i) {
377 md.frac[i] = md.frac[i]/sumf;
388 formula_calc mixtureCalculation(
double rho,
string *elementArray,
double *massFraction,
int NEP) {
390 mixtureData md = getEgsMediaData(elementArray, massFraction, NEP);
391 int numComp = md.ncomp;
392 vector<string> formulaArray(numComp);
393 vector<double> fractionArray(numComp);
394 for (
int i = 0; i < numComp; i++) {
395 formulaArray[i] = md.frm[i];
396 fractionArray[i] = md.frac[i];
400 double wate[num_elems];
401 for (
int j=0; j < num_elems; ++j) {
407 vector<double> zavArray(numComp);
408 vector<double> potArray(numComp);
410 for (
int i = 0; i < numComp; i++) {
412 fc = fcalc(2, rho, formulaArray[i]);
413 for (
int j = 0; j < fc.mmax; j++) {
414 atmoicNumIndex = fc.jz[j] - 1;
419 if (lh[atmoicNumIndex] == 0) {
420 lh[atmoicNumIndex] = 1;
421 wate[atmoicNumIndex] = md.frac[i]*fc.wt[j];
424 wate[atmoicNumIndex] = wate[atmoicNumIndex] + md.frac[i]*fc.wt[j];
429 zavArray[i] = fc.zav;
430 potArray[i] = fc.pot;
435 for (
int k = 0; k < num_elems; k++) {
444 ffc.wt[index] = wate[k];
450 int numDiffElemsUsed = index;
452 ffc.mmax = numDiffElemsUsed;
455 for (
int i = 0; i < numComp; i++) {
456 ffc.zav = ffc.zav + fractionArray[i]*zavArray[i];
457 potl = potl+fractionArray[i]*zavArray[i]*log(potArray[i]);
459 if (ffc.zav == 0.0) {
460 egsFatal(
"estar::mixtureCalculation: Mixture mean Z/A is zero.\n"
461 "Check that mass fractions and element Z/A values are non-zero.\n");
463 ffc.pot = exp(potl/ffc.zav);
Global egspp functions header file.
EGS_InfoFunction EGS_EXPORT egsInformation
Always use this function for reporting the progress of a simulation and any other type of information...
EGS_InfoFunction EGS_EXPORT egsFatal
Always use this function for reporting fatal errors.