BornAgain  1.18.0
Simulate and fit neutron and x-ray scattering at grazing incidence
anonymous_namespace{SpecularMagneticOldStrategy.cpp} Namespace Reference

Functions

void CalculateEigenvalues (const std::vector< Slice > &slices, const kvector_t k, std::vector< MatrixRTCoefficients > &coeff)
 
void CalculateTransferAndBoundary (const std::vector< Slice > &slices, std::vector< MatrixRTCoefficients > &coeff)
 
void SetForNoTransmission (std::vector< MatrixRTCoefficients > &coeff)
 
complex_t GetImExponential (complex_t exponent)
 

Function Documentation

◆ CalculateEigenvalues()

void anonymous_namespace{SpecularMagneticOldStrategy.cpp}::CalculateEigenvalues ( const std::vector< Slice > &  slices,
const kvector_t  k,
std::vector< MatrixRTCoefficients > &  coeff 
)

Definition at line 55 of file SpecularMagneticOldStrategy.cpp.

57 {
58  double mag_k = k.mag();
59  double n_ref = slices[0].material().refractiveIndex(2 * M_PI / mag_k).real();
60  double sign_kz = k.z() > 0.0 ? -1.0 : 1.0;
61  for (size_t i = 0; i < coeff.size(); ++i) {
62  coeff[i].m_scatt_matrix = slices[i].polarizedReducedPotential(k, n_ref);
63  coeff[i].m_kt = mag_k * slices[i].thickness();
64  coeff[i].m_a = coeff[i].m_scatt_matrix.trace() / 2.0;
65  coeff[i].m_b_mag =
66  sqrt(coeff[i].m_a * coeff[i].m_a - coeff[i].m_scatt_matrix.determinant());
67  coeff[i].m_bz = (coeff[i].m_scatt_matrix(0, 0) - coeff[i].m_scatt_matrix(1, 1)) / 2.0;
68  complex_t rad0 = coeff[i].m_a - coeff[i].m_b_mag;
69  complex_t rad1 = coeff[i].m_a + coeff[i].m_b_mag;
70  // use small absorptive component for layers with i>0 if radicand becomes very small:
71  if (i > 0) {
72  if (std::abs(rad0) < 1e-40)
73  rad0 = I * 1e-40;
74  if (std::abs(rad1) < 1e-40)
75  rad1 = I * 1e-40;
76  }
77  coeff[i].lambda(0) = sqrt(rad0);
78  coeff[i].lambda(1) = sqrt(rad1);
79  coeff[i].kz = mag_k * coeff[i].lambda * sign_kz;
80  }
81 }
constexpr complex_t I
Definition: Complex.h:21
std::complex< double > complex_t
Definition: Complex.h:20
#define M_PI
Definition: MathConstants.h:39
double mag() const
Returns magnitude of the vector.
T z() const
Returns z-component in cartesian coordinate system.
Definition: BasicVector3D.h:68

References I, M_PI, BasicVector3D< T >::mag(), and BasicVector3D< T >::z().

Referenced by SpecularMagneticOldStrategy::Execute().

Here is the call graph for this function:

◆ CalculateTransferAndBoundary()

void anonymous_namespace{SpecularMagneticOldStrategy.cpp}::CalculateTransferAndBoundary ( const std::vector< Slice > &  slices,
std::vector< MatrixRTCoefficients > &  coeff 
)

Definition at line 84 of file SpecularMagneticOldStrategy.cpp.

