12#define DIRECT_LOW_IF_LITTLE
19 return std::min(std::max(n, 0L), emesh->
get_q() - 2);
23 const std::vector<double>& y) {
25 const long n = findInterval(emesh, x);
26 const double x1 = emesh->
get_ec(n);
27 const double x2 = emesh->
get_ec(n + 1);
28 const double y1 = y[n];
29 const double y2 = y[n + 1];
30 return y1 + (x - x1) * (y2 - y1) / (x2 - x1);
43using CLHEP::c_squared;
45bool HeedDeltaElectron::s_low_mult_scattering =
true;
46bool HeedDeltaElectron::s_high_mult_scattering =
true;
50 long fparent_particle_number,
54 parent_particle_number(fparent_particle_number),
56 m_print_listing(fprint_listing) {
57 mfunname(
"HeedDeltaElectron::HeedDeltaElectron(...)");
61 mfunname(
"void HeedDeltaElectron::physics_mrange(double& fmrange)");
62 if (m_print_listing)
mcout <<
"HeedDeltaElectron::physics_mrange\n";
64 m_mult_low_path_length =
false;
65 m_q_low_path_length = 0.0;
66 m_path_length =
false;
67 if (fmrange <= 0.0)
return;
80 const double dedx = interpolate(emesh, ek, hdecs->eLoss);
82 double eloss = std::max(0.1 * ek, 0.00005);
89 fmrange = std::min(fmrange, (eloss / dedx) * cm);
91 const double ek_restr = std::max(ek, 0.0005);
94 double low_path_length = 0.;
95 if (s_low_mult_scattering) {
96 low_path_length = interpolate(emesh, ek_restr, hdecs->low_lambda) * cm;
98 long qscat = hdecs->eesls->get_qscat();
99 const double sigma_ctheta = hdecs->get_sigma(ek_restr, qscat);
101 if (sigma_ctheta > 0.3) qscat = long(qscat * 0.3 / sigma_ctheta);
102 const double mult_low_path_length = qscat * low_path_length;
104 if (fmrange > mult_low_path_length) {
105 fmrange = mult_low_path_length;
106 m_mult_low_path_length =
true;
107 m_q_low_path_length = hdecs->eesls->get_qscat();
108 m_stop_eloss =
false;
110 m_mult_low_path_length =
false;
111 m_q_low_path_length = fmrange / low_path_length;
113 if (m_print_listing)
Iprint2nf(
mcout, fmrange, m_q_low_path_length);
116 if (s_high_mult_scattering) {
117 const double mean_path = interpolate(emesh, ek_restr, hdecs->lambda);
119 const double path_length = -mean_path * cm * log(1.0 - SRANLUX());
121 if (fmrange > path_length) {
122 fmrange = path_length;
123 m_path_length =
true;
124 m_mult_low_path_length =
true;
125 if (s_low_mult_scattering) {
126 m_q_low_path_length = fmrange / low_path_length;
129 m_stop_eloss =
false;
131 m_path_length =
false;
135 m_phys_mrange = fmrange;
139 std::vector<gparticle*>& ) {
140 mfunname(
"void HeedDeltaElectron::physics_after_new_speed()");
141 if (m_print_listing) {
142 mcout <<
"HeedDeltaElectron::physics_after_new_speed\n";
151 if (m_print_listing)
mcout <<
"Convert to conduction electron.\n";
157 if (m_print_listing)
mcout <<
"exit due to currpos.prange <= 0.0\n";
165 if (m_print_listing) {
178 dedx = interpolate(emesh, ek, hdecs->eLoss);
180 m_total_eloss += Eloss;
186 if (m_print_listing)
mcout <<
"m_curr_ekin <= 0.0\n";
192 const double resten =
m_mass * c_squared;
198 if (m_print_listing) {
199 mcout <<
"volume is sensitive\n";
202 if (Eloss > 0.0) ionisation(Eloss, dedx, hdecs->pairprod);
204 if (m_print_listing) {
212 if (m_print_listing)
mcout <<
"Last conduction electron\n";
219 if (m_print_listing)
mcout <<
"\nstart to rotate by low angle\n";
220 double ek_restr = std::max(ek, 0.0005);
224 m_path_length =
false;
225 if (s_low_mult_scattering) {
227 const double low_path_length = interpolate(emesh, ek_restr, hdecs->low_lambda) * cm;
229 m_mult_low_path_length =
false;
236 if (m_q_low_path_length > 0.0) {
238 long random_q_low_path_length =
pois(m_q_low_path_length, ierror);
240 " q_low_path_length=" << m_q_low_path_length <<
'\n',
mcerr);
241 m_q_low_path_length = long(random_q_low_path_length);
242 if (m_print_listing) {
243 mcout <<
"After pois:\n";
248 if (m_q_low_path_length > 0) {
249#ifdef DIRECT_LOW_IF_LITTLE
250 const long max_q_low_path_length_for_direct = 5;
251 if (m_q_low_path_length < max_q_low_path_length_for_direct) {
253 if (m_print_listing) {
254 mcout <<
"direct modeling of low scatterings\n";
258 const long n1r = findInterval(emesh, ek_restr);
259 for (
long nscat = 0; nscat < m_q_low_path_length; ++nscat) {
262 hdecs->low_angular_points_ran[n1r].ran(SRANLUX()) * degree;
265 basis temp(dir,
"temp");
268 vturn = vturn *
sin(theta_rot);
269 vec new_dir(vturn.
x, vturn.
y,
cos(theta_rot));
278 double sigma_ctheta = hdecs->get_sigma(ek_restr, m_q_low_path_length);
290 double sq2 =
sqrt(2.0);
299 double x = sigma_ctheta * (-log(1.0 - y));
301 double x = sigma_ctheta * 1.0 / sq2 * (-log(1.0 - y));
305 }
while (ctheta <= -1.0);
309 double theta_rot =
acos(ctheta);
310 if (m_print_listing)
Iprint2nf(
mcout, theta_rot, theta_rot / degree);
312 basis temp(dir,
"temp");
315 vturn = vturn *
sin(theta_rot);
316 vec new_dir(vturn.
x, vturn.
y,
cos(theta_rot));
322#ifdef DIRECT_LOW_IF_LITTLE
326 if (m_print_listing) {
327 mcout <<
"\nstarting to rotate by large angle" << std::endl;
331 const long n1r = findInterval(emesh, ek_restr);
332 double theta_rot = hdecs->angular_points_ran[n1r].ran(SRANLUX()) * degree;
335 basis temp(dir,
"temp");
338 vturn = vturn *
sin(theta_rot);
339 vec new_dir(vturn.
x, vturn.
y,
cos(theta_rot));
348void HeedDeltaElectron::ionisation(
const double eloss,
const double dedx,
351 if (eloss < m_necessary_energy) {
352 m_necessary_energy -= eloss;
356 if (m_print_listing)
mcout <<
"\nstart to leave conduction electrons\n";
357 if (m_necessary_energy <= 0.0) {
361 m_necessary_energy = pairprod->
get_eloss() * eV;
364 if (m_print_listing)
Iprintnf(
mcout, m_necessary_energy / eV);
365 double eloss_left = eloss;
370 while (eloss_left >= m_necessary_energy) {
371 const double step_length = m_necessary_energy / (dedx * MeV / cm);
373 curpt = curpt + dir * step_length;
377 if (m_print_listing)
mcout <<
"New conduction electron\n";
382 eloss_left -= m_necessary_energy;
383 ekin -= m_necessary_energy;
384 if (ekin < 0.)
break;
387 m_necessary_energy = eV * pairprod->
get_eloss(ekin / eV);
389 m_necessary_energy = pairprod->
get_eloss() * eV;
391 if (m_print_listing) {
396 m_necessary_energy -= eloss_left;
397 if (m_print_listing)
Iprintnf(
mcout, m_necessary_energy / eV);
402 Ifile <<
"HeedDeltaElectron (l=" << l
403 <<
"): particle_number=" << m_particle_number <<
"\n";
406 Ifile <<
"s_low_mult_scattering=" << s_low_mult_scattering
407 <<
" s_high_mult_scattering=" << s_high_mult_scattering <<
'\n';
408 Ifile <<
"phys_mrange=" << m_phys_mrange <<
" stop_eloss=" << m_stop_eloss
409 <<
" mult_low_path_length=" << m_mult_low_path_length <<
'\n';
410 Ifile <<
"q_low_path_length=" << m_q_low_path_length
411 <<
" path_length=" << m_path_length
412 <<
" necessary_energy/eV=" << m_necessary_energy / eV <<
'\n';
#define check_econd21(a, sign1_b1_sign0, sign2_b2, stream)
#define check_econd11(a, signb, stream)
#define check_econd11a(a, signb, add, stream)
long get_q() const
Return number of bins.
double get_ec(long n) const
Return center of a given bin.
long get_interval_number_between_centers(const double ener) const
std::vector< HeedCondElectron > conduction_electrons
std::vector< HeedCondElectron > conduction_ions
long parent_particle_number
void physics_mrange(double &fmrange) override
void print(std::ostream &file, int l) const override
Print-out.
HeedDeltaElectron()=default
Default constructor.
void physics_after_new_speed(std::vector< gparticle * > &secondaries) override
Apply any other processes (turn the trajectory, kill the particle, ...).
Retrieve electric and magnetic field from Sensor.
bool inside(const point &pt)
double get_eloss() const
Calculate energy loss (in eV).
HeedFieldMap * m_fieldMap
Pointer to field map.
stvpoint m_prevpos
Previous point.
stvpoint m_currpos
Current point.
bool m_alive
Status flag whether the particle is active.
void up_absref(absref *f)
absvol * G_lavol() const
Get last address of volume.
Abstract base classs for volume "manipulators".
double m_prev_ekin
Previous kinetic energy.
double m_curr_ekin
Current kinetic energy.
void print(std::ostream &file, int l) const override
Print-out.
double m_curr_gamma_1
Current .
double m_mass
Mass (not mass * speed_of_light^2)
vec dirloc
Unit vector, in the local system (last system in the tree).
vec dir
Unit vector, in the first system in the tree.
vfloat prange
Range from previous point.
vfloat speed
Longitudinal velocity.
point pt
Coordinates in the first system in the tree.
point ptloc
Coordinates in the local system (last system in the tree).
void down(const basis *fabas)
void random_round_vec()
Generate random unit vector in plane perpendicular to z-axis.
DoubleAc cos(const DoubleAc &f)
long last_particle_number
double lorbeta(const double gamma_1)
as function of .
long pois(const double amu, int &ierror)
DoubleAc acos(const DoubleAc &f)
particle_def electron_def("electron", "e-", electron_mass_c2/c_squared, electron_charge, 1, 0, 0.5, spin_def(0.0, 0.0))
DoubleAc sin(const DoubleAc &f)
DoubleAc sqrt(const DoubleAc &f)
#define Iprint3nf(file, name1, name2, name3)
#define Iprint3n(file, name1, name2, name3)
#define Iprint(file, name)
#define Iprintn(file, name)
#define Iprintf(file, name)
#define Iprint2nf(file, name1, name2)
#define Iprint2n(file, name1, name2)
#define Iprintnf(file, name)