20 #include <Eigen/Dense>
24 const LayerRoughness* GetBottomRoughness(
const std::vector<Slice>& slices,
25 const size_t slice_index);
36 const std::vector<complex_t>& kz)
const
38 if (slices.size() != kz.size())
39 throw std::runtime_error(
"Number of slices does not match the size of the kz-vector");
43 result.push_back(std::make_unique<ScalarRTCoefficients>(coeff));
48 std::variant<complex_t, Eigen::Matrix2cd>
50 const std::vector<complex_t>& kz)
const
52 if (slices.size() != kz.size())
53 throw std::runtime_error(
"Number of slices does not match the size of the kz-vector");
55 auto N = slices.size();
59 }
else if (kz[0] == 0.)
64 for (
int i = N - 2; i >= 0; i--) {
66 if (
const auto roughness = GetBottomRoughness(slices, i))
67 sigma = roughness->getSigma();
69 const auto [mp, mm] =
transition(kz[i], kz[i + 1], sigma);
76 R_i1 = delta * (mm + mp * R_i1) * S;
82 std::vector<ScalarRTCoefficients>
84 const std::vector<complex_t>& kz)
const
86 const size_t N = slices.size();
87 std::vector<ScalarRTCoefficients> coeff(N);
89 for (
size_t i = 0; i < N; ++i)
93 coeff[0].t_r = {1.0, 0.0};
95 }
else if (kz[0] == 0.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();
108 size_t current_layer)
110 size_t N = coeff.size();
111 for (
size_t i = current_layer + 1; i < N; ++i) {
112 coeff[i].t_r.setZero();
117 const std::vector<Slice>& slices,
118 const std::vector<complex_t>& kz)
const
120 auto N = slices.size();
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--) {
127 if (
const auto roughness = GetBottomRoughness(slices, i))
128 sigma = roughness->getSigma();
130 const auto [mp, mm] =
transition(kz[i], kz[i + 1], sigma);
134 complex_t S = mp + mm * coeff[i + 1].t_r(1);
138 coeff[i].t_r(1) = delta * (mm + mp * coeff[i + 1].t_r(1)) * S;
145 for (
size_t j = 1; j < N; ++j) {
146 dumpingFactor = dumpingFactor * factors[j - 1];
148 coeff[j].t_r(0) = dumpingFactor;
149 coeff[j].t_r(1) *= dumpingFactor;
154 const LayerRoughness* GetBottomRoughness(
const std::vector<Slice>& slices,
const size_t slice_index)
156 if (slice_index + 1 < slices.size())
157 return slices[slice_index + 1].topRoughness();
std::complex< double > complex_t
complex_t exp_I(complex_t z)
Returns exp(I*z), where I is the imaginary unit.
Declares functions in namespace KzComputation.
Defines class LayerRoughness.
Defines class SpecularScalarStrategy.
std::vector< std::unique_ptr< const ILayerRTCoefficients > > coeffs_t
A roughness of interface between two layers.
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< ScalarRTCoefficients > computeTR(const std::vector< Slice > &slices, const std::vector< complex_t > &kz) const
virtual std::pair< complex_t, complex_t > transition(complex_t kzi, complex_t kzi1, double sigma) const =0
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 reflec...
void calculateUpFromLayer(std::vector< ScalarRTCoefficients > &coeff, const std::vector< Slice > &slices, const std::vector< complex_t > &kz) const
static void setZeroBelow(std::vector< ScalarRTCoefficients > &coeff, size_t current_layer)
std::vector< complex_t > computeReducedKz(const std::vector< Slice > &slices, kvector_t k)