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) {
237 long random_q_low_path_length =
pois(m_q_low_path_length);
238 m_q_low_path_length = long(random_q_low_path_length);
239 if (m_print_listing) {
240 mcout <<
"After pois:\n";
245 if (m_q_low_path_length > 0) {
246#ifdef DIRECT_LOW_IF_LITTLE
247 const long max_q_low_path_length_for_direct = 5;
248 if (m_q_low_path_length < max_q_low_path_length_for_direct) {
250 if (m_print_listing) {
251 mcout <<
"direct modeling of low scatterings\n";
255 const long n1r = findInterval(emesh, ek_restr);
256 for (
long nscat = 0; nscat < m_q_low_path_length; ++nscat) {
259 hdecs->low_angular_points_ran[n1r].ran(SRANLUX()) * degree;
262 basis temp(dir,
"temp");
265 vturn = vturn *
sin(theta_rot);
266 vec new_dir(vturn.
x, vturn.
y,
cos(theta_rot));
275 double sigma_ctheta = hdecs->get_sigma(ek_restr, m_q_low_path_length);
287 double sq2 =
sqrt(2.0);
296 double x = sigma_ctheta * (-log(1.0 - y));
298 double x = sigma_ctheta * 1.0 / sq2 * (-log(1.0 - y));
302 }
while (ctheta <= -1.0);
306 double theta_rot =
acos(ctheta);
307 if (m_print_listing)
Iprint2nf(
mcout, theta_rot, theta_rot / degree);
309 basis temp(dir,
"temp");
312 vturn = vturn *
sin(theta_rot);
313 vec new_dir(vturn.
x, vturn.
y,
cos(theta_rot));
319#ifdef DIRECT_LOW_IF_LITTLE
323 if (m_print_listing) {
324 mcout <<
"\nstarting to rotate by large angle" << std::endl;
328 const long n1r = findInterval(emesh, ek_restr);
329 double theta_rot = hdecs->angular_points_ran[n1r].ran(SRANLUX()) * degree;
332 basis temp(dir,
"temp");
335 vturn = vturn *
sin(theta_rot);
336 vec new_dir(vturn.
x, vturn.
y,
cos(theta_rot));
345void HeedDeltaElectron::ionisation(
const double eloss,
const double dedx,
348 if (eloss < m_necessary_energy) {
349 m_necessary_energy -= eloss;
353 if (m_print_listing)
mcout <<
"\nstart to leave conduction electrons\n";
354 if (m_necessary_energy <= 0.0) {
358 m_necessary_energy = pairprod->
get_eloss() * eV;
361 if (m_print_listing)
Iprintnf(
mcout, m_necessary_energy / eV);
362 double eloss_left = eloss;
367 while (eloss_left >= m_necessary_energy) {
368 const double step_length = m_necessary_energy / (dedx * MeV / cm);
370 curpt = curpt + dir * step_length;
374 if (m_print_listing)
mcout <<
"New conduction electron\n";
379 eloss_left -= m_necessary_energy;
380 ekin -= m_necessary_energy;
381 if (ekin < 0.)
break;
384 m_necessary_energy = eV * pairprod->
get_eloss(ekin / eV);
386 m_necessary_energy = pairprod->
get_eloss() * eV;
388 if (m_print_listing) {
393 m_necessary_energy -= eloss_left;
394 if (m_print_listing)
Iprintnf(
mcout, m_necessary_energy / eV);
399 Ifile <<
"HeedDeltaElectron (l=" << l
400 <<
"): particle_number=" << m_particle_number <<
"\n";
403 Ifile <<
"s_low_mult_scattering=" << s_low_mult_scattering
404 <<
" s_high_mult_scattering=" << s_high_mult_scattering <<
'\n';
405 Ifile <<
"phys_mrange=" << m_phys_mrange <<
" stop_eloss=" << m_stop_eloss
406 <<
" mult_low_path_length=" << m_mult_low_path_length <<
'\n';
407 Ifile <<
"q_low_path_length=" << m_q_low_path_length
408 <<
" path_length=" << m_path_length
409 <<
" necessary_energy/eV=" << m_necessary_energy / eV <<
'\n';
#define check_econd21(a, sign1_b1_sign0, sign2_b2, stream)
#define check_econd11(a, signb, 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)
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 .
DoubleAc acos(const DoubleAc &f)
long pois(const double amu)
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)