Geant4  10.02
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  // Loop checking, 07-Aug-2015, Vladimir Ivanchenko
239  while ((ang_stepphi>=AngCut*AngCut) || (ang_steptheta>=AngCut*AngCut))
240  {
241  a_max_theta_o=max_theta_o;
242  a_max_phi_o=max_phi_o;
243  ang_stepphi /= 2.;
244  ang_steptheta /= 2.;
245 
246  //G4cout << ang_stepphi/degree << ", "
247  // << ang_steptheta/degree << ","
248  // << AngCut/degree << G4endl;
249 
250  for (theta_o=a_max_theta_o-ang_steptheta;
251  theta_o<=a_max_theta_o-ang_steptheta+1e-6;
252  theta_o+=ang_steptheta)
253  {
254  //G4cout << "theta_o: " << theta_o/degree << G4endl;
255  costheta_o_squared=std::cos(theta_o)*std::cos(theta_o);
256  for (phi_o=a_max_phi_o-ang_stepphi;
257  phi_o<=a_max_phi_o+ang_stepphi+1e-6;
258  phi_o+=ang_stepphi)
259  {
260  //G4cout << "phi_o: " << phi_o/degree << G4endl;
261  Intens=kl4d4/costheta_i*S2(costheta_i_squared, klk2)*
262  S2(costheta_o_squared,klk2)*
263  Fmu(k2,theta_i,theta_o,phi_o,b2,w2,AngCut)*std::sin(theta_o);
264  if (Intens>*max)
265  {
266  *max=Intens;
267  max_theta_o=theta_o;
268  max_phi_o=phi_o;
269  }
270  }
271  }
272  }
273  }
274  return wkeit;
275 }
276 
277 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
278 
280  G4double theta_i,
281  G4int AngNoTheta,
282  G4int AngNoPhi, G4double b2,
283  G4double w2, G4double* max,
284  G4double AngCut)
285 {
286  G4double a_max_thetas_o, max_thetas_o = theta_i;
287  G4double a_max_phis_o, max_phis_o = 0.;
288  G4double thetas_o;
289  G4double phis_o;
290  G4double IntensS;
291  G4double ang_steptheta=180.*degree/(AngNoTheta-1);
292  G4double ang_stepphi=180.*degree/(AngNoPhi-1);
293  G4double costheta_i=std::cos(theta_i);
294  G4double costheta_i_squared=costheta_i*costheta_i;
295 
296  *max = 0.;
297  G4double wkeit=0.;
298 
299  if (E*costheta_i_squared < fermipot) return wkeit;
300 
301  //k_l^4/4
302  G4double kl4d4=neutron_mass_c2/hbarc_squared*neutron_mass_c2/
303  hbarc_squared*fermipot*fermipot;
304  // (k_l/k)^2
305  G4double klk2=fermipot/E;
306 
307  // (k_l/k')^2
308  G4double klks2=fermipot/(E-fermipot);
309 
310  // k'/k
311  G4double ksdk=std::sqrt((E-fermipot)/E);
312 
313  G4double costhetas_o_squared;
314 
315  // k
316  G4double k=std::sqrt(2*neutron_mass_c2*E/hbarc_squared);
317 
318  // k'
319  G4double kS=ksdk*k;
320 
321  for (thetas_o=0.*degree; thetas_o<=90.*degree+1e-6; thetas_o+=ang_steptheta)
322  {
323  costhetas_o_squared=std::cos(thetas_o)*std::cos(thetas_o);
324 
325  for (phis_o=-180.*degree; phis_o<=180.*degree+1e-6; phis_o+=ang_stepphi)
326  {
327  //cf. Steyerl-paper p. 176, eq. 21
328  if (costhetas_o_squared>=-klks2) {
329 
330  //calculates probability for a certain theta'_o, phi'_o pair
331 
332  G4double thetarefract = thetas_o;
333  if (std::fabs(std::sin(theta_i)/ksdk) <= 1.)
334  thetarefract = std::asin(std::sin(theta_i)/ksdk);
335 
336  IntensS = kl4d4/costheta_i*ksdk*S2(costheta_i_squared, klk2)*
337  SS2(costhetas_o_squared,klks2)*
338  FmuS(k,kS,theta_i,thetas_o,phis_o,b2,w2,AngCut,thetarefract)*
339  std::sin(thetas_o);
340  } else {
341  IntensS=0.;
342  }
343  // checks if the new probability is larger than
344  // the maximum found so far
345  if (IntensS>*max)
346  {
347  *max=IntensS;
348  }
349  wkeit+=IntensS*ang_steptheta*ang_stepphi;
350  }
351  }
352 
353  // Fine-Iteration to find maximum of distribution
354 
355  if (E>1e-10*eV)
356  {
357 
358  // Break-condition for refining
359 
360  while (ang_stepphi>=AngCut*AngCut || ang_steptheta>=AngCut*AngCut)
361  {
362  a_max_thetas_o=max_thetas_o;
363  a_max_phis_o=max_phis_o;
364  ang_stepphi /= 2.;
365  ang_steptheta /= 2.;
366  //G4cout << ang_stepphi/degree << ", " << ang_steptheta/degree
367  // << ", " << AngCut/degree << G4endl;
368  for (thetas_o=a_max_thetas_o-ang_steptheta;
369  thetas_o<=a_max_thetas_o-ang_steptheta+1e-6;
370  thetas_o+=ang_steptheta)
371  {
372  costhetas_o_squared=std::cos(thetas_o)*std::cos(thetas_o);
373  for (phis_o=a_max_phis_o-ang_stepphi;
374  phis_o<=a_max_phis_o+ang_stepphi+1e-6;
375  phis_o+=ang_stepphi)
376  {
377  G4double thetarefract = thetas_o;
378  if (std::fabs(std::sin(theta_i)/ksdk) <= 1.)
379  thetarefract = std::asin(std::sin(theta_i)/ksdk);
380 
381  IntensS=kl4d4/costheta_i*ksdk*S2(costheta_i_squared, klk2)*
382  SS2(costhetas_o_squared,klks2)*
383  FmuS(k,kS,theta_i,thetas_o,phis_o,b2,w2,AngCut,thetarefract)*
384  std::sin(thetas_o);
385  if (IntensS>*max)
386  {
387  *max=IntensS;
388  max_thetas_o=thetas_o;
389  max_phis_o=phis_o;
390  }
391  }
392  }
393  }
394  }
395  return wkeit;
396 }
397 
398 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
399 
401  G4double theta_i,
402  G4double theta_o,
403  G4double phi_o,
404  G4double b, G4double w,
405  G4double AngCut)
406 {
407  //k_l^4/4
408  G4double kl4d4=neutron_mass_c2/hbarc_squared*neutron_mass_c2/
409  hbarc_squared*fermipot*fermipot;
410 
411  // (k_l/k)^2
412  G4double klk2=fermipot/E;
413 
414  G4double costheta_i=std::cos(theta_i);
415  G4double costheta_o=std::cos(theta_o);
416 
417  // eq. 20 on page 176 in the steyerl paper
418 
419  return kl4d4/costheta_i*S2(costheta_i*costheta_i, klk2)*
420  S2(costheta_o*costheta_o,klk2)*
421  Fmu(2*neutron_mass_c2*E/hbarc_squared,theta_i,theta_o,phi_o,b*b,w*w,AngCut)*
422  std::sin(theta_o);
423 }
424 
425 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
426 
428  G4double theta_i,
429  G4double thetas_o,
430  G4double phis_o, G4double b,
431  G4double w, G4double AngCut)
432 {
433  //k_l^4/4
434  G4double kl4d4=neutron_mass_c2/hbarc_squared*neutron_mass_c2/
435  hbarc_squared*fermipot*fermipot;
436  // (k_l/k)^2
437  G4double klk2=fermipot/E;
438 
439  // (k_l/k')^2
440  G4double klks2=fermipot/(E-fermipot);
441 
442  if (E < fermipot) {
443  G4cout << " ProbIminus E < fermipot " << G4endl;
444  return 0.;
445  }
446 
447  // k'/k
448  G4double ksdk=std::sqrt((E-fermipot)/E);
449 
450  // k
451  G4double k=std::sqrt(2*neutron_mass_c2*E/hbarc_squared);
452 
453  // k'/k
454  G4double kS=ksdk*k;
455 
456  G4double costheta_i=std::cos(theta_i);
457  G4double costhetas_o=std::cos(thetas_o);
458 
459  // eq. 20 on page 176 in the steyerl paper
460 
461  G4double thetarefract = thetas_o;
462  if(std::fabs(std::sin(theta_i)/ksdk) <= 1.)thetarefract = std::asin(std::sin(theta_i)/ksdk);
463 
464  return kl4d4/costheta_i*ksdk*S2(costheta_i*costheta_i, klk2)*
465  SS2(costhetas_o*costhetas_o,klks2)*
466  FmuS(k,kS,theta_i,thetas_o,phis_o,b*b,w*w,AngCut,thetarefract)*
467  std::sin(thetas_o);
468 }
469 
470 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double Fmu(G4double, G4double, G4double, G4double, G4double, G4double, G4double)
G4double IntIplus(G4double, G4double, G4double, G4int, G4int, G4double, G4double, G4double *, G4double)
const G4double w[NPOINTSGL]
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)
static const double twopi
Definition: G4SIunits.hh:75
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:212
T max(const T t1, const T t2)
brief Return the largest of the two arguments
static const double degree
Definition: G4SIunits.hh:143
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)