Geant4  10.01.p03
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 //
27 //
28 //
29 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
30 //
31 // This file contains the source code of various functions all related to the
32 // calculation of microroughness.
33 //
34 // see A. Steyerl, Z. Physik 254 (1972) 169.
35 //
36 // A description of the functions can be found in the corresponding header file
37 //
38 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
39 
41 
42 #include "globals.hh"
43 
44 #include "G4SystemOfUnits.hh"
45 #include "G4PhysicalConstants.hh"
46 
48 
49 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
50 
51 // Constructor
52 
54 
55 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
56 
58 {
59  delete fpInstance;
60  fpInstance = 0;
61 }
62 
63 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
64 
66 {
68  return fpInstance;
69 }
70 
71 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
72 
74 {
75  // case 1: radicand is positive,
76  // case 2: radicand is negative, cf. p. 174 of the Steyerl paper
77 
78  if (costheta2>=klk2)
79  return 4*costheta2/(2*costheta2-klk2+2*std::sqrt(costheta2*(costheta2-klk2)));
80  else
81  return 4*costheta2/klk2;
82 }
83 
84 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
85 
87 {
88  // cf. p. 175 of the Steyerl paper
89 
90  return 4*costhetas2/
91  (2*costhetas2+klks2+2*std::sqrt(costhetas2*(costhetas2+klks2)));
92 }
93 
94 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
95 
97  G4double thetao, G4double phio,
98  G4double b2, G4double w2,
99  G4double AngCut)
100 {
101  G4double mu_squared;
102 
103  // Checks if the distribution is peaked around the specular direction
104 
105  if ((std::fabs(thetai-thetao)<AngCut) && (std::fabs(phio)<AngCut))
106  mu_squared=0.;
107  else
108  {
109  // cf. p. 177 of the Steyerl paper
110 
111  G4double sinthetai=std::sin(thetai);
112  G4double sinthetao=std::sin(thetao);
113  mu_squared=k2*
114  (sinthetai*sinthetai+sinthetao*sinthetao-
115  2.*sinthetai*sinthetao*std::cos(phio));
116  }
117 
118  // cf. p. 177 of the Steyerl paper
119 
120  return b2*w2/twopi*std::exp(-mu_squared*w2/2);
121 }
122 
123 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
124 
126  G4double thetai, G4double thetaSo,
127  G4double phiSo,
128  G4double b2, G4double w2,
129  G4double AngCut, G4double thetarefract)
130 {
131  G4double mu_squared;
132 
133  // Checks if the distribution is peaked around the direction of
134  // unperturbed refraction
135 
136  if ((std::fabs(thetarefract-thetaSo)<AngCut) && (std::fabs(phiSo)<AngCut))
137  mu_squared=0.;
138  else
139  {
140  G4double sinthetai=std::sin(thetai);
141  G4double sinthetaSo=std::sin(thetaSo);
142 
143  // cf. p. 177 of the Steyerl paper
144  mu_squared=k*k*sinthetai*sinthetai+kS*kS*sinthetaSo*sinthetaSo-
145  2.*k*kS*sinthetai*sinthetaSo*std::cos(phiSo);
146  }
147 
148  // cf. p. 177 of the Steyerl paper
149 
150  return b2*w2/twopi*std::exp(-mu_squared*w2/2);
151 }
152 
153 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
154 
156  G4double theta_i, G4int AngNoTheta,
157  G4int AngNoPhi, G4double b2,
158  G4double w2, G4double* max,
159  G4double AngCut)
160 {
161  *max=0.;
162 
163  // max_theta_o saves the theta-position of the max probability,
164  // the previous value is saved in a_max_theta_o
165 
166  G4double a_max_theta_o, max_theta_o=theta_i, a_max_phi_o, max_phi_o=0.;
167 
168  // max_phi_o saves the phi-position of the max probability,
169  // the previous value is saved in a_max_phi_o
170 
171  // Definition of the stepsizes in theta_o and phi_o
172 
173  G4double theta_o;
174  G4double phi_o;
175  G4double Intens;
176  G4double ang_steptheta=90.*degree/(AngNoTheta-1);
177  G4double ang_stepphi=360.*degree/(AngNoPhi-1);
178  G4double costheta_i=std::cos(theta_i);
179  G4double costheta_i_squared=costheta_i*costheta_i;
180 
181  // (k_l/k)^2
182  G4double kl4d4=neutron_mass_c2/hbarc_squared*neutron_mass_c2/
183  hbarc_squared*fermipot*fermipot;
184 
185  // (k_l/k)^2
186  G4double klk2=fermipot/E;
187 
188  G4double costheta_o_squared;
189 
190  // k^2
191  G4double k2=2*neutron_mass_c2*E/hbarc_squared;
192 
193  G4double wkeit=0.;
194 
195  // Loop through theta_o
196 
197  for (theta_o=0.*degree; theta_o<=90.*degree+1e-6; theta_o+=ang_steptheta)
198  {
199  costheta_o_squared=std::cos(theta_o)*std::cos(theta_o);
200 
201  // Loop through phi_o
202 
203  for (phi_o=-180.*degree; phi_o<=180.*degree+1e-6; phi_o+=ang_stepphi)
204  {
205  //calculates probability for a certain theta_o,phi_o pair
206 
207  Intens=kl4d4/costheta_i*S2(costheta_i_squared,klk2)*
208  S2(costheta_o_squared,klk2)*
209  Fmu(k2,theta_i,theta_o,phi_o,b2,w2,AngCut)*std::sin(theta_o);
210 
211  //G4cout << "S2: " << S2(costheta_i_squared,klk2) << G4endl;
212  //G4cout << "S2: " << S2(costheta_o_squared,klk2) << G4endl;
213  //G4cout << "Fmu: " << Fmu(k2,theta_i,theta_o,phi_o,b2,w2,AngCut)*sin(theta_o) << G4endl;
214  // checks if the new probability is larger than the
215  // maximum found so far
216 
217  if (Intens>*max)
218  {
219  *max=Intens;
220  max_theta_o=theta_o;
221  max_phi_o=phi_o;
222  }
223 
224  // Adds the newly found probability to the integral probability
225 
226  wkeit+=Intens*ang_steptheta*ang_stepphi;
227  }
228  }
229 
230  // Fine-Iteration to find maximum of distribution
231  // only if the energy is not zero
232 
233  if (E>1e-10*eV)
234  {
235 
236  // Break-condition for refining
237 
238  while ((ang_stepphi>=AngCut*AngCut) || (ang_steptheta>=AngCut*AngCut))
239  {
240  a_max_theta_o=max_theta_o;
241  a_max_phi_o=max_phi_o;
242  ang_stepphi /= 2.;
243  ang_steptheta /= 2.;
244 
245  //G4cout << ang_stepphi/degree << ", "
246  // << ang_steptheta/degree << ","
247  // << AngCut/degree << G4endl;
248 
249  for (theta_o=a_max_theta_o-ang_steptheta;
250  theta_o<=a_max_theta_o-ang_steptheta+1e-6;
251  theta_o+=ang_steptheta)
252  {
253  //G4cout << "theta_o: " << theta_o/degree << G4endl;
254  costheta_o_squared=std::cos(theta_o)*std::cos(theta_o);
255  for (phi_o=a_max_phi_o-ang_stepphi;
256  phi_o<=a_max_phi_o+ang_stepphi+1e-6;
257  phi_o+=ang_stepphi)
258  {
259  //G4cout << "phi_o: " << phi_o/degree << G4endl;
260  Intens=kl4d4/costheta_i*S2(costheta_i_squared, klk2)*
261  S2(costheta_o_squared,klk2)*
262  Fmu(k2,theta_i,theta_o,phi_o,b2,w2,AngCut)*std::sin(theta_o);
263  if (Intens>*max)
264  {
265  *max=Intens;
266  max_theta_o=theta_o;
267  max_phi_o=phi_o;
268  }
269  }
270  }
271  }
272  }
273  return wkeit;
274 }
275 
276 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
277 
279  G4double theta_i,
280  G4int AngNoTheta,
281  G4int AngNoPhi, G4double b2,
282  G4double w2, G4double* max,
283  G4double AngCut)
284 {
285  G4double a_max_thetas_o, max_thetas_o = theta_i;
286  G4double a_max_phis_o, max_phis_o = 0.;
287  G4double thetas_o;
288  G4double phis_o;
289  G4double IntensS;
290  G4double ang_steptheta=180.*degree/(AngNoTheta-1);
291  G4double ang_stepphi=180.*degree/(AngNoPhi-1);
292  G4double costheta_i=std::cos(theta_i);
293  G4double costheta_i_squared=costheta_i*costheta_i;
294 
295  *max = 0.;
296  G4double wkeit=0.;
297 
298  if (E*costheta_i_squared < fermipot) return wkeit;
299 
300  //k_l^4/4
301  G4double kl4d4=neutron_mass_c2/hbarc_squared*neutron_mass_c2/
302  hbarc_squared*fermipot*fermipot;
303  // (k_l/k)^2
304  G4double klk2=fermipot/E;
305 
306  // (k_l/k')^2
307  G4double klks2=fermipot/(E-fermipot);
308 
309  // k'/k
310  G4double ksdk=std::sqrt((E-fermipot)/E);
311 
312  G4double costhetas_o_squared;
313 
314  // k
315  G4double k=std::sqrt(2*neutron_mass_c2*E/hbarc_squared);
316 
317  // k'
318  G4double kS=ksdk*k;
319 
320  for (thetas_o=0.*degree; thetas_o<=90.*degree+1e-6; thetas_o+=ang_steptheta)
321  {
322  costhetas_o_squared=std::cos(thetas_o)*std::cos(thetas_o);
323 
324  for (phis_o=-180.*degree; phis_o<=180.*degree+1e-6; phis_o+=ang_stepphi)
325  {
326  //cf. Steyerl-paper p. 176, eq. 21
327  if (costhetas_o_squared>=-klks2) {
328 
329  //calculates probability for a certain theta'_o, phi'_o pair
330 
331  G4double thetarefract = thetas_o;
332  if (std::fabs(std::sin(theta_i)/ksdk) <= 1.)
333  thetarefract = std::asin(std::sin(theta_i)/ksdk);
334 
335  IntensS = kl4d4/costheta_i*ksdk*S2(costheta_i_squared, klk2)*
336  SS2(costhetas_o_squared,klks2)*
337  FmuS(k,kS,theta_i,thetas_o,phis_o,b2,w2,AngCut,thetarefract)*
338  std::sin(thetas_o);
339  } else {
340  IntensS=0.;
341  }
342  // checks if the new probability is larger than
343  // the maximum found so far
344  if (IntensS>*max)
345  {
346  *max=IntensS;
347  }
348  wkeit+=IntensS*ang_steptheta*ang_stepphi;
349  }
350  }
351 
352  // Fine-Iteration to find maximum of distribution
353 
354  if (E>1e-10*eV)
355  {
356 
357  // Break-condition for refining
358 
359  while (ang_stepphi>=AngCut*AngCut || ang_steptheta>=AngCut*AngCut)
360  {
361  a_max_thetas_o=max_thetas_o;
362  a_max_phis_o=max_phis_o;
363  ang_stepphi /= 2.;
364  ang_steptheta /= 2.;
365  //G4cout << ang_stepphi/degree << ", " << ang_steptheta/degree
366  // << ", " << AngCut/degree << G4endl;
367  for (thetas_o=a_max_thetas_o-ang_steptheta;
368  thetas_o<=a_max_thetas_o-ang_steptheta+1e-6;
369  thetas_o+=ang_steptheta)
370  {
371  costhetas_o_squared=std::cos(thetas_o)*std::cos(thetas_o);
372  for (phis_o=a_max_phis_o-ang_stepphi;
373  phis_o<=a_max_phis_o+ang_stepphi+1e-6;
374  phis_o+=ang_stepphi)
375  {
376  G4double thetarefract = thetas_o;
377  if (std::fabs(std::sin(theta_i)/ksdk) <= 1.)
378  thetarefract = std::asin(std::sin(theta_i)/ksdk);
379 
380  IntensS=kl4d4/costheta_i*ksdk*S2(costheta_i_squared, klk2)*
381  SS2(costhetas_o_squared,klks2)*
382  FmuS(k,kS,theta_i,thetas_o,phis_o,b2,w2,AngCut,thetarefract)*
383  std::sin(thetas_o);
384  if (IntensS>*max)
385  {
386  *max=IntensS;
387  max_thetas_o=thetas_o;
388  max_phis_o=phis_o;
389  }
390  }
391  }
392  }
393  }
394  return wkeit;
395 }
396 
397 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
398 
400  G4double theta_i,
401  G4double theta_o,
402  G4double phi_o,
403  G4double b, G4double w,
404  G4double AngCut)
405 {
406  //k_l^4/4
407  G4double kl4d4=neutron_mass_c2/hbarc_squared*neutron_mass_c2/
408  hbarc_squared*fermipot*fermipot;
409 
410  // (k_l/k)^2
411  G4double klk2=fermipot/E;
412 
413  G4double costheta_i=std::cos(theta_i);
414  G4double costheta_o=std::cos(theta_o);
415 
416  // eq. 20 on page 176 in the steyerl paper
417 
418  return kl4d4/costheta_i*S2(costheta_i*costheta_i, klk2)*
419  S2(costheta_o*costheta_o,klk2)*
420  Fmu(2*neutron_mass_c2*E/hbarc_squared,theta_i,theta_o,phi_o,b*b,w*w,AngCut)*
421  std::sin(theta_o);
422 }
423 
424 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
425 
427  G4double theta_i,
428  G4double thetas_o,
429  G4double phis_o, G4double b,
430  G4double w, G4double AngCut)
431 {
432  //k_l^4/4
433  G4double kl4d4=neutron_mass_c2/hbarc_squared*neutron_mass_c2/
434  hbarc_squared*fermipot*fermipot;
435  // (k_l/k)^2
436  G4double klk2=fermipot/E;
437 
438  // (k_l/k')^2
439  G4double klks2=fermipot/(E-fermipot);
440 
441  if (E < fermipot) {
442  G4cout << " ProbIminus E < fermipot " << G4endl;
443  return 0.;
444  }
445 
446  // k'/k
447  G4double ksdk=std::sqrt((E-fermipot)/E);
448 
449  // k
450  G4double k=std::sqrt(2*neutron_mass_c2*E/hbarc_squared);
451 
452  // k'/k
453  G4double kS=ksdk*k;
454 
455  G4double costheta_i=std::cos(theta_i);
456  G4double costhetas_o=std::cos(thetas_o);
457 
458  // eq. 20 on page 176 in the steyerl paper
459 
460  G4double thetarefract = thetas_o;
461  if(std::fabs(std::sin(theta_i)/ksdk) <= 1.)thetarefract = std::asin(std::sin(theta_i)/ksdk);
462 
463  return kl4d4/costheta_i*ksdk*S2(costheta_i*costheta_i, klk2)*
464  SS2(costhetas_o*costhetas_o,klks2)*
465  FmuS(k,kS,theta_i,thetas_o,phis_o,b*b,w*w,AngCut,thetarefract)*
466  std::sin(thetas_o);
467 }
468 
469 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double Fmu(G4double, G4double, G4double, G4double, G4double, G4double, G4double)
G4double IntIplus(G4double, G4double, G4double, G4int, G4int, G4double, G4double, G4double *, G4double)
G4double ProbIplus(G4double, G4double, G4double, G4double, G4double, G4double, G4double, G4double)
int G4int
Definition: G4Types.hh:78
G4GLOB_DLL std::ostream G4cout
G4double S2(G4double, G4double)
G4double FmuS(G4double, G4double, G4double, G4double, G4double, G4double, G4double, G4double, G4double)
static const G4double b2
static G4UCNMicroRoughnessHelper * GetInstance()
static const double eV
Definition: G4SIunits.hh:194
T max(const T t1, const T t2)
brief Return the largest of the two arguments
static const double degree
Definition: G4SIunits.hh:125
static G4UCNMicroRoughnessHelper * fpInstance
#define G4endl
Definition: G4ios.hh:61
G4double SS2(G4double, G4double)
double G4double
Definition: G4Types.hh:76
G4double ProbIminus(G4double, G4double, G4double, G4double, G4double, G4double, G4double, G4double)
G4double IntIminus(G4double, G4double, G4double, G4int, G4int, G4double, G4double, G4double *, G4double)