BornAgain  1.18.0
Simulate and fit neutron and x-ray scattering at grazing incidence
MatrixRTCoefficients_v3.cpp
Go to the documentation of this file.
1 // ************************************************************************** //
2 //
3 // BornAgain: simulate and fit scattering at grazing incidence
4 //
5 //! @file Sample/RT/MatrixRTCoefficients_v3.cpp
6 //! @brief Implements class MatrixRTCoefficients_v3.
7 //!
8 //! @homepage http://www.bornagainproject.org
9 //! @license GNU General Public License v3 or higher (see COPYING)
10 //! @copyright Forschungszentrum Jülich GmbH 2020
11 //! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS)
12 //
13 // ************************************************************************** //
14 
16 #include "Base/Utils/Assert.h"
17 
18 namespace
19 {
21 const auto eps = std::numeric_limits<double>::epsilon() * 10.;
22 } // namespace
23 
25  kvector_t b, double magnetic_SLD)
26  : m_kz_sign(kz_sign), m_lambda(std::move(eigenvalues)), m_b(std::move(b)),
27  m_magnetic_SLD(magnetic_SLD)
28 {
29  ASSERT(std::abs(m_b.mag() - 1) < eps || (m_b.mag() < eps && magnetic_SLD < eps));
30 
31  m_T << 1, 0, 0, 1;
32  m_R << -1, 0, 0, -1;
33 }
34 
36 
38 
40 {
41  return new MatrixRTCoefficients_v3(*this);
42 }
43 
44 Eigen::Matrix2cd MatrixRTCoefficients_v3::TransformationMatrix(Eigen::Vector2d selection) const
45 {
46  const Eigen::Matrix2cd exp2 = Eigen::DiagonalMatrix<complex_t, 2>(selection);
47 
48  if (std::abs(m_b.mag() - 1.) < eps) {
49  Eigen::Matrix2cd Q;
50  const double factor1 = 2. * (1. + m_b.z());
51  Q << (1. + m_b.z()), (I * m_b.y() - m_b.x()), (m_b.x() + I * m_b.y()), (m_b.z() + 1.);
52  return Q * exp2 * Q.adjoint() / factor1;
53 
54  } else if (m_b.mag() < eps)
55  return exp2;
56 
57  throw std::runtime_error("Broken magnetic field vector");
58 }
59 
60 Eigen::Matrix2cd MatrixRTCoefficients_v3::T1Matrix() const
61 {
62  return TransformationMatrix({0., 1.});
63 }
64 
65 Eigen::Matrix2cd MatrixRTCoefficients_v3::T2Matrix() const
66 {
67  return TransformationMatrix({1., 0.});
68 }
69 
70 Eigen::Vector2cd MatrixRTCoefficients_v3::T1plus() const
71 {
72  return T1Matrix() * m_T.col(0);
73 }
74 
75 Eigen::Vector2cd MatrixRTCoefficients_v3::R1plus() const
76 {
77  return T1Matrix() * m_R.col(0);
78 }
79 
80 Eigen::Vector2cd MatrixRTCoefficients_v3::T2plus() const
81 {
82  return T2Matrix() * m_T.col(0);
83 }
84 
85 Eigen::Vector2cd MatrixRTCoefficients_v3::R2plus() const
86 {
87  return T2Matrix() * m_R.col(0);
88 }
89 
90 Eigen::Vector2cd MatrixRTCoefficients_v3::T1min() const
91 {
92  return T1Matrix() * m_T.col(1);
93 }
94 
95 Eigen::Vector2cd MatrixRTCoefficients_v3::R1min() const
96 {
97  return T1Matrix() * m_R.col(1);
98 }
99 
100 Eigen::Vector2cd MatrixRTCoefficients_v3::T2min() const
101 {
102  return T2Matrix() * m_T.col(1);
103 }
104 
105 Eigen::Vector2cd MatrixRTCoefficients_v3::R2min() const
106 {
107  return T2Matrix() * m_R.col(1);
108 }
109 
110 Eigen::Vector2cd MatrixRTCoefficients_v3::getKz() const
111 {
112  return m_kz_sign * m_lambda;
113 }
114 
115 Eigen::Matrix2cd MatrixRTCoefficients_v3::pMatrixHelper(double sign) const
116 {
117  const complex_t alpha = m_lambda(1) + m_lambda(0);
118  const complex_t beta = m_lambda(1) - m_lambda(0);
119 
120  Eigen::Matrix2cd result;
121 
122  kvector_t b = m_b;
123 
124  result << alpha + sign * beta * b.z(), sign * beta * (b.x() - I * b.y()),
125  sign * beta * (b.x() + I * b.y()), alpha - sign * beta * b.z();
126 
127  return result;
128 }
129 
130 Eigen::Matrix2cd MatrixRTCoefficients_v3::computeP() const
131 {
132  Eigen::Matrix2cd result = pMatrixHelper(1.);
133  result *= 0.5;
134 
135  return result;
136 }
137 
139 {
140  const complex_t alpha = m_lambda(1) + m_lambda(0);
141  const complex_t beta = m_lambda(1) - m_lambda(0);
142 
143  if (std::abs(alpha * alpha - beta * beta) == 0.)
144  return Eigen::Matrix2cd::Zero();
145 
146  Eigen::Matrix2cd result = pMatrixHelper(-1.);
147  result *= 2. / (alpha * alpha - beta * beta);
148 
149  return result;
150 }
151 
152 Eigen::Matrix2cd MatrixRTCoefficients_v3::computeDeltaMatrix(double thickness)
153 {
154  Eigen::Matrix2cd result;
155  const complex_t alpha = 0.5 * thickness * (m_lambda(1) + m_lambda(0));
156 
157  const Eigen::Matrix2cd exp2 = Eigen::DiagonalMatrix<complex_t, 2>(
158  {GetImExponential(thickness * m_lambda(1)), GetImExponential(thickness * m_lambda(0))});
159 
160  // Compute resulting phase matrix according to exp(i p_m d_m) = exp1 * Q * exp2 * Q.adjoint();
161  if (std::abs(m_b.mag() - 1.) < eps) {
162  Eigen::Matrix2cd Q;
163  const double factor1 = 2. * (1. + m_b.z());
164  Q << (1. + m_b.z()), (I * m_b.y() - m_b.x()), (m_b.x() + I * m_b.y()), (m_b.z() + 1.);
165 
166  return Q * exp2 * Q.adjoint() / factor1;
167 
168  } else if (m_b.mag() < eps)
169  return Eigen::Matrix2cd::Identity() * GetImExponential(alpha);
170 
171  throw std::runtime_error("Broken magnetic field vector");
172 }
173 
174 namespace
175 {
177 {
178  if (exponent.imag() > -std::log(std::numeric_limits<double>::min()))
179  return 0.0;
180  return std::exp(I * exponent);
181 }
182 } // namespace
Defines the macro ASSERT.
#define ASSERT(condition)
Definition: Assert.h:26
constexpr complex_t I
Definition: Complex.h:21
std::complex< double > complex_t
Definition: Complex.h:20
Defines class MatrixRTCoefficients_v3.
double mag() const
Returns magnitude of the vector.
T z() const
Returns z-component in cartesian coordinate system.
Definition: BasicVector3D.h:68
T y() const
Returns y-component in cartesian coordinate system.
Definition: BasicVector3D.h:66
T x() const
Returns x-component in cartesian coordinate system.
Definition: BasicVector3D.h:64
Specular reflection and transmission coefficients in a layer in case of magnetic interactions between...
Eigen::Vector2cd R2plus() const override
Eigen::Matrix2cd computeDeltaMatrix(double thickness)
Eigen::Vector2cd R1plus() const override
Eigen::Matrix2cd TransformationMatrix(Eigen::Vector2d selection) const
Eigen::Matrix2cd T2Matrix() const
Eigen::Vector2cd m_lambda
wave propagation direction (-1 for direct one, 1 for time reverse)
Eigen::Vector2cd T1plus() const override
The following functions return the transmitted and reflected amplitudes for different incoming beam p...
Eigen::Matrix2cd computeInverseP() const
Eigen::Vector2cd R1min() const override
Eigen::Vector2cd T2min() const override
Eigen::Matrix2cd T1Matrix() const
Eigen::Matrix2cd computeP() const
Eigen::Matrix2cd pMatrixHelper(double sign) const
Eigen::Vector2cd getKz() const override
Returns z-part of the two wavevector eigenmodes.
kvector_t m_b
unit magnetic field vector
~MatrixRTCoefficients_v3() override
Eigen::Vector2cd R2min() const override
MatrixRTCoefficients_v3(double kz_sign, Eigen::Vector2cd eigenvalues, kvector_t b, double magnetic_SLD)
Eigen::Vector2cd T2plus() const override
Eigen::Vector2cd T1min() const override
MatrixRTCoefficients_v3 * clone() const override
Eigen::Vector2cd eigenvalues(complex_t kz, double b_mag)