Garfield++ 4.0
A toolkit for the detailed simulation of particle detectors based on ionisation measurement in gases and semiconductors
Loading...
Searching...
No Matches
HeedDeltaElectronCS.cpp
Go to the documentation of this file.
1#include <iomanip>
8
9// 2003, I. Smirnov
10
11namespace Heed {
12
13using CLHEP::twopi;
14using CLHEP::degree;
15using CLHEP::electron_mass_c2;
16using CLHEP::eV;
17using CLHEP::MeV;
18using CLHEP::cm;
19using CLHEP::cm3;
20using CLHEP::gram;
21using CLHEP::mole;
22using CLHEP::Avogadro;
23
25 ElElasticScat* fees,
27 PairProd* fpairprod, int fsruth,
28 double fmlambda, double fmthetac)
29 : hmd(fhmd),
30 ees(fees),
31 eesls(feesls),
32 pairprod(fpairprod),
33 mlambda(fmlambda),
34 sruth(fsruth),
35 mthetac(fmthetac) {
36 mfunname("HeedDeltaElectronCS::HeedDeltaElectronCS(...)");
37
38 const long qe = hmd->energy_mesh->get_q();
39 eLoss.resize(qe, 0.);
40 beta.resize(qe, 0.);
41 momentum.resize(qe, 0.);
42 std::vector<double> beta2(qe, 0.);
43 std::vector<double> momentum2(qe, 0.);
44
45 const double rho = hmd->matter->density();
46 const double zmean = hmd->matter->Z_mean();
47 const double amean = hmd->matter->A_mean();
48 const double ZA = zmean / amean;
49 const double I_eff = 15.8 * eV * zmean;
50 double smax = 0.0;
51 for (long ne = 0; ne < qe; ne++) {
52 const double ec = hmd->energy_mesh->get_ec(ne) * MeV;
53 const double gamma_1 = ec / electron_mass_c2;
54 beta[ne] = lorbeta(gamma_1);
55 beta2[ne] = beta[ne] * beta[ne];
56 const double en = electron_mass_c2 + ec;
57 momentum2[ne] =
58 (en * en - electron_mass_c2 * electron_mass_c2) / (MeV * MeV);
59 momentum[ne] = sqrt(momentum2[ne]);
60 const double dedx = e_cont_enloss(ZA, I_eff, rho, ec, DBL_MAX, -1);
61 if (smax < dedx) smax = dedx;
62 eLoss[ne] = dedx / (MeV / cm);
63 }
64 smax = smax / (MeV / cm);
65 // looking for minimal (maximal by value but negative) derivative
66 double deriv_min = 0.0;
67 long n_deriv_min = 0;
68 for (long ne = 1; ne < qe; ne++) {
69 double d =
70 (eLoss[ne] * beta[ne] - eLoss[ne - 1] * beta[ne - 1]) /
71 (hmd->energy_mesh->get_ec(ne) - hmd->energy_mesh->get_ec(ne - 1));
72 if (deriv_min > d) {
73 deriv_min = d;
74 n_deriv_min = ne - 1;
75 }
76 }
77 for (long ne = 0; ne < n_deriv_min - 1; ne++) {
78 eLoss[ne] = (eLoss[n_deriv_min - 1] * beta[n_deriv_min - 1] +
79 deriv_min * (hmd->energy_mesh->get_ec(ne) -
80 hmd->energy_mesh->get_ec(n_deriv_min - 1))) /
81 beta[ne];
82 }
83
84 lambda.resize(qe);
85 if (sruth == 2) {
87 angular_mesh_c[0] = 0.0;
88 const double amin = 0.3;
89 const double amax = 180.0;
90 const double rk = pow(amax / amin, (1.0 / (q_angular_mesh - 2.)));
91 double ar = amin;
92 angular_mesh_c[1] = ar;
93 for (long n = 2; n < q_angular_mesh; n++) {
94 angular_mesh_c[n] = angular_mesh_c[n - 1] * rk;
95 }
96 angular_mesh_c[q_angular_mesh - 1] = 180.0;
97 angular_points_ran.resize(qe);
98 low_angular_points_ran.resize(qe);
99 low_lambda.resize(qe);
100 const long qes = eesls->get_ees()->get_qe();
101#ifdef USE_MEAN_COEF
102 mean_coef_low_sigma.resize(qes);
103#else
104 coef_low_sigma.resize(qes);
105#endif
106 for (long ne = 0; ne < qes; ne++) {
107 long qat = hmd->matter->qatom();
108 double s = 0.0;
109 for (long nat = 0; nat < qat; nat++) {
110#ifdef USE_MEAN_COEF
111 s += eesls->get_mean_coef(hmd->matter->atom(nat)->Z(), ne) *
112 hmd->matter->weight_quan(nat);
113#else
114 s += eesls->get_coef(hmd->matter->atom(nat)->Z(), ne) *
115 hmd->matter->weight_quan(nat);
116#endif
117 }
118#ifdef USE_MEAN_COEF
119 mean_coef_low_sigma[ne] = s;
120#else
121 coef_low_sigma[ne] = s;
122#endif
123 }
124 }
125
126 for (long ne = 0; ne < qe; ne++) {
127 double rr;
128 double ek = hmd->energy_mesh->get_ec(ne) * 1000.0;
129 if (ek <= 10.0) {
130 rr = 1.0e-3 * amean / (gram / mole) / zmean * 3.872e-3 * pow(ek, 1.492);
131 } else {
132 rr = 1.0e-3 * 6.97e-3 * pow(ek, 1.6);
133 }
134 rr = rr / (rho / (gram / cm3));
135 rr = rr * 0.1;
136 // Iprintn(mcout, rr);
137 double cor = 1.0;
138 {
139 // b-k*(x-a)**2 = 0 => x= a +- sqrt(b/k)
140 // k = b / (x - a)**2
141 double a = 2.5;
142 double b = 4;
143 // k=1.0/4.0
144 double x = 0.0;
145 double k = b / ((x - a) * (x - a));
146 x = ek * 1000.0;
147 double r = b - k * (x - a) * (x - a);
148 if (r < 0.0)
149 r = 1;
150 else
151 r = r + 1;
152 cor = r;
153 }
154 if (sruth == 1) {
155 lambda[ne] = mlambda / (rho / (gram / cm3));
156 if (lambda[ne] < rr) lambda[ne] = rr;
157 lambda[ne] = lambda[ne] * cor;
158 // Calculate the minimum angle for restriction of field by atomic shell
159 double mT = 2.0 * asin(1.0 / (2.0 * momentum[ne] * zmean * 5.07e2));
160 // Throw out too slow interactions. They do not have any influence.
161 if (mT < mthetac) mT = mthetac;
162 // Calculate the cut angle due to mean free part
163 double A = hmd->Rutherford_const / cor / (momentum2[ne] * beta2[ne]) /
164 pow(5.07e10, 2);
165 double B = lambda[ne] * A;
166 B = sqrt(B / (B + 1.0));
167 // Threshold turn angle
168 double thetac = 2.0 * asin(B);
169
170 // If it too little, reset it. It will lead to increasing
171 // of lambda and decreasing of calculation time.
172 if (thetac < mT) {
173 thetac = mT;
174 B = mT; // B is double precision
175 double r = sin(0.5 * B);
176 lambda[ne] = 1 / A * 2.0 * r * r / (1 + cos(B));
177 // r=cos(TetacBdel(nen,nm))
178 // lamBdel=A*(1.0+r)/(1.0-r)
179 // lamBdel=1.0/lamBdel
180 // lamBdel=(p2*bet2*sin(TetacBdel/2.0)**2) / A
181 }
182 // const double CosThetac12 = cos(0.5 * thetac);
183 // const dobule SinThetac12 = sin(0.5 * thetac);
184 // Flag that scattering is spherical.
185 // const bool sisfera = thetac > 1.5 ? true : false;
186 } else if (sruth == 0) {
187 // Gauss formula
188 const double msig = sqrt(2.0) * 13.6 / (beta[ne] * momentum[ne]);
189 double x = mthetac / msig;
190 x = x * x;
191 x = x * hmd->radiation_length * cor;
192 lambda[ne] = mlambda / (rho / (gram / cm3));
193 if (lambda[ne] < rr) lambda[ne] = rr;
194 lambda[ne] = lambda[ne] * cor;
195 if (lambda[ne] < x) lambda[ne] = x;
196 } else if (sruth == 2) {
197 // Cross section for material per one av. atom, in cm^2/rad.
198 std::vector<double> smat(q_angular_mesh, 0.);
199 const double energy = hmd->energy_mesh->get_ec(ne);
200 const long qat = hmd->matter->qatom();
201 for (long nan = 0; nan < q_angular_mesh; nan++) {
202 const double angle = angular_mesh_c[nan] * degree;
203 double s = 0.0;
204 for (long nat = 0; nat < qat; nat++) {
205 const int z = hmd->matter->atom(nat)->Z();
206 const double w = hmd->matter->weight_quan(nat);
207 s += ees->get_CS(z, energy, angle) * w;
208 }
209 s = s * 1.0E-16;
210 // s = s * 1.0E-16 * C1_MEV_CM * C1_MEV_CM;
211 // Angstrem**2 -> cm**2
212 // cm**2 -> MeV**-2
213 smat[nan] = s * twopi * sin(angle); // sr -> dtheta
214 }
219 const double coef =
220 Avogadro * rho / (gram / cm3) / (amean / (gram / mole));
221 lambda[ne] =
222 1. / (angular_points_ran[ne].get_integ_active() * degree * coef);
223 low_lambda[ne] =
224 1. / (low_angular_points_ran[ne].get_integ_active() * degree * coef);
225 }
226 }
227}
228
229double HeedDeltaElectronCS::get_sigma(double energy, double nscat) const {
230 mfunname("double HeedDeltaElectronCS::get_sigma(...)");
231 check_econd11(nscat, < 0, mcerr);
232 // check_econd21(nscat , < 0 || , > eesls->get_qscat() , mcerr);
233 // ^ not compatible with Poisson
234 const long qe = ees->get_qe();
235 double energyKeV = energy * 1000.0;
236 energyKeV = std::max(energyKeV, ees->get_energy_mesh(0));
237 energyKeV = std::min(energyKeV, ees->get_energy_mesh(qe - 1));
238 long n1 = 0;
239 long n2 = qe - 1;
240 while (n2 - n1 > 1) {
241 const long n3 = n1 + (n2 - n1) / 2;
242 if (energyKeV < ees->get_energy_mesh(n3))
243 n2 = n3;
244 else
245 n1 = n3;
246 }
247 const double e1 = ees->get_energy_mesh(n1);
248 const double e2 = ees->get_energy_mesh(n2);
249#ifdef USE_MEAN_COEF
250 const double v1 = nscat * mean_coef_low_sigma[n1];
251 const double v2 = nscat * mean_coef_low_sigma[n2];
252#else
253 const double v1 = nscat * coef_low_sigma[n1];
254 const double v2 = nscat * coef_low_sigma[n2];
255#endif
256 return v1 + (v2 - v1) / (e2 - e1) * (energyKeV - e1);
257}
258
259void HeedDeltaElectronCS::print(std::ostream& file, int l) const {
260 if (l <= 0) return;
261 Ifile << "HeedDeltaElectronCS(l=" << l << "):";
262 long qe = hmd->energy_mesh->get_q();
263 // Iprintn(mcout, qe);
264 // mcout<<std::endl;
265 Iprintn(file, mlambda);
266 Iprintn(file, mthetac);
267 Iprintn(file, sruth);
268 Ifile << " get_ec, beta, momentum, eLoss, lambda, "
269 " low_lambda:" << std::endl;
270 indn.n += 2;
271 for (long ne = 0; ne < qe; ne++) {
272 Ifile << std::setw(3) << ne << ' ' << std::setw(12)
273 << hmd->energy_mesh->get_ec(ne) << ' ' << std::setw(12) << beta[ne]
274 << ' ' << std::setw(12) << momentum[ne] << ' ' << std::setw(12)
275 << eLoss[ne] << ' ' << std::setw(12) << lambda[ne] << ' '
276 << std::setw(12) << low_lambda[ne] << '\n';
277 }
278 indn.n -= 2;
279 Ifile << "na, angular_mesh_c:" << std::endl;
280 indn.n += 2;
281 for (long na = 0; na < q_angular_mesh; na++) {
282 Ifile << na << ' ' << std::setw(12) << angular_mesh_c[na] << '\n';
283 }
284 indn.n -= 2;
285 Iprintn(file, eesls->get_ees()->get_qe());
286 indn.n += 2;
287#ifdef USE_MEAN_COEF
288 Ifile << "ne, energy_mesh(ne), mean_coef_low_sigma:" << std::endl;
289 for (long ne = 0; ne < eesls->get_ees()->get_qe(); ne++) {
290 Ifile << std::setw(3) << ne << ' ' << std::setw(12)
291 << eesls->get_ees()->get_energy_mesh(ne) << " KeV " << std::setw(12)
292 << mean_coef_low_sigma[ne] << '\n';
293 }
294#else
295 Ifile << "ne, energy_mesh(ne), coef_low_sigma:" << std::endl;
296 for (long ne = 0; ne < eesls->get_ees()->get_qe(); ne++) {
297 Ifile << std::setw(3) << ne << ' ' << std::setw(12)
298 << eesls->get_ees()->get_energy_mesh(ne) << " KeV " << std::setw(12)
299 << coef_low_sigma[ne] << '\n';
300 }
301#endif
302 indn.n -= 2;
303}
304}
#define check_econd11(a, signb, stream)
Definition: FunNameStack.h:155
#define mfunname(string)
Definition: FunNameStack.h:45
const std::vector< double > & weight_quan() const
Definition: AtomDef.h:136
long qatom() const
Definition: AtomDef.h:133
double Z_mean() const
Definition: AtomDef.h:140
const std::vector< AtomDef * > & atom() const
Definition: AtomDef.h:134
double A_mean() const
Definition: AtomDef.h:141
ElElasticScat * get_ees() const
Definition: ElElasticScat.h:83
double get_coef(const long Z, const long ne) const
Definition: ElElasticScat.h:81
double get_mean_coef(const long Z, const long ne) const
Definition: ElElasticScat.h:78
double get_CS(long Z, double energy, double angle, int s_interp=0)
double get_energy_mesh(long ne) const
Definition: ElElasticScat.h:54
long get_qe(void) const
Definition: ElElasticScat.h:53
long get_q() const
Return number of bins.
Definition: EnergyMesh.h:42
double get_ec(long n) const
Return center of a given bin.
Definition: EnergyMesh.h:50
void print(std::ostream &file, int l) const
double get_sigma(double energy, double nscat) const
std::vector< PointsRan > low_angular_points_ran
ElElasticScatLowSigma * eesls
HeedDeltaElectronCS()
Default constructor.
std::vector< double > beta
Table of velocities.
static constexpr long q_angular_mesh
static constexpr double low_cut_angle_deg
std::vector< double > momentum
Table of momenta [MeV/c].
std::vector< double > eLoss
std::vector< double > angular_mesh_c
Angular mesh, centers, angles in degrees.
std::vector< double > lambda
std::vector< PointsRan > angular_points_ran
std::vector< double > mean_coef_low_sigma
std::vector< double > low_lambda
MatterDef * matter
Definition: HeedMatterDef.h:28
double Rutherford_const
Const for Rutherford cross section (1/cm3).
Definition: HeedMatterDef.h:36
double radiation_length
Radiation Length.
Definition: HeedMatterDef.h:35
EnergyMesh * energy_mesh
Definition: HeedMatterDef.h:39
double density() const
Definition: MatterDef.h:51
Definition: BGMesh.cpp:6
DoubleAc cos(const DoubleAc &f)
Definition: DoubleAc.cpp:432
double lorbeta(const double gamma_1)
as function of .
Definition: lorgamma.cpp:23
DoubleAc pow(const DoubleAc &f, double p)
Definition: DoubleAc.cpp:337
double e_cont_enloss(double ratio_Z_to_A, double I_eff, double density, double Ekin, double Ecut, double z)
DoubleAc sin(const DoubleAc &f)
Definition: DoubleAc.cpp:384
DoubleAc asin(const DoubleAc &f)
Definition: DoubleAc.cpp:470
indentation indn
Definition: prstream.cpp:15
DoubleAc sqrt(const DoubleAc &f)
Definition: DoubleAc.cpp:314
#define Ifile
Definition: prstream.h:195
#define mcerr
Definition: prstream.h:128
#define Iprintn(file, name)
Definition: prstream.h:204