Garfield++ 5.0
A toolkit for the detailed simulation of particle detectors based on ionisation measurement in gases and semiconductors
Loading...
Searching...
No Matches
HeedMatterDef.cpp
Go to the documentation of this file.
1#include <fstream>
2#include <iomanip>
6
7// 2003, I. Smirnov
8
9namespace Heed {
10
11using CLHEP::pi;
12using CLHEP::mole;
13using CLHEP::gram;
14using CLHEP::cm3;
15using CLHEP::electron_mass_c2;
16using CLHEP::fine_structure_const;
17using CLHEP::Avogadro;
18
20 const std::vector<AtomPhotoAbsCS*>& faapacs,
21 double fW, double fF)
22 : matter(amatter), W(fW), F(fF), energy_mesh(fenergy_mesh) {
23 mfunname("HeedMatterDef::HeedMatterDef(...)");
24 check_econd11(matter, == nullptr, mcerr);
25 check_econd11(matter->qatom(), <= 0, mcerr);
26 const long q = matter->qatom();
27 apacs.resize(q, nullptr);
28 for (long n = 0; n < q; ++n) {
29 apacs[n] = faapacs[n];
30 check_econd12(matter->atom(n)->Z(), !=, apacs[n]->get_Z(), mcerr);
31 }
32 check_econd11(F, == 0.0, mcerr);
33 if (W == 0.0) {
34#ifdef CALC_W_USING_CHARGES
35 double mean_I = 0.0;
36 double d = 0.0;
37 for (long n = 0; n < q; ++n) {
38 const double w = matter->weight_quan(n) * apacs[n]->get_Z();
39 mean_I += w * apacs[n]->get_I_min();
40 d += w;
41 }
42 W = coef_I_to_W * mean_I / d;
43#else
44 double mean_I = 0.0;
45 for (long n = 0; n < q; ++n) {
46 mean_I += matter->weight_quan(n) * apacs[n]->get_I_min();
47 }
48 W = coef_I_to_W * mean_I;
49#endif
50 }
51 initialize();
52}
53
55 std::vector<MolecPhotoAbsCS>& fampacs,
56 double fW, double fF)
57 : matter(agas), W(fW), F(fF), energy_mesh(fenergy_mesh) {
58 mfunname("HeedMatterDef::HeedMatterDef(...)");
59 check_econd11(agas, == nullptr, mcerr);
60 check_econd11(agas->qmolec(), <= 0, mcerr);
61 const long qat = agas->qatom();
62 apacs.resize(qat, nullptr);
63 const long qmol = agas->qmolec();
64 long nat = 0;
65 for (long nmol = 0; nmol < qmol; ++nmol) {
66 check_econd12(agas->molec(nmol)->tqatom(), !=, fampacs[nmol].get_qatom(),
67 mcerr);
68 // number of different atoms in molecule
69 const long qa = agas->molec(nmol)->qatom();
70 for (long na = 0; na < qa; ++na) {
71 apacs[nat] = fampacs[nmol].get_atom(na);
72 check_econd12(apacs[nat]->get_Z(), !=, agas->molec(nmol)->atom(na)->Z(),
73 mcerr);
74 nat++;
75 }
76 }
77 if (F == 0.0) {
78#ifdef CALC_W_USING_CHARGES
79 double u = 0.0;
80 double d = 0.0;
81 for (long n = 0; n < qmol; ++n) {
82 const double w = agas->weight_quan_molec(n) * fampacs[n].get_total_Z();
83 u += w * fampacs[n].get_F();
84 d += w;
85 }
86 F = u / d;
87#else
88 for (long n = 0; n < qmol; ++n) {
89 F += agas->weight_quan_molec(n) * fampacs[n].get_F();
90 }
91#endif
92 }
93
94 if (W == 0.0) {
95#ifdef CALC_W_USING_CHARGES
96 double u = 0.0;
97 double d = 0.0;
98 for (long n = 0; n < qmol; ++n) {
99 const double w = agas->weight_quan_molec(n) * fampacs[n].get_total_Z();
100 u += w * fampacs[n].get_W();
101 d += w;
102 }
103 W = u / d;
104#else
105 for (long n = 0; n < qmol; ++n) {
106 W += agas->weight_quan_molec(n) * fampacs[n].get_W();
107 }
108#endif
109 }
110 initialize();
111}
112
113void HeedMatterDef::initialize() {
114 mfunname("void HeedMatterDef::initialize()");
115 const double amean = matter->A_mean() / (gram / mole);
116 const double rho = matter->density() / (gram / cm3);
117 eldens_cm_3 = matter->Z_mean() / amean * Avogadro * rho;
120 wpla = eldens * 4. * pi * fine_structure_const / electron_mass_c2;
121 radiation_length = 0.0;
122 double rms = 0.0;
123 long qat = matter->qatom();
124 for (long n = 0; n < qat; ++n) {
125 rms += matter->atom(n)->A() * matter->weight_quan(n);
126 }
127 rms = rms / (gram / mole);
128
129 std::vector<double> RLenAt(qat);
130 std::vector<double> RuthAt(qat);
131 for (long n = 0; n < qat; ++n) {
132 const int z = matter->atom(n)->Z();
133 RLenAt[n] = 716.4 * matter->atom(n)->A() / (gram / mole) /
134 (z * (z + 1) * log(287. / sqrt(double(z))));
135 RuthAt[n] = 4. * pi * z * z * fine_structure_const * fine_structure_const;
136 }
137 std::vector<double> rm(qat);
138 for (long n = 0; n < qat; ++n) {
139 rm[n] = matter->atom(n)->A() / (gram / mole) * matter->weight_quan(n) / rms;
140 }
141 for (long n = 0; n < qat; ++n) {
142 radiation_length += rm[n] / RLenAt[n];
143 }
144 radiation_length = 1. / (rho * radiation_length);
145
146 Rutherford_const = 0.0;
147 for (long n = 0; n < qat; ++n) {
148 Rutherford_const += matter->weight_quan(n) * RuthAt[n];
149 }
150 Rutherford_const *= rho * Avogadro / amean;
151
152 min_ioniz_pot = DBL_MAX;
153 for (long n = 0; n < qat; ++n) {
154 if (min_ioniz_pot > apacs[n]->get_I_min()) {
155 min_ioniz_pot = apacs[n]->get_I_min();
156 }
157 }
158 long qe = energy_mesh->get_q();
159 ACS.resize(qe);
160 ICS.resize(qe);
161 epsip.resize(qe);
162 epsi1.resize(qe);
163 epsi2.resize(qe);
164 for (long ne = 0; ne < qe; ++ne) {
165 double e1 = energy_mesh->get_e(ne);
166 double e2 = energy_mesh->get_e(ne + 1);
167 double sa = 0.0;
168 double si = 0.0;
169 for (int na = 0; na < qat; ++na) {
170 const double ta = apacs[na]->get_integral_ACS(e1, e2);
171 sa += matter->weight_quan(na) * ta / (e2 - e1);
172 check_econd11a(ta, < 0, "ACS: ne=" << ne << " e1=" << e1 << " e2=" << e2
173 << " na=" << na << '\n',
174 mcerr);
175 const double ti =
177 ? apacs[na]->get_integral_TICS(e1, e2, min_ioniz_pot)
178 : apacs[na]->get_integral_ICS(e1, e2);
179 si += matter->weight_quan(na) * ti / (e2 - e1);
180 check_econd11a(ti, < 0, "ICS: ne=" << ne << " e1=" << e1 << " e2=" << e2
181 << " na=" << na << '\n',
182 mcerr);
183 }
184 ACS[ne] = sa;
185 check_econd11a(ACS[ne], < 0, "ne=" << ne << '\n', mcerr);
186 ICS[ne] = si;
187 check_econd11a(ICS[ne], < 0, "ne=" << ne << '\n', mcerr);
188
189 double ec = energy_mesh->get_ec(ne);
190 double ec2 = ec * ec;
191 epsip[ne] = -wpla / ec2;
192 epsi2[ne] = sa * C1_MEV2_MBN / ec * eldens / matter->Z_mean();
193 }
194
195 // To do next loop we need all epsi2
196 for (long ne = 0; ne < qe; ++ne) {
197 double ec = energy_mesh->get_ec(ne);
198 double ec2 = ec * ec;
199 double s = 0;
200 // integration of energy
201 for (long m = 0; m < qe; ++m) {
202 double em1 = energy_mesh->get_e(m);
203 double em2 = energy_mesh->get_e(m + 1);
204 double ecm = energy_mesh->get_ec(m);
205 if (m != ne) {
206 s += epsi2[m] * ecm * (em2 - em1) / (ecm * ecm - ec2);
207 } else {
208 double ee1 = 0.5 * (em1 + ecm);
209 double ee2 = 0.5 * (em2 + ecm);
210 double ep1, ep2; // extrapolated values to points ee1 and ee2
211 if (m == 0) {
212 ep1 = epsi2[m] + (ee1 - ecm) * (epsi2[m + 1] - epsi2[m]) /
213 (energy_mesh->get_ec(m + 1) - ecm);
214 } else {
215 ep1 = epsi2[m - 1] + (ee1 - energy_mesh->get_ec(m - 1)) *
216 (epsi2[m] - epsi2[m - 1]) /
217 (ecm - energy_mesh->get_ec(m - 1));
218 }
219 if (m < qe - 1) {
220 ep2 = epsi2[m] + (ee2 - ecm) * (epsi2[m + 1] - epsi2[m]) /
221 (energy_mesh->get_ec(m + 1) - ecm);
222 } else {
223 ep2 = epsi2[m] + (ee2 - ecm) * (epsi2[m] - epsi2[m - 1]) /
224 (ecm - energy_mesh->get_ec(m - 1));
225 }
226 s = s + ep1 * ee1 * (ecm - em1) / (ee1 * ee1 - ec2);
227 s = s + ep2 * ee2 * (em2 - ecm) / (ee2 * ee2 - ec2);
228 }
229 }
230 epsi1[ne] = (2. / pi) * s;
231 }
232}
233
234void HeedMatterDef::replace_epsi12(const std::string& file_name) {
235 mfunnamep("void HeedMatterDef::replace_epsi12(const std::string& file_name)");
236
237 std::ifstream file(file_name.c_str());
238 if (!file) {
239 funnw.ehdr(mcerr);
240 mcerr << "cannot open file " << file_name << std::endl;
241 spexit(mcerr);
242 } else {
243 mcout << "file " << file_name << " is opened" << std::endl;
244 }
245 long qe = 0; // number of points in input mesh
246 file >> qe;
247 check_econd11(qe, <= 2, mcerr);
248
249 std::vector<double> ener(qe);
250 std::vector<double> eps1(qe);
251 std::vector<double> eps2(qe);
252
253 for (long ne = 0; ne < qe; ++ne) {
254 file >> ener[ne] >> eps1[ne] >> eps2[ne];
255 check_econd11(eps2[ne], < 0.0, mcerr);
256 if (ne > 0) {
257 check_econd12(ener[ne], <, ener[ne - 1], mcerr);
258 }
259 }
260
262 double emin = ener[0] - 0.5 * (ener[1] - ener[0]);
263 double emax = ener[qe - 1] + 0.5 * (ener[qe - 1] - ener[qe - 2]);
264
265 qe = energy_mesh->get_q();
268 for (long ne = 0; ne < qe; ++ne) {
269 double ec = energy_mesh->get_ec(ne);
270 // pcmd: dimension q; eps1, eps2: dimension q - 1.
271 epsi1[ne] = interpolate(pcmd, eps1, ec, 0, 1, emin, 1, emax);
272 epsi2[ne] = interpolate(pcmd, eps2, ec, 1, 1, emin, 1, emax);
273 // Iprint3n(mcout, ec, epsi1[ne], epsi2[ne]);
274 }
275}
276
277void HeedMatterDef::print(std::ostream& file, int l) const {
278 if (l <= 0) return;
279 Ifile << "HeedMatterDef:\n";
280 indn.n += 2;
281 matter->print(file, 1);
282 if (l >= 2) {
283 long q = matter->qatom();
284 Ifile << "Printing " << q << " photoabsorption cross sections:\n";
285 indn.n += 2;
286 for (long n = 0; n < q; ++n) {
287 apacs[n]->print(file, l - 1);
288 }
289 indn.n -= 2;
290 }
291 Iprintan(file, eldens_cm_3, "1/cm^3");
292 Iprintan(file, eldens, "MeV^3");
293 Iprintan(file, xeldens, "MeV^2/cm");
294 Iprintn(file, wpla);
296 Iprintan(file, Rutherford_const, "1/cm^3");
297 Iprintn(file, W);
298 Iprintn(file, F);
299 Iprintn(file, min_ioniz_pot);
300 Iprintn(file, energy_mesh->get_q());
301 if (l >= 2) {
302 long qe = energy_mesh->get_q();
303 long ne;
304 indn.n += 2;
305 Ifile << " ne energy ACS(Mb) ICS(Mb) ACS(1/MeV^2) "
306 "ICS(1/MeV^2) epsip epsi1 epsi2 "
307 "(1+epsi1)^2+epsi2^2\n";
308 for (ne = 0; ne < qe; ne++) {
309 Ifile << std::setw(3) << ne << ' ' << std::setw(12)
310 << energy_mesh->get_e(ne) << ' ' << std::setw(12) << ACS[ne] << ' '
311 << std::setw(12) << ICS[ne] << ' ' << std::setw(12)
312 << ACS[ne] * C1_MEV2_MBN << ' ' << std::setw(12)
313 << ICS[ne] * C1_MEV2_MBN << ' ' << std::setw(12) << epsip[ne] << ' '
314 << std::setw(12) << epsi1[ne] << ' ' << std::setw(12) << epsi2[ne]
315 << ' ' << std::setw(12)
316 << pow((1 + epsi1[ne]), 2) + pow(epsi2[ne], 2) << " \n";
317 }
318 indn.n -= 2;
319 }
320 indn.n -= 2;
321}
322}
#define check_econd11(a, signb, stream)
#define check_econd11a(a, signb, add, stream)
#define mfunnamep(string)
#define spexit(stream)
#define check_econd12(a, sign, b, stream)
#define mfunname(string)
const std::vector< double > & weight_quan() const
Definition AtomDef.h:104
long qatom() const
Definition AtomDef.h:101
const std::vector< const AtomDef * > & atom() const
Definition AtomDef.h:102
double Z_mean() const
Definition AtomDef.h:108
double A_mean() const
Definition AtomDef.h:109
const std::vector< const MoleculeDef * > & molec() const
Definition GasDef.h:49
long qmolec() const
Definition GasDef.h:48
const std::vector< double > & weight_quan_molec() const
Definition GasDef.h:53
double eldens
Electron density MeV**3.
double W
Mean work per pair production, MeV.
double wpla
Squared plasma energy;.
double xeldens
Long. electron density MeV**2/cm (for x=1 cm).
std::vector< const AtomPhotoAbsCS * > apacs
HeedMatterDef()=default
Default constructor.
double eldens_cm_3
Electron density cm**-3.
std::vector< double > ACS
Photoabsorption cross section per one atom(Mb).
std::vector< double > epsip
Some plasma dielectric constant (not used, but just initialized for print)
std::vector< double > epsi1
Real part of dielectric constant (e_1 - 1).
double Rutherford_const
Const for Rutherford cross section (1/cm3).
std::vector< double > ICS
std::vector< double > epsi2
Imaginary part of dielectric constant.
double F
Fano factor.
double radiation_length
Radiation Length.
void print(std::ostream &file, int l) const
EnergyMesh * energy_mesh
void replace_epsi12(const std::string &file_name)
static constexpr int s_use_mixture_thresholds
double density() const
Definition MatterDef.h:46
Definition BGMesh.cpp:6
T t_value_straight_point_ar(const M &mesh, const D &y, T x, int s_ban_neg, int s_extrap_left, T left_bond, int s_extrap_right, T right_bond)
Definition tline.h:1590
DoubleAc pow(const DoubleAc &f, double p)
Definition DoubleAc.cpp:337
constexpr double C1_MEV2_MBN
constexpr double coef_I_to_W
Definition PhotoAbsCS.h:585
constexpr double C1_MEV_CM
indentation indn
Definition prstream.cpp:15
DoubleAc sqrt(const DoubleAc &f)
Definition DoubleAc.cpp:314
#define Iprintan(file, name, addition)
Definition prstream.h:211
#define mcout
Definition prstream.h:126
#define Ifile
Definition prstream.h:195
#define mcerr
Definition prstream.h:128
#define Iprintn(file, name)
Definition prstream.h:204