From f7332b388625309ba76123d2ff5c2bd3a6563ab3 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Wed, 21 Jul 2021 16:10:09 +0200
Subject: [PATCH] scalar specular strategy now getting roughness model per
 argument

---
 Core/Computation/SpecularComputation.cpp      |  6 +-
 GUI/ba3d/model/geometry/column.cpp            |  2 +-
 GUI/ba3d/model/geometry/sphere.cpp            |  2 +-
 Resample/DWBA/DWBA_Scalar.h                   |  2 +-
 Resample/Processed/ProcessedSample.cpp        |  4 +-
 Resample/Specular/ISpecularStrategy.h         | 10 ++-
 .../Specular/SpecularMagneticStrategy.cpp     | 11 ++-
 Resample/Specular/SpecularMagneticStrategy.h  |  9 ++-
 Resample/Specular/SpecularScalarNCStrategy.h  |  4 +-
 Resample/Specular/SpecularScalarStrategy.cpp  | 73 ++++++++++++++++---
 Resample/Specular/SpecularScalarStrategy.h    | 17 ++---
 .../Specular/SpecularScalarTanhStrategy.h     |  4 +-
 .../FormFactorDecoratorMaterial.cpp           |  4 +-
 Tests/UnitTests/Core/Sample/RTTest.cpp        | 14 ++--
 auto/Wrap/doxygenResample.i                   | 15 ++--
 15 files changed, 121 insertions(+), 56 deletions(-)

