BornAgain  1.18.0
Simulate and fit neutron and x-ray scattering at grazing incidence
KzComputation.cpp
Go to the documentation of this file.
1 // ************************************************************************** //
2 //
3 // BornAgain: simulate and fit scattering at grazing incidence
4 //
5 //! @file Sample/Slice/KzComputation.cpp
6 //! @brief Implements functions in namespace KzComputation.
7 //!
8 //! @homepage http://www.bornagainproject.org
9 //! @license GNU General Public License v3 or higher (see COPYING)
10 //! @copyright Forschungszentrum Jülich GmbH 2018
11 //! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS)
12 //
13 // ************************************************************************** //
14 
16 #include "Base/Const/Units.h"
17 #include "Sample/Slice/Slice.h"
18 
19 namespace
20 {
22 {
23  if (material.typeID() != MATERIAL_TYPES::MaterialBySLD)
24  throw std::runtime_error("Error in normalizedSLD: passed material has wrong type");
25 
26  complex_t sld = std::conj(material.materialData()) / (Units::angstrom * Units::angstrom);
27  sld *= 4.0 * M_PI;
28  return sld;
29 }
30 
32 {
33  return std::norm(val) < 1e-80 ? complex_t(0.0, 1e-40) : val;
34 }
35 } // namespace
36 
37 // ************************************************************************** //
38 // namespace KzComputatin
39 // ************************************************************************** //
40 
41 std::vector<complex_t> KzComputation::computeReducedKz(const std::vector<Slice>& slices,
42  kvector_t k)
43 {
44  const size_t N = slices.size();
45  const double n_ref = slices[0].material().refractiveIndex(2 * M_PI / k.mag()).real();
46  const double k_base = k.mag() * (k.z() > 0.0 ? -1 : 1);
47 
48  std::vector<complex_t> result(N);
49  // Calculate refraction angle, expressed as k_z, for each layer.
50  complex_t rad = slices[0].scalarReducedPotential(k, n_ref);
51  result[0] = k_base * std::sqrt(rad);
52  for (size_t i = 1; i < N; ++i) {
53  rad = checkForUnderflow(slices[i].scalarReducedPotential(k, n_ref));
54  result[i] = k_base * std::sqrt(rad);
55  }
56  return result;
57 }
58 
59 std::vector<complex_t> KzComputation::computeKzFromSLDs(const std::vector<Slice>& slices, double kz)
60 {
61  const size_t N = slices.size();
62  const double k_sign = kz > 0.0 ? -1 : 1;
63  complex_t kz2_base = kz * kz + normalizedSLD(slices[0].material());
64 
65  std::vector<complex_t> result(N);
66  result[0] = -kz;
67  // Calculate refraction angle, expressed as k_z, for each layer.
68  for (size_t i = 1; i < N; ++i) {
69  complex_t kz2 = checkForUnderflow(kz2_base - normalizedSLD(slices[i].material()));
70  result[i] = k_sign * std::sqrt(kz2);
71  }
72  return result;
73 }
74 
75 std::vector<complex_t> KzComputation::computeKzFromRefIndices(const std::vector<Slice>& slices,
76  kvector_t k)
77 {
78  const size_t N = slices.size();
79  const double kz = k.z();
80  const double k_sign = kz > 0.0 ? -1 : 1;
81  const double k2 = k.mag2();
82  const double kz2 = kz * kz;
83  const double wl = 2 * M_PI / std::sqrt(k2);
84  const complex_t n2_ref = slices[0].material().refractiveIndex2(wl);
85 
86  std::vector<complex_t> result(N);
87  result[0] = -kz;
88  for (size_t i = 1; i < N; ++i) {
89  const complex_t n2_norm = slices[i].material().refractiveIndex2(wl) - n2_ref;
90  result[i] = k_sign * std::sqrt(checkForUnderflow(k2 * n2_norm + kz2));
91  }
92  return result;
93 }
std::complex< double > complex_t
Definition: Complex.h:20
Declares functions in namespace KzComputation.
#define M_PI
Definition: MathConstants.h:39
Defines class Slice.
Defines some unit conversion factors and other constants in namespace Units.
double mag2() const
Returns magnitude squared of the vector.
double mag() const
Returns magnitude of the vector.
T z() const
Returns z-component in cartesian coordinate system.
Definition: BasicVector3D.h:68
A wrapper for underlying material implementation.
Definition: Material.h:29
MATERIAL_TYPES typeID() const
Returns the type of underlying material implementation.
Definition: Material.cpp:74
complex_t materialData() const
Returns underlying material data.
Definition: Material.cpp:84
std::vector< complex_t > computeKzFromRefIndices(const std::vector< Slice > &slices, kvector_t k)
std::vector< complex_t > computeReducedKz(const std::vector< Slice > &slices, kvector_t k)
std::vector< complex_t > computeKzFromSLDs(const std::vector< Slice > &slices, double kz)
static constexpr double rad
Definition: Units.h:53
static constexpr double angstrom
Definition: Units.h:25
complex_t checkForUnderflow(complex_t val)
complex_t normalizedSLD(const Material &material)