86 {
87  size_t N = coeff.size();
88  if (coeff[0].lambda == Eigen::Vector2cd::Zero() && N > 1) {
89  SetForNoTransmission(coeff);
90  return;
91  }
92 
93  // First, initialize bottom layer values to have no reflection
94  coeff[N - 1].initializeBottomLayerPhiPsi();
95  if (N > 1)
96  coeff[N - 1].calculateTRMatrices();
97 
98  coeff[0].calculateTRMatrices();
99  for (int signed_index = static_cast<int>(N) - 2; signed_index > 0; --signed_index) {
100  size_t i = static_cast<size_t>(signed_index);
101  double t = slices[i].thickness();
102  coeff[i].calculateTRMatrices();
103  Eigen::Matrix4cd l = coeff[i].R1m * GetImExponential(coeff[i].kz(0) * t)
104  + coeff[i].T1m * GetImExponential(-coeff[i].kz(0) * t)
105  + coeff[i].R2m * GetImExponential(coeff[i].kz(1) * t)
106  + coeff[i].T2m * GetImExponential(-coeff[i].kz(1) * t);
107  coeff[i].phi_psi_plus = l * coeff[i + 1].phi_psi_plus;
108  coeff[i].phi_psi_min = l * coeff[i + 1].phi_psi_min;
109  }
110  // If more than one layer, impose normalization and correct correspondence
111  // for spin-z polarization in top layer
112  if (N > 1) {
113  // First layer boundary is also top layer boundary:
114  coeff[0].phi_psi_plus = coeff[1].phi_psi_plus;
115  coeff[0].phi_psi_min = coeff[1].phi_psi_min;
116  // Normalize all boundary values such that top layer has unit wave
117  // amplitude for both spin up and down (and does not contain a
118  // transmitted wave amplitude for the opposite polarization)
119  Eigen::Vector2cd T0basisA = coeff[0].T1plus() + coeff[0].T2plus();
120  Eigen::Vector2cd T0basisB = coeff[0].T1min() + coeff[0].T2min();
121  complex_t cpA, cpB, cmA, cmB;
122  cpA = T0basisB(1);
123  cpB = -T0basisA(1);
124  cmA = T0basisB(0);
125  cmB = -T0basisA(0);
126  Eigen::Vector4cd phipsitemp = cpA * coeff[0].phi_psi_plus + cpB * coeff[0].phi_psi_min;
127  coeff[0].phi_psi_min = cmA * coeff[0].phi_psi_plus + cmB * coeff[0].phi_psi_min;
128  coeff[0].phi_psi_plus = phipsitemp;
129  Eigen::Vector2cd T0plusV = coeff[0].T1plus() + coeff[0].T2plus();
130  Eigen::Vector2cd T0minV = coeff[0].T1min() + coeff[0].T2min();
131  complex_t T0plus = T0plusV(0);
132  complex_t T0min = T0minV(1);
133  coeff[0].phi_psi_min = coeff[0].phi_psi_min / T0min;
134  coeff[0].phi_psi_plus = coeff[0].phi_psi_plus / T0plus;
135  for (size_t i = 1; i < N; ++i) {
136  phipsitemp = (cpA * coeff[i].phi_psi_plus + cpB * coeff[i].phi_psi_min) / T0plus;
137  coeff[i].phi_psi_min =
138  (cmA * coeff[i].phi_psi_plus + cmB * coeff[i].phi_psi_min) / T0min;
139  coeff[i].phi_psi_plus = phipsitemp;
140  }
141  }
142 }
void SetForNoTransmission(std::vector< MatrixRTCoefficients > &coeff)

References GetImExponential(), and SetForNoTransmission().

Referenced by SpecularMagneticOldStrategy::Execute().

Here is the call graph for this function:

◆ SetForNoTransmission()

void anonymous_namespace{SpecularMagneticOldStrategy.cpp}::SetForNoTransmission ( std::vector< MatrixRTCoefficients > &  coeff)

Definition at line 144 of file SpecularMagneticOldStrategy.cpp.

145 {
146  size_t N = coeff.size();
147  for (size_t i = 0; i < N; ++i) {
148  coeff[i].phi_psi_plus.setZero();
149  coeff[i].phi_psi_min.setZero();
150  coeff[i].T1m = Eigen::Matrix4cd::Identity() / 4.0;
151  coeff[i].R1m = coeff[i].T1m;
152  coeff[i].T2m = coeff[i].T1m;
153  coeff[i].R2m = coeff[i].T1m;
154  }
155 }

Referenced by CalculateTransferAndBoundary().

◆ GetImExponential()

complex_t anonymous_namespace{SpecularMagneticOldStrategy.cpp}::GetImExponential ( complex_t  exponent)

Definition at line 157 of file SpecularMagneticOldStrategy.cpp.

158 {
159  if (exponent.imag() > -std::log(std::numeric_limits<double>::min()))
160  return 0.0;
161  return std::exp(I * exponent);
162 }

References I.

Referenced by CalculateTransferAndBoundary().