Constructor.
120 mfunnamep(
"EnTransfCS::EnTransfCS(...)");
121
122 const double beta =
lorbeta(fgamma_1);
123 const double beta2 = beta * beta;
124 const double beta12 = 1.0 - beta2;
125 const double gamma = fgamma_1 + 1.;
126
129
132 } else {
134 double rme = electron_mass_c2;
135 if (beta12 > 1.0e-10) {
137 2.0 * rm2 * electron_mass_c2 * beta2 /
138 ((rm2 + rme * rme + 2.0 * rme * gamma *
particle_mass) * beta12);
140 } else {
142 }
143 }
144 const long qe =
hmd->energy_mesh->get_q();
145
146 std::vector<double> log1C(qe, 0.);
147
148 std::vector<double> log2C(qe, 0.);
149
150 std::vector<double> chereC(qe, 0.);
151
152 std::vector<double> chereCangle(qe, 0.);
153
154 std::vector<double> Rruth(qe, 0.);
155
156 std::vector<double> addaC(qe, 0.);
157
158#ifndef EXCLUDE_A_VALUES
159
160 std::vector<double> addaC_a(qe, 0.);
161#endif
162
163 const long qa =
hmd->matter->qatom();
166
167 std::vector<std::vector<std::vector<double> > > cher(qa);
168
169 std::vector<std::vector<std::vector<double> > > fruth(qa);
170
171 std::vector<std::vector<std::vector<double> > > adda(qa);
172
173 std::vector<std::vector<double> > mean(qa);
174#ifndef EXCLUDE_A_VALUES
175 quan_a.resize(qa);
176 fadda_a.resize(qa);
177
178 std::vector<std::vector<std::vector<double> > > cher_a(qa);
179
180 std::vector<std::vector<std::vector<double> > > adda_a(qa);
181
182 std::vector<std::vector<double> > mean_a(qa);
183#endif
184
185 for (long na = 0; na < qa; na++) {
186 const long qs =
hmd->apacs[na]->get_qshell();
187 cher[na].assign(qs, std::vector<double>(qe, 0.));
188 fruth[na].assign(qs, std::vector<double>(qe, 0.));
189 adda[na].assign(qs, std::vector<double>(qe, 0.));
190 fadda[na].assign(qs, std::vector<double>(qe, 0.));
191 quan[na].assign(qs, 0.);
192 mean[na].assign(qs, 0.);
193#ifndef EXCLUDE_A_VALUES
194 cher_a[na].assign(qs, std::vector<double>(qe, 0.));
195 adda_a[na].assign(qs, std::vector<double>(qe, 0.));
196 fadda_a[na].assign(qs, std::vector<double>(qe, 0.));
197 quan_a[na].assign(qs, 0.);
198 mean_a[na].assign(qs, 0.);
199#endif
200 }
201
203 double coefpa = fine_structure_const * q2 / CLHEP::pi;
204 if (beta2 > 0.) {
205 coefpa /= beta2;
206 } else {
207 std::cerr << "Heed::EnTransfCS: Particle has zero speed.\n";
209 coefpa = 0.;
210 }
211 const double coefCh = coefpa /
hmd->eldens;
212 for (long ne = 0; ne < qe; ne++) {
213 const double eps1 =
hmd->epsi1[ne];
214 const double eps2 =
hmd->epsi2[ne];
215 const double a0 = 1. + eps1;
216 const double a1 = -eps1 + a0 * beta12;
217 const double a2 = beta2 * eps2;
218 log1C[ne] = log(1. /
sqrt(a1 * a1 + a2 * a2));
219
220 const double ec =
hmd->energy_mesh->get_ec(ne);
221 const double a3 = 2. * electron_mass_c2 * beta2 / ec;
222 log2C[ne] = a3 > 0. ? log(a3) : 0.;
223
224 double a4 = atan(a2 / a1);
225 if (a1 < 0) a4 += CLHEP::pi;
226 chereCangle[ne] = a4;
227
228 const double a5 = eps2 * eps2;
229 const double a6 = (-a0 * a1 + beta2 * a5) / (a0 * a0 + a5);
230 chereC[ne] = coefCh * a6 * a4;
231
233 Rruth[ne] = 1. / (ec * ec);
236 }
237 } else {
239 Rruth[ne] = 1. / (ec * ec) * (1. - beta2 * ec /
max_etransf +
240 ec * ec / (2. * ener * ener));
241 } else {
243 const double pg2 = gamma * gamma;
244 const double dgd = delta * (
gamma_1 - delta);
247 (2.0 * pg2 + 2.0 * gamma - 1.0) / dgd + 1.0);
248 }
249 }
250 }
251
252 double Z_mean =
hmd->matter->Z_mean();
253 const double ethr =
hmd->min_ioniz_pot;
254 for (long na = 0; na < qa; na++) {
255 auto pacs =
hmd->apacs[na];
256 const double awq =
hmd->matter->weight_quan(na);
257 const long qs = pacs->get_qshell();
258 for (long ns = 0; ns < qs; ns++) {
259 for (long ne = 0; ne < qe; ne++) {
260 double e1 =
hmd->energy_mesh->get_e(ne);
261 double e2 =
hmd->energy_mesh->get_e(ne + 1);
262 double ics = 0.;
263 if (
hmd->s_use_mixture_thresholds == 1) {
264 ics = pacs->get_integral_TICS(ns, e1, e2, ethr) / (e2 - e1);
265 } else {
266 ics = pacs->get_integral_ICS(ns, e1, e2) / (e2 - e1);
267 }
269 "na=" << na << " ns=" << ns << " ne=" << ne << '\n',
271 const double tacs =
hmd->ACS[ne];
272 if (tacs <= 0.0) continue;
273 cher[na][ns][ne] = chereC[ne] * awq * ics / tacs;
274#ifndef EXCLUDE_A_VALUES
275 double acs = pacs->get_integral_ACS(ns, e1, e2) / (e2 - e1);
276 cher_a[na][ns][ne] = chereC[ne] * awq * acs / tacs;
277#endif
278 }
279
280 const double cR =
C1_MEV2_MBN * awq * coefpa / Z_mean;
281 double s = 0.;
282 for (long ne = 0; ne < qe; ne++) {
283 const double e1 =
hmd->energy_mesh->get_e(ne);
284 const double ec =
hmd->energy_mesh->get_ec(ne);
285 const double e2 =
hmd->energy_mesh->get_e(ne + 1);
286 const double r = pacs->get_integral_ACS(ns, e1, e2) * cR;
287
288 check_econd11a(r, < 0.0,
"na=" << na <<
" ns=" << ns <<
" ne=" << ne,
291 fruth[na][ns][ne] = (s + 0.5 * r) * Rruth[ne];
293 "na=" << na <<
" ns=" << ns <<
" na=" << na,
mcerr);
294 }
295 s += r;
296 }
297 }
298 }
299 long nNegative = 0;
300 for (long ne = 0; ne < qe; ++ne) {
301 double s = 0.0;
302#ifndef EXCLUDE_A_VALUES
303 double s_a = 0.0;
304#endif
305 double e1 =
hmd->energy_mesh->get_e(ne);
306 double ec =
hmd->energy_mesh->get_ec(ne);
307 double e2 =
hmd->energy_mesh->get_e(ne + 1);
308 const double eps1 =
hmd->epsi1[ne];
309 const double eps2 =
hmd->epsi2[ne];
310 const double eps11 = 1. + eps1;
311 const double sqepsi = eps11 * eps11 + eps2 * eps2;
312 const double cL =
C1_MEV2_MBN * coefpa * (log1C[ne] + log2C[ne]) /
313 (ec * Z_mean * sqepsi);
314 for (long na = 0; na < qa; na++) {
315 double awq =
hmd->matter->weight_quan(na);
316 auto pacs =
hmd->apacs[na];
317 const long qs = pacs->get_qshell();
318 for (long ns = 0; ns < qs; ns++) {
319 double ics = 0.;
320 if (
hmd->s_use_mixture_thresholds == 1) {
321 ics = pacs->get_integral_TICS(ns, e1, e2, ethr) / (e2 - e1);
322 } else {
323 ics = pacs->get_integral_ICS(ns, e1, e2) / (e2 - e1);
324 }
325 double r = std::max(cL * awq * ics + fruth[na][ns][ne], 0.);
326 if (ec > ethr) r += cher[na][ns][ne];
327 if (r < 0.) {
328 ++nNegative;
329 if (debug) {
331 mcout <<
"negative adda\n";
332 mcout <<
"na=" << na <<
" ns=" << ns <<
" ne=" << ne
333 << ": " << r << '\n';
334 }
335 r = 0.;
336 }
337 adda[na][ns][ne] = r;
338 s += r;
339#ifndef EXCLUDE_A_VALUES
340 double acs = pacs->get_integral_ACS(ns, e1, e2) / (e2 - e1);
341 double r_a = std::max(cL * awq * acs + fruth[na][ns][ne], 0.);
342 r_a += cher[na][ns][ne];
343 if (r_a < 0.) {
344 if (debug) {
346 mcout <<
"negative adda_a\n";
347 mcout <<
"na=" << na <<
" ns=" << ns <<
" ne=" << ne
348 << ": " << r_a << '\n';
349 }
350 r_a = 0.;
351 }
352 adda_a[na][ns][ne] = r_a;
353 s_a += r_a;
354#endif
355 }
356 }
357 addaC[ne] = s;
358#ifndef EXCLUDE_A_VALUES
359 addaC_a[ne] = s_a;
360#endif
361 }
362 if (nNegative > 0) {
363 std::cerr << "Heed::EnTransfCS:\n " << nNegative
364 << " negative values in the differential cross-section table.\n"
365 << " The particle speed might be too low.\n";
367 }
368 const double* aetemp =
hmd->energy_mesh->get_ae();
369 PointCoorMesh<double, const double*> pcm_e(qe + 1, &(aetemp));
370 double emin =
hmd->energy_mesh->get_emin();
371 double emax =
hmd->energy_mesh->get_emax();
372
373 const double rho =
hmd->xeldens;
374 quanC = integrate(pcm_e, addaC, emin, emax, 0) * rho;
375 meanC = integrate(pcm_e, addaC, emin, emax, 1) * rho;
376
377#ifndef EXCLUDE_A_VALUES
378 quanC_a = integrate(pcm_e, addaC_a, emin, emax, 0) * rho;
379 meanC_a = integrate(pcm_e, addaC_a, emin, emax, 1) * rho;
380#endif
382 const double coef = fine_structure_const * fine_structure_const * q2 * twopi /
383 (electron_mass_c2 * beta2) * rho;
387 double e1 =
hmd->energy_mesh->get_e(qe);
390 }
391 } else {
393 double e1 =
hmd->energy_mesh->get_e(qe);
395 meanC1 += coef * log(e2 / e1);
396 }
397 }
398 } else {
401 double e1 =
hmd->energy_mesh->get_e(qe);
405 (e2 * e2 - e1 * e1) / (4.0 * ener * ener));
406 }
407#ifndef EXCLUDE_A_VALUES
408 meanC1_a = meanC_a;
410 double e1 =
hmd->energy_mesh->get_e(qe);
412 meanC1_a += coef * (log(e2 / e1) - beta2 /
max_etransf * (e2 - e1) +
413 (e2 * e2 - e1 * e1) /
414 (4.0 * ener * ener));
415 }
416#endif
417 }
418 }
419
420 for (long na = 0; na < qa; na++) {
421 const long qs =
hmd->apacs[na]->get_qshell();
422 for (long ns = 0; ns < qs; ns++) {
423 quan[na][ns] = integrate(pcm_e, adda[na][ns], emin, emax, 0) * rho;
424 mean[na][ns] = integrate(pcm_e, adda[na][ns], emin, emax, 1) * rho;
425#ifndef EXCLUDE_A_VALUES
426 quan_a[na][ns] = integrate(pcm_e, adda_a[na][ns], emin, emax, 0) * rho;
427 mean_a[na][ns] = integrate(pcm_e, adda_a[na][ns], emin, emax, 1) * rho;
428#endif
429 }
430 }
431
432 for (long na = 0; na < qa; na++) {
433 const long qs =
hmd->apacs[na]->get_qshell();
434 for (long ns = 0; ns < qs; ns++) {
435 if (
quan[na][ns] > 0.0) {
436 const double s = cdf(pcm_e, adda[na][ns],
fadda[na][ns]);
437 if (
fabs(s * rho -
quan[na][ns]) > 1.e-10) {
438 std::cerr << "Heed::EnTransfCS: Integrals differ (warning).\n";
440 }
441 }
442#ifndef EXCLUDE_A_VALUES
443 if (quan_a[na][ns] > 0.0) {
444 const double s = cdf(pcm_e, adda_a[na][ns], fadda_a[na][ns]);
445 if (
fabs(s * rho - quan_a[na][ns]) > 1.e-10) {
446 std::cerr << "Heed::EnTransfCS: Integrals differ (warning).\n";
448 }
449 }
450#endif
451 }
452 }
453
455 for (long ne = 0; ne < qe; ne++) {
456 const double k0 =
hmd->energy_mesh->get_ec(ne) / (hbarc / cm);
457 const double det_value = 1.0 / (gamma * gamma) -
hmd->epsi1[ne] * beta2;
458 length_y0[ne] = det_value > 0. ? beta / k0 * 1.0 /
sqrt(det_value) : 0.;
459 }
460
461
463
464 if (!debug) return;
465 std::ofstream dcsfile;
466 dcsfile.open("dcs.txt", std::ios::out);
467 dcsfile << "# energy [MeV] vs. diff. cs per electron [Mbarn / MeV]\n";
468 for (int i = 0; i < qe; ++i) {
469 double sumR = 0.;
470 double sumC = 0.;
471 double sumL = 0.;
472 for (long na = 0; na < qa; ++na) {
473 const long qs =
hmd->apacs[na]->get_qshell();
474 for (long ns = 0; ns < qs; ++ns) {
475 sumR += fruth[na][ns][i];
476 sumC += cher[na][ns][i];
477 sumL += adda[na][ns][i] - cher[na][ns][i] - fruth[na][ns][i];
478 }
479 }
480 const double f1 = log1C[i] / (log1C[i] + log2C[i]);
481 const double f2 = 1. - f1;
485 const double sumL1 = f1 * sumL;
486 const double sumL2 = f2 * sumL;
487 dcsfile <<
hmd->energy_mesh->get_ec(i) <<
" " << addaC[i] /
C1_MEV2_MBN
488 << " " << sumL1 << " " << " " << sumC << " " << sumL2 << " " << sumR
489 << "\n";
490 }
491 dcsfile.close();
492
493}
#define check_econd11a(a, signb, add, stream)
#define mfunnamep(string)
std::vector< std::vector< double > > quan
Number of collisions / cm, for each atom and shell.
double particle_charge
Charge in units of electron charge (used square, sign does not matter).
double gamma_1
Lorentz factor - 1 (the best dimensionless measurement of speed).
double meanC
First moment (mean restricted energy loss) [MeV].
std::vector< std::vector< std::vector< double > > > fadda
Integral, normalised to unity for each atom, shell and energy.
double particle_mass
Particle mass [MeV].
bool s_primary_electron
Flag indicating whether the primary particle is an electron.
bool m_ok
Flag indicating whether the calculation was successful.
std::vector< double > length_y0
double quanC
Integrated (ionization) cross-section.
double max_etransf
Max. energy transfer [MeV].
double lorbeta(const double gamma_1)
as function of .
constexpr double C1_MEV2_MBN
DoubleAc fabs(const DoubleAc &f)
DoubleAc sqrt(const DoubleAc &f)