diff --git a/Core/Computation/SpecularComputation.cpp b/Core/Computation/SpecularComputation.cpp
index 61667f5b33a..3dc37bf134f 100644
--- a/Core/Computation/SpecularComputation.cpp
+++ b/Core/Computation/SpecularComputation.cpp
@@ -34,13 +34,14 @@ void SpecularComputation::runProtected()
 {
     const SliceStack& slices = m_re_sample.averageSlices();
     const ISpecularStrategy* strategy = m_re_sample.getSpecularStrategy();
+    const RoughnessModel& r_model = m_re_sample.sample().roughnessModel();
     for (auto it = m_begin_it; it != m_end_it; ++it) {
         SpecularElement& ele = *it;
         if (!ele.isCalculated())
             continue;
         if (m_re_sample.polarizing()) {
             const auto R = std::get<Eigen::Matrix2cd>(
-                strategy->computeTopLayerR(slices, ele.produceKz(slices)));
+                strategy->computeTopLayerR(slices, ele.produceKz(slices), r_model));
 
             const auto& polarization = ele.polarizationHandler().getPolarization();
             const auto& analyzer = ele.polarizationHandler().getAnalyzerOperator();
@@ -51,7 +52,8 @@ void SpecularComputation::runProtected()
 
         } else {
             const auto R =
-                std::get<complex_t>(strategy->computeTopLayerR(slices, ele.produceKz(slices)));
+                std::get<complex_t>(strategy->computeTopLayerR(
+                                        slices, ele.produceKz(slices), r_model));
             ele.setIntensity(std::norm(R));
         }
 
diff --git a/GUI/ba3d/model/geometry/column.cpp b/GUI/ba3d/model/geometry/column.cpp
index 9eb92a9d614..d9199f7eb44 100644
--- a/GUI/ba3d/model/geometry/column.cpp
+++ b/GUI/ba3d/model/geometry/column.cpp
@@ -12,8 +12,8 @@
 //
 //  ************************************************************************************************
 
-#include "Base/Utils/Assert.h"
 #include "Base/Math/Constants.h"
+#include "Base/Utils/Assert.h"
 #include "GUI/ba3d/model/geometry.h"
 #include <qmath.h>
 
diff --git a/GUI/ba3d/model/geometry/sphere.cpp b/GUI/ba3d/model/geometry/sphere.cpp
index a3eef90664a..5173b100e37 100644
--- a/GUI/ba3d/model/geometry/sphere.cpp
+++ b/GUI/ba3d/model/geometry/sphere.cpp
@@ -12,8 +12,8 @@
 //
 //  ************************************************************************************************
 
-#include "Base/Utils/Assert.h"
 #include "Base/Math/Constants.h"
+#include "Base/Utils/Assert.h"
 #include "GUI/ba3d/model/geometry.h"
 #include <qmath.h>
 
diff --git a/Resample/DWBA/DWBA_Scalar.h b/Resample/DWBA/DWBA_Scalar.h
index fb228f13a3a..1ff52b5ec65 100644
--- a/Resample/DWBA/DWBA_Scalar.h
+++ b/Resample/DWBA/DWBA_Scalar.h
@@ -20,8 +20,8 @@
 #ifndef BORNAGAIN_RESAMPLE_DWBA_DWBA_SCALAR_H
 #define BORNAGAIN_RESAMPLE_DWBA_DWBA_SCALAR_H
 
-#include "Resample/DWBA/IDWBA.h"
 #include "Base/Types/Complex.h"
+#include "Resample/DWBA/IDWBA.h"
 
 class IFlux;
 
diff --git a/Resample/Processed/ProcessedSample.cpp b/Resample/Processed/ProcessedSample.cpp
index 9017019a23f..1bbd5246e6b 100644
--- a/Resample/Processed/ProcessedSample.cpp
+++ b/Resample/Processed/ProcessedSample.cpp
@@ -313,12 +313,12 @@ bool ProcessedSample::hasRoughness() const
 
 Fluxes ProcessedSample::fluxesIn(const kvector_t& k) const
 {
-    return m_specular_strategy->Execute(m_refined_stack, k);
+    return m_specular_strategy->Execute(m_refined_stack, k, m_sample.roughnessModel());
 }
 
 Fluxes ProcessedSample::fluxesOut(const kvector_t& k) const
 {
-    return m_specular_strategy->Execute(m_reversed_stack, -k);
+    return m_specular_strategy->Execute(m_reversed_stack, -k, m_sample.roughnessModel());
 }
 
 double ProcessedSample::crossCorrSpectralFun(const kvector_t kvec, size_t j, size_t k) const
diff --git a/Resample/Specular/ISpecularStrategy.h b/Resample/Specular/ISpecularStrategy.h
index 492ecb22f97..a305c4fcf80 100644
--- a/Resample/Specular/ISpecularStrategy.h
+++ b/Resample/Specular/ISpecularStrategy.h
@@ -22,6 +22,7 @@
 
 #include "Base/Vector/EigenCore.h"
 #include "Base/Vector/Vectors3D.h"
+#include "Sample/Multilayer/RoughnessModels.h"
 #include <memory>
 #include <variant>
 #include <vector>
@@ -39,13 +40,16 @@ public:
     virtual ~ISpecularStrategy() = default;
     ISpecularStrategy(const ISpecularStrategy& other) = delete;
 
-    virtual Fluxes Execute(const SliceStack& slices, const kvector_t& k) const = 0;
+    virtual Fluxes Execute(const SliceStack& slices, const kvector_t& k,
+                           const RoughnessModel& r_model) const = 0;
 
     virtual std::variant<complex_t, Eigen::Matrix2cd>
-    computeTopLayerR(const SliceStack& slices, const std::vector<complex_t>& kz) const = 0;
+    computeTopLayerR(const SliceStack& slices, const std::vector<complex_t>& kz,
+                           const RoughnessModel& r_model) const = 0;
 
 protected:
-    virtual Fluxes Execute(const SliceStack& slices, const std::vector<complex_t>& kz) const = 0;
+    virtual Fluxes Execute(const SliceStack& slices, const std::vector<complex_t>& kz,
+                           const RoughnessModel& r_model) const = 0;
 
     friend class RTTest;
 };
diff --git a/Resample/Specular/SpecularMagneticStrategy.cpp b/Resample/Specular/SpecularMagneticStrategy.cpp
index 4bb6e68a230..6c05f2f0563 100644
--- a/Resample/Specular/SpecularMagneticStrategy.cpp
+++ b/Resample/Specular/SpecularMagneticStrategy.cpp
@@ -47,13 +47,15 @@ Eigen::Vector2cd checkForUnderflow(const Eigen::Vector2cd& eigenvs)
 } // namespace
 
 
