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