BornAgain  1.19.79
Open-source research software to simulate and fit neutron and x-ray reflectometry and grazing-incidence small-angle scattering
MatrixFlux.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file Resample/Flux/MatrixFlux.cpp
6 //! @brief Implements class MatrixFlux.
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/Util/Assert.h"
17 
18 namespace {
19 
20 const auto eps = std::numeric_limits<double>::epsilon() * 10.;
21 
22 complex_t GetImExponential(complex_t exponent)
23 {
24  if (exponent.imag() > -std::log(std::numeric_limits<double>::min()))
25  return 0.0;
26  return std::exp(I * exponent);
27 }
28 
29 } // namespace
30 
31 
32 MatrixFlux::MatrixFlux(double kz_sign, const Spinor& eigenvalues, const R3& b, double magnetic_SLD)
33  : m_lambda(std::move(eigenvalues))
34  , m_T(+1, 0, 0, +1)
35  , m_R(-1, 0, 0, -1)
36  , m_b(b)
37  , m_kz_sign(kz_sign)
38  , m_magnetic_SLD(magnetic_SLD)
39 {
40  ASSERT(std::abs(m_b.mag() - 1) < eps || (m_b.mag() < eps && magnetic_SLD < eps));
41 }
42 
44 {
45  const SpinMatrix exp2(selection.u, 0, 0, selection.v);
46 
47  if (std::abs(m_b.mag() - 1.) < eps) {
48  const double factor1 = 2. * (1. + m_b.z());
49  SpinMatrix Q(1. + m_b.z(), I * m_b.y() - m_b.x(), m_b.x() + I * m_b.y(), m_b.z() + 1.);
50  return Q * exp2 * Q.adjoint() / factor1;
51  }
52  if (m_b.mag() < eps)
53  return exp2;
54 
55  throw std::runtime_error("Broken magnetic field vector");
56 }
57 
59 {
60  return TransformationMatrix({0., 1.});
61 }
62 
64 {
65  return TransformationMatrix({1., 0.});
66 }
67 
69 {
70  return T1Matrix() * m_T.col0();
71 }
72 
74 {
75  return T1Matrix() * m_R.col0();
76 }
77 
79 {
80  return T2Matrix() * m_T.col0();
81 }
82 
84 {
85  return T2Matrix() * m_R.col0();
86 }
87 
89 {
90  return T1Matrix() * m_T.col1();
91 }
92 
94 {
95  return T1Matrix() * m_R.col1();
96 }
97 
99 {
100  return T2Matrix() * m_T.col1();
101 }
102 
104 {
105  return T2Matrix() * m_R.col1();
106 }
107 
109 {
110  return m_kz_sign * m_lambda;
111 }
112 
114 {
115  const complex_t alpha = m_lambda.v + m_lambda.u;
116  const complex_t beta = m_lambda.v - m_lambda.u;
117 
118  SpinMatrix result(alpha + sign * beta * m_b.z(), sign * beta * (m_b.x() - I * m_b.y()),
119  sign * beta * (m_b.x() + I * m_b.y()), alpha - sign * beta * m_b.z());
120 
121  return m_kz_sign * result;
122 }
123 
125 {
126  SpinMatrix result = pMatrixHelper(1.);
127  result *= 0.5;
128 
129  return result;
130 }
131 
133 {
134  const complex_t alpha = m_lambda.v + m_lambda.u;
135  const complex_t beta = m_lambda.v - m_lambda.u;
136 
137  if (std::abs(alpha * alpha - beta * beta) == 0.)
138  return SpinMatrix();
139 
140  SpinMatrix result = pMatrixHelper(-1.);
141  result *= 2. / (alpha * alpha - beta * beta);
142 
143  return result;
144 }
145 
147 {
148  const complex_t alpha = 0.5 * thickness * (m_lambda.v + m_lambda.u);
149 
150  // Compute resulting phase matrix according to exp(i p_m d_m) = exp1 * Q * exp2 * Q.adjoint();
151  if (std::abs(m_b.mag() - 1.) < eps) {
152  const SpinMatrix exp2(GetImExponential(m_kz_sign * thickness * m_lambda.v), 0, 0,
153  GetImExponential(m_kz_sign * thickness * m_lambda.u));
154  const double factor1 = 2. * (1. + m_b.z());
155  SpinMatrix Q((1. + m_b.z()), (I * m_b.y() - m_b.x()), (m_b.x() + I * m_b.y()),
156  (m_b.z() + 1.));
157 
158  return Q * exp2 * Q.adjoint() / factor1;
159  }
160  if (m_b.mag() < eps)
161  return SpinMatrix::One() * GetImExponential(m_kz_sign * alpha);
162 
163  throw std::runtime_error("Broken magnetic field vector");
164 }
Defines the macro ASSERT.
#define ASSERT(condition)
Definition: Assert.h:45
Defines class MatrixFlux.
SpinMatrix computeP() const
Definition: MatrixFlux.cpp:124
Spinor T1min() const override
Definition: MatrixFlux.cpp:88
Spinor R1plus() const override
Definition: MatrixFlux.cpp:73
Spinor T1plus() const override
The following functions return the transmitted and reflected amplitudes for different incoming beam p...
Definition: MatrixFlux.cpp:68
Spinor T2min() const override
Definition: MatrixFlux.cpp:98
Spinor m_lambda
eigenvalues for wave propagation
Definition: MatrixFlux.h:55
SpinMatrix TransformationMatrix(const Spinor &selection) const
Definition: MatrixFlux.cpp:43
SpinMatrix T1Matrix() const
Definition: MatrixFlux.cpp:58
Spinor T2plus() const override
Definition: MatrixFlux.cpp:78
SpinMatrix pMatrixHelper(double sign) const
Definition: MatrixFlux.cpp:113
SpinMatrix T2Matrix() const
Definition: MatrixFlux.cpp:63
SpinMatrix m_T
Definition: MatrixFlux.h:58
SpinMatrix computeInverseP() const
Definition: MatrixFlux.cpp:132
Spinor getKz() const override
Returns z-part of the two wavevector eigenmodes.
Definition: MatrixFlux.cpp:108
SpinMatrix m_R
Definition: MatrixFlux.h:59
Spinor R2min() const override
Definition: MatrixFlux.cpp:103
double m_kz_sign
Definition: MatrixFlux.h:63
R3 m_b
unit magnetic field vector
Definition: MatrixFlux.h:60
MatrixFlux(double kz_sign, const Spinor &eigenvalues, const R3 &b, double magnetic_SLD)
Definition: MatrixFlux.cpp:32
Spinor R2plus() const override
Definition: MatrixFlux.cpp:83
Spinor R1min() const override
Definition: MatrixFlux.cpp:93
SpinMatrix computeDeltaMatrix(double thickness)
Definition: MatrixFlux.cpp:146
SpinMatrix adjoint() const
Definition: SpinMatrix.cpp:180
static SpinMatrix One()
Definition: SpinMatrix.cpp:36
Spinor col1() const
Definition: SpinMatrix.cpp:160
Spinor col0() const
Definition: SpinMatrix.cpp:155
Definition: Spinor.h:20
complex_t v
Definition: Spinor.h:31
complex_t u
Definition: Spinor.h:31
double beta(double z, double w)