Garfield++ 3.0
A toolkit for the detailed simulation of particle detectors based on ionisation measurement in gases and semiconductors
Loading...
Searching...
No Matches
ElElasticScat.cpp
Go to the documentation of this file.
1#include <fstream>
2#include <iomanip>
3#include <cmath>
4
11#include "wcpplib/matter/AtomDef.h" // to find atomic weights for histogramms
13
16
17// 2003, I. Smirnov
18
19namespace Heed {
20
21using CLHEP::electron_mass_c2;
22using CLHEP::fine_structure_const;
23
24double ElElasticScatDataStruct::CS(const double theta) const {
25 if (A[0] == -1.0) return -1.0;
26 double s = 0.0;
27 const double ctheta = cos(theta);
28 for (long n = 0; n < 4; ++n) {
29 s += A[n] / (pow(1.0 - ctheta + 2.0 * B, n + 1));
30 }
31 for (long n = 0; n < 7; ++n) {
32 s += C[n] * polleg(n, ctheta);
33 }
34 return s;
35}
36
37ElElasticScat::ElElasticScat(const std::string& file_name) : atom(0) {
38 mfunnamep("ElElasticScat::ElElasticScat(const string& filename)");
39 std::ifstream file(file_name.c_str());
40 if (!file) {
41 funnw.ehdr(mcerr);
42 mcerr << "cannot open file " << file_name << std::endl;
44 }
45 int i = findmark(file, "#");
46 check_econd11a(i, != 1, "cannot find sign #, wrong file format", mcerr);
47 file >> qe;
48 energy_mesh.resize(qe);
49 gamma_beta2.resize(qe);
50 for (long ne = 0; ne < qe; ++ne) {
51 file >> energy_mesh[ne];
52 if (!file.good()) {
53 funnw.ehdr(mcerr);
54 mcerr << "error at reading energy_mesh, ne=" << ne << '\n';
56 }
57 // energy mesh in keV
58 const double rm = 0.001 * energy_mesh[ne] / electron_mass_c2;
59 const double gamma = 1. + rm;
60 const double beta2 = (2 * rm + rm * rm) / (gamma * gamma);
61 gamma_beta2[ne] = gamma * beta2;
62 }
63 while (findmark(file, "$") == 1) {
64 long Z;
65 file >> Z;
66 check_econd21(Z, < 1 ||, > 110, mcerr);
67 atom.emplace_back(ElElasticScatData(Z, qe));
68 for (int nc = 0; nc < 4; ++nc) {
69 for (long ne = 0; ne < qe; ++ne) {
70 file >> atom.back().data[ne].A[nc];
71 if (!file.good()) {
72 funnw.ehdr(mcerr);
73 mcerr << "error at reading A, Z=" << Z << " nc=" << nc << " ne=" << ne
74 << '\n';
76 }
77 }
78 }
79 for (int nc = 0; nc < 7; ++nc) {
80 for (long ne = 0; ne < qe; ++ne) {
81 file >> atom.back().data[ne].C[nc];
82 if (!file.good()) {
83 funnw.ehdr(mcerr);
84 mcerr << "error at reading C, Z=" << Z << " nc=" << nc << " ne=" << ne
85 << '\n';
87 }
88 }
89 }
90 for (long ne = 0; ne < qe; ++ne) {
91 file >> atom.back().data[ne].B;
92 if (!file.good()) {
93 funnw.ehdr(mcerr);
94 mcerr << "error at reading B, Z=" << Z << " ne=" << ne << '\n';
96 }
97 }
98 }
99}
100
101double ElElasticScat::get_CS_for_presented_atom(long na, double energy,
102 double angle) {
103 mfunnamep(
104 "double ElElasticScat::get_CS_for_presented_atom(long na, double "
105 "energy, double angle)");
106 const double enKeV = energy * 1000.0;
107 const double rm = energy / electron_mass_c2;
108 const double gamma = 1. + rm;
109 const double beta2 = (2. * rm + rm * rm) / (gamma * gamma);
110 const double gamma_beta2_t = gamma * beta2;
111 const double coe =
112 fine_structure_const * fine_structure_const * atom[na].Z / gamma_beta2_t;
113 if (enKeV < energy_mesh[0]) {
114 double r = -1.;
115 // looking for valid data
116 for (long ne = 0; ne < qe; ne++) {
117 r = atom[na].data[ne].CS(angle);
118 if (r >= 0.0) break;
119 }
120 check_econd11(r, < 0.0, mcerr);
121 return r * coe * coe;
122 }
123 if (enKeV >= energy_mesh[qe - 1]) {
124 double r = -1.;
125 // looking for valid data
126 for (long ne = qe - 1; ne >= 0; ne--) {
127 r = atom[na].data[ne].CS(angle);
128 if (r >= 0.0) break;
129 }
130 check_econd11(r, < 0.0, mcerr);
131 return r * coe * coe;
132 }
133 long ne = 1;
134 for (ne = 1; ne < qe; ne++) {
135 if (energy_mesh[ne] > enKeV) break;
136 }
137 double cs[2] = {-1., -1.};
138 // starting points
139 long ne_left = ne - 1;
140 long ne_right = ne;
141 // looking for valid data
142 for (ne = ne_left; ne >= 0; ne--) {
143 cs[0] = atom[na].data[ne].CS(angle);
144 if (cs[0] >= 0.0) break;
145 }
146 for (ne = ne_right; ne < qe; ne++) {
147 cs[1] = atom[na].data[ne].CS(angle);
148 if (cs[1] >= 0.0) break;
149 }
150 double r = cs[0];
151 if (cs[0] >= 0.0 && cs[1] >= 0.0) {
152 r = cs[0] + (cs[1] - cs[0]) / (energy_mesh[ne] - energy_mesh[ne - 1]) *
153 (enKeV - energy_mesh[ne - 1]);
154 } else {
155 if (cs[0] >= 0.0) {
156 r = cs[0];
157 } else if (cs[1] >= 0.0) {
158 r = cs[1];
159 } else {
160 funnw.ehdr(mcerr);
161 mcerr << "not implemented case\n";
162 spexit(mcerr);
163 }
164 }
165 return r * coe * coe;
166}
167
168double ElElasticScat::get_CS(long Z, double energy, double angle,
169 int s_interp) {
170 mfunname(
171 "double ElElasticScat::get_CS(long Z, double energy, double angle, "
172 "int s_interp)");
173 const long qa = atom.size();
174 long na_left = 0;
175 long Z_left = -100;
176 long na_right = qa - 1;
177 long Z_right = 10000;
178 for (long na = 0; na < qa; na++) {
179 if (atom[na].Z == Z && s_interp == 0) {
180 return get_CS_for_presented_atom(na, energy, angle);
181 }
182 if (atom[na].Z > Z_left && atom[na].Z < Z) {
183 Z_left = atom[na].Z;
184 na_left = na;
185 } else if (atom[na].Z < Z_right && atom[na].Z > Z) {
186 Z_right = atom[na].Z;
187 na_right = na;
188 }
189 }
190 check_econd11a(Z_left, == -100, " have not found previous atom", mcerr);
191 check_econd11a(Z_right, == 10000, " have not found next atom", mcerr);
192 const double f1 = get_CS_for_presented_atom(na_left, energy, angle);
193 const double f2 = get_CS_for_presented_atom(na_right, energy, angle);
194 const double z1 = atom[na_left].Z;
195 const double z2 = atom[na_right].Z;
196 const double c = (f1 * 4 - f2 * z1 * z1) / (f2 * z1 - f1 * z2);
197 const double k = f1 / (z1 * (z1 + c));
198 double r = k * Z * (Z + c);
199 if (r < 0.0) r = 0.0;
200 return r;
201}
202
203double ElElasticScat::get_CS_Rutherford(long Z, double energy, double angle) {
204 mfunname(
205 "double ElElasticScat::get_CS_Rutherford(long Z, double energy, "
206 "double angle)");
207 const double gamma_1 = energy / electron_mass_c2;
208 const double beta2 = lorbeta2(gamma_1);
209 const double momentum2 = energy * energy + 2.0 * electron_mass_c2 * energy;
210 // TODO
211 double r = 0.25 * Z * Z * fine_structure_const * fine_structure_const /
212 (momentum2 * beta2 * pow(sin(0.5 * angle), 4)) /
213 (pow(5.07E10, 2)) * 1.0e16;
214 return r;
215}
216
217void ElElasticScat::print(std::ostream& file, int l) const {
218 if (l <= 0) return;
219 Ifile << "ElElasticScat(l=" << l << "): qe=" << qe
220 << " atom.size()=" << atom.size() << std::endl;
221 if (l <= 1) return;
222 indn.n += 2;
223 Ifile << "energy_mesh=";
224 for (long ne = 0; ne < qe; ++ne) {
225 file << std::setw(12) << energy_mesh[ne];
226 }
227 file << std::endl;
228 Ifile << "gamma_beta2=";
229 for (long ne = 0; ne < qe; ++ne) {
230 file << std::setw(12) << gamma_beta2[ne];
231 }
232 file << std::endl;
233 indn.n -= 2;
234 const long qa = atom.size();
235 for (long na = 0; na < qa; ++na) {
236 Ifile << "atom[na].Z=" << atom[na].Z << '\n';
237 Ifile << " ";
238 for (long ne = 0; ne < qe; ++ne) {
239 file << std::setw(12) << energy_mesh[ne];
240 }
241 file << std::endl;
242 for (long n = 0; n < 4; ++n) {
243 Ifile << "A[" << n << "]";
244 for (long ne = 0; ne < qe; ++ne) {
245 file << std::setw(12) << atom[na].data[ne].A[n];
246 }
247 file << std::endl;
248 }
249 for (int n = 0; n < 7; ++n) {
250 Ifile << "C[" << n << "]";
251 for (long ne = 0; ne < qe; ++ne) {
252 file << std::setw(12) << atom[na].data[ne].C[n];
253 }
254 file << std::endl;
255 }
256 Ifile << "B ";
257 for (long ne = 0; ne < qe; ++ne) {
258 file << std::setw(12) << atom[na].data[ne].B;
259 }
260 file << std::endl;
261 }
262}
263
265 const std::string& file_name)
266 : ees(fees) {
267 mfunnamep("ElElasticScatLowSigma::ElElasticScatLowSigma(...)");
268 std::ifstream file(file_name.c_str());
269 if (!file) {
270 funnw.ehdr(mcerr);
271 mcerr << "cannot open file " << file_name << std::endl;
272 spexit(mcerr);
273 }
274 int i = findmark(file, "$");
275 check_econd11(i, != 1, mcerr);
276 file >> qat >> qscat;
277 check_econd11(qat, <= 0, mcerr);
278 check_econd11(qscat, <= 0, mcerr);
279 mean_coef.resize(qat);
280 coef.resize(qat);
281 for (long nat = 0; nat < qat; ++nat) {
282 mean_coef[nat].resize(ees->get_qe());
283 coef[nat].resize(ees->get_qe());
284 long z;
285 file >> z;
286 check_econd12(z, !=, nat + 1, mcerr);
287 for (long ne = 0; ne < ees->get_qe(); ++ne) {
288 long fne;
289 double e;
290 mean_coef[nat][ne] = 0.0;
291 coef[nat][ne] = 0.0;
292 file >> fne >> e >> mean_coef[nat][ne] >> coef[nat][ne];
293 check_econd12(fne, !=, ne, mcerr);
294 check_econd12(e, !=, ees->get_energy_mesh(ne), mcerr);
295 check_econd11(mean_coef[nat][ne], <= 0, mcerr);
296 check_econd11(coef[nat][ne], <= 0, mcerr);
297 }
298 }
299}
300}
#define check_econd21(a, sign1_b1_sign0, sign2_b2, stream)
Definition: FunNameStack.h:191
#define check_econd11(a, signb, stream)
Definition: FunNameStack.h:155
#define check_econd11a(a, signb, add, stream)
Definition: FunNameStack.h:172
#define mfunnamep(string)
Definition: FunNameStack.h:49
#define spexit(stream)
Definition: FunNameStack.h:256
#define check_econd12(a, sign, b, stream)
Definition: FunNameStack.h:163
#define mfunname(string)
Definition: FunNameStack.h:45
double CS(const double theta) const
Return -1 if not valid.
double A[4]
If -1.0 then the combination is not valid.
Definition: ElElasticScat.h:12
Array of ElElasticScatDataStruct objects for a set of energies.
Definition: ElElasticScat.h:19
ElElasticScatLowSigma()=default
Default constructor.
double get_CS(long Z, double energy, double angle, int s_interp=0)
double get_energy_mesh(long ne) const
Definition: ElElasticScat.h:54
ElElasticScat()=default
Default constructor.
void print(std::ostream &file, int l) const
double get_CS_Rutherford(long Z, double energy, double angle)
long get_qe(void) const
Definition: ElElasticScat.h:53
Definition: BGMesh.cpp:6
DoubleAc cos(const DoubleAc &f)
Definition: DoubleAc.cpp:432
DoubleAc pow(const DoubleAc &f, double p)
Definition: DoubleAc.cpp:337
int findmark(std::istream &file, const char *s)
Definition: findmark.cpp:19
double polleg(const int l, const double x)
Definition: PolLeg.cpp:17
DoubleAc sin(const DoubleAc &f)
Definition: DoubleAc.cpp:384
double lorbeta2(const double gamma_1)
as function of .
Definition: lorgamma.cpp:27
indentation indn
Definition: prstream.cpp:15
#define Ifile
Definition: prstream.h:196
#define mcerr
Definition: prstream.h:128