Geant4 11.2.2
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4UCNMicroRoughnessHelper.cc
Go to the documentation of this file.
1//
2// ********************************************************************
3// * License and Disclaimer *
4// * *
5// * The Geant4 software is copyright of the Copyright Holders of *
6// * the Geant4 Collaboration. It is provided under the terms and *
7// * conditions of the Geant4 Software License, included in the file *
8// * LICENSE and available at http://cern.ch/geant4/license . These *
9// * include a list of copyright holders. *
10// * *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work make any representation or warranty, express or implied, *
14// * regarding this software system or assume any liability for its *
15// * use. Please see the license in the file LICENSE and URL above *
16// * for the full disclaimer and the limitation of liability. *
17// * *
18// * This code implementation is the result of the scientific and *
19// * technical work of the GEANT4 collaboration. *
20// * By using, copying, modifying or distributing the software (or *
21// * any work based on the software) you agree to acknowledge its *
22// * use in resulting scientific publications, and indicate your *
23// * acceptance of all terms of the Geant4 Software license. *
24// ********************************************************************
25
26// This file contains the source code of various functions all related to the
27// calculation of microroughness.
28//
29// see A. Steyerl, Z. Physik 254 (1972) 169.
30//
31// A description of the functions can be found in the corresponding header file
32
34
36#include "G4SystemOfUnits.hh"
37#include "globals.hh"
38
39G4UCNMicroRoughnessHelper* G4UCNMicroRoughnessHelper::fpInstance = nullptr;
40
41//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
42
44
45//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
46
48{
49 if (fpInstance == nullptr) {
50 fpInstance = new G4UCNMicroRoughnessHelper;
51 }
52 return fpInstance;
53}
54
55//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
56
58{
59 // case 1: radicand is positive,
60 // case 2: radicand is negative, cf. p. 174 of the Steyerl paper
61
62 if (costheta2 >= klk2) {
63 return 4 * costheta2 / (2 * costheta2 - klk2 + 2 * std::sqrt(costheta2 * (costheta2 - klk2)));
64 }
65
66 return std::norm(2 * std::sqrt(costheta2) /
67 (std::sqrt(costheta2) + std::sqrt(std::complex<G4double>(costheta2 - klk2))));
68}
69
70//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
71
73{
74 // cf. p. 175 of the Steyerl paper
75
76 return 4 * costhetas2 /
77 (2 * costhetas2 + klks2 + 2 * std::sqrt(costhetas2 * (costhetas2 + klks2)));
78}
79
80//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
81
83 G4double phio, G4double b2, G4double w2, G4double AngCut) const
84{
85 G4double mu_squared;
86
87 // Checks if the distribution is peaked around the specular direction
88
89 if ((std::fabs(thetai - thetao) < AngCut) && (std::fabs(phio) < AngCut)) {
90 mu_squared = 0.;
91 }
92 else {
93 // cf. p. 177 of the Steyerl paper
94
95 G4double sinthetai = std::sin(thetai);
96 G4double sinthetao = std::sin(thetao);
97 mu_squared = k2 * (sinthetai * sinthetai + sinthetao * sinthetao -
98 2. * sinthetai * sinthetao * std::cos(phio));
99 }
100
101 // cf. p. 177 of the Steyerl paper
102
103 return b2 * w2 / twopi * std::exp(-mu_squared * w2 / 2);
104}
105
106//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
107
109 G4double phiSo, G4double b2, G4double w2, G4double AngCut, G4double thetarefract) const
110{
111 G4double mu_squared;
112
113 // Checks if the distribution is peaked around the direction of
114 // unperturbed refraction
115
116 if ((std::fabs(thetarefract - thetaSo) < AngCut) && (std::fabs(phiSo) < AngCut)) {
117 mu_squared = 0.;
118 }
119 else {
120 G4double sinthetai = std::sin(thetai);
121 G4double sinthetaSo = std::sin(thetaSo);
122
123 // cf. p. 177 of the Steyerl paper
124 mu_squared = k * k * sinthetai * sinthetai + kS * kS * sinthetaSo * sinthetaSo -
125 2. * k * kS * sinthetai * sinthetaSo * std::cos(phiSo);
126 }
127
128 // cf. p. 177 of the Steyerl paper
129
130 return b2 * w2 / twopi * std::exp(-mu_squared * w2 / 2);
131}
132
133//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
134
136 G4int AngNoTheta, G4int AngNoPhi, G4double b2, G4double w2, G4double* max, G4double AngCut) const
137{
138 *max = 0.;
139
140 // max_theta_o saves the theta-position of the max probability,
141 // the previous value is saved in a_max_theta_o
142
143 G4double a_max_theta_o, max_theta_o = theta_i, a_max_phi_o, max_phi_o = 0.;
144
145 // max_phi_o saves the phi-position of the max probability,
146 // the previous value is saved in a_max_phi_o
147
148 // Definition of the stepsizes in theta_o and phi_o
149
150 G4double theta_o;
151 G4double phi_o;
152 G4double Intens;
153 G4double ang_steptheta = 90. * degree / (AngNoTheta - 1);
154 G4double ang_stepphi = 360. * degree / (AngNoPhi - 1);
155 G4double costheta_i = std::cos(theta_i);
156 G4double costheta_i_squared = costheta_i * costheta_i;
157
158 // (k_l/k)^2
159 G4double kl4d4 =
160 neutron_mass_c2 / hbarc_squared * neutron_mass_c2 / hbarc_squared * fermipot * fermipot;
161
162 // (k_l/k)^2
163 G4double klk2 = fermipot / E;
164
165 G4double costheta_o_squared;
166
167 // k^2
168 G4double k2 = 2 * neutron_mass_c2 * E / hbarc_squared;
169
170 G4double wkeit = 0.;
171
172 // Loop through theta_o
173
174 for (theta_o = 0. * degree; theta_o <= 90. * degree + 1e-6; theta_o += ang_steptheta) {
175 costheta_o_squared = std::cos(theta_o) * std::cos(theta_o);
176
177 // Loop through phi_o
178
179 for (phi_o = -180. * degree; phi_o <= 180. * degree + 1e-6; phi_o += ang_stepphi) {
180 // calculates probability for a certain theta_o,phi_o pair
181
182 Intens = kl4d4 / costheta_i * S2(costheta_i_squared, klk2) * S2(costheta_o_squared, klk2) *
183 Fmu(k2, theta_i, theta_o, phi_o, b2, w2, AngCut) * std::sin(theta_o);
184
185 if (Intens > *max) {
186 *max = Intens;
187 max_theta_o = theta_o;
188 max_phi_o = phi_o;
189 }
190
191 // Adds the newly found probability to the integral probability
192
193 wkeit += Intens * ang_steptheta * ang_stepphi;
194 }
195 }
196
197 // Fine-Iteration to find maximum of distribution
198 // only if the energy is not zero
199
200 if (E > 1e-10 * eV) {
201 // Break-condition for refining
202
203 // Loop checking, 07-Aug-2015, Vladimir Ivanchenko
204 while ((ang_stepphi >= AngCut * AngCut) || (ang_steptheta >= AngCut * AngCut)) {
205 a_max_theta_o = max_theta_o;
206 a_max_phi_o = max_phi_o;
207 ang_stepphi /= 2.;
208 ang_steptheta /= 2.;
209
210 for (theta_o = a_max_theta_o - ang_steptheta; theta_o <= a_max_theta_o - ang_steptheta + 1e-6;
211 theta_o += ang_steptheta)
212 {
213 // G4cout << "theta_o: " << theta_o/degree << G4endl;
214 costheta_o_squared = std::cos(theta_o) * std::cos(theta_o);
215 for (phi_o = a_max_phi_o - ang_stepphi; phi_o <= a_max_phi_o + ang_stepphi + 1e-6;
216 phi_o += ang_stepphi)
217 {
218 // G4cout << "phi_o: " << phi_o/degree << G4endl;
219 Intens = kl4d4 / costheta_i * S2(costheta_i_squared, klk2) *
220 S2(costheta_o_squared, klk2) * Fmu(k2, theta_i, theta_o, phi_o, b2, w2, AngCut) *
221 std::sin(theta_o);
222 if (Intens > *max) {
223 *max = Intens;
224 max_theta_o = theta_o;
225 max_phi_o = phi_o;
226 }
227 }
228 }
229 }
230 }
231 return wkeit;
232}
233
234//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
235
237 G4int AngNoTheta, G4int AngNoPhi, G4double b2, G4double w2, G4double* max, G4double AngCut) const
238{
239 G4double a_max_thetas_o, max_thetas_o = theta_i;
240 G4double a_max_phis_o, max_phis_o = 0.;
241 G4double thetas_o;
242 G4double phis_o;
243 G4double IntensS;
244 G4double ang_steptheta = 180. * degree / (AngNoTheta - 1);
245 G4double ang_stepphi = 180. * degree / (AngNoPhi - 1);
246 G4double costheta_i = std::cos(theta_i);
247 G4double costheta_i_squared = costheta_i * costheta_i;
248
249 *max = 0.;
250 G4double wkeit = 0.;
251
252 if (E < fermipot) {
253 return wkeit;
254 }
255
256 // k_l^4/4
257 G4double kl4d4 =
258 neutron_mass_c2 / hbarc_squared * neutron_mass_c2 / hbarc_squared * fermipot * fermipot;
259 // (k_l/k)^2
260 G4double klk2 = fermipot / E;
261
262 // (k_l/k')^2
263 G4double klks2 = fermipot / (E - fermipot);
264
265 // k'/k
266 G4double ksdk = std::sqrt((E - fermipot) / E);
267
268 G4double costhetas_o_squared;
269
270 // k
271 G4double k = std::sqrt(2 * neutron_mass_c2 * E / hbarc_squared);
272
273 // k'
274 G4double kS = ksdk * k;
275
276 for (thetas_o = 0. * degree; thetas_o <= 90. * degree + 1e-6; thetas_o += ang_steptheta) {
277 costhetas_o_squared = std::cos(thetas_o) * std::cos(thetas_o);
278
279 for (phis_o = -180. * degree; phis_o <= 180. * degree + 1e-6; phis_o += ang_stepphi) {
280 // cf. Steyerl-paper p. 176, eq. 21
281 if (costhetas_o_squared >= -klks2) {
282 // calculates probability for a certain theta'_o, phi'_o pair
283
284 G4double thetarefract = thetas_o;
285 if (std::fabs(std::sin(theta_i) / ksdk) <= 1.) {
286 thetarefract = std::asin(std::sin(theta_i) / ksdk);
287 }
288
289 IntensS = kl4d4 / costheta_i * ksdk * S2(costheta_i_squared, klk2) *
290 SS2(costhetas_o_squared, klks2) *
291 FmuS(k, kS, theta_i, thetas_o, phis_o, b2, w2, AngCut, thetarefract) *
292 std::sin(thetas_o);
293 }
294 else {
295 IntensS = 0.;
296 }
297 // checks if the new probability is larger than
298 // the maximum found so far
299 if (IntensS > *max) {
300 *max = IntensS;
301 }
302 wkeit += IntensS * ang_steptheta * ang_stepphi;
303 }
304 }
305
306 // Fine-Iteration to find maximum of distribution
307
308 if (E > 1e-10 * eV) {
309 // Break-condition for refining
310
311 while (ang_stepphi >= AngCut * AngCut || ang_steptheta >= AngCut * AngCut) {
312 a_max_thetas_o = max_thetas_o;
313 a_max_phis_o = max_phis_o;
314 ang_stepphi /= 2.;
315 ang_steptheta /= 2.;
316
317 for (thetas_o = a_max_thetas_o - ang_steptheta;
318 thetas_o <= a_max_thetas_o - ang_steptheta + 1e-6; thetas_o += ang_steptheta)
319 {
320 costhetas_o_squared = std::cos(thetas_o) * std::cos(thetas_o);
321 for (phis_o = a_max_phis_o - ang_stepphi; phis_o <= a_max_phis_o + ang_stepphi + 1e-6;
322 phis_o += ang_stepphi)
323 {
324 G4double thetarefract = thetas_o;
325 if (std::fabs(std::sin(theta_i) / ksdk) <= 1.) {
326 thetarefract = std::asin(std::sin(theta_i) / ksdk);
327 }
328
329 IntensS = kl4d4 / costheta_i * ksdk * S2(costheta_i_squared, klk2) *
330 SS2(costhetas_o_squared, klks2) *
331 FmuS(k, kS, theta_i, thetas_o, phis_o, b2, w2, AngCut, thetarefract) *
332 std::sin(thetas_o);
333 if (IntensS > *max) {
334 *max = IntensS;
335 max_thetas_o = thetas_o;
336 max_phis_o = phis_o;
337 }
338 }
339 }
340 }
341 }
342 return wkeit;
343}
344
345//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
346
348 G4double theta_o, G4double phi_o, G4double b, G4double w, G4double AngCut) const
349{
350 // k_l^4/4
351 G4double kl4d4 =
352 neutron_mass_c2 / hbarc_squared * neutron_mass_c2 / hbarc_squared * fermipot * fermipot;
353
354 // (k_l/k)^2
355 G4double klk2 = fermipot / E;
356
357 G4double costheta_i = std::cos(theta_i);
358 G4double costheta_o = std::cos(theta_o);
359
360 // eq. 20 on page 176 in the steyerl paper
361
362 return kl4d4 / costheta_i * S2(costheta_i * costheta_i, klk2) *
363 S2(costheta_o * costheta_o, klk2) *
364 Fmu(
365 2 * neutron_mass_c2 * E / hbarc_squared, theta_i, theta_o, phi_o, b * b, w * w, AngCut) *
366 std::sin(theta_o);
367}
368
369//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
370
372 G4double thetas_o, G4double phis_o, G4double b, G4double w, G4double AngCut) const
373{
374 // k_l^4/4
375 G4double kl4d4 =
376 neutron_mass_c2 / hbarc_squared * neutron_mass_c2 / hbarc_squared * fermipot * fermipot;
377 // (k_l/k)^2
378 G4double klk2 = fermipot / E;
379
380 // (k_l/k')^2
381 G4double klks2 = fermipot / (E - fermipot);
382
383 if (E < fermipot) {
384 G4cout << " ProbIminus E < fermipot " << G4endl;
385 return 0.;
386 }
387
388 // k'/k
389 G4double ksdk = std::sqrt((E - fermipot) / E);
390
391 // k
392 G4double k = std::sqrt(2 * neutron_mass_c2 * E / hbarc_squared);
393
394 // k'/k
395 G4double kS = ksdk * k;
396
397 G4double costheta_i = std::cos(theta_i);
398 G4double costhetas_o = std::cos(thetas_o);
399
400 // eq. 20 on page 176 in the steyerl paper
401
402 G4double thetarefract = thetas_o;
403 if (std::fabs(std::sin(theta_i) / ksdk) <= 1.) {
404 thetarefract = std::asin(std::sin(theta_i) / ksdk);
405 }
406
407 return kl4d4 / costheta_i * ksdk * S2(costheta_i * costheta_i, klk2) *
408 SS2(costhetas_o * costhetas_o, klks2) *
409 FmuS(k, kS, theta_i, thetas_o, phis_o, b * b, w * w, AngCut, thetarefract) *
410 std::sin(thetas_o);
411}
double G4double
Definition G4Types.hh:83
int G4int
Definition G4Types.hh:85
#define G4endl
Definition G4ios.hh:67
G4GLOB_DLL std::ostream G4cout
G4UCNMicroRoughnessHelper()=default
G4double ProbIplus(G4double, G4double, G4double, G4double, G4double, G4double, G4double, G4double) const
G4double FmuS(G4double, G4double, G4double, G4double, G4double, G4double, G4double, G4double, G4double) const
G4double IntIminus(G4double, G4double, G4double, G4int, G4int, G4double, G4double, G4double *, G4double) const
G4double S2(G4double, G4double) const
G4double SS2(G4double, G4double) const
static G4UCNMicroRoughnessHelper * GetInstance()
G4double Fmu(G4double, G4double, G4double, G4double, G4double, G4double, G4double) const
G4double ProbIminus(G4double, G4double, G4double, G4double, G4double, G4double, G4double, G4double) const
G4double IntIplus(G4double, G4double, G4double, G4int, G4int, G4double, G4double, G4double *, G4double) const