BornAgain  1.19.0
Simulate and fit neutron and x-ray scattering at grazing incidence
SpecularScalarNCStrategy Class Reference

Implements Nevot-Croce roughness for a scaler computation. More...

Inheritance diagram for SpecularScalarNCStrategy:
[legend]
Collaboration diagram for SpecularScalarNCStrategy:
[legend]

Public Types

using coefficient_pointer_type = std::unique_ptr< const coefficient_type >
 
using coefficient_type = ScalarRTCoefficients
 
using coeffs_t = std::vector< coefficient_pointer_type >
 

Public Member Functions

virtual std::variant< complex_t, Eigen::Matrix2cd > computeTopLayerR (const std::vector< Slice > &slices, const std::vector< complex_t > &kz) const override
 Computes the Fresnel R coefficient for the top layer only Introduced in order to speed up pure reflectivity computations. More...
 
virtual ISpecularStrategy::coeffs_t Execute (const std::vector< Slice > &slices, const kvector_t &k) const override
 Computes refraction angles and transmission/reflection coefficients for given coherent wave propagation in a multilayer. More...
 
virtual ISpecularStrategy::coeffs_t Execute (const std::vector< Slice > &slices, const std::vector< complex_t > &kz) const override
 

Private Member Functions

void calculateUpFromLayer (std::vector< ScalarRTCoefficients > &coeff, const std::vector< Slice > &slices, const std::vector< complex_t > &kz) const
 
std::vector< ScalarRTCoefficientscomputeTR (const std::vector< Slice > &slices, const std::vector< complex_t > &kz) const
 
virtual std::pair< complex_t, complex_ttransition (complex_t kzi, complex_t kzi1, double sigma) const override
 Roughness is modelled by a Gaussian profile, i.e. More...
 

Static Private Member Functions

static void setZeroBelow (std::vector< ScalarRTCoefficients > &coeff, size_t current_layer)
 

Detailed Description

Implements Nevot-Croce roughness for a scaler computation.

Implements the transition function that includes Nevot-Croce roughness in the computation of the coefficients for coherent wave propagation in a multilayer by applying modified Fresnel coefficients.

Definition at line 35 of file SpecularScalarNCStrategy.h.

Member Typedef Documentation

◆ coefficient_pointer_type

using SpecularScalarStrategy::coefficient_pointer_type = std::unique_ptr<const coefficient_type>
inherited

Definition at line 43 of file SpecularScalarStrategy.h.

◆ coefficient_type

◆ coeffs_t

Definition at line 44 of file SpecularScalarStrategy.h.

Member Function Documentation

◆ calculateUpFromLayer()

void SpecularScalarStrategy::calculateUpFromLayer ( std::vector< ScalarRTCoefficients > &  coeff,
const std::vector< Slice > &  slices,
const std::vector< complex_t > &  kz 
) const
privateinherited

Definition at line 116 of file SpecularScalarStrategy.cpp.

119 {
120  auto N = slices.size();
121 
122  coeff.back().t_r(0) = 1.0;
123  coeff.back().t_r(1) = 0.0;
124  std::vector<complex_t> factors(N - 1);
125  for (int i = N - 2; i >= 0; i--) {
126  double sigma = 0.0;
127  if (const auto roughness = GetBottomRoughness(slices, i))
128  sigma = roughness->getSigma();
129 
130  const auto [mp, mm] = transition(kz[i], kz[i + 1], sigma);
131 
132  const complex_t delta = exp_I(kz[i] * slices[i].thickness());
133 
134  complex_t S = mp + mm * coeff[i + 1].t_r(1);
135  S = 1. / S * delta;
136  factors[i] = S;
137 
138  coeff[i].t_r(1) = delta * (mm + mp * coeff[i + 1].t_r(1)) * S;
139  }
140 
141  // now correct all amplitudes by dividing the with the remaining factors in forward direction
142  // at some point this divison underflows, which is the point when all further amplitudes are set
143  // to zero
144  complex_t dumpingFactor = 1;
145  for (size_t j = 1; j < N; ++j) {
146  dumpingFactor = dumpingFactor * factors[j - 1];
147 
148  coeff[j].t_r(0) = dumpingFactor;
149  coeff[j].t_r(1) *= dumpingFactor;
150  }
151 }
std::complex< double > complex_t
Definition: Complex.h:20
complex_t exp_I(complex_t z)
Returns exp(I*z), where I is the imaginary unit.
Definition: Complex.h:30
virtual std::pair< complex_t, complex_t > transition(complex_t kzi, complex_t kzi1, double sigma) const =0

References exp_I(), and SpecularScalarStrategy::transition().

Referenced by SpecularScalarStrategy::computeTR().

Here is the call graph for this function:

◆ computeTopLayerR()

std::variant< complex_t, Eigen::Matrix2cd > SpecularScalarStrategy::computeTopLayerR ( const std::vector< Slice > &  slices,
const std::vector< complex_t > &  kz 
) const
overridevirtualinherited

Computes the Fresnel R coefficient for the top layer only Introduced in order to speed up pure reflectivity computations.

Implements ISpecularStrategy.

Definition at line 49 of file SpecularScalarStrategy.cpp.

51 {
52  if (slices.size() != kz.size())
53  throw std::runtime_error("Number of slices does not match the size of the kz-vector");
54 
55  auto N = slices.size();
56 
57  if (N == 1) { // If only one layer present, there's nothing left to calculate
58  return 0.;
59  }else if (kz[0] == 0.)
60  return -1.;
61 
62  complex_t R_i1 = 0.;
63 
64  for (int i = N - 2; i >= 0; i--) {
65  double sigma = 0.0;
66  if (const auto roughness = GetBottomRoughness(slices, i))
67  sigma = roughness->getSigma();
68 
69  const auto [mp, mm] = transition(kz[i], kz[i + 1], sigma);
70 
71  const complex_t delta = exp_I(kz[i] * slices[i].thickness());
72 
73  complex_t S = mp + mm * R_i1;
74  S = 1. / S * delta;
75 
76  R_i1 = delta * (mm + mp * R_i1) * S;
77  }
78 
79  return R_i1;
80 }

