12#define DIRECT_LOW_IF_LITTLE
19 return std::min(std::max(n, 0L), emesh->
get_q() - 2);
31using CLHEP::c_squared;
33bool HeedDeltaElectron::s_low_mult_scattering =
true;
34bool HeedDeltaElectron::s_high_mult_scattering =
true;
38 long fparent_particle_number,
40 bool fs_print_listing)
42 parent_particle_number(fparent_particle_number),
44 s_print_listing(fs_print_listing),
47 s_mult_low_path_length(false),
48 q_low_path_length(0.0),
50 necessary_energy(0.0),
52 mfunname(
"HeedDeltaElectron::HeedDeltaElectron(...)");
56 mfunname(
"void HeedDeltaElectron::physics_mrange(double& fmrange)");
57 if (s_print_listing)
mcout <<
"void HeedDeltaElectron::physics_mrange\n";
59 s_mult_low_path_length =
false;
60 q_low_path_length = 0.0;
61 s_path_length =
false;
62 if (fmrange <= 0.0)
return;
75 const long n1 = findInterval(emesh, ek);
76 const double e1 = emesh->
get_ec(n1);
77 const double e2 = emesh->
get_ec(n1 + 1);
78 const double loss1 = hdecs->
eLoss[n1];
79 const double loss2 = hdecs->
eLoss[n1 + 1];
80 double dedx = loss1 + (loss2 - loss1) / (e2 - e1) * (ek - e1);
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 const long n1r = findInterval(emesh, ek_restr);
95 double low_path_length = 0.;
96 if (s_low_mult_scattering) {
97 const double e1r = emesh->
get_ec(n1r);
98 const double e2r = emesh->
get_ec(n1r + 1);
101 low_path_length = (y1 + (y2 - y1) / (e2r - e1r) * (ek_restr - e1r)) * cm;
103 long qscat = hdecs->
eesls->get_qscat();
104 const double sigma_ctheta = hdecs->
get_sigma(ek_restr, qscat);
106 if (sigma_ctheta > 0.3) qscat = long(qscat * 0.3 / sigma_ctheta);
107 double mult_low_path_length = qscat * low_path_length;
109 if (fmrange > mult_low_path_length) {
110 fmrange = mult_low_path_length;
111 s_mult_low_path_length =
true;
112 q_low_path_length = hdecs->
eesls->get_qscat();
113 s_stop_eloss =
false;
115 s_mult_low_path_length =
false;
116 q_low_path_length = fmrange / low_path_length;
118 if (s_print_listing)
Iprint2nf(
mcout, fmrange, q_low_path_length);
121 if (s_high_mult_scattering) {
122 const double e1r = emesh->
get_ec(n1r);
123 const double e2r = emesh->
get_ec(n1r + 1);
124 if (s_print_listing) {
130 const double y1 = hdecs->
lambda[n1r];
131 const double y2 = hdecs->
lambda[n1r + 1];
132 const double mean_path = y1 + (y2 - y1) / (e2r - e1r) * (ek_restr - e1r);
134 const double path_length = -mean_path * cm * log(1.0 - SRANLUX());
136 if (fmrange > path_length) {
137 fmrange = path_length;
138 s_path_length =
true;
139 s_mult_low_path_length =
true;
140 if (s_low_mult_scattering) {
141 q_low_path_length = fmrange / low_path_length;
144 s_stop_eloss =
false;
146 s_path_length =
false;
150 phys_mrange = fmrange;
154 std::vector<gparticle*>& ) {
155 mfunname(
"void HeedDeltaElectron::physics_after_new_speed()");
156 if (s_print_listing) {
157 mcout <<
"HeedDeltaElectron::physics_after_new_speed is started\n";
166 if (s_print_listing) {
167 mcout <<
"HeedDeltaElectron::physics_after_new_speed: \n";
168 mcout <<
"This is converted to conduction\n";
176 if (s_print_listing)
mcout <<
"exit due to currpos.prange <= 0.0\n";
179 if (s_print_listing)
mcout <<
"physics_after_new_speed: started" << std::endl;
186 if (s_print_listing) {
199 const long n1 = findInterval(emesh, ek);
201 const double e1 = emesh->
get_ec(n1);
202 const double e2 = emesh->
get_ec(n1 + 1);
203 const double y1 = hdecs->
eLoss[n1];
204 const double y2 = hdecs->
eLoss[n1 + 1];
205 dedx = y1 + (y2 - y1) / (e2 - e1) * (ek - e1);
207 total_Eloss += Eloss;
213 if (s_print_listing)
mcout <<
"curr_kin_energy <= 0.0\n";
219 const double resten =
mass * c_squared;
225 if (s_print_listing) {
226 mcout <<
"volume is sensitive\n";
229 if (Eloss > 0.0) ionisation(Eloss, dedx, hdecs->
pairprod.get());
231 if (s_print_listing) {
239 if (s_print_listing)
mcout <<
"Last conduction electron\n";
246 if (s_print_listing)
mcout <<
"\nstart to rotate by low angle\n";
247 double ek_restr = std::max(ek, 0.0005);
251 s_path_length =
false;
252 if (s_low_mult_scattering) {
254 const long n1r = findInterval(emesh, ek_restr);
255 const double e1 = emesh->
get_ec(n1r);
256 const double e2 = emesh->
get_ec(n1r + 1);
260 double low_path_length =
261 (y1 + (y2 - y1) / (e2 - e1) * (ek_restr - e1)) * cm;
263 s_mult_low_path_length =
false;
270 if (q_low_path_length > 0.0) {
272 long random_q_low_path_length =
pois(q_low_path_length, ierror);
274 " q_low_path_length=" << q_low_path_length <<
'\n',
mcerr);
275 q_low_path_length = long(random_q_low_path_length);
276 if (s_print_listing) {
277 mcout <<
"After pois:\n";
282 if (q_low_path_length > 0) {
283#ifdef DIRECT_LOW_IF_LITTLE
284 const long max_q_low_path_length_for_direct = 5;
285 if (q_low_path_length < max_q_low_path_length_for_direct) {
287 if (s_print_listing) {
288 mcout <<
"direct modeling of low scatterings\n";
292 const long n1r = findInterval(emesh, ek_restr);
293 for (
long nscat = 0; nscat < q_low_path_length; ++nscat) {
299 basis temp(dir,
"temp");
302 vturn = vturn *
sin(theta_rot);
303 vec new_dir(vturn.
x, vturn.
y,
cos(theta_rot));
312 double sigma_ctheta = hdecs->
get_sigma(ek_restr, q_low_path_length);
324 double sq2 =
sqrt(2.0);
333 double x = sigma_ctheta * (-log(1.0 - y));
335 double x = sigma_ctheta * 1.0 / sq2 * (-log(1.0 - y));
339 }
while (ctheta <= -1.0);
343 double theta_rot =
acos(ctheta);
344 if (s_print_listing)
Iprint2nf(
mcout, theta_rot, theta_rot / degree);
346 basis temp(dir,
"temp");
349 vturn = vturn *
sin(theta_rot);
350 vec new_dir(vturn.
x, vturn.
y,
cos(theta_rot));
356#ifdef DIRECT_LOW_IF_LITTLE
360 if (s_print_listing) {
361 mcout <<
"\nstarting to rotate by large angle" << std::endl;
365 const long n1r = findInterval(emesh, ek_restr);
369 basis temp(dir,
"temp");
372 vturn = vturn *
sin(theta_rot);
373 vec new_dir(vturn.
x, vturn.
y,
cos(theta_rot));
382void HeedDeltaElectron::ionisation(
const double eloss,
const double dedx,
385 if (eloss < necessary_energy) {
386 necessary_energy -= eloss;
390 if (s_print_listing)
mcout <<
"\nstart to leave conduction electrons\n";
391 if (necessary_energy <= 0.0) {
395 necessary_energy = pairprod->
get_eloss() * eV;
399 double eloss_left = eloss;
404 while (eloss_left >= necessary_energy) {
405 const double step_length = necessary_energy / (dedx * MeV / cm);
407 curpt = curpt + dir * step_length;
411 if (s_print_listing)
mcout <<
"New conduction electron\n";
417 eloss_left -= necessary_energy;
418 ekin -= necessary_energy;
421 necessary_energy = eV * pairprod->
get_eloss(ekin / eV);
423 necessary_energy = pairprod->
get_eloss() * eV;
425 if (s_print_listing) {
430 necessary_energy -= eloss_left;
436 Ifile <<
"HeedDeltaElectron (l=" << l
437 <<
"): particle_number=" << particle_number <<
"\n";
440 Ifile <<
"s_low_mult_scattering=" << s_low_mult_scattering
441 <<
" s_high_mult_scattering=" << s_high_mult_scattering <<
'\n';
442 Ifile <<
"phys_mrange=" << phys_mrange <<
" s_stop_eloss=" << s_stop_eloss
443 <<
" s_mult_low_path_length=" << s_mult_low_path_length <<
'\n';
444 Ifile <<
"q_low_path_length=" << q_low_path_length
445 <<
" s_path_length=" << s_path_length
446 <<
" necessary_energy/eV=" << 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
double get_sigma(double energy, double nscat) const
PassivePtr< HeedMatterDef > hmd
std::vector< PointsRan > low_angular_points_ran
PassivePtr< PairProd > pairprod
std::vector< double > eLoss
std::vector< double > lambda
std::vector< PointsRan > angular_points_ran
PassivePtr< ElElasticScatLowSigma > eesls
std::vector< double > low_lambda
std::vector< HeedCondElectron > conduction_electrons
std::vector< HeedCondElectron > conduction_ions
virtual void physics_mrange(double &fmrange)
long parent_particle_number
virtual void print(std::ostream &file, int l) const
HeedDeltaElectron()
Default constructor.
virtual void physics_after_new_speed(std::vector< gparticle * > &secondaries)
Retrieve electric and magnetic field from Sensor.
bool inside(const point &pt)
double get_eloss() const
Calculate energy loss (in eV).
HeedFieldMap * m_fieldMap
void up_absref(absref *f)
absvol * G_lavol() const
Get last address of volume.
Abstract base classs for volume "manipulators".
double mass
Mass (not mass * speed_of_light^2)
virtual void print(std::ostream &file, int l) const
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)