28 std::pair<complex_t, complex_t> transition(complex_t kzi, complex_t kzi1,
double sigma,
31 if (r_model == RoughnessModel::NEVOT_CROCE) {
36 complex_t roughness_diff = 1;
37 complex_t roughness_sum = 1;
39 roughness_diff = std::exp(-(kzi1 - kzi) * (kzi1 - kzi) * sigma * sigma / 2.);
40 roughness_sum = std::exp(-(kzi1 + kzi) * (kzi1 + kzi) * sigma * sigma / 2.);
42 const complex_t kz_ratio = kzi1 / kzi;
44 const complex_t a00 = 0.5 * (1. + kz_ratio) * roughness_diff;
45 const complex_t a01 = 0.5 * (1. - kz_ratio) * roughness_sum;
52 complex_t roughness = 1;
54 const double sigeff = std::pow(
M_PI_2, 1.5) * sigma;
57 const complex_t inv_roughness = 1.0 / roughness;
58 const complex_t kz_ratio = kzi1 / kzi * roughness;
60 const complex_t a00 = 0.5 * (inv_roughness + kz_ratio);
61 const complex_t a01 = 0.5 * (inv_roughness - kz_ratio);
66 std::vector<Spinor> computeTR(
const SliceStack& slices,
const std::vector<complex_t>& kz,
69 const size_t N = slices.size();
70 std::vector<Spinor> TR(
N, {1., 0.});
76 std::vector<size_t> X(
N, 0);
77 for (
size_t i = 0; i <
N; ++i)
78 X[i] = top_exit ? i :
N - 1 - i;
80 if (kz[X[0]] == 0.0) {
81 TR[X[0]] = {1.0, -1.0};
82 for (
size_t i = 1; i <
N; ++i)
88 TR[X[
N - 1]] = {1.0, 0.0};
89 std::vector<complex_t> factors(
N - 1);
90 for (
size_t i =
N - 1; i > 0; i--) {
91 size_t jthis = X[i - 1];
94 const double sigma = roughness ? roughness->
sigma() : 0.;
96 const auto [mp, mm] = transition(kz[jthis], kz[jlast], sigma, r_model);
98 const complex_t delta = exp_I(kz[jthis] * slices[jthis].thicknessOr0());
100 complex_t S = delta / (mp + mm * TR[jlast].v);
102 TR[jthis].v = delta * (mm + mp * TR[jlast].v) * S;
107 complex_t dampingFactor = 1;
108 for (
size_t i = 1; i <
N; ++i) {
109 dampingFactor = dampingFactor * factors[i - 1];
110 TR[X[i]] =
Spinor(dampingFactor, TR[X[i]].v * dampingFactor);
124 const bool top_exit = k.z() <= 0;
126 ASSERT(slices.size() == kz.size());
128 const std::vector<Spinor> TR = computeTR(slices, kz, slices.
roughnessModel(), top_exit);
131 for (
size_t i = 0; i < kz.size(); ++i)
132 result.emplace_back(std::make_unique<const ScalarFlux>(kz[i], TR[i]));
137 const std::vector<complex_t>& kz)
141 ASSERT(slices.size() == kz.size());
142 const size_t N = slices.size();
150 for (
size_t i =
N - 1; i > 0; i--) {
153 sigma = roughness->sigma();
155 const auto [mp, mm] = transition(kz[i - 1], kz[i], sigma, r_model);
157 const complex_t delta = exp_I(kz[i - 1] * slices[i - 1].thicknessOr0());
159 R_i1 = pow(delta, 2) * (mm + mp * R_i1) / (mp + mm * R_i1);
Defines the macro ASSERT.
#define ASSERT(condition)
Defines namespace Compute::SpecularScalar.
Defines M_PI and some more mathematical constants.
std::vector< std::unique_ptr< const IFlux > > Fluxes
Declares functions in namespace ComputateKz.
Defines class LayerRoughness.
Defines class ScalarFlux.
Defines class SliceStack.
double sigma() const
Returns rms of roughness.
const LayerRoughness * bottomRoughness(size_t i_slice) const
RoughnessModel roughnessModel() const
std::vector< complex_t > computeReducedKz(const SliceStack &slices, R3 k)
Computes kz values from known k vector and slices with the following assumptions:
complex_t topLayerR(const SliceStack &slices, const std::vector< complex_t > &kz)
Computes the Fresnel R coefficient for the top layer only. Introduced in order to speed up pure refle...
Fluxes fluxes(const SliceStack &slices, const R3 &k)
Computes refraction angles and transmission/reflection coefficients for given coherent wave propagati...
complex_t tanhc(complex_t z)
Complex tanhc function: .