References exp_I(), and SpecularScalarStrategy::transition().

Here is the call graph for this function:

◆ computeTR()

std::vector< ScalarRTCoefficients > SpecularScalarStrategy::computeTR ( const std::vector< Slice > &  slices,
const std::vector< complex_t > &  kz 
) const
privateinherited

Definition at line 83 of file SpecularScalarStrategy.cpp.

85 {
86  const size_t N = slices.size();
87  std::vector<ScalarRTCoefficients> coeff(N);
88 
89  for (size_t i = 0; i < N; ++i)
90  coeff[i].kz = kz[i];
91 
92  if (N == 1) { // If only one layer present, there's nothing left to calculate
93  coeff[0].t_r = {1.0, 0.0};
94  return coeff;
95  } else if (kz[0] == 0.0) { // If kz in layer 0 is zero, R0 = -T0 and all others equal to 0
96  coeff[0].t_r = {1.0, -1.0};
97  for (size_t i = 1; i < N; ++i)
98  coeff[i].t_r.setZero();
99  return coeff;
100  }
101 
102  // Calculate transmission/refraction coefficients t_r for each layer, from bottom to top.
103  calculateUpFromLayer(coeff, slices, kz);
104  return coeff;
105 }
void calculateUpFromLayer(std::vector< ScalarRTCoefficients > &coeff, const std::vector< Slice > &slices, const std::vector< complex_t > &kz) const

References SpecularScalarStrategy::calculateUpFromLayer().

Referenced by SpecularScalarStrategy::Execute().

Here is the call graph for this function:

◆ Execute() [1/2]

ISpecularStrategy::coeffs_t SpecularScalarStrategy::Execute ( const std::vector< Slice > &  slices,
const kvector_t k 
) const
overridevirtualinherited

Computes refraction angles and transmission/reflection coefficients for given coherent wave propagation in a multilayer.

Implements ISpecularStrategy.

Definition at line 28 of file SpecularScalarStrategy.cpp.

30 {
31  std::vector<complex_t> kz = KzComputation::computeReducedKz(slices, k);
32  return Execute(slices, kz);
33 }
virtual ISpecularStrategy::coeffs_t Execute(const std::vector< Slice > &slices, const kvector_t &k) const override
Computes refraction angles and transmission/reflection coefficients for given coherent wave propagati...
std::vector< complex_t > computeReducedKz(const std::vector< Slice > &slices, kvector_t k)

References KzComputation::computeReducedKz().

Here is the call graph for this function:

◆ Execute() [2/2]

ISpecularStrategy::coeffs_t SpecularScalarStrategy::Execute ( const std::vector< Slice > &  slices,
const std::vector< complex_t > &  kz 
) const
overridevirtualinherited

Implements ISpecularStrategy.

Definition at line 35 of file SpecularScalarStrategy.cpp.

37 {
38  if (slices.size() != kz.size())
39  throw std::runtime_error("Number of slices does not match the size of the kz-vector");
40 
42  for (auto& coeff : computeTR(slices, kz))
43  result.push_back(std::make_unique<ScalarRTCoefficients>(coeff));
44 
45  return result;
46 }
std::vector< std::unique_ptr< const ILayerRTCoefficients > > coeffs_t
std::vector< ScalarRTCoefficients > computeTR(const std::vector< Slice > &slices, const std::vector< complex_t > &kz) const

References SpecularScalarStrategy::computeTR().

Here is the call graph for this function:

◆ setZeroBelow()

void SpecularScalarStrategy::setZeroBelow ( std::vector< ScalarRTCoefficients > &  coeff,
size_t  current_layer 
)
staticprivateinherited

Definition at line 107 of file SpecularScalarStrategy.cpp.

109 {
110  size_t N = coeff.size();
111  for (size_t i = current_layer + 1; i < N; ++i) {
112  coeff[i].t_r.setZero();
113  }
114 }

◆ transition()

std::pair< complex_t, complex_t > SpecularScalarNCStrategy::transition ( complex_t  kzi,
complex_t  kzi1,
double  sigma 
) const
overrideprivatevirtual

Roughness is modelled by a Gaussian profile, i.e.

Nevot-Croce factors for the reflection coefficients. Implementation follows A. Gibaud and G. Vignaud, in X-ray and Neutron Reflectivity, edited by J. Daillant and A. Gibaud, volume 770 of Lecture Notes in Physics (2009)

Implements SpecularScalarStrategy.

Definition at line 18 of file SpecularScalarNCStrategy.cpp.

20 {
21  complex_t roughness_diff = 1;
22  complex_t roughness_sum = 1;
23  if (sigma > 0.0) {
24  roughness_diff = std::exp(-(kzi1 - kzi) * (kzi1 - kzi) * sigma * sigma / 2.);
25  roughness_sum = std::exp(-(kzi1 + kzi) * (kzi1 + kzi) * sigma * sigma / 2.);
26  }
27  const complex_t kz_ratio = kzi1 / kzi;
28 
29  const complex_t a00 = 0.5 * (1. + kz_ratio) * roughness_diff;
30  const complex_t a01 = 0.5 * (1. - kz_ratio) * roughness_sum;
31 
32  return {a00, a01};
33 }

The documentation for this class was generated from the following files: