Garfield++ v2r0
A toolkit for the detailed simulation of particle detectors based on ionisation measurement in gases and semiconductors
Loading...
Searching...
No Matches
PhotoAbsCS.cpp
Go to the documentation of this file.
1#include <cmath>
2#include <fstream>
3#include <iomanip>
8
9// 2004, I. Smirnov
10
11//#define DEBUG_PRINT_get_escape_particles
12//#define DEBUG_ignore_non_standard_channels
13
14//#define ALWAYS_LINEAR_INTERPOLATION // how the paper was computed
15
16namespace {
17
18/// Determine whether to use linear or nonlinear interpolation.
19/// Usually photoabsorption cross sections decrease as inverse power function
20/// of power like -2.75. Its linear interpolation inside large energy
21/// intervals is remarkably not precise. This function is designed
22/// to determine the cases common for the total program when the inverse power
23/// function is applied in such intervals.
24/// Conditions are empirical.
25/// true - nonlinear, false - linear.
26/// Energies and threshold are given in MeV.
27/// e1 should be < e2.
28bool sign_nonlinear_interpolation(double e1, double cs1, double e2, double cs2,
29 double threshold) {
30#ifdef ALWAYS_LINEAR_INTERPOLATION
31 return false;
32#else
33 // normal case:
34 if (cs2 >= cs1 || cs2 <= 0 || e1 < 300.0e-6 || e1 < 1.5 * threshold) {
35 return false;
36 }
37 const double pw = log(cs1 / cs2) / log(e1 / e2);
38 if (pw >= -1.0) {
39 // good case for linear interpolation
40 return false;
41 } else if (pw < -5.0) {
42 // unclear odd case, power would be dangerous
43 return false;
44 }
45 // non-linear interpolation
46 return true;
47#endif
48}
49
50/// Fit table by a straight line or by inverse power function
51/// (see sign_nonlinear_interpolation) and integrate the area below it.
52/// The function (and the result) are assumed to be non-negative.
53/// The tail is not added right here, but added after the call of this function.
54/// The theshold is used to restrict this function from the left.
55/// If threshold is less than e[0], the function is extrapolated
56/// by the straight line till threshold.
57/// If this line crosses zero, it is extrapolated only till this point.
58double my_integr_fun(double xp1, double yp1, double xp2, double yp2,
59 double xmin, double /*xmax*/, double x1, double x2) {
60 const bool nonlin = sign_nonlinear_interpolation(xp1, yp1, xp2, yp2, xmin);
61 return nonlin ? Heed::t_integ_power_2point<double>(xp1, yp1, xp2, yp2, x1, x2)
62 : Heed::t_integ_straight_2point<double>(xp1, yp1, xp2, yp2, x1,
63 x2, 0, 1);
64}
65
66double my_val_fun(double xp1, double yp1, double xp2, double yp2, double xmin,
67 double /*xmax*/, double x) {
68 const bool nonlin = sign_nonlinear_interpolation(xp1, yp1, xp2, yp2, xmin);
69 return nonlin
70 ? Heed::t_value_power_2point<double>(xp1, yp1, xp2, yp2, x)
71 : Heed::t_value_straight_2point<double>(xp1, yp1, xp2, yp2, x, 1);
72}
73}
74
75namespace Heed {
76
77//---------------------------------------------------------
78
79PhotoAbsCS::PhotoAbsCS() : name(""), number(-1), Z(0), threshold(0.0) {}
80
81PhotoAbsCS::PhotoAbsCS(const std::string& fname, int fZ, double fthreshold)
82 : name(fname), number(-1), Z(fZ), threshold(fthreshold) {
83
84 // Try to get the (shell) number from the name.
85 std::istringstream ss(name);
86 int i = -100;
87 ss >> i;
88 if (i >= 1 && i <= 50) number = i;
89}
90
91void PhotoAbsCS::print(std::ostream& file, int l) const {
92 if (l <= 0) return;
93 Ifile << "PhotoAbsCS: name=" << name << " Z = " << Z
94 << " threshold = " << threshold << std::endl;
95}
96
97//---------------------------------------------------------
98
100 double fstep, long fmax_q_step)
101 : real_pacs(apacs, do_clone),
102 width(fwidth),
103 max_q_step(fmax_q_step),
104 step(fstep) {
105 mfunname("AveragePhotoAbsCS::AveragePhotoAbsCS(...)");
106 check_econd11(apacs, == NULL, mcerr);
107 // Check the parameters (step = 0.5 * width is bad but OK).
108 if (fwidth > 0.0) check_econd11(fstep, >= 0.6 * fwidth, mcerr);
109 // Copy the parameters of the "real" cross-section.
110 name = real_pacs->get_name();
111 number = real_pacs->get_number();
112 Z = real_pacs->get_Z();
113 threshold = real_pacs->get_threshold();
114}
115
116double AveragePhotoAbsCS::get_CS(double energy) const {
117 mfunname("double AveragePhotoAbsCS::get_CS(double energy) const");
118 // In case of zero width, return the unmodified "real" cross-section.
119 if (width == 0.0) return real_pacs->get_CS(energy);
120 const double w2 = width * 0.5;
121 const double e1 = std::max(energy - w2, 0.);
122 return real_pacs->get_integral_CS(e1, energy + w2) / width;
123}
124
126 double energy2) const {
127 mfunname("double AveragePhotoAbsCS::get_integral_CS(...) const");
128 if (width == 0.0 || energy1 >= energy2) {
129 // Return the integral of the unmodified "real" cross-section.
130 return real_pacs->get_integral_CS(energy1, energy2);
131 }
132 long q = long((energy2 - energy1) / step);
133 if (q > max_q_step) {
134 return real_pacs->get_integral_CS(energy1, energy2);
135 }
136 q++;
137 const double rstep = (energy2 - energy1) / q;
138 double x0 = energy1 + 0.5 * rstep;
139 double s = 0.0;
140 for (long n = 0; n < q; n++) s += get_CS(x0 + rstep * n);
141 return s * rstep;
142}
143
144void AveragePhotoAbsCS::scale(double fact) {
145 mfunname("void AveragePhotoAbsCS::scale(double fact)");
146 real_pacs->scale(fact);
147}
148
149void AveragePhotoAbsCS::print(std::ostream& file, int l) const {
150 mfunname("void PhotoAbsCS::print(std::ostream& file, int l) const");
151 Ifile << "AveragePhotoAbsCS: width = " << width << " step=" << step
152 << " max_q_step=" << max_q_step << '\n';
153 indn.n += 2;
154 real_pacs->print(file, l);
155 indn.n -= 2;
156}
157
158//---------------------------------------------------------
159
161 : PhotoAbsCS("H", 1, 15.43e-6), prefactor(1.) {
162 number = 1;
163}
164
165double HydrogenPhotoAbsCS::get_CS(double energy) const {
166 if (energy < threshold || energy == DBL_MAX) return 0.0;
167 // The factor 0.5 is needed because we have one atom instead of two.
168 return 0.5 * prefactor * 0.0535 * (pow(100.0e-6 / energy, 3.228));
169}
170
172 double energy2) const {
173 if (energy2 < threshold) return 0.;
174 if (energy1 < threshold) energy1 = threshold;
175 if (energy2 == DBL_MAX) {
176 return 0.5 * prefactor * 0.0535 * pow(100.0e-6, 3.228) / 2.228 *
177 (1.0 / pow(energy1, 2.228));
178 } else {
179 return 0.5 * prefactor * 0.0535 * pow(100.0e-6, 3.228) / 2.228 *
180 (1.0 / pow(energy1, 2.228) - 1.0 / pow(energy2, 2.228));
181 }
182}
183
184void HydrogenPhotoAbsCS::scale(double fact) { prefactor = fact; }
185
186void HydrogenPhotoAbsCS::print(std::ostream& file, int l) const {
187 if (l <= 0) return;
188 Ifile << "HydrogenPhotoAbsCS: name=" << name << " Z = " << Z
189 << " threshold = " << threshold << std::endl;
190}
191
192//---------------------------------------------------------
193
194SimpleTablePhotoAbsCS::SimpleTablePhotoAbsCS(const std::string& fname, int fZ,
195 double fthreshold,
196 const std::string& ffile_name)
197 : PhotoAbsCS(fname, fZ, fthreshold), file_name(ffile_name) {
198 mfunnamep("SimpleTablePhotoAbsCS::SimpleTablePhotoAbsCS(...)");
199 std::ifstream file(file_name.c_str());
200 if (!file) {
201 funnw.ehdr(mcerr);
202 mcerr << "cannot open file " << file_name << std::endl;
203 spexit(mcerr);
204 }
205 ener.reserve(20);
206 cs.reserve(20);
207 do {
208 // Read the energy.
209 double x = 0.;
210 file >> x;
211 if (!file.good()) break;
212 // Make sure it is non-negative and in ascending order.
213 check_econd11(x, < 0.0, mcerr);
214 if (!ener.empty()) check_econd12(x, <, ener.back(), mcerr);
215 // Read the cross-section.
216 double y = 0.;
217 file >> y;
218 if (!file.good()) break;
219 check_econd11(y, < 0.0, mcerr);
220 // Add the point to the table.
221 ener.push_back(x * 1.e-6);
222 cs.push_back(y);
223 } while (1);
224}
225
226SimpleTablePhotoAbsCS::SimpleTablePhotoAbsCS(const std::string& fname, int fZ,
227 double fthreshold,
228 const std::vector<double>& fener,
229 const std::vector<double>& fcs)
230 : PhotoAbsCS(fname, fZ, fthreshold),
231 file_name("none"),
232 ener(fener),
233 cs(fcs) {
234 mfunname("SimpleTablePhotoAbsCS::SimpleTablePhotoAbsCS(...)");
235 check_econd12(ener.size(), !=, cs.size(), mcerr);
236}
237
238SimpleTablePhotoAbsCS::SimpleTablePhotoAbsCS(const std::string& fname, int fZ,
239 double fthreshold, int l,
240 double E0, double yw, double ya,
241 double P, double sigma)
242 : PhotoAbsCS(fname, fZ, fthreshold) {
243 mfunname("SimpleTablePhotoAbsCS::SimpleTablePhotoAbsCS(...)");
244 const long q = 1000;
245 // Make a logarithmic energy mesh.
246 ener.resize(q, 0.);
247 const double emin = 2.e-6;
248 const double emax = 2.e-1;
249 const double rk = pow(emax / emin, (1.0 / double(q)));
250 double e2 = emin;
251 for (long n = 0; n < q; n++) {
252 const double e1 = e2;
253 e2 = e2 * rk;
254 ener[n] = (e1 + e2) * 0.5;
255 }
256 cs.assign(q, 0.);
257 for (long n = 0; n < q; n++) {
258 double energy = ener[n];
259 if (energy < threshold) continue;
260 const double Q = 5.5 + l - 0.5 * P;
261 const double y = energy / E0;
262 const double Fpasc = ((y - 1) * (y - 1) + yw * yw) * pow(y, (-Q)) *
263 pow((1.0 + sqrt(y / ya)), (-P));
264 cs[n] = Fpasc * sigma;
265 }
267}
268
270 const SimpleTablePhotoAbsCS& part,
271 double emax_repl) {
272 mfunname(
273 "SimpleTablePhotoAbsCS::SimpleTablePhotoAbsCS(const "
274 "SimpleTablePhotoAbsCS& total,...)");
275
276 *this = total; // to assure that all is preserved
277
278 long qe_i = total.ener.size();
279
280 const std::vector<double>& ener_r = part.get_arr_ener();
281 const std::vector<double>& cs_r = part.get_arr_CS();
282 long qe_r = ener_r.size();
283 std::vector<double> new_ener;
284 std::vector<double> new_cs;
285 // first write replacements
286 for (long ne = 0; ne < qe_r; ne++) {
287 if (ener_r[ne] >= total.get_threshold() && ener_r[ne] <= emax_repl) {
288 new_ener.push_back(ener_r[ne]);
289 new_cs.push_back(cs_r[ne]);
290 }
291 }
292 for (long ne = 0; ne < qe_i; ne++) {
293 if (ener[ne] >= total.get_threshold() && ener[ne] > emax_repl) {
294 new_ener.push_back(total.ener[ne]);
295 new_cs.push_back(total.cs[ne]);
296 }
297 }
298 ener.swap(new_ener);
299 cs.swap(new_cs);
300}
301
303 const long q = ener.size();
304 long ne = 0;
305 for (ne = 0; ne < q; ne++) {
306 if (cs[ne] > 0.0) break;
307 }
308 if (ne <= 0) return;
309 const long qn = q - ne;
310 std::vector<double> enern(qn);
311 std::vector<double> csn(qn);
312 for (long nez = ne; nez < q; nez++) {
313 enern[nez - ne] = ener[nez];
314 csn[nez - ne] = cs[nez];
315 }
316 ener = enern;
317 cs = csn;
318}
320 const long q = ener.size();
321 long ne = 0;
322 for (ne = 0; ne < q; ne++) {
323 if (cs[ne] > level) break;
324 }
325 if (ne <= 0) return;
326 const long qn = q - ne;
327 std::vector<double> enern(qn);
328 std::vector<double> csn(qn);
329 for (long nez = ne; nez < q; nez++) {
330 enern[nez - ne] = ener[nez];
331 csn[nez - ne] = cs[nez];
332 }
333 ener = enern;
334 cs = csn;
335}
336
337double SimpleTablePhotoAbsCS::get_CS(double energy) const {
338 mfunname("double SimpleTablePhotoAbsCS::get_CS(double energy) const");
339 long q = ener.size();
340 if (q == 0) return 0.0;
341 check_econd11(q, == 1, mcerr);
342 if (energy < threshold) return 0.;
343 if (energy <= ener[q - 1]) {
346 double, std::vector<double>,
348 pcm, cs, &my_val_fun, energy, 1, threshold, 0, DBL_MAX);
349 } else {
350 if (energy == DBL_MAX)
351 return 0.0;
352 else
353 return cs[q - 1] * pow(energy, -2.75) / pow(ener[q - 1], -2.75);
354 }
355}
356
358 double energy2) const {
359 mfunname("double SimpleTablePhotoAbsCS::get_integral_CS(...)");
360
361 const long q = ener.size();
362 if (q == 0) return 0.0;
363 check_econd11(q, == 1, mcerr);
364 if (energy2 < threshold) return 0.0;
365 if (energy1 < threshold) energy1 = threshold;
366 double s = 0.0;
367 double energy21 = ener[q - 1];
368 if (energy1 < energy21) {
369 if (energy21 > energy2) energy21 = energy2;
370 check_econd12(energy1, >, energy21, mcerr);
373 double, std::vector<double>,
375 pcm, cs, &my_integr_fun, energy1, energy21, 1, threshold, 0, DBL_MAX);
376 }
377 // print(mcout, 3);
378 // mcout << "energy1="<<energy1
379 // << " energy21="<<energy21
380 // << " ener[q-1]="<<ener[q-1]
381 // << " threshold="<<threshold
382 // << " s="<<s<<'\n';
383 check_econd11(s, < 0.0, mcout);
384 if (energy2 > ener[q - 1]) {
385 // add tail
386 if (energy2 == DBL_MAX) {
387 if (energy1 < ener[q - 1]) energy1 = ener[q - 1];
388 double c =
389 cs[q - 1] / (1.75 * pow(ener[q - 1], -2.75)) * pow(energy1, -1.75);
390 // check_econd11(c , < 0.0, mcout);
391 s += c;
392 } else {
393 if (energy1 < ener[q - 1]) energy1 = ener[q - 1];
394 double c = cs[q - 1] / (1.75 * pow(ener[q - 1], -2.75)) *
395 (pow(energy1, -1.75) - pow(energy2, -1.75));
396 // check_econd11(c , < 0.0, mcout);
397 s += c;
398 }
399 }
400 return s;
401}
402
404 mfunnamep("void SimpleTablePhotoAbsCS::scale(double fact)");
405 const long q = ener.size();
406 for (long n = 0; n < q; ++n) cs[n] *= fact;
407}
408
409void SimpleTablePhotoAbsCS::print(std::ostream& file, int l) const {
410 if (l <= 0) return;
411 Ifile << "SimpleTablePhotoAbsCS: name=" << name << " Z = " << Z << "\n";
412 Ifile << " threshold = " << threshold << " file_name=" << file_name << "\n";
413 if (l > 1) {
414 indn.n += 2;
415 const long q = ener.size();
416 for (long n = 0; n < q; ++n) {
417 Ifile << "n=" << n << " ener=" << ener[n] << " cs=" << cs[n] << "\n";
418 }
419 indn.n -= 2;
420 }
421}
422
423//---------------------------------------------------------
424
425PhenoPhotoAbsCS::PhenoPhotoAbsCS() : PhotoAbsCS("none", 0, 0.0), power(0.0) {}
426
427PhenoPhotoAbsCS::PhenoPhotoAbsCS(const std::string& fname, int fZ,
428 double fthreshold, double fpower)
429 : PhotoAbsCS(fname, fZ, fthreshold), power(fpower) {
430 mfunname("PhenoPhotoAbsCS::PhenoPhotoAbsCS(...)");
431 check_econd11a(power, <= 2, " value not allowed, integral would be infinite",
432 mcerr);
433 const double a = power - 1.;
434 factor = pow(threshold, a) * Thomas_sum_rule_const_Mb * Z * a;
435}
436
437double PhenoPhotoAbsCS::get_CS(double energy) const {
438 if (energy < threshold || energy == DBL_MAX) return 0.0;
439 return factor * pow(energy, -power);
440}
441
442double PhenoPhotoAbsCS::get_integral_CS(double energy1, double energy2) const {
443 if (energy2 < threshold) return 0.0;
444 if (energy1 < threshold) energy1 = threshold;
445 const double a = power - 1.;
446 double s;
447 if (energy2 == DBL_MAX) {
448 s = factor / a * (1. / pow(energy1, a));
449 } else {
450 s = factor / a * (1. / pow(energy1, a) - 1. / pow(energy2, a));
451 }
452 return s;
453}
454
455void PhenoPhotoAbsCS::scale(double fact) {
456 mfunnamep("void PhenoPhotoAbsCS::scale(double fact)");
457 factor *= fact;
458}
459
460void PhenoPhotoAbsCS::print(std::ostream& file, int l) const {
461 if (l <= 0) return;
462 Ifile << "PhenoPhotoAbsCS: name=" << name << " Z = " << Z << std::endl;
463 Ifile << " threshold = " << threshold << " power=" << power
464 << " factor=" << factor << std::endl;
465}
466
467//------------------------------------------------------------------------
468
470 double fchannel_prob_dens, const std::vector<double>& felectron_energy,
471 const std::vector<double>& fphoton_energy, int s_all_rest) {
472 mfunnamep("void AtomicSecondaryProducts::add_channel(...)");
473 check_econd21(fchannel_prob_dens, < 0.0 ||, > 1.0, mcerr);
474 long q_old = channel_prob_dens.size();
475 long q_new = q_old + 1;
476 channel_prob_dens.resize(q_new);
477 electron_energy.resize(q_new);
478 photon_energy.resize(q_new);
479 if (s_all_rest == 1) {
480 double s = 0.0;
481 for (long n = 0; n < q_old; ++n) {
482 s += channel_prob_dens[n];
483 }
484 check_econd21(s, < 0.0 ||, > 1.0, mcerr);
485 fchannel_prob_dens = 1.0 - s;
486 }
487 channel_prob_dens[q_old] = fchannel_prob_dens;
488 electron_energy[q_old] = felectron_energy;
489 photon_energy[q_old] = fphoton_energy;
490 double s = 0.0;
491 for (long n = 0; n < q_new; ++n) {
492 s += channel_prob_dens[n];
493 }
494 if (s > 1.0) {
495 funnw.ehdr(mcerr);
496 mcerr << "s > 1.0, s=" << s << '\n';
497 Iprintn(mcerr, q_new);
498 for (long n = 0; n < q_new; ++n) {
499 mcerr << "n=" << n << " channel_prob_dens[n]=" << channel_prob_dens[n]
500 << '\n';
501 }
502 spexit(mcerr);
503 }
504}
505
506int AtomicSecondaryProducts::get_channel(std::vector<double>& felectron_energy,
507 std::vector<double>& fphoton_energy)
508 const {
509 mfunname("int AtomicSecondaryProducts::get_channel(...)");
510#ifdef DEBUG_PRINT_get_escape_particles
511 mcout << "AtomicSecondaryProducts::get_channel is started\n";
513#endif
514 if (channel_prob_dens.empty()) return 0;
515 int ir = 0;
516 double rn = SRANLUX();
517#ifdef DEBUG_PRINT_get_escape_particles
518 Iprintn(mcout, rn);
519#endif
520 if (channel_prob_dens.size() == 1) {
521 if (rn < channel_prob_dens[0]) {
522 felectron_energy = electron_energy[0];
523 fphoton_energy = photon_energy[0];
524 ir = 1;
525 }
526 } else {
527 long q = channel_prob_dens.size();
528 double s = 0.0;
529 for (long n = 0; n < q; ++n) {
530 s += channel_prob_dens[n];
531 if (rn <= s) {
532 felectron_energy = electron_energy[n];
533 fphoton_energy = photon_energy[n];
534 ir = 1;
535#ifdef DEBUG_PRINT_get_escape_particles
536 Iprint2n(mcout, n, s);
537#endif
538 break;
539 }
540 }
541 }
542#ifdef DEBUG_PRINT_get_escape_particles
543 mcout << "AtomicSecondaryProducts::get_channel is finishing\n";
544 Iprintn(mcout, ir);
545#endif
546 return ir;
547}
548
549void AtomicSecondaryProducts::print(std::ostream& file, int l) const {
550 if (l <= 0) return;
551 Ifile << "AtomicSecondaryProducts(l=" << l << "):\n";
552 const long q = channel_prob_dens.size();
553 Ifile << "number of channels=" << q << '\n';
554 indn.n += 2;
555 for (long n = 0; n < q; ++n) {
556 Ifile << "n_channel=" << n << " probability=" << channel_prob_dens[n]
557 << '\n';
558 indn.n += 2;
559 long qel = electron_energy[n].size();
560 Ifile << "number of electrons=" << qel << '\n';
561 indn.n += 2;
562 for (long nel = 0; nel < qel; ++nel) {
563 Ifile << "nel=" << nel << " electron_energy=" << electron_energy[n][nel]
564 << '\n';
565 }
566 indn.n -= 2;
567 long qph = photon_energy[n].size();
568 Ifile << "number of photons=" << qph << '\n';
569 indn.n += 2;
570 for (long nph = 0; nph < qph; ++nph) {
571 Ifile << "nph=" << nph << " photon_energy=" << photon_energy[n][nph]
572 << '\n';
573 }
574 indn.n -= 2;
575 indn.n -= 2;
576 }
577 indn.n -= 2;
578}
579
580AtomPhotoAbsCS::AtomPhotoAbsCS() : name("none"), Z(0), qshell(0) {}
581
582double AtomPhotoAbsCS::get_TICS(double energy,
583 double factual_minimal_threshold) const {
584 mfunname("double AtomPhotoAbsCS::get_TICS(...) const");
585 if (factual_minimal_threshold <= energy) {
586 // Above threshold, the ionization cross-section is assumed to be
587 // idential to the absorption cross-section.
588 return get_ACS(energy);
589 }
590 return 0.0;
591}
592
594 double energy1, double energy2, double factual_minimal_threshold) const {
595 mfunname("double AtomPhotoAbsCS::get_integral_TICS(...) const");
596 if (factual_minimal_threshold > energy2) return 0.;
597 energy1 = std::max(energy1, factual_minimal_threshold);
598 return get_integral_ACS(energy1, energy2);
599}
600
601double AtomPhotoAbsCS::get_TICS(int nshell, double energy,
602 double factual_minimal_threshold) const {
603 mfunname("double AtomPhotoAbsCS::get_TICS(...) const");
604 if (s_ignore_shell[nshell]) return 0.;
605 if (factual_minimal_threshold <= energy) {
606 return get_integral_ACS(nshell, energy);
607 }
608 return 0.;
609}
610
612 int nshell, double energy1, double energy2,
613 double factual_minimal_threshold) const {
614 mfunname("double AtomPhotoAbsCS::get_integral_TICS(...) const");
615 if (s_ignore_shell[nshell]) return 0.;
616 if (factual_minimal_threshold <= energy1) {
617 return get_integral_ACS(nshell, energy1, energy2);
618 }
619 if (factual_minimal_threshold >= energy2) return 0.0;
620 return get_integral_ACS(nshell, factual_minimal_threshold, energy2);
621}
622
624 mfunname("void AtomPhotoAbsCS::remove_shell(int nshell)");
625 check_econd21(nshell, < 0 ||, >= qshell, mcerr);
626 s_ignore_shell[nshell] = true;
627}
628
630 mfunname("void AtomPhotoAbsCS::restore_shell(int nshell)");
631 check_econd21(nshell, < 0 ||, >= qshell, mcerr);
632 s_ignore_shell[nshell] = false;
633}
634
635void AtomPhotoAbsCS::print(std::ostream& file, int l) const {
636 mfunnamep("void AtomPhotoAbsCS::print(std::ostream& file, int l) const");
637 if (l <= 0) return;
638 Ifile << "AtomPhotoAbsCS(l=" << l << "): name=" << name << " Z = " << Z
639 << " qshell = " << qshell << std::endl;
640 Iprintn(mcout, asp.size());
641 long q = asp.size();
642 if (q == 0) {
643 q = s_ignore_shell.size();
644 indn.n += 2;
645 for (long n = 0; n < q; ++n) {
646 Ifile << "n=" << n << " s_ignore_shell[n] = " << s_ignore_shell[n]
647 << '\n';
648 }
649 indn.n -= 2;
650 } else {
651 check_econd12(asp.size(), !=, s_ignore_shell.size(), mcerr);
652 indn.n += 2;
653 for (long n = 0; n < q; ++n) {
654 Ifile << "n=" << n << " s_ignore_shell[n] = " << s_ignore_shell[n]
655 << '\n';
656 asp[n].print(mcout, l);
657 }
658 indn.n -= 2;
659 }
660}
661
662std::ostream& operator<<(std::ostream& file, const AtomPhotoAbsCS& f) {
663 f.print(file, 1);
664 return file;
665}
666
668 mfunname("double AtomPhotoAbsCS::get_I_min() const");
669 double st = DBL_MAX;
670 // The minimal shell is normally the last, but to be safe we check all.
671 for (int n = 0; n < qshell; ++n) st = std::min(st, get_threshold(n));
672 return st;
673}
674
676 const int nshell, double energy, std::vector<double>& el_energy,
677 std::vector<double>& ph_energy) const {
678 mfunname("void AtomPhotoAbsCS::get_escape_particles(...)");
679#ifdef DEBUG_PRINT_get_escape_particles
680 mcout << "AtomPhotoAbsCS::get_escape_particles is started\n";
681 Iprintn(mcout, nshell);
682 Iprintn(mcout, energy);
683#endif
684 // In principle, the energy is allowed to be slightly less than threshold
685 // due to unprecision of definition of point-wise cross sections.
686 // To keep correct norm it is better not to ignore such events.
687 // They usually can be treated quite well.
688 // The factor 0.5 is put there just as arbitrary check for full stupidity.
689 const double thrShell = get_threshold(nshell);
690 check_econd12(energy, <, 0.5 * thrShell, mcerr);
691
692 el_energy.clear();
693 ph_energy.clear();
694
695 // Find the shell with the lowest threshold (should be the last).
696 int n_min = 0;
697 double thrMin = DBL_MAX;
698 for (int n = 0; n < qshell; ++n) {
699 if (get_threshold(n) < thrMin) {
700 n_min = n;
701 thrMin = get_threshold(n);
702 }
703 }
704#ifdef DEBUG_PRINT_get_escape_particles
705 Iprintn(mcout, n_min);
706#endif
707 if (nshell == n_min) {
708 // Outermost (valence) shell. Only generate the delta electron.
709 const double en = std::max(energy - thrMin, 0.);
710 el_energy.push_back(en);
711 return;
712 }
713 // Energy of photo-electron
714 double en = energy - thrShell;
715 double hdist = 0.0; // used to preserve the balance of energy
716 // virtual gamma are generated by energy mesh
717 // and their energy could be little less than the shell energy.
718 // To avoid generation of electrons with negative energy
719 // their energy is corrected. The value of correction is hdist.
720 // To preserve energy this hdist is then distributed over
721 // the other secondary products if they exist.
722 if (en < 0.0) {
723 hdist = -en;
724 en = 0.0;
725 }
726 int is = 0;
727 std::vector<double> felectron_energy;
728 std::vector<double> fphoton_energy;
729#ifdef DEBUG_PRINT_get_escape_particles
730 Iprint2n(mcout, asp.size(), get_qshell());
731#endif
732#ifndef DEBUG_ignore_non_standard_channels
733 if (asp.size() == get_qshell()) {
734 // works only in this case?
735 is = asp[nshell].get_channel(felectron_energy, fphoton_energy);
736 // Here zero can be if the shell is not included in database
737 // or if not standard channel is not chosen by random way.
738 // In both cases the standard way should be invoked.
739 }
740#endif
741 int main_n = get_main_shell_number(nshell);
742#ifdef DEBUG_PRINT_get_escape_particles
743 Iprint2n(mcout, nshell, main_n);
744 Iprintn(mcout, is);
745 Iprint(mcout, felectron_energy);
746 Iprint(mcout, fphoton_energy);
747#endif
748
749 if (is != 0) {
750 // Generate photo-electron and just copy all what is proposed by
751 // get_channel with corrections by hdist.
752 el_energy.resize(1 + felectron_energy.size());
753 el_energy[0] = en;
754 long q = felectron_energy.size();
755 for (long n = 0; n < q; ++n) {
756 check_econd21(felectron_energy[n], < 0 ||, > thrShell, mcerr);
757 el_energy[1 + n] = felectron_energy[n] - hdist;
758 if (el_energy[1 + n] < 0) {
759 hdist = -el_energy[1 + n];
760 el_energy[1 + n] = 0.0;
761 } else {
762 hdist = 0.0;
763 }
764 }
765 ph_energy.resize(fphoton_energy.size());
766 q = fphoton_energy.size();
767 for (long n = 0; n < q; ++n) {
768 check_econd21(fphoton_energy[n], < 0 ||, > thrShell, mcerr);
769 ph_energy[n] = fphoton_energy[n] - hdist;
770 if (ph_energy[n] < 0) {
771 hdist = -ph_energy[n];
772 ph_energy[n] = 0.0;
773 } else {
774 hdist = 0.0;
775 }
776 }
777 return;
778 }
779
780 // Generate default channel.
781 if (main_n <= 0) {
782 // Principal numbers are not available. Generate Auger to outmost shell.
783 const double en1 = thrShell - hdist - 2 * thrMin;
784 el_energy.push_back(en);
785 if (en1 >= 0.0) el_energy.push_back(en1);
786 return;
787 }
788 // First find the principal quantum number of the deepest shell.
789 int main_n_largest = 0;
790 for (int n = 0; n < qshell; ++n) {
791 main_n_largest = std::max(main_n_largest, get_main_shell_number(n));
792 }
793#ifdef DEBUG_PRINT_get_escape_particles
794 Iprintn(mcout, main_n_largest);
795#endif
796 if (main_n_largest - main_n < 2) {
797 // Generate Auger from the outermost shell.
798 double en1 = thrShell - hdist - 2 * thrMin;
799 el_energy.push_back(en);
800 if (en1 >= 0.0) el_energy.push_back(en1);
801 return;
802 }
803 // At least K, l, M shells exist.
804 // In this case we use more advanced scheme.
805 // Look for shell with larger main number and with less energy
806 int n_chosen = -1;
807 double thr = DBL_MAX; // this will be the least threshold
808 // among the shells with next principal number
809 for (int n = 0; n < qshell; ++n) {
810 // currently the minimal shell is the last,
811 // but to avoid this assumption we check all
812 int main_n_t = get_main_shell_number(n);
813 if (main_n_t > 0 && main_n_t == main_n + 1) {
814 if (thr > get_threshold(n)) {
815 n_chosen = n;
816 thr = get_threshold(n);
817 }
818 }
819 }
820#ifdef DEBUG_PRINT_get_escape_particles
821 Iprint2n(mcout, n_chosen, thr);
822#endif
823 check_econd11(n_chosen, < 0, mcerr);
824 double en1 = thrShell - hdist - 2 * get_threshold(n_chosen);
825 if (en1 > 0.) {
826 // Photo-electron
827 el_energy.push_back(en);
828 // First Auger from chosen shell
829 el_energy.push_back(en1);
830 // Then filling two vacancies at the next (chosen) shell
831 // from the outermost one
832 const double en2 = get_threshold(n_chosen) - 2 * thrMin;
833 if (en2 > 0.) {
834 el_energy.push_back(en2);
835 el_energy.push_back(en2);
836 check_econd11(el_energy[2], < 0.0, mcerr);
837 }
838 return;
839 }
840 en1 = thrShell - hdist - get_threshold(n_chosen) - thrMin;
841 if (en1 > 0.) {
842 // Photo-electron
843 el_energy.push_back(en);
844 el_energy.push_back(en1);
845 // Filling initially ionized level from chosen
846 // and emittance of Auger from outermost.
847 check_econd11(el_energy[1], < 0.0, mcerr);
848 const double en2 = get_threshold(n_chosen) - 2 * thrMin;
849 if (en2 > 0.) el_energy.push_back(en2);
850 }
851}
852
854 mfunnamep("AtomicSecondaryProducts* AtomPhotoAbsCS::get_asp(int nshell)");
855 check_econd21(nshell, < 0 ||, >= qshell, mcerr);
856 return &(asp[nshell]);
857}
858
860
862 const std::string& ffile_name)
863 : file_name(ffile_name) {
864 mfunnamep("SimpleAtomPhotoAbsCS::SimpleAtomPhotoAbsCS(...)");
865 check_econd11(fZ, < 1, mcerr);
866 std::ifstream file(file_name.c_str());
867 if (!file) {
868 funnw.ehdr(mcerr);
869 mcerr << "cannot open file " << file_name << std::endl;
870 spexit(mcerr);
871 }
872 while (findmark(file, "#") == 1) {
873 file >> Z;
874 if (Z != fZ) continue;
875 file >> qshell;
876 check_econd21(qshell, < 1 ||, > 10000, mcerr);
877 s_ignore_shell.resize(qshell, false);
878 file >> name;
879 acs.resize(qshell);
880 asp.resize(qshell);
881 std::vector<double> fl(qshell);
882 int sZshell = 0;
883 for (int nshell = 0; nshell < qshell; ++nshell) {
884 double thr = 0.0;
885 int Zshell = 0;
886 std::string shell_name;
887 file >> thr;
888 check_econd11(thr, <= 0.0, mcerr);
889 file >> Zshell;
890 check_econd11(Zshell, <= 0, mcerr);
891 sZshell += Zshell;
892 file >> fl[nshell];
893 findmark(file, "!");
894 file >> shell_name;
895 acs[nshell].pass(new PhenoPhotoAbsCS(shell_name, Zshell, thr * 1.0e-6));
896 }
897 check_econd12(sZshell, !=, Z, mcerr);
898
899 int n_min = 0;
900 double st = DBL_MAX;
901 for (int nshell = 0; nshell < qshell; ++nshell) {
902 // currently the minimal shell is the last,
903 // but to avoid this assumption we check all
904 if (get_threshold(nshell) < st) n_min = nshell;
905 }
906 for (int nshell = 0; nshell < qshell; ++nshell) {
907 if (fl[nshell] <= 0) continue;
908 check_econd12(nshell, ==, n_min, mcerr);
909 std::vector<double> felectron_energy;
910 std::vector<double> fphoton_energy;
911 fphoton_energy.push_back(get_threshold(nshell) - get_threshold(n_min));
912 asp[nshell].add_channel(fl[nshell], felectron_energy, fphoton_energy);
913 }
914 return;
915 }
916 funnw.ehdr(mcerr);
917 mcerr << "there is no element Z=" << fZ << " in file " << file_name << '\n';
918 spexit(mcerr);
919}
920
922 mfunname("SimpleAtomPhotoAbsCS::SimpleAtomPhotoAbsCS(...)");
923 check_econd11(fZ, <= 0, mcerr);
924 check_econd12(fZ, !=, facs.get_Z(), mcerr);
925 Z = fZ;
926 qshell = 1;
927 s_ignore_shell.resize(qshell, false);
928 name = facs.get_name();
929 acs.resize(1);
930 acs[0].put(&facs);
931}
932
933double SimpleAtomPhotoAbsCS::get_threshold(int nshell) const {
934 mfunname("double SimpleAtomPhotoAbsCS::get_threshold(int nshell) const");
935 check_econd21(nshell, < 0 ||, > qshell, mcerr);
936 return acs[nshell]->get_threshold();
937}
938
939double SimpleAtomPhotoAbsCS::get_ACS(double energy) const {
940 mfunname("double SimpleAtomPhotoAbsCS::get_ACS(double energy) const");
941 double s = 0.0;
942 for (int n = 0; n < qshell; ++n) {
943 if (!s_ignore_shell[n]) s += acs[n]->get_CS(energy);
944 }
945 return s;
946}
948 double energy2) const {
949 mfunnamep("double SimpleAtomPhotoAbsCS::get_integral_ACS(...) const");
950 double s = 0.0;
951 for (int n = 0; n < qshell; ++n) {
952 if (s_ignore_shell[n]) continue;
953 const double t = acs[n]->get_integral_CS(energy1, energy2);
954 if (t < 0) {
955 funnw.ehdr(mcout);
956 mcout << "t < 0\n";
957 Iprintn(mcout, t);
958 print(mcout, 4);
959 spexit(mcout);
960 }
961 s += t;
962 }
963 return s;
964}
965
966double SimpleAtomPhotoAbsCS::get_ACS(int nshell, double energy) const {
967 mfunname("double SimpleAtomPhotoAbsCS::get_ACS(int nshell, double energy)");
968 check_econd21(nshell, < 0 ||, > qshell, mcerr);
969 return s_ignore_shell[nshell] ? 0. : acs[nshell]->get_CS(energy);
970}
971
972double SimpleAtomPhotoAbsCS::get_integral_ACS(int nshell, double en1,
973 double en2) const {
974 mfunname("double SimpleAtomPhotoAbsCS::get_integral_ACS(...) const");
975 check_econd21(nshell, < 0 ||, > qshell, mcerr);
976 return s_ignore_shell[nshell] ? 0. : acs[nshell]->get_integral_CS(en1, en2);
977}
978
979double SimpleAtomPhotoAbsCS::get_ICS(double energy) const {
980 mfunname("double SimpleAtomPhotoAbsCS::get_ICS(double energy) const");
981 double s = 0.0;
982 for (int n = 0; n < qshell; ++n) {
983 if (!s_ignore_shell[n]) s += acs[n]->get_CS(energy);
984 }
985 return s;
986}
987
989 double energy2) const {
990 mfunname("double SimpleAtomPhotoAbsCS::get_integral_ICS(...) const");
991 double s = 0.0;
992 for (int n = 0; n < qshell; ++n) {
993 if (!s_ignore_shell[n]) s += acs[n]->get_integral_CS(energy1, energy2);
994 }
995 return s;
996}
997
998double SimpleAtomPhotoAbsCS::get_ICS(int nshell, double energy) const {
999 mfunname("double SimpleAtomPhotoAbsCS::get_ICS(int nshell, double energy)");
1000 check_econd21(nshell, < 0 ||, > qshell, mcerr);
1001 return s_ignore_shell[nshell] ? 0. : acs[nshell]->get_CS(energy);
1002}
1003
1004double SimpleAtomPhotoAbsCS::get_integral_ICS(int nshell, double en1,
1005 double en2) const {
1006 mfunname("double SimpleAtomPhotoAbsCS::get_integral_ICS(...) const");
1007 check_econd21(nshell, < 0 ||, > qshell, mcerr);
1008 return s_ignore_shell[nshell] ? 0. : acs[nshell]->get_integral_CS(en1, en2);
1009}
1010
1011void SimpleAtomPhotoAbsCS::print(std::ostream& file, int l) const {
1012 if (l <= 0) return;
1013 Ifile << "SimpleAtomPhotoAbsCS(l=" << l << "): name=" << name << " Z = " << Z
1014 << " qshell = " << qshell << " file_name=" << file_name << std::endl;
1015 l--;
1016 if (l <= 0) return;
1017 indn.n += 2;
1018 for (int n = 0; n < qshell; ++n) {
1019 Ifile << "nshell=" << n << std::endl;
1020 acs[n].print(file, l);
1021 }
1022 AtomPhotoAbsCS::print(file, l);
1023 indn.n -= 2;
1024}
1025
1026//----------------------------------------------------------------------
1027
1029 const std::string& fthreshold_file_name,
1030 const std::string& fsimple_table_file_name,
1031 const std::string& fname,
1032 double fminimal_threshold)
1033 : threshold_file_name(fthreshold_file_name),
1034 simple_table_file_name(fsimple_table_file_name),
1035 BT_file_name("none"),
1036 minimal_threshold(fminimal_threshold) {
1037 mfunnamep("ExAtomPhotoAbsCS::ExAtomPhotoAbsCS(...) const");
1038 check_econd11(fZ, < 1, mcerr);
1039 std::ifstream threshold_file(threshold_file_name.c_str());
1040 if (!threshold_file) {
1041 funnw.ehdr(mcerr);
1042 mcerr << "cannot open file " << threshold_file_name << std::endl;
1043 spexit(mcerr);
1044 }
1045 std::vector<double> thr;
1046 std::vector<int> Zshell;
1047 std::vector<double> fl;
1048 std::vector<std::string> shell_name;
1049 bool foundZ = false;
1050 while (findmark(threshold_file, "#") == 1) {
1051 threshold_file >> Z;
1052 if (Z != fZ) continue;
1053 threshold_file >> qshell;
1054 check_econd21(qshell, < 1 ||, > 10000, mcerr);
1055 s_ignore_shell.resize(qshell, false);
1056 // Iprintn(mcout, qshell);
1057 thr.resize(qshell, 0.0);
1058 Zshell.resize(qshell, 0);
1059 fl.resize(qshell, 0.0);
1060 shell_name.resize(qshell);
1061 acs.resize(qshell);
1062 asp.resize(qshell);
1063 std::string temp_name;
1064 threshold_file >> temp_name;
1065 name = fname == "none" ? temp_name : fname;
1066 int sZshell = 0;
1067 for (int nshell = 0; nshell < qshell; nshell++) {
1068 threshold_file >> thr[nshell];
1069 check_econd11(thr[nshell], <= 0.0, mcerr);
1070 thr[nshell] *= 1.0e-6;
1071 threshold_file >> Zshell[nshell];
1072 check_econd11(Zshell[nshell], <= 0, mcerr);
1073 sZshell += Zshell[nshell];
1074 threshold_file >> fl[nshell];
1075 findmark(threshold_file, "!");
1076 threshold_file >> shell_name[nshell];
1077 }
1078 check_econd12(sZshell, !=, Z, mcerr);
1079 // currently the minimal shell is the last,
1080 // but to avoid this assumption, we check all.
1081 int n_min = 0;
1082 double st = DBL_MAX;
1083 for (int nshell = 0; nshell < qshell; nshell++) {
1084 if (thr[nshell] < st) {
1085 n_min = nshell;
1086 st = thr[nshell];
1087 }
1088 }
1089 for (int nshell = 0; nshell < qshell; nshell++) {
1090 if (fl[nshell] <= 0) continue;
1091 check_econd12(nshell, ==, n_min, mcerr);
1092 std::vector<double> felectron_energy;
1093 std::vector<double> fphoton_energy;
1094 fphoton_energy.push_back(thr[nshell] - thr[n_min]);
1095 asp[nshell].add_channel(fl[nshell], felectron_energy, fphoton_energy);
1096 }
1097 foundZ = true;
1098 break;
1099 }
1100 if (!foundZ) {
1101 funnw.ehdr(mcerr);
1102 mcerr << "there is no element Z=" << fZ << " in file "
1103 << threshold_file_name << std::endl;
1104 spexit(mcerr);
1105 }
1106 // Here it reads the PACS as an one shell curve:
1107 SimpleTablePhotoAbsCS stpacs(name, Z, 0.0, fsimple_table_file_name);
1108 const std::vector<double>& ener = stpacs.get_arr_ener();
1109 const std::vector<double>& CS = stpacs.get_arr_CS();
1110 std::vector<double> left_CS = CS; // used in sequencial algorithm
1111 const long qe = ener.size();
1112 // here cs is saved
1113 std::vector<std::vector<double> > SCS(qshell, std::vector<double>(qe, 0.));
1114 int nct = qshell - 1; // "current" threshold index
1115 unsigned long nce = 0; // "current" energy index
1116 // We ignore values below the lowest threshold.
1117 // It is not clear whether it is right, perhaps this is one of possible ways
1118 if (ener[0] < thr[qshell - 1]) {
1119 for (long ne = 0; ne < qe && (ener[ne] < thr[qshell - 1] ||
1120 (ener[ne] >= thr[qshell - 1] && ne > 1 &&
1121 CS[ne - 1] <= CS[ne - 2]));
1122 ne++) {
1123 if (ne > 0) left_CS[ne - 1] = 0.0;
1124 nce = ne;
1125 }
1126 }
1127 int s_more;
1128 int nt2 = 0; // < nt1
1129 int s_spes = 0;
1130 // Actually this is a loop by the group of thresholds
1131 do {
1132 // Find all thresholds which are less then the current energy
1133 int nt;
1134 // sign that there are thresholds more than the current energy
1135 s_more = 0;
1136 for (nt = nct; nt >= 0; nt--) {
1137 if (s_spes == 0) {
1138 if (thr[nt] > ener[nce]) {
1139 s_more = 1;
1140 break;
1141 }
1142 } else {
1143 if (thr[nt] > ener[nce + 1]) {
1144 s_more = 1;
1145 break;
1146 }
1147 }
1148 }
1149 // nt is now index of the next threshold or -1, if the thresholds are
1150 // made up.
1151 int nt1 = nct;
1152 int nce_next = ener.size();
1153 nt2 = nt + 1;
1154 // mcout<<"nt="<<nt<<" nt1="<<nt1<<" nt2="<<nt2<<" s_more="<<s_more<<'\n';
1155 if (s_more == 1) {
1156 // if(nt >= 0) // so if there are other larger thresholds,
1157 //{ // we should check how far we can pass at this step
1158 unsigned long ne;
1159 // finding energy larger than the next threshold
1160 for (ne = nce; ne < ener.size(); ne++) {
1161 if (thr[nt] <= ener[ne]) {
1162 nce_next = ne;
1163 s_spes = 0;
1164 break;
1165 }
1166 // At the following condition energy could be less than threshold,
1167 // but this point will anyway be associated with the next shell
1168 // corresponding to this threshold.
1169 // This is related to not precise measurement of cross section
1170 // and not precise knowledge of shell energies.
1171 // Occurence of this condition is marked by s_spes = 1.
1172 // At the next passing of this loop the thresholds are compared with
1173 // the next energy.
1174 if (ne > 1 && ne < ener.size() - 1 && ne > nce + 2 &&
1175 thr[nt] <= ener[ne + 1] &&
1176 (thr[nt] - ener[ne]) / (ener[ne + 1] - ener[ne]) < 0.1 &&
1177 CS[ne] > CS[ne - 1]) {
1178 // mcout<<"special condition is satisf.\n";
1179 nce_next = ne;
1180 s_spes = 1;
1181 break;
1182 }
1183 }
1184 if (ne == ener.size()) // threshold is larger then energy mesh
1185 s_more = 0; // to finish the loop
1186 }
1187 // Iprintn(mcout, nce_next);
1188 // Iprintn(mcout, ener[nce_next-1]);
1189 int qt = nt1 - nt2 + 1; // quantity of the new thresholds
1190 // Iprintn(mcout, qt);
1191
1192 // Calculate sum of Z.
1193 int s = 0;
1194 for (nt = 0; nt < qt; nt++) {
1195 const int nshell = nct - nt;
1196 s += Zshell[nshell];
1197 }
1198 // Weights according to charges
1199 std::vector<double> w(qt);
1200 for (nt = 0; nt < qt; nt++) {
1201 const int nshell = nct - nt;
1202 w[nt] = double(Zshell[nshell]) / s;
1203 }
1204 double save_left_CS = left_CS[nce_next - 1];
1205 for (long ne = 0; ne < nce_next; ne++) {
1206 for (nt = 0; nt < qt; nt++) {
1207 int nshell = nct - nt;
1208 SCS[nshell][ne] = left_CS[ne] * w[nt];
1209 }
1210 left_CS[ne] = 0.0;
1211 }
1212 for (unsigned long ne = nce_next; ne < ener.size(); ne++) {
1213 double extrap_CS =
1214 save_left_CS * pow(ener[nce_next - 1], 2.75) / pow(ener[ne], 2.75);
1215 if (extrap_CS > left_CS[ne]) extrap_CS = left_CS[ne];
1216 for (nt = 0; nt < qt; nt++) {
1217 int nshell = nct - nt;
1218 SCS[nshell][ne] = extrap_CS * w[nt];
1219 }
1220 left_CS[ne] -= extrap_CS;
1221 }
1222 nce = nce_next;
1223 nct = nt2 - 1;
1224 } while (s_more != 0);
1225 // now nt2 will be index of last filled shell
1226 // Now to fill the shells which are absent in the input table.
1227 // They will be initialized phenomenologically, based on the sum rule.
1228 for (int ns = 0; ns < nt2; ns++) {
1229 acs[ns].pass(new PhenoPhotoAbsCS(shell_name[ns], Zshell[ns], thr[ns]));
1230 }
1231 // Initialization of input shells.
1232 for (int ns = nt2; ns < qshell; ns++) {
1234 shell_name[ns], Zshell[ns], thr[ns], ener, SCS[ns]);
1235 adr->remove_leading_zeros();
1236 acs[ns].pass(adr);
1237 }
1239 exener[0] = exener[1] = 0.0;
1240 double integ = get_integral_ACS(0.0, DBL_MAX);
1241 // Iprintn(mcout, integ);
1242 integ_abs_before_corr = integ;
1243 double pred_integ = Thomas_sum_rule_const_Mb * Z;
1244 // Iprintn(mcout, pred_integ);
1245 if (pred_integ > integ) {
1247 const double threshold = acs[qshell - 1]->get_threshold();
1248 // add excitation
1249 exener[0] = low_boundary_of_excitations * threshold;
1250 exener[1] = threshold;
1251 height_of_excitation = (pred_integ - integ) / (exener[1] - exener[0]);
1252 if (minimal_threshold > 0.0) {
1253 if (minimal_threshold > threshold) {
1254 // currently the minimal shell is the last one
1255 exener[0] += minimal_threshold - threshold;
1256 exener[1] += minimal_threshold - threshold;
1257 }
1258 }
1259 }
1260 } else if (pred_integ < integ) {
1262 const double fact = pred_integ / integ;
1263 for (int nshell = 0; nshell < qshell; ++nshell) {
1264 acs[nshell]->scale(fact);
1265 }
1266 }
1267 }
1268 integ_abs_after_corr = get_integral_ACS(0.0, DBL_MAX);
1270}
1271
1272ExAtomPhotoAbsCS::ExAtomPhotoAbsCS(int fZ, const std::string& fname,
1273 const std::string& fBT_file_name, int id,
1274 double fminimal_threshold)
1275 : threshold_file_name("none"),
1276 simple_table_file_name("none"),
1277 BT_file_name(fBT_file_name),
1278 minimal_threshold(fminimal_threshold) {
1279 mfunnamep(
1280 "ExAtomPhotoAbsCS::ExAtomPhotoAbsCS(int fZ, const std::string& fname, "
1281 "const std::string& fBT_file_name, int id, double fminimal_threshold)");
1282 check_econd11(fZ, < 1, mcerr);
1283 check_econd21(id, < 1 ||, > 2, mcerr);
1284
1285 name = fname;
1286 std::ifstream BT_file(BT_file_name.c_str());
1287 if (!BT_file) {
1288 funnw.ehdr(mcerr);
1289 mcerr << "cannot open file " << BT_file_name << std::endl;
1290 spexit(mcerr);
1291 }
1292 std::vector<double> thresh;
1293 std::vector<double> fl;
1294 Z = fZ;
1295 int i = findmark(BT_file, "NUCLEAR CHARGE =");
1296 check_econd11a(i, != 1, "wrong file format", mcerr);
1297 int Z_from_file;
1298 BT_file >> Z_from_file;
1299 check_econd12(Z_from_file, !=, Z, mcerr);
1300 qshell = 0;
1301 while ((i = findmark(BT_file, "Z =")) == 1) {
1302 BT_file >> i;
1303 check_econd11(i, != Z, mcerr);
1304 std::string shellname;
1305 BT_file >> shellname;
1306 // Iprintn(mcout, shellname);
1307 i = findmark(BT_file, "$");
1308 check_econd11(i, != 1, mcerr);
1309 long qen;
1310 BT_file >> qen;
1311 check_econd11(qen, <= 0, mcerr);
1312 std::vector<double> fener(qen, 0.0);
1313 std::vector<double> fcs(qen, 0.0);
1314 double thr = 0.0;
1315 BT_file >> thr;
1316 check_econd11(thr, <= 0, mcerr);
1317 thr *= 1.0e-3; // pass from keV to MeV
1318 if (id == 2) {
1319 thresh.push_back(thr);
1320 fl.resize(fl.size() + 1);
1321 BT_file >> fl[qshell];
1322 check_econd21(fl[qshell], < 0.0 ||, > 1.0, mcerr);
1323 // Iprintn(mcout, fl[qshell]);
1324 }
1325 long nen;
1326 for (nen = 0; nen < qen; nen++) {
1327 BT_file >> fener[nen] >> fcs[nen];
1328 check_econd11(fener[nen], <= 0.0, mcerr);
1329 check_econd11(fcs[nen], < 0.0, mcerr);
1330 fener[nen] *= 1.0e-3; // pass from keV to MeV
1331 }
1332 qshell++;
1333 acs.resize(qshell);
1334 acs[qshell - 1]
1335 .pass(new SimpleTablePhotoAbsCS(shellname, 0, // unknown here
1336 thr, fener, fcs));
1337 }
1338 if (id == 2) {
1339 // a copy of similar thing from subroutine above
1340 int n_min = 0;
1341 double st = DBL_MAX;
1342 for (int nshell = 0; nshell < qshell; ++nshell) {
1343 // currently the minimal shell is the last,
1344 // but to avoid this assumption we check all
1345 if (thresh[nshell] < st) {
1346 n_min = nshell;
1347 st = thresh[nshell];
1348 }
1349 }
1350 asp.resize(qshell);
1351 for (int nshell = 0; nshell < qshell; ++nshell) {
1352 if (fl[nshell] > 0) {
1353 check_econd12(nshell, ==, n_min, mcerr);
1354 std::vector<double> felectron_energy;
1355 std::vector<double> fphoton_energy;
1356 fphoton_energy.push_back(thresh[nshell] - thresh[n_min]);
1357 asp[nshell].add_channel(fl[nshell], felectron_energy, fphoton_energy);
1358 }
1359 }
1360 }
1361
1362 check_econd11(qshell, <= 0, mcerr);
1363 s_ignore_shell.resize(qshell, false);
1365 exener[0] = exener[1] = 0.0;
1366 double integ = get_integral_ACS(0.0, DBL_MAX);
1367 // Iprintn(mcout, integ);
1368 integ_abs_before_corr = integ;
1369 double pred_integ = Thomas_sum_rule_const_Mb * Z;
1370 // Iprintn(mcout, pred_integ);
1371 if (pred_integ > integ) {
1373 const double thr = acs[qshell - 1]->get_threshold();
1374 // add excitation
1376 exener[1] = thr;
1377 height_of_excitation = (pred_integ - integ) / (exener[1] - exener[0]);
1378 if (minimal_threshold > 0.0) {
1379 if (minimal_threshold > thr) {
1380 // currently the minimal shell is the last one
1381 exener[0] += minimal_threshold - thr;
1382 exener[1] += minimal_threshold - thr;
1383 }
1384 }
1385 }
1386 } else {
1388 const double fact = pred_integ / integ;
1389 for (int nshell = 0; nshell < qshell; ++nshell) {
1390 acs[nshell]->scale(fact);
1391 }
1392 }
1393 }
1394 integ_abs_after_corr = get_integral_ACS(0.0, DBL_MAX);
1396}
1397
1398#define READ_FILE_WITH_PRINCIPAL_NUMBERS
1399
1400ExAtomPhotoAbsCS::ExAtomPhotoAbsCS(int fZ, const std::string& fname,
1401 const std::string& fFitBT_file_name,
1402 int id,
1403 int s_no_scale, double fminimal_threshold)
1404 : threshold_file_name("none"),
1405 simple_table_file_name("none"),
1406 BT_file_name(fFitBT_file_name),
1407 minimal_threshold(fminimal_threshold) {
1408 mfunnamep(
1409 "ExAtomPhotoAbsCS::ExAtomPhotoAbsCS(int fZ, const std::string& fname, "
1410 "const "
1411 "std::string& fFitBT_file_name, int id, int id1, double "
1412 "fminimal_threshold)");
1413 check_econd11(fZ, < 1, mcerr);
1414 check_econd21(id, < 1 ||, > 2, mcerr);
1415 Z = fZ;
1416 name = fname;
1417 std::ifstream BT_file(fFitBT_file_name.c_str());
1418 if (!BT_file) {
1419 funnw.ehdr(mcerr);
1420 mcerr << "cannot open file " << BT_file_name << std::endl;
1421 spexit(mcerr);
1422 }
1423 std::vector<double> thresh;
1424 std::vector<double> fl;
1425 int i = 0;
1426 while ((i = findmark(BT_file, "$")) == 1) {
1427 long iZ;
1428 BT_file >> iZ;
1429 if (iZ != Z) continue;
1430 BT_file >> qshell;
1431 // Iprintn(mcout, qshell);
1432 check_econd11(qshell, <= 0, mcerr);
1433 check_econd11(qshell, > 1000, mcerr);
1434 acs.resize(qshell);
1435 if (id == 2) {
1436 thresh.resize(qshell);
1437 fl.resize(qshell);
1438 }
1439 for (int nshell = 0; nshell < qshell; ++nshell) {
1440#ifdef READ_FILE_WITH_PRINCIPAL_NUMBERS
1441 int n_princ = 0;
1442#endif
1443 int l;
1444 double threshold;
1445 double E0;
1446 double yw;
1447 double ya;
1448 double P;
1449 double sigma;
1450 if (BT_file.eof()) {
1451 mcerr << "unexpected end of file " << BT_file_name << '\n';
1452 spexit(mcerr);
1453 }
1454 if (!BT_file.good()) {
1455 mcerr << "bad format of file " << BT_file_name << '\n';
1456 spexit(mcerr);
1457 }
1458#ifdef READ_FILE_WITH_PRINCIPAL_NUMBERS
1459 BT_file >> n_princ;
1460 if (!BT_file.good()) {
1461 mcerr << "bad format of file " << BT_file_name << '\n';
1462 spexit(mcerr);
1463 }
1464 check_econd21(n_princ, < 0 ||, > 10, mcerr);
1465#endif
1466 BT_file >> l >> threshold >> E0 >> sigma >> ya >> P >> yw;
1467 check_econd11(l, < 0, mcerr);
1468 check_econd11(l, > 20, mcerr);
1469 threshold *= 1.0e-6;
1470 E0 *= 1.0e-6;
1471
1472 check_econd11a(threshold, <= 2.0e-6,
1473 "n_princ=" << n_princ << " l=" << l << '\n', mcerr);
1474 check_econd11(E0, <= 0, mcerr);
1475 double flu = 0.0;
1476 if (id == 2) {
1477 if (BT_file.eof()) {
1478 mcerr << "unexpected end of file " << BT_file_name << '\n';
1479 spexit(mcerr);
1480 }
1481 if (!BT_file.good()) {
1482 mcerr << "bad format of file " << BT_file_name << '\n';
1483 spexit(mcerr);
1484 }
1485 BT_file >> flu;
1486 check_econd11(flu, < 0.0, mcerr);
1487 check_econd11(flu, > 1.0, mcerr);
1488 thresh[nshell] = threshold;
1489 fl[nshell] = flu;
1490 }
1491#ifdef READ_FILE_WITH_PRINCIPAL_NUMBERS
1492 // necessary for generation escape products
1493 std::string shellname(long_to_String(n_princ) + " shell number " +
1494 long_to_String(nshell));
1495#else
1496 std::string shellname("shell number " + long_to_String(nshell));
1497#endif
1498 acs[nshell]
1499 .pass(new SimpleTablePhotoAbsCS(shellname, 0, // unknown here
1500 threshold, l, E0, yw, ya, P, sigma));
1501 // Iprintn(mcout, nshell);
1502 // Iprint3n(mcout, l, threshold, E0);
1503 // Iprint4n(mcout, yw, ya, P, sigma);
1504 // acs[nshell]->print(mcout, 5);
1505 }
1506 goto mark1;
1507 }
1508 funnw.ehdr(mcerr);
1509 mcerr << "there is no element Z=" << fZ << " in file " << fFitBT_file_name
1510 << std::endl;
1511 spexit(mcerr);
1512mark1:
1513 if (id == 2) {
1514 // a copy of similar thing from subroutine above
1515 int n_min = 0;
1516 double st = DBL_MAX;
1517 for (int nshell = 0; nshell < qshell; ++nshell) {
1518 // currently the minimal shell is the last,
1519 // but to avoid this assumption we check all
1520 if (thresh[nshell] < st) {
1521 n_min = nshell;
1522 st = thresh[nshell];
1523 }
1524 }
1525 asp.resize(qshell);
1526 for (int nshell = 0; nshell < qshell; ++nshell) {
1527 if (fl[nshell] > 0) {
1528 check_econd12(nshell, ==, n_min, mcerr);
1529 std::vector<double> felectron_energy;
1530 std::vector<double> fphoton_energy;
1531 fphoton_energy.push_back(thresh[nshell] - thresh[n_min]);
1532 asp[nshell].add_channel(fl[nshell], felectron_energy, fphoton_energy);
1533 }
1534 }
1535 }
1536
1537 check_econd11(qshell, <= 0, mcerr);
1538 s_ignore_shell.resize(qshell, false);
1540 exener[0] = exener[1] = 0.0;
1541 double integ = get_integral_ACS(0.0, DBL_MAX);
1542 // Iprintn(mcout, integ);
1543 integ_abs_before_corr = integ;
1544 double pred_integ = Thomas_sum_rule_const_Mb * Z;
1545 // Iprintn(mcout, pred_integ);
1546 if (pred_integ > integ) {
1548 const double thr = acs[qshell - 1]->get_threshold();
1549 // add excitation
1551 exener[1] = thr;
1552 height_of_excitation = (pred_integ - integ) / (exener[1] - exener[0]);
1553 if (minimal_threshold > 0.0) {
1554 if (minimal_threshold > thr) {
1555 // currently the minimal shell is the last one
1556 exener[0] += minimal_threshold - thr;
1557 exener[1] += minimal_threshold - thr;
1558 }
1559 }
1560 }
1561 } else {
1562 if (s_scale_to_normalize_if_more == 1 && s_no_scale == 0) {
1563 const double fact = pred_integ / integ;
1564 for (int nshell = 0; nshell < qshell; ++nshell) {
1565 acs[nshell]->scale(fact);
1566 }
1567 }
1568 }
1569 integ_abs_after_corr = get_integral_ACS(0.0, DBL_MAX);
1571}
1572
1574 int fZ, const std::string& fname, const std::string& fFitBT_file_name,
1575 const std::string& fsimple_table_file_name, double emax_repl,
1576 int id, // to distinguish it from constructor above
1577 double fminimal_threshold) {
1578 mfunname("ExAtomPhotoAbsCS::ExAtomPhotoAbsCS(...)");
1579 Z = fZ;
1580 name = fname;
1581 int s_no_scale = 1;
1582 *this = ExAtomPhotoAbsCS(fZ, fname, fFitBT_file_name, id, s_no_scale,
1583 fminimal_threshold);
1584
1586 exener[0] = exener[1] = 0.0;
1587
1588 double thrmin = DBL_MAX;
1589 long nsmin = -1;
1590 // Look for minimal shell (usually the last).
1591 for (long ns = 0; ns < qshell; ++ns) {
1592 if (thrmin > acs[ns]->get_threshold()) {
1593 nsmin = ns;
1594 thrmin = acs[ns]->get_threshold();
1595 }
1596 }
1597 // Iprint3n(mcout, nsmin, acs[nsmin]->get_threshold(), thrmin);
1598 check_econd11(nsmin, < 0, mcerr);
1599 check_econd11(nsmin, != qshell - 1, mcerr); // now it has to be by this way
1600 ActivePtr<PhotoAbsCS> facs = acs[nsmin]; // copying the valence shell
1601 PhotoAbsCS* apacs = facs.get();
1602 SimpleTablePhotoAbsCS* first_shell =
1603 dynamic_cast<SimpleTablePhotoAbsCS*>(apacs);
1604 check_econd11(first_shell, == NULL, mcerr);
1605
1606 SimpleTablePhotoAbsCS stpacs(name, Z, 0.0, fsimple_table_file_name);
1607 stpacs.remove_leading_tiny(1.0e-10);
1608
1609 // Merging shells:
1610 acs[nsmin].pass(new SimpleTablePhotoAbsCS(*first_shell, stpacs, emax_repl));
1611
1612 s_ignore_shell.resize(qshell, false);
1614 exener[0] = exener[1] = 0.0;
1615 double integ = get_integral_ACS(0.0, DBL_MAX);
1616 integ_abs_before_corr = integ;
1617 double pred_integ = Thomas_sum_rule_const_Mb * Z;
1618 if (pred_integ > integ) {
1620 const double thr = acs[qshell - 1]->get_threshold();
1621 // add excitation
1623 exener[1] = thr;
1624 height_of_excitation = (pred_integ - integ) / (exener[1] - exener[0]);
1625 if (minimal_threshold > 0.0) {
1626 if (minimal_threshold > thr) {
1627 // currently the minimal shell is the last one
1628 exener[0] += minimal_threshold - thr;
1629 exener[1] += minimal_threshold - thr;
1630 }
1631 }
1632 }
1633 } else {
1635 const double fact = pred_integ / integ;
1636 for (int nshell = 0; nshell < qshell; ++nshell) {
1637 acs[nshell]->scale(fact);
1638 }
1639 }
1640 }
1641 integ_abs_after_corr = get_integral_ACS(0.0, DBL_MAX);
1643}
1644
1645double ExAtomPhotoAbsCS::get_threshold(int nshell) const {
1646 mfunname("double ExAtomPhotoAbsCS::get_threshold(int nshell) const");
1647 check_econd21(nshell, < 0 ||, > qshell, mcerr);
1648 double r = acs[nshell]->get_threshold();
1649 if (minimal_threshold > 0.0) {
1651 }
1652 return r;
1653}
1654
1655double ExAtomPhotoAbsCS::get_ICS(double energy) const {
1656 mfunname("double ExAtomPhotoAbsCS::get_ACS(double energy) const");
1657 double s = 0.0;
1658 for (int n = 0; n < qshell; ++n) {
1659 if (s_ignore_shell[n]) continue;
1660 double shift = 0.0;
1661 const double t = acs[n]->get_threshold();
1662 if (minimal_threshold > 0.0) {
1663 if (t < minimal_threshold) shift = minimal_threshold - t;
1664 }
1665 s += acs[n]->get_CS(energy - shift);
1666 }
1667 return s;
1668}
1669
1671 double energy2) const {
1672 mfunname("double ExAtomPhotoAbsCS::get_integral_ICS(double energy) const");
1673 double s = 0.0;
1674 for (int n = 0; n < qshell; ++n) {
1675 if (s_ignore_shell[n]) continue;
1676 double shift = 0.0;
1677 const double t = acs[n]->get_threshold();
1678 if (minimal_threshold > 0.0) {
1679 if (t < minimal_threshold) shift = minimal_threshold - t;
1680 }
1681 s += acs[n]->get_integral_CS(energy1 - shift, energy2 - shift);
1682 }
1683 return s;
1684}
1685
1686double ExAtomPhotoAbsCS::get_ICS(int nshell, double energy) const {
1687 mfunname("double ExAtomPhotoAbsCS::get_ICS(int nshell, double energy) const");
1688 check_econd21(nshell, < 0 ||, > qshell, mcerr);
1689 if (s_ignore_shell[nshell]) return 0.;
1690 double shift = 0.0;
1691 const double t = acs[nshell]->get_threshold();
1692 if (minimal_threshold > 0.0) {
1693 if (t < minimal_threshold) shift = minimal_threshold - t;
1694 }
1695 return acs[nshell]->get_CS(energy - shift);
1696}
1697
1698double ExAtomPhotoAbsCS::get_integral_ICS(int nshell, double energy1,
1699 double energy2) const {
1700 mfunname("double ExAtomPhotoAbsCS::get_integral_ICS(int nshell, ...) const");
1701 check_econd21(nshell, < 0 ||, > qshell, mcerr);
1702 if (s_ignore_shell[nshell]) return 0.;
1703 double shift = 0.0;
1704 const double t = acs[nshell]->get_threshold();
1705 if (minimal_threshold > 0.0) {
1706 if (t < minimal_threshold) shift = minimal_threshold - t;
1707 }
1708 return acs[nshell]->get_integral_CS(energy1 - shift, energy2 - shift);
1709}
1710
1711double ExAtomPhotoAbsCS::get_ACS(double energy) const {
1712 mfunname("double ExAtomPhotoAbsCS::get_ACS(double energy) const");
1713 double s = 0.0;
1714 for (int n = 0; n < qshell; ++n) {
1715 if (s_ignore_shell[n]) continue;
1716 double shift = 0.0;
1717 const double t = acs[n]->get_threshold();
1718 if (minimal_threshold > 0.0) {
1719 if (t < minimal_threshold) shift = minimal_threshold - t;
1720 }
1721 s += acs[n]->get_CS(energy - shift);
1722 }
1723 if (energy >= exener[0] && energy <= exener[1]) s += height_of_excitation;
1724 return s;
1725}
1726
1728 double energy2) const {
1729 mfunname("double ExAtomPhotoAbsCS::get_integral_ACS(...) const");
1730 double s = 0.0;
1731 for (int n = 0; n < qshell; ++n) {
1732 if (s_ignore_shell[n]) continue;
1733 double shift = 0.0;
1734 const double t = acs[n]->get_threshold();
1735 if (minimal_threshold > 0.0) {
1736 if (t < minimal_threshold) shift = minimal_threshold - t;
1737 }
1738 s += acs[n]->get_integral_CS(energy1 - shift, energy2 - shift);
1739 }
1740 double b[2] = {std::max(exener[0], energy1), std::min(exener[1], energy2)};
1741 if (b[1] >= b[0]) s += height_of_excitation * (b[1] - b[0]);
1742 return s;
1743}
1744
1745double ExAtomPhotoAbsCS::get_ACS(int nshell, double energy) const {
1746 mfunname("double ExAtomPhotoAbsCS::get_ACS(int nshell, double energy)");
1747 check_econd21(nshell, < 0 ||, > qshell, mcerr);
1748 if (s_ignore_shell[nshell]) return 0.;
1749 double shift = 0.0;
1750 const double t = acs[nshell]->get_threshold();
1751 if (minimal_threshold > 0.0) {
1752 if (t < minimal_threshold) shift = minimal_threshold - t;
1753 }
1754 double s = acs[nshell]->get_CS(energy - shift);
1755 if (nshell == qshell - 1 && energy >= exener[0] && energy <= exener[1]) {
1757 }
1758 return s;
1759}
1760
1761double ExAtomPhotoAbsCS::get_integral_ACS(int nshell, double energy1,
1762 double energy2) const {
1763 mfunname("double ExAtomPhotoAbsCS::get_integral_ACS(int nshell, ...) const");
1764 check_econd21(nshell, < 0 ||, > qshell, mcerr);
1765 if (s_ignore_shell[nshell]) return 0.;
1766 double shift = 0.0;
1767 const double t = acs[nshell]->get_threshold();
1768 if (minimal_threshold > 0.0) {
1769 if (t < minimal_threshold) shift = minimal_threshold - t;
1770 }
1771 double s = acs[nshell]->get_integral_CS(energy1 - shift, energy2 - shift);
1772 if (nshell == qshell - 1) {
1773 double b[2] = {std::max(exener[0], energy1), std::min(exener[1], energy2)};
1774 if (b[1] >= b[0]) s += height_of_excitation * (b[1] - b[0]);
1775 }
1776 return s;
1777}
1778
1779void ExAtomPhotoAbsCS::print(std::ostream& file, int l) const {
1780 if (l <= 0) return;
1781 Ifile << "ExAtomPhotoAbsCS(l=" << l << "): name=" << name << " Z = " << Z
1782 << " qshell = " << qshell << std::endl;
1783 indn.n += 2;
1784 Ifile << "threshold_file_name=" << threshold_file_name << '\n';
1785 Ifile << "simple_table_file_name=" << simple_table_file_name << '\n';
1786 Ifile << "BT_file_name=" << BT_file_name << std::endl;
1787 Ifile << "Thomas_sum_rule_const_Mb * Z = " << Thomas_sum_rule_const_Mb* Z
1788 << '\n';
1789 Ifile << "integ_abs_before_corr = " << integ_abs_before_corr << '\n';
1790 Ifile << "integ_abs_after_corr = " << integ_abs_after_corr << '\n';
1791 Ifile << "integ_ioniz_after_corr = " << integ_ioniz_after_corr << '\n';
1792 Ifile << "height_of_excitation=" << height_of_excitation
1793 << " exener=" << exener[0] << ' ' << exener[1] << '\n';
1795 Ifile << "integrals by shells:\n";
1796 Ifile << "nshell, int(acs), int(ics)\n";
1797 for (long n = 0; n < qshell; n++) {
1798 double ainteg = get_integral_ACS(n, 0.0, DBL_MAX);
1799 double iinteg = get_integral_ICS(n, 0.0, DBL_MAX);
1800 Ifile << n << " " << ainteg << " " << iinteg << '\n';
1801 }
1802
1803 if (l > 1) {
1804 l--;
1805 indn.n += 2;
1806 for (long n = 0; n < qshell; ++n) {
1807 Ifile << "nshell=" << n << std::endl;
1808 acs[n].print(file, l);
1809 }
1810 AtomPhotoAbsCS::print(file, l);
1811 indn.n -= 2;
1812 }
1813 indn.n -= 2;
1814}
1815
1816void ExAtomPhotoAbsCS::replace_shells_by_average(double fwidth, double fstep,
1817 long fmax_q_step) {
1818 mfunname("void ExAtomPhotoAbsCS::replace_shells_by_average(...)");
1819 for (long n = 0; n < qshell; n++) {
1820 PhotoAbsCS* a =
1821 new AveragePhotoAbsCS(acs[n].getver(), fwidth, fstep, fmax_q_step);
1822 acs[n].pass(a);
1823 }
1824}
1825
1826//---------------------------------------------------------
1827
1829 double fW, double fF)
1830 : qatom(fqatom), W(fW), F(fF) {
1831 qatom_ps.push_back(qatom);
1832 atom.push_back(PassivePtr<const AtomPhotoAbsCS>(&fatom));
1833 if (W == 0.0) W = coef_I_to_W * atom[0]->get_I_min();
1834}
1835
1837 const AtomPhotoAbsCS& fatom2, int fqatom_ps2,
1838 double fW, double fF)
1839 : qatom(fqatom_ps1 + fqatom_ps2), W(fW), F(fF) {
1840 qatom_ps.push_back(fqatom_ps1);
1841 qatom_ps.push_back(fqatom_ps2);
1842 atom.push_back(fatom1);
1843 atom.push_back(fatom2);
1844 if (W != 0.0) return;
1845#ifdef CALC_W_USING_CHARGES
1846 W = coef_I_to_W * (qatom_ps[0] * atom[0]->get_Z() * atom[0]->get_I_min() +
1847 qatom_ps[1] * atom[1]->get_Z() * atom[1]->get_I_min()) /
1848 (qatom_ps[0] * atom[0]->get_Z() + qatom_ps[1] * atom[1]->get_Z());
1849#else
1850 W = coef_I_to_W * (qatom_ps[0] * atom[0]->get_I_min() +
1851 qatom_ps[1] * atom[1]->get_I_min()) /
1852 qatom;
1853#endif
1854}
1855
1857 const AtomPhotoAbsCS& fatom2, int fqatom_ps2,
1858 const AtomPhotoAbsCS& fatom3, int fqatom_ps3,
1859 double fW, double fF)
1860 : qatom(fqatom_ps1 + fqatom_ps2 + fqatom_ps3), W(fW), F(fF) {
1861 qatom_ps.push_back(fqatom_ps1);
1862 qatom_ps.push_back(fqatom_ps2);
1863 qatom_ps.push_back(fqatom_ps3);
1864 atom.push_back(fatom1);
1865 atom.push_back(fatom2);
1866 atom.push_back(fatom3);
1867 if (W != 0.0) return;
1868#ifdef CALC_W_USING_CHARGES
1869 W = coef_I_to_W * (qatom_ps[0] * atom[0]->get_Z() * atom[0]->get_I_min() +
1870 qatom_ps[1] * atom[1]->get_Z() * atom[1]->get_I_min() +
1871 qatom_ps[2] * atom[2]->get_Z() * atom[2]->get_I_min()) /
1872 (qatom_ps[0] * atom[0]->get_Z() + qatom_ps[1] * atom[1]->get_Z() +
1873 qatom_ps[2] * atom[2]->get_Z());
1874#else
1875 W = coef_I_to_W *
1876 (qatom_ps[0] * atom[0]->get_I_min() + qatom_ps[1] * atom[1]->get_I_min() +
1877 qatom_ps[2] * atom[2]->get_I_min()) /
1878 qatom;
1879#endif
1880}
1881
1882double MolecPhotoAbsCS::get_ACS(const double energy) const {
1883 mfunname("double MolecPhotoAbsCS::get_ACS(double energy) const");
1884 const long q = qatom_ps.size();
1885 double s = 0.0;
1886 for (long n = 0; n < q; n++) s += qatom_ps[n] * atom[n]->get_ACS(energy);
1887 return s;
1888}
1889
1890double MolecPhotoAbsCS::get_integral_ACS(double en1, double en2) const {
1891 mfunname("double MolecPhotoAbsCS::get_integral_ACS(double e1, double e2)");
1892 const long q = qatom_ps.size();
1893 double s = 0.0;
1894 for (long n = 0; n < q; n++) {
1895 s += qatom_ps[n] * atom[n]->get_integral_ACS(en1, en2);
1896 }
1897 return s;
1898}
1899
1900double MolecPhotoAbsCS::get_ICS(double energy) const {
1901 mfunname("double MolecPhotoAbsCS::get_ICS(double energy) const");
1902 const long q = qatom_ps.size();
1903 double s = 0.0;
1904 for (long n = 0; n < q; n++) s += qatom_ps[n] * atom[n]->get_ICS(energy);
1905 return s;
1906}
1907
1908double MolecPhotoAbsCS::get_integral_ICS(double en1, double en2) const {
1909 mfunname("double MolecPhotoAbsCS::get_integral_ICS(double e1, double e2)");
1910 const long q = qatom_ps.size();
1911 double s = 0.0;
1912 for (long n = 0; n < q; n++) {
1913 s += qatom_ps[n] * atom[n]->get_integral_ICS(en1, en2);
1914 }
1915 return s;
1916}
1917
1919 mfunname("int MolecPhotoAbsCS::get_total_Z() const");
1920 const long q = qatom_ps.size();
1921 int s = 0;
1922 for (long n = 0; n < q; n++) {
1923 s += qatom_ps[n] * atom[n]->get_Z();
1924 }
1925 return s;
1926}
1927
1928void MolecPhotoAbsCS::print(std::ostream& file, int l) const {
1929 Ifile << "MolecPhotoAbsCS (l=" << l << "):\n";
1930 Iprintn(file, qatom);
1931 Iprintn(file, W);
1932 Iprintn(file, F);
1933 const long q = qatom_ps.size();
1934 Ifile << "number of sorts of atoms is " << q << '\n';
1935 indn.n += 2;
1936 for (long n = 0; n < q; n++) {
1937 Ifile << "n=" << n << " qatom_ps[n]=" << qatom_ps[n] << " atom:\n";
1938 atom[n]->print(file, l);
1939 }
1940 indn.n -= 2;
1941}
1942
1943std::ostream& operator<<(std::ostream& file, const MolecPhotoAbsCS& f) {
1944 f.print(file, 1);
1945 return file;
1946}
1947}
#define check_econd21(a, sign1_b1_sign0, sign2_b2, stream)
Definition: FunNameStack.h:191
#define check_econd11(a, signb, stream)
Definition: FunNameStack.h:155
#define check_econd11a(a, signb, add, stream)
Definition: FunNameStack.h:172
#define mfunnamep(string)
Definition: FunNameStack.h:49
#define spexit(stream)
Definition: FunNameStack.h:256
#define check_econd12(a, sign, b, stream)
Definition: FunNameStack.h:163
#define mfunname(string)
Definition: FunNameStack.h:45
Active pointer or automatic container or controlling pointer.
Definition: AbsPtr.h:199
X * get(void) const
Definition: AbsPtr.h:215
Atomic photoabsorption cross-section abstract base class.
Definition: PhotoAbsCS.h:285
AtomPhotoAbsCS()
Default constructor.
Definition: PhotoAbsCS.cpp:580
std::vector< bool > s_ignore_shell
Definition: PhotoAbsCS.h:378
int Z
Atomic number.
Definition: PhotoAbsCS.h:370
virtual void remove_shell(int nshell)
Deactivate a sub-shell. Set s_ignore_shell flag to true.
Definition: PhotoAbsCS.cpp:623
std::string name
Name of the atom.
Definition: PhotoAbsCS.h:368
virtual double get_I_min() const
Get the lowest ionization threshold among all shells.
Definition: PhotoAbsCS.cpp:667
virtual double get_ACS(double energy) const =0
virtual int get_main_shell_number(int nshell) const =0
virtual void print(std::ostream &file, int l) const
Definition: PhotoAbsCS.cpp:635
virtual double get_TICS(double energy, double factual_minimal_threshold) const
Definition: PhotoAbsCS.cpp:582
virtual double get_threshold(int nshell) const =0
Get the ionization threshold for a given shell.
virtual double get_integral_TICS(double energy1, double energy2, double factual_minimal_threshold) const
Integral photo-ionization cross-section with redefined threshold.
Definition: PhotoAbsCS.cpp:593
virtual void restore_shell(int nshell)
Activate a sub-shell. Set s_ignore_shell flag to false.
Definition: PhotoAbsCS.cpp:629
int qshell
Number of shells.
Definition: PhotoAbsCS.h:372
unsigned int get_qshell() const
Get the number of shells.
Definition: PhotoAbsCS.h:293
virtual void get_escape_particles(const int nshell, double energy, std::vector< double > &el_energy, std::vector< double > &ph_energy) const
Definition: PhotoAbsCS.cpp:675
std::vector< AtomicSecondaryProducts > asp
Sampling of relaxation products for each shell.
Definition: PhotoAbsCS.h:380
AtomicSecondaryProducts * get_asp(int nshell)
Definition: PhotoAbsCS.cpp:853
virtual double get_integral_ACS(double energy1, double energy2) const =0
Integrated photo-absorption cross-section overa given interval.
int get_channel(std::vector< double > &felectron_energy, std::vector< double > &fphoton_energy) const
Definition: PhotoAbsCS.cpp:506
virtual void print(std::ostream &file, int l) const
Definition: PhotoAbsCS.cpp:549
std::vector< std::vector< double > > electron_energy
Definition: PhotoAbsCS.h:280
std::vector< std::vector< double > > photon_energy
Definition: PhotoAbsCS.h:281
void add_channel(double fchannel_prob_dens, const std::vector< double > &felectron_energy, const std::vector< double > &fphoton_energy, int s_all_rest=0)
Definition: PhotoAbsCS.cpp:469
std::vector< double > channel_prob_dens
Definition: PhotoAbsCS.h:278
Smoothed/smeared photoabsorption cross-section.
Definition: PhotoAbsCS.h:83
virtual double get_CS(double energy) const
Retrieve cross-section [Mb] at a given energy [MeV].
Definition: PhotoAbsCS.cpp:116
virtual void print(std::ostream &file, int l) const
Definition: PhotoAbsCS.cpp:149
virtual double get_integral_CS(double energy1, double energy2) const
Retrieve integral cross-section [Mb * MeV] in a given interval [MeV].
Definition: PhotoAbsCS.cpp:125
AveragePhotoAbsCS()
Default constructor.
Definition: PhotoAbsCS.h:94
virtual void scale(double fact)
Multiply by some factor. Can be useful for debugging and other purposes.
Definition: PhotoAbsCS.cpp:144
void replace_shells_by_average(double fwidth, double fstep, long fmax_q_step)
std::vector< ActivePtr< PhotoAbsCS > > acs
Definition: PhotoAbsCS.h:545
std::string BT_file_name
Definition: PhotoAbsCS.h:542
double height_of_excitation
Excitation cross-section (assumed in the lowest shell).
Definition: PhotoAbsCS.h:552
virtual double get_threshold(int nshell) const
Get the ionization threshold for a given shell.
static const int s_add_excitations_to_normalize
Definition: PhotoAbsCS.h:568
double exener[2]
Boundaries of excitation.
Definition: PhotoAbsCS.h:554
virtual double get_integral_ACS(double energy1, double energy2) const
Integrated photo-absorption cross-section overa given interval.
virtual double get_ACS(double energy) const
static const int s_scale_to_normalize_if_more
Definition: PhotoAbsCS.h:569
std::string threshold_file_name
Definition: PhotoAbsCS.h:540
ExAtomPhotoAbsCS()
Default constructor.
Definition: PhotoAbsCS.h:454
std::string simple_table_file_name
Definition: PhotoAbsCS.h:541
virtual void print(std::ostream &file, int l) const
virtual double get_ICS(double energy) const
virtual double get_integral_ICS(double energy1, double energy2) const
Integrated photo-ionization cross-section over a given interval.
virtual void print(std::ostream &file, int l) const
Definition: PhotoAbsCS.cpp:186
virtual double get_CS(double energy) const
Retrieve cross-section [Mb] at a given energy [MeV].
Definition: PhotoAbsCS.cpp:165
virtual double get_integral_CS(double energy1, double energy2) const
Retrieve integral cross-section [Mb * MeV] in a given interval [MeV].
Definition: PhotoAbsCS.cpp:171
HydrogenPhotoAbsCS()
Constructor.
Definition: PhotoAbsCS.cpp:160
virtual void scale(double fact)
Multiply by some factor. Can be useful for debugging and other purposes.
Definition: PhotoAbsCS.cpp:184
virtual double get_ACS(double energy) const
Photo-absorption cross-section [Mbarn] at a given energy [MeV].
int get_total_Z() const
Sum up the atomic numbers of all atoms in the molecule.
virtual double get_ICS(double energy) const
Photo-ionization cross-section [Mbarn] at a given energy [MeV].
virtual double get_integral_ICS(double energy1, double energy2) const
Integral photo-ionization cross-section.
MolecPhotoAbsCS()
Default constructor.
Definition: PhotoAbsCS.h:617
virtual double get_integral_ACS(double energy1, double energy2) const
Integral photo-absorption cross-section.
virtual void print(std::ostream &file, int l) const
Simple phenomenological CS for any shell (analytic formula).
Definition: PhotoAbsCS.h:211
virtual double get_integral_CS(double energy1, double energy2) const
Retrieve integral cross-section [Mb * MeV] in a given interval [MeV].
Definition: PhotoAbsCS.cpp:442
virtual double get_CS(double energy) const
Retrieve cross-section [Mb] at a given energy [MeV].
Definition: PhotoAbsCS.cpp:437
virtual void print(std::ostream &file, int l) const
Definition: PhotoAbsCS.cpp:460
PhenoPhotoAbsCS()
Default constructor.
Definition: PhotoAbsCS.cpp:425
virtual void scale(double fact)
Multiply by some factor. Can be useful for debugging and other purposes.
Definition: PhotoAbsCS.cpp:455
PhotoAbsCS()
Default constructor.
Definition: PhotoAbsCS.cpp:79
double threshold
Definition: PhotoAbsCS.h:79
double get_threshold() const
Return the threshold energy.
Definition: PhotoAbsCS.h:64
virtual void print(std::ostream &file, int l) const
Definition: PhotoAbsCS.cpp:91
std::string name
Definition: PhotoAbsCS.h:76
const std::string & get_name() const
Name of this shell or atom.
Definition: PhotoAbsCS.h:56
int get_Z() const
Definition: PhotoAbsCS.h:62
SimpleAtomPhotoAbsCS()
Default constructor.
Definition: PhotoAbsCS.cpp:859
virtual double get_ACS(double energy) const
Definition: PhotoAbsCS.cpp:939
virtual void print(std::ostream &file, int l) const
std::string file_name
Filename (saved for printing).
Definition: PhotoAbsCS.h:422
virtual double get_integral_ACS(double energy1, double energy2) const
Integrated photo-absorption cross-section overa given interval.
Definition: PhotoAbsCS.cpp:947
virtual double get_integral_ICS(double energy1, double energy2) const
Integrated photo-ionization cross-section over a given interval.
Definition: PhotoAbsCS.cpp:988
virtual double get_threshold(int nshell) const
Get the ionization threshold for a given shell.
Definition: PhotoAbsCS.cpp:933
virtual double get_ICS(double energy) const
Definition: PhotoAbsCS.cpp:979
std::vector< ActivePtr< PhotoAbsCS > > acs
Definition: PhotoAbsCS.h:423
SimpleTablePhotoAbsCS()
Default constructor.
virtual double get_integral_CS(double energy1, double energy2) const
Retrieve integral cross-section [Mb * MeV] in a given interval [MeV].
Definition: PhotoAbsCS.cpp:357
void remove_leading_tiny(double level)
Definition: PhotoAbsCS.cpp:319
virtual double get_CS(double energy) const
Retrieve cross-section [Mb] at a given energy [MeV].
Definition: PhotoAbsCS.cpp:337
virtual void print(std::ostream &file, int l) const
Definition: PhotoAbsCS.cpp:409
virtual void scale(double fact)
Multiply by some factor. Can be useful for debugging and other purposes.
Definition: PhotoAbsCS.cpp:403
const std::vector< double > & get_arr_CS() const
Definition: PhotoAbsCS.h:194
const std::vector< double > & get_arr_ener() const
Definition: PhotoAbsCS.h:193
void remove_leading_zeros()
Remove points with zero cross-section from the table.
Definition: PhotoAbsCS.cpp:302
Definition: BGMesh.cpp:5
T t_value_straight_2point(T x1, T y1, T x2, T y2, T x, int s_ban_neg)
Definition: tline.h:1510
const double low_boundary_of_excitations
Definition: PhotoAbsCS.h:426
std::ostream & operator<<(std::ostream &file, const BGMesh &bgm)
Definition: BGMesh.cpp:36
DoubleAc pow(const DoubleAc &f, double p)
Definition: DoubleAc.cpp:337
@ do_clone
Definition: AbsPtr.h:191
T t_integ_straight_2point(T x1, T y1, T x2, T y2, T xl, T xr, int xpower, int s_ban_neg)
Definition: tline.h:1544
T t_integ_generic_point_ar(const M &mesh, const D &y, T(*fun)(T xp1, T yp1, T xp2, T yp2, T xmin, T xmax, T x1, T x2), T x1, T x2, int s_extrap_left, T left_bond, int s_extrap_right, T right_bond)
Definition: tline.h:1824
const double coef_I_to_W
Definition: PhotoAbsCS.h:584
const double Thomas_sum_rule_const_Mb
TRK sum rule [Mb * MeV].
Definition: PhotoAbsCS.h:19
int findmark(std::istream &file, const char *s)
Definition: findmark.cpp:19
indentation indn
Definition: prstream.cpp:15
DoubleAc sqrt(const DoubleAc &f)
Definition: DoubleAc.cpp:314
String long_to_String(const long n)
Definition: String.h:71
T t_value_generic_point_ar(const M &mesh, const D &y, T(*funval)(T xp1, T yp1, T xp2, T yp2, T xmin, T xmax, T x), T x, int s_extrap_left, T left_bond, int s_extrap_right, T right_bond)
Definition: tline.h:1607
#define mcout
Definition: prstream.h:126
#define Ifile
Definition: prstream.h:196
#define Iprint(file, name)
Definition: prstream.h:198
#define mcerr
Definition: prstream.h:128
#define Iprintn(file, name)
Definition: prstream.h:205
#define Iprint2n(file, name1, name2)
Definition: prstream.h:220