-Fluxes SpecularMagneticStrategy::Execute(const SliceStack& slices, const kvector_t& k) const
+Fluxes SpecularMagneticStrategy::Execute(const SliceStack& slices, const kvector_t& k,
+                           const RoughnessModel& r_model) const
 {
-    return Execute(slices, SampleUtils::KzComputation::computeReducedKz(slices, k));
+    return Execute(slices, SampleUtils::KzComputation::computeReducedKz(slices, k), r_model);
 }
 
 Fluxes SpecularMagneticStrategy::Execute(const SliceStack& slices,
-                                         const std::vector<complex_t>& kz) const
+                                         const std::vector<complex_t>& kz,
+                           const RoughnessModel&) const
 {
     ASSERT(slices.size() == kz.size());
 
@@ -66,7 +68,8 @@ Fluxes SpecularMagneticStrategy::Execute(const SliceStack& slices,
 
 std::variant<complex_t, Eigen::Matrix2cd>
 SpecularMagneticStrategy::computeTopLayerR(const SliceStack& slices,
-                                           const std::vector<complex_t>& kzs) const
+                                           const std::vector<complex_t>& kzs,
+                           const RoughnessModel&) const
 {
     ASSERT(slices.size() == kzs.size());
 
diff --git a/Resample/Specular/SpecularMagneticStrategy.h b/Resample/Specular/SpecularMagneticStrategy.h
index 5ae4f2d4e63..6f33156847f 100644
--- a/Resample/Specular/SpecularMagneticStrategy.h
+++ b/Resample/Specular/SpecularMagneticStrategy.h
@@ -37,16 +37,19 @@ class SpecularMagneticStrategy : public ISpecularStrategy {
 public:
     //! Computes refraction angle reflection/transmission coefficients
     //! for given sliced multilayer and wavevector k
-    Fluxes Execute(const SliceStack& slices, const kvector_t& k) const override;
+    Fluxes Execute(const SliceStack& slices, const kvector_t& k,
+                           const RoughnessModel& r_model) const override;
 
     //! Computes refraction angle reflection/transmission coefficients
     //! for given sliced multilayer and a set of kz projections corresponding to each slice
-    Fluxes Execute(const SliceStack& slices, const std::vector<complex_t>& kz) const override;
+    Fluxes Execute(const SliceStack& slices, const std::vector<complex_t>& kz,
+                           const RoughnessModel& r_model) const override;
 
     //! Computes the Fresnel R coefficient for the top layer only
     //! Introduced in order to speed up pure reflectivity computations
     virtual std::variant<complex_t, Eigen::Matrix2cd>
-    computeTopLayerR(const SliceStack& slices, const std::vector<complex_t>& kzs) const override;
+    computeTopLayerR(const SliceStack& slices, const std::vector<complex_t>& kzs,
+                           const RoughnessModel& r_model) const override;
 
 private:
     std::vector<MatrixFlux> computeFlux(const SliceStack& slices,
diff --git a/Resample/Specular/SpecularScalarNCStrategy.h b/Resample/Specular/SpecularScalarNCStrategy.h
index f9b7a3344dd..a6a378e41a8 100644
--- a/Resample/Specular/SpecularScalarNCStrategy.h
+++ b/Resample/Specular/SpecularScalarNCStrategy.h
@@ -34,8 +34,8 @@ private:
     //! 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)
-    virtual std::pair<complex_t, complex_t> transition(complex_t kzi, complex_t kzi1,
-                                                       double sigma) const override;
+    std::pair<complex_t, complex_t> transition(complex_t kzi, complex_t kzi1,
+                                                       double sigma) const;
 };
 
 #endif // BORNAGAIN_RESAMPLE_SPECULAR_SPECULARSCALARNCSTRATEGY_H
diff --git a/Resample/Specular/SpecularScalarStrategy.cpp b/Resample/Specular/SpecularScalarStrategy.cpp
index ba15d332919..07866d7c267 100644
--- a/Resample/Specular/SpecularScalarStrategy.cpp
+++ b/Resample/Specular/SpecularScalarStrategy.cpp
@@ -13,6 +13,8 @@
 //  ************************************************************************************************
 
 #include "Resample/Specular/SpecularScalarStrategy.h"
+#include "Base/Math/Constants.h"
+#include "Base/Math/Functions.h"
 #include "Base/Utils/Assert.h"
 #include "Resample/Slice/KzComputation.h"
 #include "Resample/Slice/Slice.h"
@@ -22,18 +24,66 @@
 #include <Eigen/Dense>
 #include <stdexcept>
 
-Fluxes SpecularScalarStrategy::Execute(const SliceStack& slices, const kvector_t& k) const
+namespace {
+
+std::pair<complex_t, complex_t>
+transition(complex_t kzi, complex_t kzi1, double sigma, const RoughnessModel& r_model)
+{
+    if (r_model == RoughnessModel::NEVOT_CROCE) {
+        // 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)
+        complex_t roughness_diff = 1;
+        complex_t roughness_sum = 1;
+        if (sigma > 0.0) {
+            roughness_diff = std::exp(-(kzi1 - kzi) * (kzi1 - kzi) * sigma * sigma / 2.);
+            roughness_sum = std::exp(-(kzi1 + kzi) * (kzi1 + kzi) * sigma * sigma / 2.);
+        }
+        const complex_t kz_ratio = kzi1 / kzi;
+
+        const complex_t a00 = 0.5 * (1. + kz_ratio) * roughness_diff;
+        const complex_t a01 = 0.5 * (1. - kz_ratio) * roughness_sum;
+
+        return {a00, a01};
+
+    } else { // TANH model assumed
+        // Roughness is modelled by tanh profile
+        // [e.g. Bahr, Press, et al, Phys. Rev. B, vol. 47 (8), p. 4385 (1993)].
+        complex_t roughness = 1;
+        if (sigma > 0.0) {
+            const double sigeff = std::pow(M_PI_2, 1.5) * sigma;
+            roughness = std::sqrt(Math::tanhc(sigeff * kzi1) / Math::tanhc(sigeff * kzi));
+        }
+        const complex_t inv_roughness = 1.0 / roughness;
+        const complex_t kz_ratio = kzi1 / kzi * roughness;
+
+        const complex_t a00 = 0.5 * (inv_roughness + kz_ratio);
+        const complex_t a01 = 0.5 * (inv_roughness - kz_ratio);
+
+        return {a00, a01};
+    }
+}
+
+} //namespace
+
+//  ************************************************************************************************
+//  class implementation
+//  ************************************************************************************************
+
+Fluxes SpecularScalarStrategy::Execute(const SliceStack& slices, const kvector_t& k,
+                                       const RoughnessModel& r_model) const
 {
     std::vector<complex_t> kz = SampleUtils::KzComputation::computeReducedKz(slices, k);
-    return Execute(slices, kz);
+    return Execute(slices, kz, r_model);
 }
 
-Fluxes SpecularScalarStrategy::Execute(const SliceStack& slices,
-                                       const std::vector<complex_t>& kz) const
+Fluxes SpecularScalarStrategy::Execute(const SliceStack& slices, const std::vector<complex_t>& kz,
+                                       const RoughnessModel& r_model) const
 {
     ASSERT(slices.size() == kz.size());
 
-    const std::vector<Eigen::Vector2cd> TR = computeTR(slices, kz);
+    const std::vector<Eigen::Vector2cd> TR = computeTR(slices, kz, r_model);
 
     Fluxes result;
     for (size_t i = 0; i < kz.size(); ++i)
@@ -42,8 +92,8 @@ Fluxes SpecularScalarStrategy::Execute(const SliceStack& slices,
 }
 
 std::variant<complex_t, Eigen::Matrix2cd>
-SpecularScalarStrategy::computeTopLayerR(const SliceStack& slices,
-                                         const std::vector<complex_t>& kz) const
+SpecularScalarStrategy::computeTopLayerR(const SliceStack& slices, const std::vector<complex_t>& kz,
+                                         const RoughnessModel& r_model) const
 {
     ASSERT(slices.size() == kz.size());
 
@@ -61,7 +111,7 @@ SpecularScalarStrategy::computeTopLayerR(const SliceStack& slices,
         if (const auto roughness = slices.bottomRoughness(i))
             sigma = roughness->getSigma();
 
-        const auto [mp, mm] = transition(kz[i], kz[i + 1], sigma);
+        const auto [mp, mm] = ::transition(kz[i], kz[i + 1], sigma, r_model);
 
         const complex_t delta = exp_I(kz[i] * slices[i].thicknessOr0());
 
@@ -74,8 +124,9 @@ SpecularScalarStrategy::computeTopLayerR(const SliceStack& slices,
     return R_i1;
 }
 
-std::vector<Eigen::Vector2cd>
-SpecularScalarStrategy::computeTR(const SliceStack& slices, const std::vector<complex_t>& kz) const
+std::vector<Eigen::Vector2cd> SpecularScalarStrategy::computeTR(const SliceStack& slices,
+                                                                const std::vector<complex_t>& kz,
+                                                                const RoughnessModel& r_model) const
 {
     const size_t N = slices.size();
     std::vector<Eigen::Vector2cd> TR(N, {1., 0.});
@@ -98,7 +149,7 @@ SpecularScalarStrategy::computeTR(const SliceStack& slices, const std::vector<co
         if (const auto roughness = slices.bottomRoughness(i))
             sigma = roughness->getSigma();
 
-        const auto [mp, mm] = transition(kz[i], kz[i + 1], sigma);
+        const auto [mp, mm] = ::transition(kz[i], kz[i + 1], sigma, r_model);
 
         const complex_t delta = exp_I(kz[i] * slices[i].thicknessOr0());
 
diff --git a/Resample/Specular/SpecularScalarStrategy.h b/Resample/Specular/SpecularScalarStrategy.h
index f6c8f83dc88..b59df137538 100644
--- a/Resample/Specular/SpecularScalarStrategy.h
+++ b/Resample/Specular/SpecularScalarStrategy.h
@@ -38,24 +38,23 @@ class SpecularScalarStrategy : public ISpecularStrategy {
 public: // directly accessed in test
     //! Computes refraction angles and transmission/reflection coefficients
     //! for given coherent wave propagation in a multilayer.
-    virtual Fluxes Execute(const SliceStack& slices, const kvector_t& k) const override;
-
-protected:
-    virtual std::pair<complex_t, complex_t> transition(complex_t kzi, complex_t kzi1,
-                                                       double sigma) const = 0;
+    virtual Fluxes Execute(const SliceStack& slices, const kvector_t& k,
+                           const RoughnessModel& r_model) const override;
 
 private:
-    virtual Fluxes Execute(const SliceStack& slices,
-                           const std::vector<complex_t>& kz) const override;
+    virtual Fluxes Execute(const SliceStack& slices, const std::vector<complex_t>& kz,
+                           const RoughnessModel& r_model) const override;
 
     //! Computes the Fresnel R coefficient for the top layer only.
     //! Introduced in order to speed up pure reflectivity computations.
     virtual std::variant<complex_t, Eigen::Matrix2cd>
-    computeTopLayerR(const SliceStack& slices, const std::vector<complex_t>& kz) const override;
+    computeTopLayerR(const SliceStack& slices, const std::vector<complex_t>& kz,
+                     const RoughnessModel& r_model) const override;
 
     //! Computes the fluxes in T and R direction for each slice.
     std::vector<Eigen::Vector2cd> computeTR(const SliceStack& slices,
-                                            const std::vector<complex_t>& kz) const;
+                                            const std::vector<complex_t>& kz,
+                                            const RoughnessModel& r_model) const;
 };
 
 #endif // BORNAGAIN_RESAMPLE_SPECULAR_SPECULARSCALARSTRATEGY_H
diff --git a/Resample/Specular/SpecularScalarTanhStrategy.h b/Resample/Specular/SpecularScalarTanhStrategy.h
index 592de010629..399e45f7cee 100644
--- a/Resample/Specular/SpecularScalarTanhStrategy.h
+++ b/Resample/Specular/SpecularScalarTanhStrategy.h
@@ -31,8 +31,8 @@ class SpecularScalarTanhStrategy : public SpecularScalarStrategy {
 private:
     //! Roughness is modelled by tanh profile
     //! [e.g. Bahr, Press, et al, Phys. Rev. B, vol. 47 (8), p. 4385 (1993)].
-    virtual std::pair<complex_t, complex_t> transition(complex_t kzi, complex_t kzi1,
-                                                       double sigma) const override;
+    std::pair<complex_t, complex_t> transition(complex_t kzi, complex_t kzi1,
+                                                       double sigma) const;
 };
 
 #endif // BORNAGAIN_RESAMPLE_SPECULAR_SPECULARSCALARTANHSTRATEGY_H
diff --git a/Sample/Scattering/FormFactorDecoratorMaterial.cpp b/Sample/Scattering/FormFactorDecoratorMaterial.cpp
index e8fba077707..0194340f63a 100644
--- a/Sample/Scattering/FormFactorDecoratorMaterial.cpp
+++ b/Sample/Scattering/FormFactorDecoratorMaterial.cpp
@@ -47,8 +47,8 @@ void FormFactorDecoratorMaterial::setAmbientMaterial(const Material& material)
 
 complex_t FormFactorDecoratorMaterial::theFF(const WavevectorInfo& wavevectors) const
 {
-    const complex_t refrDiff = m_material.scalarSubtrSLD(wavevectors)
-        - m_ambient_material.scalarSubtrSLD(wavevectors);
+    const complex_t refrDiff =
+        m_material.scalarSubtrSLD(wavevectors) - m_ambient_material.scalarSubtrSLD(wavevectors);
     return refrDiff * m_ff->theFF(wavevectors);
 }
 
diff --git a/Tests/UnitTests/Core/Sample/RTTest.cpp b/Tests/UnitTests/Core/Sample/RTTest.cpp
index 295db652178..e7e80536090 100644
--- a/Tests/UnitTests/Core/Sample/RTTest.cpp
+++ b/Tests/UnitTests/Core/Sample/RTTest.cpp
@@ -1,7 +1,7 @@
 #include "Base/Math/Constants.h"
 #include "Resample/Options/SimulationOptions.h"
 #include "Resample/Processed/ProcessedSample.h"
-#include "Resample/Specular/SpecularScalarTanhStrategy.h"
+#include "Resample/Specular/SpecularScalarStrategy.h"
 #include "Sample/Aggregate/ParticleLayout.h"
 #include "Sample/Interface/LayerInterface.h"
 #include "Sample/Interface/LayerRoughness.h"
@@ -65,9 +65,9 @@ TEST_F(RTTest, SplitLayer)
     const ProcessedSample sample_2 = ProcessedSample::make(sample2, options);
 
     coeffs1 = getCoeffs(
-        std::make_unique<SpecularScalarTanhStrategy>()->Execute(sample_1.averageSlices(), k));
+        std::make_unique<SpecularScalarStrategy>()->Execute(sample_1.averageSlices(), k, {}));
     coeffs2 = getCoeffs(
-        std::make_unique<SpecularScalarTanhStrategy>()->Execute(sample_2.averageSlices(), k));
+        std::make_unique<SpecularScalarStrategy>()->Execute(sample_2.averageSlices(), k, {}));
 
     // printCoeffs( coeffs1 );
     // printCoeffs( coeffs2 );
@@ -103,9 +103,9 @@ TEST_F(RTTest, SplitBilayers)
     ProcessedSample sample_2 = ProcessedSample::make(sample2, options);
 
     coeffs1 = getCoeffs(
-        std::make_unique<SpecularScalarTanhStrategy>()->Execute(sample_1.averageSlices(), k));
+        std::make_unique<SpecularScalarStrategy>()->Execute(sample_1.averageSlices(), k, {}));
     coeffs2 = getCoeffs(
-        std::make_unique<SpecularScalarTanhStrategy>()->Execute(sample_2.averageSlices(), k));
+        std::make_unique<SpecularScalarStrategy>()->Execute(sample_2.averageSlices(), k, {}));
 
     //     printCoeffs( coeffs1 );
     //     printCoeffs( coeffs2 );
@@ -146,9 +146,9 @@ TEST_F(RTTest, Overflow)
     ProcessedSample sample_2 = ProcessedSample::make(sample2, options);
 
     coeffs1 = getCoeffs(
-        std::make_unique<SpecularScalarTanhStrategy>()->Execute(sample_1.averageSlices(), k));
+        std::make_unique<SpecularScalarStrategy>()->Execute(sample_1.averageSlices(), k, {}));
     coeffs2 = getCoeffs(
-        std::make_unique<SpecularScalarTanhStrategy>()->Execute(sample_2.averageSlices(), k));
+        std::make_unique<SpecularScalarStrategy>()->Execute(sample_2.averageSlices(), k, {}));
 
     //     printCoeffs( coeffs1 );
     //     printCoeffs( coeffs2 );
diff --git a/auto/Wrap/doxygenResample.i b/auto/Wrap/doxygenResample.i
index b5162dc5df7..eb6fba3f372 100644
--- a/auto/Wrap/doxygenResample.i
+++ b/auto/Wrap/doxygenResample.i
@@ -290,10 +290,10 @@ C++ includes: ISpecularStrategy.h
 %feature("docstring")  ISpecularStrategy::ISpecularStrategy "ISpecularStrategy::ISpecularStrategy(const ISpecularStrategy &other)=delete
 ";
 
-%feature("docstring")  ISpecularStrategy::Execute "virtual Fluxes ISpecularStrategy::Execute(const SliceStack &slices, const kvector_t &k) const =0
+%feature("docstring")  ISpecularStrategy::Execute "virtual Fluxes ISpecularStrategy::Execute(const SliceStack &slices, const kvector_t &k, const RoughnessModel &r_model) const =0
 ";
 
-%feature("docstring")  ISpecularStrategy::computeTopLayerR "virtual std::variant<complex_t, Eigen::Matrix2cd> ISpecularStrategy::computeTopLayerR(const SliceStack &slices, const std::vector< complex_t > &kz) const =0
+%feature("docstring")  ISpecularStrategy::computeTopLayerR "virtual std::variant<complex_t, Eigen::Matrix2cd> ISpecularStrategy::computeTopLayerR(const SliceStack &slices, const std::vector< complex_t > &kz, const RoughnessModel &r_model) const =0
 ";
 
 
@@ -739,17 +739,17 @@ Implements the transfer matrix formalism for the calculation of wave amplitudes
 C++ includes: SpecularMagneticStrategy.h
 ";
 
-%feature("docstring")  SpecularMagneticStrategy::Execute "Fluxes SpecularMagneticStrategy::Execute(const SliceStack &slices, const kvector_t &k) const override
+%feature("docstring")  SpecularMagneticStrategy::Execute "Fluxes SpecularMagneticStrategy::Execute(const SliceStack &slices, const kvector_t &k, const RoughnessModel &r_model) const override
 
 Computes refraction angle reflection/transmission coefficients for given sliced multilayer and wavevector k 
 ";
 
-%feature("docstring")  SpecularMagneticStrategy::Execute "Fluxes SpecularMagneticStrategy::Execute(const SliceStack &slices, const std::vector< complex_t > &kz) const override
+%feature("docstring")  SpecularMagneticStrategy::Execute "Fluxes SpecularMagneticStrategy::Execute(const SliceStack &slices, const std::vector< complex_t > &kz, const RoughnessModel &r_model) const override
 
 Computes refraction angle reflection/transmission coefficients for given sliced multilayer and a set of kz projections corresponding to each slice 
 ";
 
-%feature("docstring")  SpecularMagneticStrategy::computeTopLayerR "std::variant< complex_t, Eigen::Matrix2cd > SpecularMagneticStrategy::computeTopLayerR(const SliceStack &slices, const std::vector< complex_t > &kzs) const override
+%feature("docstring")  SpecularMagneticStrategy::computeTopLayerR "std::variant< complex_t, Eigen::Matrix2cd > SpecularMagneticStrategy::computeTopLayerR(const SliceStack &slices, const std::vector< complex_t > &kzs, const RoughnessModel &r_model) const override
 
 Computes the Fresnel R coefficient for the top layer only Introduced in order to speed up pure reflectivity computations 
 ";
@@ -789,7 +789,7 @@ Inherited by  SpecularScalarNCStrategy,  SpecularScalarTanhStrategy
 C++ includes: SpecularScalarStrategy.h
 ";
 
-%feature("docstring")  SpecularScalarStrategy::Execute "Fluxes SpecularScalarStrategy::Execute(const SliceStack &slices, const kvector_t &k) const override
+%feature("docstring")  SpecularScalarStrategy::Execute "Fluxes SpecularScalarStrategy::Execute(const SliceStack &slices, const kvector_t &k, const RoughnessModel &r_model) const override
 
 Computes refraction angles and transmission/reflection coefficients for given coherent wave propagation in a multilayer. 
 ";
@@ -848,6 +848,9 @@ C++ includes: SSCAStrategy.h
 // File: namespace_0d40.xml
 
 
+// File: namespace_0d46.xml
+
+
 // File: namespaceSampleUtils.xml
 
 
-- 
GitLab