diff --git a/Base/Math/Functions.cpp b/Base/Math/Functions.cpp
index 9d05d9c095f2ca8e93b617ae57bcd27fc62e7d7f..8eb82624b028128edf067532d55196a5faa645de 100644
--- a/Base/Math/Functions.cpp
+++ b/Base/Math/Functions.cpp
@@ -46,6 +46,11 @@ double Math::IntegratedGaussian(double x, double average, double std_dev)
     return (gsl_sf_erf(normalized_x / root2) + 1.0) / 2.0;
 }
 
+double Math::Heaviside(double x)
+{
+    return x > 0.0 ? 1.0 : 0.0;
+}
+
 double Math::cot(double x)
 {
     return tan((pi / 2) - x);
diff --git a/Base/Math/Functions.h b/Base/Math/Functions.h
index c293005724f43620712e88f9b78b672e8c0c0df7..6ee4bca54f454d6caf3f2be2e0497ec687a2f0e4 100644
--- a/Base/Math/Functions.h
+++ b/Base/Math/Functions.h
@@ -32,6 +32,7 @@ namespace Math {
 double StandardNormal(double x);
 double Gaussian(double x, double average, double std_dev);
 double IntegratedGaussian(double x, double average, double std_dev);
+double Heaviside(double x);
 
 //! cotangent function: \f$cot(x)\equiv1/tan(x)\f$
 double cot(double x);
diff --git a/Resample/Slice/ProfileHelper.cpp b/Resample/Slice/ProfileHelper.cpp
index d564804a6921fa949ae4284c5c97a455f838b501..1cd5b395e9db424bf55ffa6808bd6dee413c49cb 100644
--- a/Resample/Slice/ProfileHelper.cpp
+++ b/Resample/Slice/ProfileHelper.cpp
@@ -13,6 +13,7 @@
 //  ************************************************************************************************
 
 #include "Resample/Slice/ProfileHelper.h"
+#include "Base/Math/Functions.h"
 #include "Base/Util/Assert.h"
 #include "Sample/Interface/LayerRoughness.h"
 #include <numbers>
@@ -21,18 +22,12 @@ using std::numbers::pi;
 
 namespace {
 
-const double prefactor = std::sqrt(2.0 / pi);
-
-double TransitionTanh(double x)
+double Transition(double x, const LayerRoughness* roughness)
 {
-    return (1.0 - std::tanh(prefactor * x)) / 2.0;
-}
+    if (!roughness)
+        return Math::Heaviside(x);
 
-double Transition(double x, double sigma)
-{
-    if (sigma <= 0.0)
-        return x < 0.0 ? 1.0 : 0.0;
-    return TransitionTanh(x / sigma);
+    return roughness->roughnessModel()->transient(x, roughness->sigma());
 }
 
 const std::string SLD = "SLD";
@@ -81,9 +76,8 @@ std::vector<complex_t> ProfileHelper::profile(const std::vector<double>& z_value
         const complex_t diff =
             quantity(slice.material(), component) - quantity(sliceAbove.material(), component);
         for (size_t j = 0; j < z_values.size(); ++j) {
-            const double arg = (z_values[j] - slice.hig());
-            const LayerRoughness* roughness = slice.topRoughness();
-            const double t = Transition(arg, roughness ? roughness->sigma() : 0);
+            const double arg = (slice.hig() - z_values[j]);
+            const double t = Transition(arg, slice.topRoughness());
             result[j] += diff * t;
         }
     }
diff --git a/Resample/Specular/ComputeFluxMagnetic.cpp b/Resample/Specular/ComputeFluxMagnetic.cpp
index 8cb2beb827eca8c9231238a5c5e4514280eed9e6..27bd9ab9ad4144e738d1088c577ce761469a267e 100644
--- a/Resample/Specular/ComputeFluxMagnetic.cpp
+++ b/Resample/Specular/ComputeFluxMagnetic.cpp
@@ -117,7 +117,7 @@ Spinor checkForUnderflow(const Spinor& eigenvs)
 
 std::pair<SpinMatrix, SpinMatrix> refractionMatrixBlocks(const MatrixFlux& tr_a,
                                                          const MatrixFlux& tr_b, double sigma,
-                                                         const RoughnessModel& r_model)
+                                                         const RoughnessModel* r_model)
 {
     ASSERT(sigma >= 0);
     if (sigma < 10 * std::numeric_limits<double>::epsilon()) {
@@ -126,8 +126,9 @@ std::pair<SpinMatrix, SpinMatrix> refractionMatrixBlocks(const MatrixFlux& tr_a,
         const SpinMatrix sm = (SpinMatrix::One() - kk) / 2;
         return {sp, sm};
     }
+    ASSERT(r_model);
 
-    if (r_model == RoughnessModel::NEVOT_CROCE)
+    if (dynamic_cast<const ErfRoughness*>(r_model))
         return refractionMatrixBlocksNevot(tr_a, tr_b, sigma);
 
     return refractionMatrixBlocksTanh(tr_a, tr_b, sigma);
@@ -180,15 +181,12 @@ std::vector<MatrixFlux> computeTR(const SliceStack& slices, const std::vector<co
     TR[N - 1].m_R = SpinMatrix::Null(); // holds x = t^-1 * r.
 
     for (size_t i = N - 1; i > 0; --i) {
-        double sigma = 0.;
-        auto r_profile = RoughnessModel::DEFAULT;
-        if (const auto* roughness = slices.bottomRoughness(i)) {
-            sigma = roughness->sigma();
-            r_profile = roughness->profileModel();
-        }
+        const auto* roughness = slices.bottomRoughness(i);
+        const double sigma = roughness ? roughness->sigma() : 0.;
+        const auto r_model = roughness ? roughness->roughnessModel() : nullptr;
 
         // compute the 2x2 blocks of the transfer matrix
-        const auto [sp, sm] = refractionMatrixBlocks(TR[i - 1], TR[i], sigma, r_profile);
+        const auto [sp, sm] = refractionMatrixBlocks(TR[i - 1], TR[i], sigma, r_model);
         const SpinMatrix delta = TR[i - 1].computeDeltaMatrix(slices[i - 1].thicknessOr0());
 
         // compute the rotation matrix
@@ -289,16 +287,12 @@ SpinMatrix Compute::polarizedReflectivity(const SliceStack& slices,
 
     for (size_t i = N - 1; i > 0; --i) {
         MatrixFlux tr_i = createCoeff(i - 1);
-
-        double sigma = 0.;
-        auto r_profile = RoughnessModel::DEFAULT;
-        if (const auto* const roughness = slices.bottomRoughness(i - 1)) {
-            sigma = roughness->sigma();
-            r_profile = roughness->profileModel();
-        }
+        const auto* roughness = slices.bottomRoughness(i - 1);
+        const double sigma = roughness ? roughness->sigma() : 0.;
+        const auto r_model = roughness ? roughness->roughnessModel() : nullptr;
 
         // compute the 2x2 blocks of the transfer matrix
-        const auto [sp, sm] = ::refractionMatrixBlocks(tr_i, tr_i1, sigma, r_profile);
+        const auto [sp, sm] = ::refractionMatrixBlocks(tr_i, tr_i1, sigma, r_model);
         const SpinMatrix delta = tr_i.computeDeltaMatrix(slices[i - 1].thicknessOr0());
 
         // compute the rotation matrix
diff --git a/Resample/Specular/ComputeFluxScalar.cpp b/Resample/Specular/ComputeFluxScalar.cpp
index 35385c58b530a939f9bb42e562c3444f7e2e789d..bb27196696dfa26d519ccc5a429f97ea3e78dd18 100644
--- a/Resample/Specular/ComputeFluxScalar.cpp
+++ b/Resample/Specular/ComputeFluxScalar.cpp
@@ -28,7 +28,7 @@ namespace {
 
 //! See PhysRef, chapter "Scattering by rough interfaces", section "Interface with tanh profile".
 std::pair<complex_t, complex_t> transition(complex_t kzi, complex_t kzi1, double sigma,
-                                           const RoughnessModel& r_model)
+                                           const RoughnessModel* r_model)
 {
     const complex_t kz_ratio = kzi1 / kzi;
 
@@ -36,8 +36,9 @@ std::pair<complex_t, complex_t> transition(complex_t kzi, complex_t kzi1, double
         return {1. + kz_ratio, 1. - kz_ratio};
 
     ASSERT(sigma > 0);
+    ASSERT(r_model);
 
-    if (r_model == RoughnessModel::NEVOT_CROCE)
+    if (dynamic_cast<const ErfRoughness*>(r_model))
         // 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,
@@ -83,9 +84,9 @@ std::vector<Spinor> computeTR(const SliceStack& slices, const std::vector<comple
         const size_t jlast = X[i];
         const auto* roughness = slices.bottomRoughness(jthis);
         const double sigma = roughness ? roughness->sigma() : 0.;
-        const auto r_profile = roughness ? roughness->profileModel() : RoughnessModel::DEFAULT;
+        const auto r_model = roughness ? roughness->roughnessModel() : nullptr;
 
-        const auto [slp, slm] = transition(kz[jthis], kz[jlast], sigma, r_profile);
+        const auto [slp, slm] = transition(kz[jthis], kz[jlast], sigma, r_model);
 
         const complex_t delta = exp_I(kz[jthis] * slices[jthis].thicknessOr0());
         const complex_t f = delta / (slp + slm * ratio[jlast]);
@@ -135,14 +136,11 @@ complex_t Compute::scalarReflectivity(const SliceStack& slices, const std::vecto
     complex_t R_i1 = 0.;
 
     for (size_t i = N - 1; i > 0; i--) {
-        double sigma = 0.0;
-        auto r_profile = RoughnessModel::DEFAULT;
-        if (const auto* const roughness = slices.bottomRoughness(i - 1)) {
-            sigma = roughness->sigma();
-            r_profile = roughness->profileModel();
-        }
-
-        const auto [sp, sm] = ::transition(kz[i - 1], kz[i], sigma, r_profile);
+        const auto* roughness = slices.bottomRoughness(i - 1);
+        const double sigma = roughness ? roughness->sigma() : 0.;
+        const auto r_model = roughness ? roughness->roughnessModel() : nullptr;
+
+        const auto [sp, sm] = ::transition(kz[i - 1], kz[i], sigma, r_model);
 
         const complex_t delta = exp_I(kz[i - 1] * slices[i - 1].thicknessOr0());
 
diff --git a/Sample/Interface/LayerRoughness.cpp b/Sample/Interface/LayerRoughness.cpp
index b75423e5ff5c6e9f41264ad25baf6cc571133532..897a3a9b679179d44c1a4d90311f0896a5c6564a 100644
--- a/Sample/Interface/LayerRoughness.cpp
+++ b/Sample/Interface/LayerRoughness.cpp
@@ -25,26 +25,33 @@ using std::numbers::pi;
 //! @param hurstParameter: hurst parameter which describes how jagged the interface,
 //! dimensionless [0.0, 1.0], where 0.0 gives more spikes, 1.0 more smoothness
 //! @param lateralCorrLength: lateral correlation length of the roughness in nanometers
+//! @param profileModel: shape of the interfacial transition region
 LayerRoughness::LayerRoughness(double sigma, double hurstParameter, double lateralCorrLength,
-                               const RoughnessModel& profileModel)
+                               const RoughnessModel* roughnessModel)
     : m_sigma(sigma)
     , m_hurst_parameter(hurstParameter)
     , m_lateral_corr_length(lateralCorrLength)
-    , m_profile_model(profileModel)
 {
+    setRoughnessModel(roughnessModel);
     validateOrThrow();
 }
 
-LayerRoughness::LayerRoughness(double sigma, const RoughnessModel& profileModel)
-    : LayerRoughness(sigma, 0, 0, profileModel)
+LayerRoughness::LayerRoughness(double sigma, const RoughnessModel* roughnessModel)
+    : LayerRoughness(sigma, 0, 0, roughnessModel)
 {
 }
 
 LayerRoughness::LayerRoughness()
-    : LayerRoughness(0, 0, 0, RoughnessModel::DEFAULT)
+    : LayerRoughness(0, 0, 0, nullptr)
 {
 }
 
+LayerRoughness* LayerRoughness::clone() const
+{
+    return new LayerRoughness(m_sigma, m_hurst_parameter, m_lateral_corr_length,
+                              m_roughness_model.get());
+}
+
 //! Power spectral density of the surface roughness is a result of two-dimensional
 //! Fourier transform of the correlation function of the roughness profile.
 //!
@@ -88,3 +95,11 @@ std::string LayerRoughness::validate() const
     m_validated = true;
     return "";
 }
+
+void LayerRoughness::setRoughnessModel(const RoughnessModel* roughnessModel)
+{
+    if (!roughnessModel)
+        m_roughness_model = std::make_unique<DefaultRoughness>();
+    else
+        m_roughness_model.reset(roughnessModel->clone());
+}
diff --git a/Sample/Interface/LayerRoughness.h b/Sample/Interface/LayerRoughness.h
index 2f6885b42f7cee49586e0a19c4c5088a93158349..60265d97da91846ba71b9efd6033c29e96db947c 100644
--- a/Sample/Interface/LayerRoughness.h
+++ b/Sample/Interface/LayerRoughness.h
@@ -15,7 +15,7 @@
 #ifndef BORNAGAIN_SAMPLE_INTERFACE_LAYERROUGHNESS_H
 #define BORNAGAIN_SAMPLE_INTERFACE_LAYERROUGHNESS_H
 
-#include "Sample/Multilayer/RoughnessModels.h"
+#include "Sample/Interface/RoughnessModels.h"
 #include "Sample/Scattering/ISampleNode.h"
 #include <heinz/Vectors3D.h>
 
@@ -27,15 +27,11 @@
 class LayerRoughness : public ISampleNode {
 public:
     LayerRoughness(double sigma, double hurstParameter = 0, double lateralCorrLength = 0,
-                   const RoughnessModel& profileModel = RoughnessModel::DEFAULT);
-    LayerRoughness(double sigma, const RoughnessModel& profileModel);
+                   const RoughnessModel* roughnessModel = nullptr);
+    LayerRoughness(double sigma, const RoughnessModel* roughnessModel);
     LayerRoughness();
 
-    LayerRoughness* clone() const override
-    {
-        return new LayerRoughness(m_sigma, m_hurst_parameter, m_lateral_corr_length,
-                                  m_profile_model);
-    }
+    LayerRoughness* clone() const override;
     std::string className() const final { return "LayerRoughness"; }
     std::vector<ParaMeta> parDefs() const final
     {
@@ -72,20 +68,17 @@ public:
 
     std::string validate() const override;
 
-    void setProfileModel(const RoughnessModel& profileModel)
-    {
-        m_profile_model = profileModel;
-    }
-    RoughnessModel profileModel() const
+    void setRoughnessModel(const RoughnessModel* roughnessModel);
+    const RoughnessModel* roughnessModel() const
     {
-        return m_profile_model;
+        return m_roughness_model.get();
     }
 
 private:
     double m_sigma;           //!< rms of roughness
     double m_hurst_parameter; //!< Hurst parameter which describes how jagged the interface, 0<H<=1
     double m_lateral_corr_length; //!< lateral correlation length of the roughness
-    RoughnessModel m_profile_model;
+    std::unique_ptr<RoughnessModel> m_roughness_model; // never nullptr
 };
 
 #endif // BORNAGAIN_SAMPLE_INTERFACE_LAYERROUGHNESS_H
diff --git a/Sample/Interface/RoughnessModels.cpp b/Sample/Interface/RoughnessModels.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5ff88387020fa6ed2a8a69a24cc1f3addaa6395e
--- /dev/null
+++ b/Sample/Interface/RoughnessModels.cpp
@@ -0,0 +1,61 @@
+//  ************************************************************************************************
+//
+//  BornAgain: simulate and fit reflection and scattering
+//
+//! @file      Sample/Interface/RoughnessModels.cpp
+//! @brief     Implements RoughnessModels enumerator and Python wrapper.
+//!
+//! @homepage  http://www.bornagainproject.org
+//! @license   GNU General Public License v3 or higher (see COPYING)
+//! @copyright Forschungszentrum Jülich GmbH 2018
+//! @authors   Scientific Computing Group at MLZ (see CITATION, AUTHORS)
+//
+//  ************************************************************************************************
+
+#include "Sample/Interface/RoughnessModels.h"
+#include "Base/Math/Functions.h"
+#include "Base/Util/Assert.h"
+#include <cmath>
+#include <numbers>
+
+using std::numbers::pi;
+
+ErfRoughness::ErfRoughness()
+    : RoughnessModel()
+{
+}
+
+double ErfRoughness::transient(double x, double sigma) const
+{
+    ASSERT(sigma >= 0);
+    if (sigma == 0.0)
+        return Math::Heaviside(x);
+
+    const double prefactor = std::sqrt(1.0 / 2.0);
+    return (1.0 + std::erf(prefactor * x / sigma)) / 2.0;
+}
+
+ErfRoughness* ErfRoughness::clone() const
+{
+    return new ErfRoughness;
+}
+
+TanhRoughness::TanhRoughness()
+    : RoughnessModel()
+{
+}
+
+double TanhRoughness::transient(double x, double sigma) const
+{
+    ASSERT(sigma >= 0);
+    if (sigma == 0.0)
+        return Math::Heaviside(x);
+
+    const double prefactor = std::sqrt(2.0 / pi);
+    return (1.0 + std::tanh(prefactor * x / sigma)) / 2.0;
+}
+
+TanhRoughness* TanhRoughness::clone() const
+{
+    return new TanhRoughness;
+}
diff --git a/Sample/Multilayer/RoughnessModels.h b/Sample/Interface/RoughnessModels.h
similarity index 53%
rename from Sample/Multilayer/RoughnessModels.h
rename to Sample/Interface/RoughnessModels.h
index 5ef30e68a4bdac1eba31a5ee221940d66e19e060..53fa419fc4d66eb4ecb6e3a718d1f52ebc206d9e 100644
--- a/Sample/Multilayer/RoughnessModels.h
+++ b/Sample/Interface/RoughnessModels.h
@@ -2,7 +2,7 @@
 //
 //  BornAgain: simulate and fit reflection and scattering
 //
-//! @file      Sample/Multilayer/RoughnessModels.h
+//! @file      Sample/Interface/RoughnessModels.h
 //! @brief     Define RoughnessModels enumerator and Python wrapper.
 //!
 //! @homepage  http://www.bornagainproject.org
@@ -15,18 +15,28 @@
 #ifndef BORNAGAIN_SAMPLE_MULTILAYER_ROUGHNESSMODELS_H
 #define BORNAGAIN_SAMPLE_MULTILAYER_ROUGHNESSMODELS_H
 
-#include <string>
+#include "Base/Type/ICloneable.h"
 
-// workaround for SWIG (instead of just writing enum class RoughnessModel ...)
-struct RoughnessModelWrap {
-    enum RoughnessModel { DEFAULT, TANH, NEVOT_CROCE };
-#ifndef SWIG
-    // TODO: to automatize enum to string convertion, one can possibly use this solution
-    // https://stackoverflow.com/questions/147267/easy-way-to-use-variables-of-enum-types-as-string-in-c#202511
-    static std::string roughnessModelName(RoughnessModel model);
-#endif // SWIG
+class RoughnessModel : public ICloneable {
+public:
+    RoughnessModel* clone() const override = 0;
+    virtual double transient(double x, double sigma) const = 0;
 };
 
-using RoughnessModel = RoughnessModelWrap::RoughnessModel;
+class ErfRoughness : public RoughnessModel {
+public:
+    ErfRoughness();
+    double transient(double x, double sigma) const override;
+    ErfRoughness* clone() const override;
+};
+
+class TanhRoughness : public RoughnessModel {
+public:
+    TanhRoughness();
+    double transient(double x, double sigma) const override;
+    TanhRoughness* clone() const override;
+};
+
+using DefaultRoughness = TanhRoughness;
 
 #endif // BORNAGAIN_SAMPLE_MULTILAYER_ROUGHNESSMODELS_H
diff --git a/Sample/Multilayer/MultiLayer.h b/Sample/Multilayer/MultiLayer.h
index b911bfa2fc2a1626c1cb2d49b3d7db1089acf2c5..56f835a1912ffb9325f519e32bf066c9446ff289 100644
--- a/Sample/Multilayer/MultiLayer.h
+++ b/Sample/Multilayer/MultiLayer.h
@@ -16,7 +16,7 @@
 #define BORNAGAIN_SAMPLE_MULTILAYER_MULTILAYER_H
 
 #include "Base/Type/OwningVector.h"
-#include "Sample/Multilayer/RoughnessModels.h"
+#include "Sample/Interface/RoughnessModels.h"
 #include "Sample/Scattering/ISampleNode.h"
 #include <functional>
 #include <heinz/Vectors3D.h>
diff --git a/Sample/Multilayer/RoughnessModels.cpp b/Sample/Multilayer/RoughnessModels.cpp
deleted file mode 100644
index 3be97319244be839e61d1f1e36c437993a78a4b1..0000000000000000000000000000000000000000
--- a/Sample/Multilayer/RoughnessModels.cpp
+++ /dev/null
@@ -1,31 +0,0 @@
-//  ************************************************************************************************
-//
-//  BornAgain: simulate and fit reflection and scattering
-//
-//! @file      Sample/Multilayer/RoughnessModels.cpp
-//! @brief     Implements RoughnessModels enumerator and Python wrapper.
-//!
-//! @homepage  http://www.bornagainproject.org
-//! @license   GNU General Public License v3 or higher (see COPYING)
-//! @copyright Forschungszentrum Jülich GmbH 2018
-//! @authors   Scientific Computing Group at MLZ (see CITATION, AUTHORS)
-//
-//  ************************************************************************************************
-
-#include "Sample/Multilayer/RoughnessModels.h"
-#include <map>
-
-namespace {
-
-const std::map<RoughnessModel, std::string> roughnessModelNames = {
-    {RoughnessModel::DEFAULT, "RoughnessModel::DEFAULT"},
-    {RoughnessModel::TANH, "RoughnessModel::TANH"},
-    {RoughnessModel::NEVOT_CROCE, "RoughnessModel::NEVOT_CROCE"}};
-
-} // namespace
-
-
-std::string RoughnessModelWrap::roughnessModelName(RoughnessModel model)
-{
-    return roughnessModelNames.at(model);
-}
diff --git a/Sample/StandardSample/FeNiBilayerBuilder.cpp b/Sample/StandardSample/FeNiBilayerBuilder.cpp
index a56ee7aea1896625204a567eb91b2af0d02350a6..53a7401c80712dd2fa57ff2bcde6ce7410feb97b 100644
--- a/Sample/StandardSample/FeNiBilayerBuilder.cpp
+++ b/Sample/StandardSample/FeNiBilayerBuilder.cpp
@@ -41,49 +41,17 @@ public:
     double m_thickness_ni = 40. * Units::angstrom;
     double m_sigma_roughness = 0.;
     int m_effectiveSLD = 0;
-    RoughnessModel m_roughness_model = RoughnessModel::TANH;
+    std::unique_ptr<RoughnessModel> m_roughness_model;
 
     Options() = default;
-    Options NBilayers(int n)
-    {
-        m_NBilayers = n;
-        return *this;
-    }
-    Options angle(double angle)
-    {
-        m_angle = angle;
-        return *this;
-    }
-    Options magnetizationMagnitude(double M)
-    {
-        m_magnetization_magnitude = M;
-        return *this;
-    }
-    Options thicknessFe(double t)
-    {
-        m_thickness_fe = t;
-        return *this;
-    }
-    Options thicknessNi(double t)
-    {
-        m_thickness_ni = t;
-        return *this;
-    }
-    Options sigmaRoughness(double r)
-    {
-        m_sigma_roughness = r;
-        return *this;
-    }
-    Options effectiveSLD(int i)
-    {
-        m_effectiveSLD = i;
-        return *this;
-    }
-    Options roughnessModel(RoughnessModel rm)
-    {
-        m_roughness_model = rm;
-        return *this;
-    }
+    void setNBilayers(int n) { m_NBilayers = n; }
+    void setAngle(double angle) { m_angle = angle; }
+    void setMagnetizationMagnitude(double M) { m_magnetization_magnitude = M; }
+    void setThicknessFe(double t) { m_thickness_fe = t; }
+    void setThicknessNi(double t) { m_thickness_ni = t; }
+    void setSigmaRoughness(double r) { m_sigma_roughness = r; }
+    void setEffectiveSLD(int i) { m_effectiveSLD = i; }
+    void setRoughnessModel(RoughnessModel* rm) { m_roughness_model.reset(rm); }
 };
 
 
@@ -98,7 +66,7 @@ public:
         , thicknessNi(opt.m_thickness_ni)
         , sigmaRoughness(opt.m_sigma_roughness)
         , effectiveSLD(opt.m_effectiveSLD)
-        , roughnessProfile(opt.m_roughness_model)
+        , roughnessModel(opt.m_roughness_model ? opt.m_roughness_model->clone() : nullptr)
     {
         if (angle != 0. && effectiveSLD != 0.)
             throw std::runtime_error("Cannot perform scalar computation "
@@ -119,7 +87,7 @@ private:
     double thicknessNi;
     double sigmaRoughness;
     int effectiveSLD;
-    RoughnessModel roughnessProfile;
+    std::unique_ptr<RoughnessModel> roughnessModel;
 
     R3 magnetizationVector;
 
@@ -145,7 +113,7 @@ std::unique_ptr<MultiLayer> FeNiBilayer::constructSample()
     Layer l_Fe{m_Fe, thicknessFe};
     Layer l_Ni{m_Ni, thicknessNi};
 
-    LayerRoughness roughness{sigmaRoughness, 0., 0., roughnessProfile};
+    LayerRoughness roughness{sigmaRoughness, 0., 0., roughnessModel.get()};
     result->addLayer(Layer{m_ambient});
 
     for (auto i = 0; i < NBilayers; ++i) {
@@ -168,38 +136,46 @@ MultiLayer* ExemplarySamples::createFeNiBilayer()
 
 MultiLayer* ExemplarySamples::createFeNiBilayerTanh()
 {
-    auto sample = FeNiBilayer{
-        Options().sigmaRoughness(2. * Units::angstrom).roughnessModel(RoughnessModel::TANH)};
+    Options opt;
+    opt.setSigmaRoughness(2. * Units::angstrom);
+    opt.setRoughnessModel(new TanhRoughness);
+    auto sample = FeNiBilayer{std::move(opt)};
     return sample.release();
 }
 
 MultiLayer* ExemplarySamples::createFeNiBilayerNC()
 {
-    auto sample = FeNiBilayer{
-        Options().sigmaRoughness(2. * Units::angstrom).roughnessModel(RoughnessModel::NEVOT_CROCE)};
+    Options opt;
+    opt.setSigmaRoughness(2. * Units::angstrom);
+    opt.setRoughnessModel(new ErfRoughness);
+    auto sample = FeNiBilayer{std::move(opt)};
     return sample.release();
 }
 
 MultiLayer* ExemplarySamples::createFeNiBilayerSpinFlip()
 {
-    auto sample = FeNiBilayer{Options().angle(38. * deg)};
+    Options opt;
+    opt.setAngle(38. * deg);
+    auto sample = FeNiBilayer{std::move(opt)};
     return sample.release();
 }
 
 MultiLayer* ExemplarySamples::createFeNiBilayerSpinFlipTanh()
 {
-    auto sample = FeNiBilayer{Options()
-                                  .angle(38 * deg)
-                                  .sigmaRoughness(2. * Units::angstrom)
-                                  .roughnessModel(RoughnessModel::TANH)};
+    Options opt;
+    opt.setAngle(38. * deg);
+    opt.setSigmaRoughness(2. * Units::angstrom);
+    opt.setRoughnessModel(new TanhRoughness);
+    auto sample = FeNiBilayer{std::move(opt)};
     return sample.release();
 }
 
 MultiLayer* ExemplarySamples::createFeNiBilayerSpinFlipNC()
 {
-    auto sample = FeNiBilayer{Options()
-                                  .angle(38 * deg)
-                                  .sigmaRoughness(2. * Units::angstrom)
-                                  .roughnessModel(RoughnessModel::NEVOT_CROCE)};
+    Options opt;
+    opt.setAngle(38. * deg);
+    opt.setSigmaRoughness(2. * Units::angstrom);
+    opt.setRoughnessModel(new ErfRoughness);
+    auto sample = FeNiBilayer{std::move(opt)};
     return sample.release();
 }
diff --git a/Sample/StandardSample/MagneticLayersBuilder.cpp b/Sample/StandardSample/MagneticLayersBuilder.cpp
index 7eb368909072cfb9b826ffe313bf7d5a3fbfc66a..d49c76fab7d9f9cc595c7008abb0c38c37ee0752 100644
--- a/Sample/StandardSample/MagneticLayersBuilder.cpp
+++ b/Sample/StandardSample/MagneticLayersBuilder.cpp
@@ -31,12 +31,6 @@ namespace {
 
 const double sphere_radius = 5;
 
-const std::map<std::string, std::pair<double, RoughnessModel>> RoughnessCases = {
-    {"Flat", {0., RoughnessModel::TANH}},
-    {"Tanh", {2., RoughnessModel::TANH}},
-    {"NevotCroce", {2., RoughnessModel::NEVOT_CROCE}},
-};
-
 } // namespace
 
 //  ************************************************************************************************
@@ -119,7 +113,20 @@ MultiLayer* ExemplarySamples::createMagneticLayer()
 MultiLayer*
 ExemplarySamples::createSimpleMagneticRotationWithRoughness(const std::string& roughnessKey)
 {
-    const auto& [sigmaRoughness, roughnessProfile] = RoughnessCases.at(roughnessKey);
+    double sigmaRoughness = 0.;
+    std::unique_ptr<RoughnessModel> roughnessModel;
+
+    if (roughnessKey == "Flat") {
+        sigmaRoughness = 0.;
+    } else if (roughnessKey == "Tanh") {
+        sigmaRoughness = 2. * Units::angstrom;
+        roughnessModel.reset(new TanhRoughness);
+    } else if (roughnessKey == "Erf") {
+        sigmaRoughness = 2. * Units::angstrom;
+        roughnessModel.reset(new ErfRoughness);
+    } else
+        ASSERT_NEVER;
+
     auto* sample = new MultiLayer();
 
     R3 substr_field = R3(0.0, 1e6, 0.0);
@@ -129,8 +136,8 @@ ExemplarySamples::createSimpleMagneticRotationWithRoughness(const std::string& r
     Material layer_material = RefractiveMaterial("MagLayer", 6e-4, 2e-8, layer_field);
 
     auto roughness = LayerRoughness();
-    roughness.setSigma(sigmaRoughness * Units::angstrom);
-    roughness.setProfileModel(roughnessProfile);
+    roughness.setSigma(sigmaRoughness);
+    roughness.setRoughnessModel(roughnessModel.get());
 
     Layer vacuum_layer(vacuum_material);
     Layer substrate_layer(substrate_material);
diff --git a/Sample/StandardSample/MagneticLayersBuilder.h b/Sample/StandardSample/MagneticLayersBuilder.h
index d7943f40bd127f53b7bb021e1d446e39bc26c92f..5c62d7de8090df55115c4aad1ffb0ecc54f934a5 100644
--- a/Sample/StandardSample/MagneticLayersBuilder.h
+++ b/Sample/StandardSample/MagneticLayersBuilder.h
@@ -20,7 +20,8 @@
 
 class MultiLayer;
 
-#include "Sample/Multilayer/RoughnessModels.h"
+#include "Sample/Interface/RoughnessModels.h"
+#include <string>
 
 //! Builds sample: spheres in substrate layer with a zero magnetic field.
 
diff --git a/Sample/StandardSample/MultiLayerWithRoughnessBuilder.cpp b/Sample/StandardSample/MultiLayerWithRoughnessBuilder.cpp
index 5315c82ce55abcccd362d71caaa464dfb08ec10e..cbd58028caa50564dc7740c7e880e0a44c468cae 100644
--- a/Sample/StandardSample/MultiLayerWithRoughnessBuilder.cpp
+++ b/Sample/StandardSample/MultiLayerWithRoughnessBuilder.cpp
@@ -19,7 +19,7 @@
 #include "Sample/Multilayer/MultiLayer.h"
 
 namespace {
-MultiLayer* createMultiLayerWithRoughnessModel(const RoughnessModel& profileModel)
+MultiLayer* createMultiLayerWithRoughnessModel(const RoughnessModel* roughnessModel)
 {
     const double thicknessA(2.5);
     const double thicknessB(5.0);
@@ -38,7 +38,7 @@ MultiLayer* createMultiLayerWithRoughnessModel(const RoughnessModel& profileMode
     Layer partB_layer(part_b_material, thicknessB);
     Layer substrate_layer(substrate_material, 0);
 
-    LayerRoughness roughness(sigma, hurst, lateralCorrLength, profileModel);
+    LayerRoughness roughness(sigma, hurst, lateralCorrLength, roughnessModel);
 
     auto* sample = new MultiLayer();
     sample->addLayer(vacuum_layer);
@@ -54,10 +54,11 @@ MultiLayer* createMultiLayerWithRoughnessModel(const RoughnessModel& profileMode
 
 MultiLayer* ExemplarySamples::createMultiLayerWithRoughness()
 {
-    return createMultiLayerWithRoughnessModel(RoughnessModel::DEFAULT);
+    return createMultiLayerWithRoughnessModel(nullptr);
 }
 
 MultiLayer* ExemplarySamples::createMultiLayerWithNCRoughness()
 {
-    return createMultiLayerWithRoughnessModel(RoughnessModel::NEVOT_CROCE);
+    std::unique_ptr<RoughnessModel> rm = std::make_unique<ErfRoughness>();
+    return createMultiLayerWithRoughnessModel(rm.get());
 }
diff --git a/Tests/ReferenceData/Suite/MagneticRotationReflectivityMM_NevotCroce.int b/Tests/ReferenceData/Suite/MagneticRotationReflectivityMM_Erf.int
similarity index 100%
rename from Tests/ReferenceData/Suite/MagneticRotationReflectivityMM_NevotCroce.int
rename to Tests/ReferenceData/Suite/MagneticRotationReflectivityMM_Erf.int
diff --git a/Tests/ReferenceData/Suite/MagneticRotationReflectivityMP_NevotCroce.int b/Tests/ReferenceData/Suite/MagneticRotationReflectivityMP_Erf.int
similarity index 100%
rename from Tests/ReferenceData/Suite/MagneticRotationReflectivityMP_NevotCroce.int
rename to Tests/ReferenceData/Suite/MagneticRotationReflectivityMP_Erf.int
diff --git a/Tests/ReferenceData/Suite/MagneticRotationReflectivityPM_NevotCroce.int b/Tests/ReferenceData/Suite/MagneticRotationReflectivityPM_Erf.int
similarity index 100%
rename from Tests/ReferenceData/Suite/MagneticRotationReflectivityPM_NevotCroce.int
rename to Tests/ReferenceData/Suite/MagneticRotationReflectivityPM_Erf.int
diff --git a/Tests/ReferenceData/Suite/MagneticRotationReflectivityPP_NevotCroce.int b/Tests/ReferenceData/Suite/MagneticRotationReflectivityPP_Erf.int
similarity index 100%
rename from Tests/ReferenceData/Suite/MagneticRotationReflectivityPP_NevotCroce.int
rename to Tests/ReferenceData/Suite/MagneticRotationReflectivityPP_Erf.int
diff --git a/Tests/Suite/Common/TestSuite.h b/Tests/Suite/Common/TestSuite.h
index ed646ecffde291e64a840157c8effc5345bde6c0..03c256848303579e03c3152b27de4838ea3cacbc 100644
--- a/Tests/Suite/Common/TestSuite.h
+++ b/Tests/Suite/Common/TestSuite.h
@@ -668,7 +668,7 @@ TEST(TESTNAME, PolarizedQAngleReflectivity)
 
 TEST(TESTNAME, MagneticRotationReflectivity)
 {
-    for (const auto roughnessKey : {"Flat", "Tanh", "NevotCroce"}) {
+    for (const auto roughnessKey : {"Flat", "Tanh", "Erf"}) {
         std::unique_ptr<const MultiLayer> sample(
             ExemplarySamples::createSimpleMagneticRotationWithRoughness(roughnessKey));
         for (const std::string polKey : {"PP", "PM", "MP", "MM"}) {
diff --git a/Wrap/Swig/libBornAgainSample.i b/Wrap/Swig/libBornAgainSample.i
index 71c29b83a2b3b2d4ea32e7a7cc24d0cbfdd968e1..237c37dd6949604216fe7445cf8d4e731e856c76 100644
--- a/Wrap/Swig/libBornAgainSample.i
+++ b/Wrap/Swig/libBornAgainSample.i
@@ -101,9 +101,7 @@
 %include "Sample/Multilayer/Layer.h"
 %include "Sample/Multilayer/MultiLayer.h"
 
-// SWIG workaround for using axes units the same way as they are used in cpp files
-%rename(RoughnessModel) RoughnessModelWrap;
-%include "Sample/Multilayer/RoughnessModels.h"
+%include "Sample/Interface/RoughnessModels.h"
 
 %include "Sample/HardParticle/IFormFactorPolyhedron.h"
 %include "Sample/HardParticle/IFormFactorPrism.h"
diff --git a/auto/Examples/fit/specular/Honeycomb_fit.py b/auto/Examples/fit/specular/Honeycomb_fit.py
index 8a363b9bdfa03693c629138845ea779d56a2d4a2..e67e00e6fcbfd9931d7ef4919378a56431c05126 100755
--- a/auto/Examples/fit/specular/Honeycomb_fit.py
+++ b/auto/Examples/fit/specular/Honeycomb_fit.py
@@ -48,7 +48,7 @@ def get_sample(P, sign, T):
     l_SiO2 = ba.Layer(material_SiO2, P["t_SiO2"]*angstrom)
     l_Si = ba.Layer(material_Si)
 
-    roughness_model = ba.RoughnessModel.NEVOT_CROCE
+    roughness_model = ba.ErfRoughness()
     rPyOx = ba.LayerRoughness(P["rPyOx"]*angstrom, roughness_model)
     rPy2 = ba.LayerRoughness(P["rPy2"]*angstrom, roughness_model)
     rPy1 = ba.LayerRoughness(P["rPy1"]*angstrom, roughness_model)
diff --git a/auto/Examples/specular/RoughnessModel.py b/auto/Examples/specular/RoughnessModel.py
index 6654146f3b3244bcc8fbdea2693ef204f196e8aa..31c3d448e029b406627db64023bf7b11fb3b9c0c 100755
--- a/auto/Examples/specular/RoughnessModel.py
+++ b/auto/Examples/specular/RoughnessModel.py
@@ -57,8 +57,8 @@ def simulate(roughness_model, title):
 
 if __name__ == '__main__':
     results = [
-        simulate(ba.RoughnessModel.NEVOT_CROCE, "Névot-Croce"),
-        simulate(ba.RoughnessModel.TANH, "Tanh"),
+        simulate(ba.ErfRoughness(), "Névot-Croce"),
+        simulate(ba.TanhRoughness(), "Tanh"),
     ]
 
     bp.plot_multicurve(results)
diff --git a/auto/Examples/varia/MaterialProfile.py b/auto/Examples/varia/MaterialProfile.py
index 11099b3a5ea8bff478f53f3695c18f7179ee45ce..bd7e7d0278d80d948eda1c44cc0150a4aea6216a 100755
--- a/auto/Examples/varia/MaterialProfile.py
+++ b/auto/Examples/varia/MaterialProfile.py
@@ -29,7 +29,8 @@ def get_sample():
     # sample
     sample = ba.MultiLayer()
     sample.addLayer(ambient_layer)
-    roughness = ba.LayerRoughness(5*angstrom, 0.5, 10*angstrom)
+    roughness_model = ba.TanhRoughness()
+    roughness = ba.LayerRoughness(5*angstrom, 0.5, 10*angstrom, roughness_model)
     for _ in range(4):
         sample.addLayerWithTopRoughness(ti_layer, roughness)
         sample.addLayerWithTopRoughness(ni_layer, roughness)
diff --git a/auto/MiniExamples/fit/specular/Honeycomb_fit.py b/auto/MiniExamples/fit/specular/Honeycomb_fit.py
index 7ace55254893ceca361ccfe7cf843c100ac8f1e8..54c11676bb70db82ba398d5c33136d970e35fb4e 100755
--- a/auto/MiniExamples/fit/specular/Honeycomb_fit.py
+++ b/auto/MiniExamples/fit/specular/Honeycomb_fit.py
@@ -48,7 +48,7 @@ def get_sample(P, sign, T):
     l_SiO2 = ba.Layer(material_SiO2, P["t_SiO2"]*angstrom)
     l_Si = ba.Layer(material_Si)
 
-    roughness_model = ba.RoughnessModel.NEVOT_CROCE
+    roughness_model = ba.ErfRoughness()
     rPyOx = ba.LayerRoughness(P["rPyOx"]*angstrom, roughness_model)
     rPy2 = ba.LayerRoughness(P["rPy2"]*angstrom, roughness_model)
     rPy1 = ba.LayerRoughness(P["rPy1"]*angstrom, roughness_model)
diff --git a/auto/MiniExamples/specular/RoughnessModel.py b/auto/MiniExamples/specular/RoughnessModel.py
index cbff0a9ed81079c854fc092947739af7e621f6e0..b8de9ff317ba2a4ba4a6e74720fdafac1b13b366 100755
--- a/auto/MiniExamples/specular/RoughnessModel.py
+++ b/auto/MiniExamples/specular/RoughnessModel.py
@@ -57,8 +57,8 @@ def simulate(roughness_model, title):
 
 if __name__ == '__main__':
     results = [
-        simulate(ba.RoughnessModel.NEVOT_CROCE, "Névot-Croce"),
-        simulate(ba.RoughnessModel.TANH, "Tanh"),
+        simulate(ba.ErfRoughness(), "Névot-Croce"),
+        simulate(ba.TanhRoughness(), "Tanh"),
     ]
 
     bp.plot_multicurve(results)
diff --git a/auto/MiniExamples/varia/MaterialProfile.py b/auto/MiniExamples/varia/MaterialProfile.py
index 11099b3a5ea8bff478f53f3695c18f7179ee45ce..bd7e7d0278d80d948eda1c44cc0150a4aea6216a 100755
--- a/auto/MiniExamples/varia/MaterialProfile.py
+++ b/auto/MiniExamples/varia/MaterialProfile.py
@@ -29,7 +29,8 @@ def get_sample():
     # sample
     sample = ba.MultiLayer()
     sample.addLayer(ambient_layer)
-    roughness = ba.LayerRoughness(5*angstrom, 0.5, 10*angstrom)
+    roughness_model = ba.TanhRoughness()
+    roughness = ba.LayerRoughness(5*angstrom, 0.5, 10*angstrom, roughness_model)
     for _ in range(4):
         sample.addLayerWithTopRoughness(ti_layer, roughness)
         sample.addLayerWithTopRoughness(ni_layer, roughness)
diff --git a/auto/Wrap/libBornAgainSample.py b/auto/Wrap/libBornAgainSample.py
index 7705a9e31c7365de71d23aaad577e7955f2bc3e3..f4248bd0dfbff2b95dd9bfe665fb5bae37194708 100644
--- a/auto/Wrap/libBornAgainSample.py
+++ b/auto/Wrap/libBornAgainSample.py
@@ -4177,8 +4177,8 @@ class LayerRoughness(ISampleNode):
 
     def __init__(self, *args):
         r"""
-        __init__(LayerRoughness self, double sigma, double hurstParameter=0, double lateralCorrLength=0, RoughnessModel const & profileModel=RoughnessModel::DEFAULT) -> LayerRoughness
-        __init__(LayerRoughness self, double sigma, RoughnessModel const & profileModel) -> LayerRoughness
+        __init__(LayerRoughness self, double sigma, double hurstParameter=0, double lateralCorrLength=0, RoughnessModel roughnessModel=None) -> LayerRoughness
+        __init__(LayerRoughness self, double sigma, RoughnessModel roughnessModel) -> LayerRoughness
         __init__(LayerRoughness self) -> LayerRoughness
         """
         _libBornAgainSample.LayerRoughness_swiginit(self, _libBornAgainSample.new_LayerRoughness(*args))
@@ -4231,13 +4231,13 @@ class LayerRoughness(ISampleNode):
         r"""validate(LayerRoughness self) -> std::string"""
         return _libBornAgainSample.LayerRoughness_validate(self)
 
-    def setProfileModel(self, profileModel):
-        r"""setProfileModel(LayerRoughness self, RoughnessModel const & profileModel)"""
-        return _libBornAgainSample.LayerRoughness_setProfileModel(self, profileModel)
+    def setRoughnessModel(self, roughnessModel):
+        r"""setRoughnessModel(LayerRoughness self, RoughnessModel roughnessModel)"""
+        return _libBornAgainSample.LayerRoughness_setRoughnessModel(self, roughnessModel)
 
-    def profileModel(self):
-        r"""profileModel(LayerRoughness self) -> RoughnessModel"""
-        return _libBornAgainSample.LayerRoughness_profileModel(self)
+    def roughnessModel(self):
+        r"""roughnessModel(LayerRoughness self) -> RoughnessModel"""
+        return _libBornAgainSample.LayerRoughness_roughnessModel(self)
     __swig_destroy__ = _libBornAgainSample.delete_LayerRoughness
 
 # Register LayerRoughness in _libBornAgainSample:
@@ -4316,24 +4316,68 @@ class MultiLayer(ISampleNode):
 
 # Register MultiLayer in _libBornAgainSample:
 _libBornAgainSample.MultiLayer_swigregister(MultiLayer)
-class RoughnessModel(object):
-    r"""Proxy of C++ RoughnessModelWrap class."""
+class RoughnessModel(libBornAgainBase.ICloneable):
+    r"""Proxy of C++ RoughnessModel class."""
 
     thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
 
     def __init__(self, *args, **kwargs):
-        raise AttributeError("No constructor defined")
+        raise AttributeError("No constructor defined - class is abstract")
     __repr__ = _swig_repr
-    DEFAULT = _libBornAgainSample.RoughnessModel_DEFAULT
-    
-    TANH = _libBornAgainSample.RoughnessModel_TANH
-    
-    NEVOT_CROCE = _libBornAgainSample.RoughnessModel_NEVOT_CROCE
-    
+
+    def clone(self):
+        r"""clone(RoughnessModel self) -> RoughnessModel"""
+        return _libBornAgainSample.RoughnessModel_clone(self)
+
+    def transient(self, x, sigma):
+        r"""transient(RoughnessModel self, double x, double sigma) -> double"""
+        return _libBornAgainSample.RoughnessModel_transient(self, x, sigma)
     __swig_destroy__ = _libBornAgainSample.delete_RoughnessModel
 
 # Register RoughnessModel in _libBornAgainSample:
 _libBornAgainSample.RoughnessModel_swigregister(RoughnessModel)
+class ErfRoughness(RoughnessModel):
+    r"""Proxy of C++ ErfRoughness class."""
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+    __repr__ = _swig_repr
+
+    def __init__(self):
+        r"""__init__(ErfRoughness self) -> ErfRoughness"""
+        _libBornAgainSample.ErfRoughness_swiginit(self, _libBornAgainSample.new_ErfRoughness())
+
+    def transient(self, x, sigma):
+        r"""transient(ErfRoughness self, double x, double sigma) -> double"""
+        return _libBornAgainSample.ErfRoughness_transient(self, x, sigma)
+
+    def clone(self):
+        r"""clone(ErfRoughness self) -> ErfRoughness"""
+        return _libBornAgainSample.ErfRoughness_clone(self)
+    __swig_destroy__ = _libBornAgainSample.delete_ErfRoughness
+
+# Register ErfRoughness in _libBornAgainSample:
+_libBornAgainSample.ErfRoughness_swigregister(ErfRoughness)
+class TanhRoughness(RoughnessModel):
+    r"""Proxy of C++ TanhRoughness class."""
+
+    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
+    __repr__ = _swig_repr
+
+    def __init__(self):
+        r"""__init__(TanhRoughness self) -> TanhRoughness"""
+        _libBornAgainSample.TanhRoughness_swiginit(self, _libBornAgainSample.new_TanhRoughness())
+
+    def transient(self, x, sigma):
+        r"""transient(TanhRoughness self, double x, double sigma) -> double"""
+        return _libBornAgainSample.TanhRoughness_transient(self, x, sigma)
+
+    def clone(self):
+        r"""clone(TanhRoughness self) -> TanhRoughness"""
+        return _libBornAgainSample.TanhRoughness_clone(self)
+    __swig_destroy__ = _libBornAgainSample.delete_TanhRoughness
+
+# Register TanhRoughness in _libBornAgainSample:
+_libBornAgainSample.TanhRoughness_swigregister(TanhRoughness)
 class IFormFactorPolyhedron(IFormFactor):
     r"""Proxy of C++ IFormFactorPolyhedron class."""
 
diff --git a/auto/Wrap/libBornAgainSample_wrap.cpp b/auto/Wrap/libBornAgainSample_wrap.cpp
index 512cd6c4c20ae75adb4b766f890f5c8736a216c1..ce5579ccbba0d2ef1f0c55a4f7b8a77f6a3c54ec 100644
--- a/auto/Wrap/libBornAgainSample_wrap.cpp
+++ b/auto/Wrap/libBornAgainSample_wrap.cpp
@@ -3661,85 +3661,85 @@ namespace Swig {
 #define SWIGTYPE_p_Cylinder swig_types[13]
 #define SWIGTYPE_p_Dodecahedron swig_types[14]
 #define SWIGTYPE_p_EllipsoidalCylinder swig_types[15]
-#define SWIGTYPE_p_FuzzySphere swig_types[16]
-#define SWIGTYPE_p_GaussFisherPeakShape swig_types[17]
-#define SWIGTYPE_p_GaussSphere swig_types[18]
-#define SWIGTYPE_p_HemiEllipsoid swig_types[19]
-#define SWIGTYPE_p_HexagonalLattice2D swig_types[20]
-#define SWIGTYPE_p_HorizontalCylinder swig_types[21]
-#define SWIGTYPE_p_ICloneable swig_types[22]
-#define SWIGTYPE_p_ICosineRipple swig_types[23]
-#define SWIGTYPE_p_IFormFactor swig_types[24]
-#define SWIGTYPE_p_IFormFactorPolyhedron swig_types[25]
-#define SWIGTYPE_p_IFormFactorPrism swig_types[26]
-#define SWIGTYPE_p_IInterference swig_types[27]
-#define SWIGTYPE_p_IMaterialImpl swig_types[28]
-#define SWIGTYPE_p_INode swig_types[29]
-#define SWIGTYPE_p_IParticle swig_types[30]
-#define SWIGTYPE_p_IPeakShape swig_types[31]
-#define SWIGTYPE_p_IProfile1D swig_types[32]
-#define SWIGTYPE_p_IProfile2D swig_types[33]
-#define SWIGTYPE_p_IProfileRectangularRipple swig_types[34]
-#define SWIGTYPE_p_IProfileRipple swig_types[35]
-#define SWIGTYPE_p_IRotation swig_types[36]
-#define SWIGTYPE_p_ISampleNode swig_types[37]
-#define SWIGTYPE_p_ISawtoothRipple swig_types[38]
-#define SWIGTYPE_p_ISelectionRule swig_types[39]
-#define SWIGTYPE_p_Icosahedron swig_types[40]
-#define SWIGTYPE_p_IdentityRotation swig_types[41]
-#define SWIGTYPE_p_Interference1DLattice swig_types[42]
-#define SWIGTYPE_p_Interference2DLattice swig_types[43]
-#define SWIGTYPE_p_Interference2DParacrystal swig_types[44]
-#define SWIGTYPE_p_Interference2DSuperLattice swig_types[45]
-#define SWIGTYPE_p_InterferenceFinite2DLattice swig_types[46]
-#define SWIGTYPE_p_InterferenceHardDisk swig_types[47]
-#define SWIGTYPE_p_InterferenceNone swig_types[48]
-#define SWIGTYPE_p_InterferenceRadialParacrystal swig_types[49]
-#define SWIGTYPE_p_IsotropicGaussPeakShape swig_types[50]
-#define SWIGTYPE_p_IsotropicLorentzPeakShape swig_types[51]
-#define SWIGTYPE_p_Lattice2D swig_types[52]
-#define SWIGTYPE_p_Lattice2D__ReciprocalBases swig_types[53]
-#define SWIGTYPE_p_Lattice3D swig_types[54]
-#define SWIGTYPE_p_Layer swig_types[55]
-#define SWIGTYPE_p_LayerRoughness swig_types[56]
-#define SWIGTYPE_p_LongBoxGauss swig_types[57]
-#define SWIGTYPE_p_LongBoxLorentz swig_types[58]
-#define SWIGTYPE_p_LorentzFisherPeakShape swig_types[59]
-#define SWIGTYPE_p_Material swig_types[60]
-#define SWIGTYPE_p_MaterialBySLDImpl swig_types[61]
-#define SWIGTYPE_p_Mesocrystal swig_types[62]
-#define SWIGTYPE_p_MisesFisherGaussPeakShape swig_types[63]
-#define SWIGTYPE_p_MisesGaussPeakShape swig_types[64]
-#define SWIGTYPE_p_MultiLayer swig_types[65]
-#define SWIGTYPE_p_Particle swig_types[66]
-#define SWIGTYPE_p_ParticleLayout swig_types[67]
-#define SWIGTYPE_p_PlatonicOctahedron swig_types[68]
-#define SWIGTYPE_p_PlatonicTetrahedron swig_types[69]
-#define SWIGTYPE_p_Prism3 swig_types[70]
-#define SWIGTYPE_p_Prism6 swig_types[71]
-#define SWIGTYPE_p_Profile1DCauchy swig_types[72]
-#define SWIGTYPE_p_Profile1DCosine swig_types[73]
-#define SWIGTYPE_p_Profile1DGate swig_types[74]
-#define SWIGTYPE_p_Profile1DGauss swig_types[75]
-#define SWIGTYPE_p_Profile1DTriangle swig_types[76]
-#define SWIGTYPE_p_Profile1DVoigt swig_types[77]
-#define SWIGTYPE_p_Profile2DCauchy swig_types[78]
-#define SWIGTYPE_p_Profile2DCone swig_types[79]
-#define SWIGTYPE_p_Profile2DGate swig_types[80]
-#define SWIGTYPE_p_Profile2DGauss swig_types[81]
-#define SWIGTYPE_p_Profile2DVoigt swig_types[82]
-#define SWIGTYPE_p_Pyramid2 swig_types[83]
-#define SWIGTYPE_p_Pyramid3 swig_types[84]
-#define SWIGTYPE_p_Pyramid4 swig_types[85]
-#define SWIGTYPE_p_Pyramid6 swig_types[86]
-#define SWIGTYPE_p_RefractiveMaterialImpl swig_types[87]
-#define SWIGTYPE_p_Rotation3DT_double_t swig_types[88]
-#define SWIGTYPE_p_RotationEuler swig_types[89]
-#define SWIGTYPE_p_RotationX swig_types[90]
-#define SWIGTYPE_p_RotationY swig_types[91]
-#define SWIGTYPE_p_RotationZ swig_types[92]
-#define SWIGTYPE_p_RoughnessModelWrap swig_types[93]
-#define SWIGTYPE_p_RoughnessModelWrap__RoughnessModel swig_types[94]
+#define SWIGTYPE_p_ErfRoughness swig_types[16]
+#define SWIGTYPE_p_FuzzySphere swig_types[17]
+#define SWIGTYPE_p_GaussFisherPeakShape swig_types[18]
+#define SWIGTYPE_p_GaussSphere swig_types[19]
+#define SWIGTYPE_p_HemiEllipsoid swig_types[20]
+#define SWIGTYPE_p_HexagonalLattice2D swig_types[21]
+#define SWIGTYPE_p_HorizontalCylinder swig_types[22]
+#define SWIGTYPE_p_ICloneable swig_types[23]
+#define SWIGTYPE_p_ICosineRipple swig_types[24]
+#define SWIGTYPE_p_IFormFactor swig_types[25]
+#define SWIGTYPE_p_IFormFactorPolyhedron swig_types[26]
+#define SWIGTYPE_p_IFormFactorPrism swig_types[27]
+#define SWIGTYPE_p_IInterference swig_types[28]
+#define SWIGTYPE_p_IMaterialImpl swig_types[29]
+#define SWIGTYPE_p_INode swig_types[30]
+#define SWIGTYPE_p_IParticle swig_types[31]
+#define SWIGTYPE_p_IPeakShape swig_types[32]
+#define SWIGTYPE_p_IProfile1D swig_types[33]
+#define SWIGTYPE_p_IProfile2D swig_types[34]
+#define SWIGTYPE_p_IProfileRectangularRipple swig_types[35]
+#define SWIGTYPE_p_IProfileRipple swig_types[36]
+#define SWIGTYPE_p_IRotation swig_types[37]
+#define SWIGTYPE_p_ISampleNode swig_types[38]
+#define SWIGTYPE_p_ISawtoothRipple swig_types[39]
+#define SWIGTYPE_p_ISelectionRule swig_types[40]
+#define SWIGTYPE_p_Icosahedron swig_types[41]
+#define SWIGTYPE_p_IdentityRotation swig_types[42]
+#define SWIGTYPE_p_Interference1DLattice swig_types[43]
+#define SWIGTYPE_p_Interference2DLattice swig_types[44]
+#define SWIGTYPE_p_Interference2DParacrystal swig_types[45]
+#define SWIGTYPE_p_Interference2DSuperLattice swig_types[46]
+#define SWIGTYPE_p_InterferenceFinite2DLattice swig_types[47]
+#define SWIGTYPE_p_InterferenceHardDisk swig_types[48]
+#define SWIGTYPE_p_InterferenceNone swig_types[49]
+#define SWIGTYPE_p_InterferenceRadialParacrystal swig_types[50]
+#define SWIGTYPE_p_IsotropicGaussPeakShape swig_types[51]
+#define SWIGTYPE_p_IsotropicLorentzPeakShape swig_types[52]
+#define SWIGTYPE_p_Lattice2D swig_types[53]
+#define SWIGTYPE_p_Lattice2D__ReciprocalBases swig_types[54]
+#define SWIGTYPE_p_Lattice3D swig_types[55]
+#define SWIGTYPE_p_Layer swig_types[56]
+#define SWIGTYPE_p_LayerRoughness swig_types[57]
+#define SWIGTYPE_p_LongBoxGauss swig_types[58]
+#define SWIGTYPE_p_LongBoxLorentz swig_types[59]
+#define SWIGTYPE_p_LorentzFisherPeakShape swig_types[60]
+#define SWIGTYPE_p_Material swig_types[61]
+#define SWIGTYPE_p_MaterialBySLDImpl swig_types[62]
+#define SWIGTYPE_p_Mesocrystal swig_types[63]
+#define SWIGTYPE_p_MisesFisherGaussPeakShape swig_types[64]
+#define SWIGTYPE_p_MisesGaussPeakShape swig_types[65]
+#define SWIGTYPE_p_MultiLayer swig_types[66]
+#define SWIGTYPE_p_Particle swig_types[67]
+#define SWIGTYPE_p_ParticleLayout swig_types[68]
+#define SWIGTYPE_p_PlatonicOctahedron swig_types[69]
+#define SWIGTYPE_p_PlatonicTetrahedron swig_types[70]
+#define SWIGTYPE_p_Prism3 swig_types[71]
+#define SWIGTYPE_p_Prism6 swig_types[72]
+#define SWIGTYPE_p_Profile1DCauchy swig_types[73]
+#define SWIGTYPE_p_Profile1DCosine swig_types[74]
+#define SWIGTYPE_p_Profile1DGate swig_types[75]
+#define SWIGTYPE_p_Profile1DGauss swig_types[76]
+#define SWIGTYPE_p_Profile1DTriangle swig_types[77]
+#define SWIGTYPE_p_Profile1DVoigt swig_types[78]
+#define SWIGTYPE_p_Profile2DCauchy swig_types[79]
+#define SWIGTYPE_p_Profile2DCone swig_types[80]
+#define SWIGTYPE_p_Profile2DGate swig_types[81]
+#define SWIGTYPE_p_Profile2DGauss swig_types[82]
+#define SWIGTYPE_p_Profile2DVoigt swig_types[83]
+#define SWIGTYPE_p_Pyramid2 swig_types[84]
+#define SWIGTYPE_p_Pyramid3 swig_types[85]
+#define SWIGTYPE_p_Pyramid4 swig_types[86]
+#define SWIGTYPE_p_Pyramid6 swig_types[87]
+#define SWIGTYPE_p_RefractiveMaterialImpl swig_types[88]
+#define SWIGTYPE_p_Rotation3DT_double_t swig_types[89]
+#define SWIGTYPE_p_RotationEuler swig_types[90]
+#define SWIGTYPE_p_RotationX swig_types[91]
+#define SWIGTYPE_p_RotationY swig_types[92]
+#define SWIGTYPE_p_RotationZ swig_types[93]
+#define SWIGTYPE_p_RoughnessModel swig_types[94]
 #define SWIGTYPE_p_SawtoothRippleBox swig_types[95]
 #define SWIGTYPE_p_SawtoothRippleGauss swig_types[96]
 #define SWIGTYPE_p_SawtoothRippleLorentz swig_types[97]
@@ -3749,62 +3749,63 @@ namespace Swig {
 #define SWIGTYPE_p_Spheroid swig_types[101]
 #define SWIGTYPE_p_SpinMatrix swig_types[102]
 #define SWIGTYPE_p_SquareLattice2D swig_types[103]
-#define SWIGTYPE_p_TruncatedCube swig_types[104]
-#define SWIGTYPE_p_TruncatedSphere swig_types[105]
-#define SWIGTYPE_p_TruncatedSpheroid swig_types[106]
-#define SWIGTYPE_p_Vec3T_double_t swig_types[107]
-#define SWIGTYPE_p_Vec3T_int_t swig_types[108]
-#define SWIGTYPE_p_Vec3T_std__complexT_double_t_t swig_types[109]
-#define SWIGTYPE_p_WavevectorInfo swig_types[110]
-#define SWIGTYPE_p_allocator_type swig_types[111]
-#define SWIGTYPE_p_char swig_types[112]
-#define SWIGTYPE_p_difference_type swig_types[113]
-#define SWIGTYPE_p_first_type swig_types[114]
-#define SWIGTYPE_p_int swig_types[115]
-#define SWIGTYPE_p_key_type swig_types[116]
-#define SWIGTYPE_p_long_long swig_types[117]
-#define SWIGTYPE_p_mapped_type swig_types[118]
-#define SWIGTYPE_p_p_PyObject swig_types[119]
-#define SWIGTYPE_p_second_type swig_types[120]
-#define SWIGTYPE_p_short swig_types[121]
-#define SWIGTYPE_p_signed_char swig_types[122]
-#define SWIGTYPE_p_size_type swig_types[123]
-#define SWIGTYPE_p_std__allocatorT_INode_const_p_t swig_types[124]
-#define SWIGTYPE_p_std__allocatorT_Vec3T_double_t_t swig_types[125]
-#define SWIGTYPE_p_std__allocatorT_double_t swig_types[126]
-#define SWIGTYPE_p_std__allocatorT_int_t swig_types[127]
-#define SWIGTYPE_p_std__allocatorT_std__complexT_double_t_t swig_types[128]
-#define SWIGTYPE_p_std__allocatorT_std__pairT_double_double_t_t swig_types[129]
-#define SWIGTYPE_p_std__allocatorT_std__pairT_std__string_const_double_t_t swig_types[130]
-#define SWIGTYPE_p_std__allocatorT_std__string_t swig_types[131]
-#define SWIGTYPE_p_std__allocatorT_std__vectorT_double_t_t swig_types[132]
-#define SWIGTYPE_p_std__allocatorT_std__vectorT_int_t_t swig_types[133]
-#define SWIGTYPE_p_std__allocatorT_unsigned_long_t swig_types[134]
-#define SWIGTYPE_p_std__complexT_double_t swig_types[135]
-#define SWIGTYPE_p_std__functionT_double_fdoubleF_t swig_types[136]
-#define SWIGTYPE_p_std__invalid_argument swig_types[137]
-#define SWIGTYPE_p_std__lessT_std__string_t swig_types[138]
-#define SWIGTYPE_p_std__mapT_std__string_double_t swig_types[139]
-#define SWIGTYPE_p_std__pairT_double_double_t swig_types[140]
-#define SWIGTYPE_p_std__vectorT_INode_const_p_t swig_types[141]
-#define SWIGTYPE_p_std__vectorT_ParaMeta_std__allocatorT_ParaMeta_t_t swig_types[142]
-#define SWIGTYPE_p_std__vectorT_Vec3T_double_t_t swig_types[143]
-#define SWIGTYPE_p_std__vectorT_double_t swig_types[144]
-#define SWIGTYPE_p_std__vectorT_int_t swig_types[145]
-#define SWIGTYPE_p_std__vectorT_std__complexT_double_t_t swig_types[146]
-#define SWIGTYPE_p_std__vectorT_std__pairT_double_double_t_t swig_types[147]
-#define SWIGTYPE_p_std__vectorT_std__string_t swig_types[148]
-#define SWIGTYPE_p_std__vectorT_std__vectorT_double_t_t swig_types[149]
-#define SWIGTYPE_p_std__vectorT_std__vectorT_int_t_t swig_types[150]
-#define SWIGTYPE_p_std__vectorT_unsigned_long_t swig_types[151]
-#define SWIGTYPE_p_swig__SwigPyIterator swig_types[152]
-#define SWIGTYPE_p_unsigned_char swig_types[153]
-#define SWIGTYPE_p_unsigned_int swig_types[154]
-#define SWIGTYPE_p_unsigned_long_long swig_types[155]
-#define SWIGTYPE_p_unsigned_short swig_types[156]
-#define SWIGTYPE_p_value_type swig_types[157]
-static swig_type_info *swig_types[159];
-static swig_module_info swig_module = {swig_types, 158, 0, 0, 0, 0};
+#define SWIGTYPE_p_TanhRoughness swig_types[104]
+#define SWIGTYPE_p_TruncatedCube swig_types[105]
+#define SWIGTYPE_p_TruncatedSphere swig_types[106]
+#define SWIGTYPE_p_TruncatedSpheroid swig_types[107]
+#define SWIGTYPE_p_Vec3T_double_t swig_types[108]
+#define SWIGTYPE_p_Vec3T_int_t swig_types[109]
+#define SWIGTYPE_p_Vec3T_std__complexT_double_t_t swig_types[110]
+#define SWIGTYPE_p_WavevectorInfo swig_types[111]
+#define SWIGTYPE_p_allocator_type swig_types[112]
+#define SWIGTYPE_p_char swig_types[113]
+#define SWIGTYPE_p_difference_type swig_types[114]
+#define SWIGTYPE_p_first_type swig_types[115]
+#define SWIGTYPE_p_int swig_types[116]
+#define SWIGTYPE_p_key_type swig_types[117]
+#define SWIGTYPE_p_long_long swig_types[118]
+#define SWIGTYPE_p_mapped_type swig_types[119]
+#define SWIGTYPE_p_p_PyObject swig_types[120]
+#define SWIGTYPE_p_second_type swig_types[121]
+#define SWIGTYPE_p_short swig_types[122]
+#define SWIGTYPE_p_signed_char swig_types[123]
+#define SWIGTYPE_p_size_type swig_types[124]
+#define SWIGTYPE_p_std__allocatorT_INode_const_p_t swig_types[125]
+#define SWIGTYPE_p_std__allocatorT_Vec3T_double_t_t swig_types[126]
+#define SWIGTYPE_p_std__allocatorT_double_t swig_types[127]
+#define SWIGTYPE_p_std__allocatorT_int_t swig_types[128]
+#define SWIGTYPE_p_std__allocatorT_std__complexT_double_t_t swig_types[129]
+#define SWIGTYPE_p_std__allocatorT_std__pairT_double_double_t_t swig_types[130]
+#define SWIGTYPE_p_std__allocatorT_std__pairT_std__string_const_double_t_t swig_types[131]
+#define SWIGTYPE_p_std__allocatorT_std__string_t swig_types[132]
+#define SWIGTYPE_p_std__allocatorT_std__vectorT_double_t_t swig_types[133]
+#define SWIGTYPE_p_std__allocatorT_std__vectorT_int_t_t swig_types[134]
+#define SWIGTYPE_p_std__allocatorT_unsigned_long_t swig_types[135]
+#define SWIGTYPE_p_std__complexT_double_t swig_types[136]
+#define SWIGTYPE_p_std__functionT_double_fdoubleF_t swig_types[137]
+#define SWIGTYPE_p_std__invalid_argument swig_types[138]
+#define SWIGTYPE_p_std__lessT_std__string_t swig_types[139]
+#define SWIGTYPE_p_std__mapT_std__string_double_t swig_types[140]
+#define SWIGTYPE_p_std__pairT_double_double_t swig_types[141]
+#define SWIGTYPE_p_std__vectorT_INode_const_p_t swig_types[142]
+#define SWIGTYPE_p_std__vectorT_ParaMeta_std__allocatorT_ParaMeta_t_t swig_types[143]
+#define SWIGTYPE_p_std__vectorT_Vec3T_double_t_t swig_types[144]
+#define SWIGTYPE_p_std__vectorT_double_t swig_types[145]
+#define SWIGTYPE_p_std__vectorT_int_t swig_types[146]
+#define SWIGTYPE_p_std__vectorT_std__complexT_double_t_t swig_types[147]
+#define SWIGTYPE_p_std__vectorT_std__pairT_double_double_t_t swig_types[148]
+#define SWIGTYPE_p_std__vectorT_std__string_t swig_types[149]
+#define SWIGTYPE_p_std__vectorT_std__vectorT_double_t_t swig_types[150]
+#define SWIGTYPE_p_std__vectorT_std__vectorT_int_t_t swig_types[151]
+#define SWIGTYPE_p_std__vectorT_unsigned_long_t swig_types[152]
+#define SWIGTYPE_p_swig__SwigPyIterator swig_types[153]
+#define SWIGTYPE_p_unsigned_char swig_types[154]
+#define SWIGTYPE_p_unsigned_int swig_types[155]
+#define SWIGTYPE_p_unsigned_long_long swig_types[156]
+#define SWIGTYPE_p_unsigned_short swig_types[157]
+#define SWIGTYPE_p_value_type swig_types[158]
+static swig_type_info *swig_types[160];
+static swig_module_info swig_module = {swig_types, 159, 0, 0, 0, 0};
 #define SWIG_TypeQuery(name) SWIG_TypeQueryModule(&swig_module, &swig_module, name)
 #define SWIG_MangledTypeQuery(name) SWIG_MangledTypeQueryModule(&swig_module, &swig_module, name)
 
@@ -50498,16 +50499,15 @@ SWIGINTERN PyObject *_wrap_new_LayerRoughness__SWIG_0(PyObject *self, Py_ssize_t
   double arg1 ;
   double arg2 ;
   double arg3 ;
-  RoughnessModel *arg4 = 0 ;
+  RoughnessModel *arg4 = (RoughnessModel *) 0 ;
   double val1 ;
   int ecode1 = 0 ;
   double val2 ;
   int ecode2 = 0 ;
   double val3 ;
   int ecode3 = 0 ;
-  int val4 ;
-  int ecode4 ;
-  RoughnessModel temp4 ;
+  void *argp4 = 0 ;
+  int res4 = 0 ;
   LayerRoughness *result = 0 ;
   
   (void)self;
@@ -50527,16 +50527,14 @@ SWIGINTERN PyObject *_wrap_new_LayerRoughness__SWIG_0(PyObject *self, Py_ssize_t
     SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "new_LayerRoughness" "', argument " "3"" of type '" "double""'");
   } 
   arg3 = static_cast< double >(val3);
-  ecode4 = SWIG_AsVal_int (swig_obj[3], &val4);
-  if (!SWIG_IsOK(ecode4)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "new_LayerRoughness" "', argument " "4"" of type '" "RoughnessModel const &""'");
-  } else {
-    temp4 = static_cast< RoughnessModel >(val4);
-    arg4 = &temp4;
+  res4 = SWIG_ConvertPtr(swig_obj[3], &argp4,SWIGTYPE_p_RoughnessModel, 0 |  0 );
+  if (!SWIG_IsOK(res4)) {
+    SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "new_LayerRoughness" "', argument " "4"" of type '" "RoughnessModel const *""'"); 
   }
+  arg4 = reinterpret_cast< RoughnessModel * >(argp4);
   {
     try {
-      result = (LayerRoughness *)new LayerRoughness(arg1,arg2,arg3,(RoughnessModel const &)*arg4);
+      result = (LayerRoughness *)new LayerRoughness(arg1,arg2,arg3,(RoughnessModel const *)arg4);
     } catch (const std::exception& ex) {
       // message shown in the Python interpreter
       const std::string msg {
@@ -50675,12 +50673,11 @@ fail:
 SWIGINTERN PyObject *_wrap_new_LayerRoughness__SWIG_4(PyObject *self, Py_ssize_t nobjs, PyObject **swig_obj) {
   PyObject *resultobj = 0;
   double arg1 ;
-  RoughnessModel *arg2 = 0 ;
+  RoughnessModel *arg2 = (RoughnessModel *) 0 ;
   double val1 ;
   int ecode1 = 0 ;
-  int val2 ;
-  int ecode2 ;
-  RoughnessModel temp2 ;
+  void *argp2 = 0 ;
+  int res2 = 0 ;
   LayerRoughness *result = 0 ;
   
   (void)self;
@@ -50690,16 +50687,14 @@ SWIGINTERN PyObject *_wrap_new_LayerRoughness__SWIG_4(PyObject *self, Py_ssize_t
     SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "new_LayerRoughness" "', argument " "1"" of type '" "double""'");
   } 
   arg1 = static_cast< double >(val1);
-  ecode2 = SWIG_AsVal_int (swig_obj[1], &val2);
-  if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "new_LayerRoughness" "', argument " "2"" of type '" "RoughnessModel const &""'");
-  } else {
-    temp2 = static_cast< RoughnessModel >(val2);
-    arg2 = &temp2;
+  res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_RoughnessModel, 0 |  0 );
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "new_LayerRoughness" "', argument " "2"" of type '" "RoughnessModel const *""'"); 
   }
+  arg2 = reinterpret_cast< RoughnessModel * >(argp2);
   {
     try {
-      result = (LayerRoughness *)new LayerRoughness(arg1,(RoughnessModel const &)*arg2);
+      result = (LayerRoughness *)new LayerRoughness(arg1,(RoughnessModel const *)arg2);
     } catch (const std::exception& ex) {
       // message shown in the Python interpreter
       const std::string msg {
@@ -50767,10 +50762,9 @@ SWIGINTERN PyObject *_wrap_new_LayerRoughness(PyObject *self, PyObject *args) {
       _v = SWIG_CheckState(res);
     }
     if (_v) {
-      {
-        int res = SWIG_AsVal_int(argv[1], NULL);
-        _v = SWIG_CheckState(res);
-      }
+      void *vptr = 0;
+      int res = SWIG_ConvertPtr(argv[1], &vptr, SWIGTYPE_p_RoughnessModel, 0);
+      _v = SWIG_CheckState(res);
       if (_v) {
         return _wrap_new_LayerRoughness__SWIG_4(self, argc, argv);
       }
@@ -50831,10 +50825,9 @@ SWIGINTERN PyObject *_wrap_new_LayerRoughness(PyObject *self, PyObject *args) {
           _v = SWIG_CheckState(res);
         }
         if (_v) {
-          {
-            int res = SWIG_AsVal_int(argv[3], NULL);
-            _v = SWIG_CheckState(res);
-          }
+          void *vptr = 0;
+          int res = SWIG_ConvertPtr(argv[3], &vptr, SWIGTYPE_p_RoughnessModel, 0);
+          _v = SWIG_CheckState(res);
           if (_v) {
             return _wrap_new_LayerRoughness__SWIG_0(self, argc, argv);
           }
@@ -50846,11 +50839,11 @@ SWIGINTERN PyObject *_wrap_new_LayerRoughness(PyObject *self, PyObject *args) {
 fail:
   SWIG_Python_RaiseOrModifyTypeError("Wrong number or type of arguments for overloaded function 'new_LayerRoughness'.\n"
     "  Possible C/C++ prototypes are:\n"
-    "    LayerRoughness::LayerRoughness(double,double,double,RoughnessModel const &)\n"
+    "    LayerRoughness::LayerRoughness(double,double,double,RoughnessModel const *)\n"
     "    LayerRoughness::LayerRoughness(double,double,double)\n"
     "    LayerRoughness::LayerRoughness(double,double)\n"
     "    LayerRoughness::LayerRoughness(double)\n"
-    "    LayerRoughness::LayerRoughness(double,RoughnessModel const &)\n"
+    "    LayerRoughness::LayerRoughness(double,RoughnessModel const *)\n"
     "    LayerRoughness::LayerRoughness()\n");
   return 0;
 }
@@ -51312,34 +51305,31 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_LayerRoughness_setProfileModel(PyObject *self, PyObject *args) {
+SWIGINTERN PyObject *_wrap_LayerRoughness_setRoughnessModel(PyObject *self, PyObject *args) {
   PyObject *resultobj = 0;
   LayerRoughness *arg1 = (LayerRoughness *) 0 ;
-  RoughnessModel *arg2 = 0 ;
+  RoughnessModel *arg2 = (RoughnessModel *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
-  int val2 ;
-  int ecode2 ;
-  RoughnessModel temp2 ;
+  void *argp2 = 0 ;
+  int res2 = 0 ;
   PyObject *swig_obj[2] ;
   
   (void)self;
-  if (!SWIG_Python_UnpackTuple(args, "LayerRoughness_setProfileModel", 2, 2, swig_obj)) SWIG_fail;
+  if (!SWIG_Python_UnpackTuple(args, "LayerRoughness_setRoughnessModel", 2, 2, swig_obj)) SWIG_fail;
   res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_LayerRoughness, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "LayerRoughness_setProfileModel" "', argument " "1"" of type '" "LayerRoughness *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "LayerRoughness_setRoughnessModel" "', argument " "1"" of type '" "LayerRoughness *""'"); 
   }
   arg1 = reinterpret_cast< LayerRoughness * >(argp1);
-  ecode2 = SWIG_AsVal_int (swig_obj[1], &val2);
-  if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "LayerRoughness_setProfileModel" "', argument " "2"" of type '" "RoughnessModel const &""'");
-  } else {
-    temp2 = static_cast< RoughnessModel >(val2);
-    arg2 = &temp2;
+  res2 = SWIG_ConvertPtr(swig_obj[1], &argp2,SWIGTYPE_p_RoughnessModel, 0 |  0 );
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "LayerRoughness_setRoughnessModel" "', argument " "2"" of type '" "RoughnessModel const *""'"); 
   }
+  arg2 = reinterpret_cast< RoughnessModel * >(argp2);
   {
     try {
-      (arg1)->setProfileModel((RoughnessModel const &)*arg2);
+      (arg1)->setRoughnessModel((RoughnessModel const *)arg2);
     } catch (const std::exception& ex) {
       // message shown in the Python interpreter
       const std::string msg {
@@ -51355,25 +51345,25 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_LayerRoughness_profileModel(PyObject *self, PyObject *args) {
+SWIGINTERN PyObject *_wrap_LayerRoughness_roughnessModel(PyObject *self, PyObject *args) {
   PyObject *resultobj = 0;
   LayerRoughness *arg1 = (LayerRoughness *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject *swig_obj[1] ;
-  RoughnessModel result;
+  RoughnessModel *result = 0 ;
   
   (void)self;
   if (!args) SWIG_fail;
   swig_obj[0] = args;
   res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_LayerRoughness, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "LayerRoughness_profileModel" "', argument " "1"" of type '" "LayerRoughness const *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "LayerRoughness_roughnessModel" "', argument " "1"" of type '" "LayerRoughness const *""'"); 
   }
   arg1 = reinterpret_cast< LayerRoughness * >(argp1);
   {
     try {
-      result = (RoughnessModel)((LayerRoughness const *)arg1)->profileModel();
+      result = (RoughnessModel *)((LayerRoughness const *)arg1)->roughnessModel();
     } catch (const std::exception& ex) {
       // message shown in the Python interpreter
       const std::string msg {
@@ -51382,7 +51372,7 @@ SWIGINTERN PyObject *_wrap_LayerRoughness_profileModel(PyObject *self, PyObject
       SWIG_exception(SWIG_RuntimeError, msg.c_str());
     }
   }
-  resultobj = SWIG_From_int(static_cast< int >(result));
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_RoughnessModel, 0 |  0 );
   return resultobj;
 fail:
   return NULL;
@@ -52158,9 +52148,92 @@ SWIGINTERN PyObject *MultiLayer_swiginit(PyObject *SWIGUNUSEDPARM(self), PyObjec
   return SWIG_Python_InitShadowInstance(args);
 }
 
+SWIGINTERN PyObject *_wrap_RoughnessModel_clone(PyObject *self, PyObject *args) {
+  PyObject *resultobj = 0;
+  RoughnessModel *arg1 = (RoughnessModel *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject *swig_obj[1] ;
+  RoughnessModel *result = 0 ;
+  
+  (void)self;
+  if (!args) SWIG_fail;
+  swig_obj[0] = args;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_RoughnessModel, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "RoughnessModel_clone" "', argument " "1"" of type '" "RoughnessModel const *""'"); 
+  }
+  arg1 = reinterpret_cast< RoughnessModel * >(argp1);
+  {
+    try {
+      result = (RoughnessModel *)((RoughnessModel const *)arg1)->clone();
+    } catch (const std::exception& ex) {
+      // message shown in the Python interpreter
+      const std::string msg {
+        "BornAgain C++ Exception: " + std::string(ex.what())
+      };
+      SWIG_exception(SWIG_RuntimeError, msg.c_str());
+    }
+  }
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_RoughnessModel, 0 |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_RoughnessModel_transient(PyObject *self, PyObject *args) {
+  PyObject *resultobj = 0;
+  RoughnessModel *arg1 = (RoughnessModel *) 0 ;
+  double arg2 ;
+  double arg3 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  double val2 ;
+  int ecode2 = 0 ;
+  double val3 ;
+  int ecode3 = 0 ;
+  PyObject *swig_obj[3] ;
+  double result;
+  
+  (void)self;
+  if (!SWIG_Python_UnpackTuple(args, "RoughnessModel_transient", 3, 3, swig_obj)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_RoughnessModel, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "RoughnessModel_transient" "', argument " "1"" of type '" "RoughnessModel const *""'"); 
+  }
+  arg1 = reinterpret_cast< RoughnessModel * >(argp1);
+  ecode2 = SWIG_AsVal_double(swig_obj[1], &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "RoughnessModel_transient" "', argument " "2"" of type '" "double""'");
+  } 
+  arg2 = static_cast< double >(val2);
+  ecode3 = SWIG_AsVal_double(swig_obj[2], &val3);
+  if (!SWIG_IsOK(ecode3)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "RoughnessModel_transient" "', argument " "3"" of type '" "double""'");
+  } 
+  arg3 = static_cast< double >(val3);
+  {
+    try {
+      result = (double)((RoughnessModel const *)arg1)->transient(arg2,arg3);
+    } catch (const std::exception& ex) {
+      // message shown in the Python interpreter
+      const std::string msg {
+        "BornAgain C++ Exception: " + std::string(ex.what())
+      };
+      SWIG_exception(SWIG_RuntimeError, msg.c_str());
+    }
+  }
+  resultobj = SWIG_From_double(static_cast< double >(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_delete_RoughnessModel(PyObject *self, PyObject *args) {
   PyObject *resultobj = 0;
-  RoughnessModelWrap *arg1 = (RoughnessModelWrap *) 0 ;
+  RoughnessModel *arg1 = (RoughnessModel *) 0 ;
   void *argp1 = 0 ;
   int res1 = 0 ;
   PyObject *swig_obj[1] ;
@@ -52168,11 +52241,11 @@ SWIGINTERN PyObject *_wrap_delete_RoughnessModel(PyObject *self, PyObject *args)
   (void)self;
   if (!args) SWIG_fail;
   swig_obj[0] = args;
-  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_RoughnessModelWrap, SWIG_POINTER_DISOWN |  0 );
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_RoughnessModel, SWIG_POINTER_DISOWN |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_RoughnessModel" "', argument " "1"" of type '" "RoughnessModelWrap *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_RoughnessModel" "', argument " "1"" of type '" "RoughnessModel *""'"); 
   }
-  arg1 = reinterpret_cast< RoughnessModelWrap * >(argp1);
+  arg1 = reinterpret_cast< RoughnessModel * >(argp1);
   {
     try {
       delete arg1;
@@ -52194,10 +52267,312 @@ fail:
 SWIGINTERN PyObject *RoughnessModel_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *obj;
   if (!SWIG_Python_UnpackTuple(args, "swigregister", 1, 1, &obj)) return NULL;
-  SWIG_TypeNewClientData(SWIGTYPE_p_RoughnessModelWrap, SWIG_NewClientData(obj));
+  SWIG_TypeNewClientData(SWIGTYPE_p_RoughnessModel, SWIG_NewClientData(obj));
+  return SWIG_Py_Void();
+}
+
+SWIGINTERN PyObject *_wrap_new_ErfRoughness(PyObject *self, PyObject *args) {
+  PyObject *resultobj = 0;
+  ErfRoughness *result = 0 ;
+  
+  (void)self;
+  if (!SWIG_Python_UnpackTuple(args, "new_ErfRoughness", 0, 0, 0)) SWIG_fail;
+  {
+    try {
+      result = (ErfRoughness *)new ErfRoughness();
+    } catch (const std::exception& ex) {
+      // message shown in the Python interpreter
+      const std::string msg {
+        "BornAgain C++ Exception: " + std::string(ex.what())
+      };
+      SWIG_exception(SWIG_RuntimeError, msg.c_str());
+    }
+  }
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_ErfRoughness, SWIG_POINTER_NEW |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ErfRoughness_transient(PyObject *self, PyObject *args) {
+  PyObject *resultobj = 0;
+  ErfRoughness *arg1 = (ErfRoughness *) 0 ;
+  double arg2 ;
+  double arg3 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  double val2 ;
+  int ecode2 = 0 ;
+  double val3 ;
+  int ecode3 = 0 ;
+  PyObject *swig_obj[3] ;
+  double result;
+  
+  (void)self;
+  if (!SWIG_Python_UnpackTuple(args, "ErfRoughness_transient", 3, 3, swig_obj)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_ErfRoughness, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ErfRoughness_transient" "', argument " "1"" of type '" "ErfRoughness const *""'"); 
+  }
+  arg1 = reinterpret_cast< ErfRoughness * >(argp1);
+  ecode2 = SWIG_AsVal_double(swig_obj[1], &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "ErfRoughness_transient" "', argument " "2"" of type '" "double""'");
+  } 
+  arg2 = static_cast< double >(val2);
+  ecode3 = SWIG_AsVal_double(swig_obj[2], &val3);
+  if (!SWIG_IsOK(ecode3)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "ErfRoughness_transient" "', argument " "3"" of type '" "double""'");
+  } 
+  arg3 = static_cast< double >(val3);
+  {
+    try {
+      result = (double)((ErfRoughness const *)arg1)->transient(arg2,arg3);
+    } catch (const std::exception& ex) {
+      // message shown in the Python interpreter
+      const std::string msg {
+        "BornAgain C++ Exception: " + std::string(ex.what())
+      };
+      SWIG_exception(SWIG_RuntimeError, msg.c_str());
+    }
+  }
+  resultobj = SWIG_From_double(static_cast< double >(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ErfRoughness_clone(PyObject *self, PyObject *args) {
+  PyObject *resultobj = 0;
+  ErfRoughness *arg1 = (ErfRoughness *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject *swig_obj[1] ;
+  ErfRoughness *result = 0 ;
+  
+  (void)self;
+  if (!args) SWIG_fail;
+  swig_obj[0] = args;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_ErfRoughness, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ErfRoughness_clone" "', argument " "1"" of type '" "ErfRoughness const *""'"); 
+  }
+  arg1 = reinterpret_cast< ErfRoughness * >(argp1);
+  {
+    try {
+      result = (ErfRoughness *)((ErfRoughness const *)arg1)->clone();
+    } catch (const std::exception& ex) {
+      // message shown in the Python interpreter
+      const std::string msg {
+        "BornAgain C++ Exception: " + std::string(ex.what())
+      };
+      SWIG_exception(SWIG_RuntimeError, msg.c_str());
+    }
+  }
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_ErfRoughness, 0 |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_delete_ErfRoughness(PyObject *self, PyObject *args) {
+  PyObject *resultobj = 0;
+  ErfRoughness *arg1 = (ErfRoughness *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject *swig_obj[1] ;
+  
+  (void)self;
+  if (!args) SWIG_fail;
+  swig_obj[0] = args;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_ErfRoughness, SWIG_POINTER_DISOWN |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_ErfRoughness" "', argument " "1"" of type '" "ErfRoughness *""'"); 
+  }
+  arg1 = reinterpret_cast< ErfRoughness * >(argp1);
+  {
+    try {
+      delete arg1;
+    } catch (const std::exception& ex) {
+      // message shown in the Python interpreter
+      const std::string msg {
+        "BornAgain C++ Exception: " + std::string(ex.what())
+      };
+      SWIG_exception(SWIG_RuntimeError, msg.c_str());
+    }
+  }
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *ErfRoughness_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *obj;
+  if (!SWIG_Python_UnpackTuple(args, "swigregister", 1, 1, &obj)) return NULL;
+  SWIG_TypeNewClientData(SWIGTYPE_p_ErfRoughness, SWIG_NewClientData(obj));
+  return SWIG_Py_Void();
+}
+
+SWIGINTERN PyObject *ErfRoughness_swiginit(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  return SWIG_Python_InitShadowInstance(args);
+}
+
+SWIGINTERN PyObject *_wrap_new_TanhRoughness(PyObject *self, PyObject *args) {
+  PyObject *resultobj = 0;
+  TanhRoughness *result = 0 ;
+  
+  (void)self;
+  if (!SWIG_Python_UnpackTuple(args, "new_TanhRoughness", 0, 0, 0)) SWIG_fail;
+  {
+    try {
+      result = (TanhRoughness *)new TanhRoughness();
+    } catch (const std::exception& ex) {
+      // message shown in the Python interpreter
+      const std::string msg {
+        "BornAgain C++ Exception: " + std::string(ex.what())
+      };
+      SWIG_exception(SWIG_RuntimeError, msg.c_str());
+    }
+  }
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_TanhRoughness, SWIG_POINTER_NEW |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_TanhRoughness_transient(PyObject *self, PyObject *args) {
+  PyObject *resultobj = 0;
+  TanhRoughness *arg1 = (TanhRoughness *) 0 ;
+  double arg2 ;
+  double arg3 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  double val2 ;
+  int ecode2 = 0 ;
+  double val3 ;
+  int ecode3 = 0 ;
+  PyObject *swig_obj[3] ;
+  double result;
+  
+  (void)self;
+  if (!SWIG_Python_UnpackTuple(args, "TanhRoughness_transient", 3, 3, swig_obj)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_TanhRoughness, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "TanhRoughness_transient" "', argument " "1"" of type '" "TanhRoughness const *""'"); 
+  }
+  arg1 = reinterpret_cast< TanhRoughness * >(argp1);
+  ecode2 = SWIG_AsVal_double(swig_obj[1], &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "TanhRoughness_transient" "', argument " "2"" of type '" "double""'");
+  } 
+  arg2 = static_cast< double >(val2);
+  ecode3 = SWIG_AsVal_double(swig_obj[2], &val3);
+  if (!SWIG_IsOK(ecode3)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "TanhRoughness_transient" "', argument " "3"" of type '" "double""'");
+  } 
+  arg3 = static_cast< double >(val3);
+  {
+    try {
+      result = (double)((TanhRoughness const *)arg1)->transient(arg2,arg3);
+    } catch (const std::exception& ex) {
+      // message shown in the Python interpreter
+      const std::string msg {
+        "BornAgain C++ Exception: " + std::string(ex.what())
+      };
+      SWIG_exception(SWIG_RuntimeError, msg.c_str());
+    }
+  }
+  resultobj = SWIG_From_double(static_cast< double >(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_TanhRoughness_clone(PyObject *self, PyObject *args) {
+  PyObject *resultobj = 0;
+  TanhRoughness *arg1 = (TanhRoughness *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject *swig_obj[1] ;
+  TanhRoughness *result = 0 ;
+  
+  (void)self;
+  if (!args) SWIG_fail;
+  swig_obj[0] = args;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_TanhRoughness, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "TanhRoughness_clone" "', argument " "1"" of type '" "TanhRoughness const *""'"); 
+  }
+  arg1 = reinterpret_cast< TanhRoughness * >(argp1);
+  {
+    try {
+      result = (TanhRoughness *)((TanhRoughness const *)arg1)->clone();
+    } catch (const std::exception& ex) {
+      // message shown in the Python interpreter
+      const std::string msg {
+        "BornAgain C++ Exception: " + std::string(ex.what())
+      };
+      SWIG_exception(SWIG_RuntimeError, msg.c_str());
+    }
+  }
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_TanhRoughness, 0 |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_delete_TanhRoughness(PyObject *self, PyObject *args) {
+  PyObject *resultobj = 0;
+  TanhRoughness *arg1 = (TanhRoughness *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject *swig_obj[1] ;
+  
+  (void)self;
+  if (!args) SWIG_fail;
+  swig_obj[0] = args;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_TanhRoughness, SWIG_POINTER_DISOWN |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_TanhRoughness" "', argument " "1"" of type '" "TanhRoughness *""'"); 
+  }
+  arg1 = reinterpret_cast< TanhRoughness * >(argp1);
+  {
+    try {
+      delete arg1;
+    } catch (const std::exception& ex) {
+      // message shown in the Python interpreter
+      const std::string msg {
+        "BornAgain C++ Exception: " + std::string(ex.what())
+      };
+      SWIG_exception(SWIG_RuntimeError, msg.c_str());
+    }
+  }
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *TanhRoughness_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *obj;
+  if (!SWIG_Python_UnpackTuple(args, "swigregister", 1, 1, &obj)) return NULL;
+  SWIG_TypeNewClientData(SWIGTYPE_p_TanhRoughness, SWIG_NewClientData(obj));
   return SWIG_Py_Void();
 }
 
+SWIGINTERN PyObject *TanhRoughness_swiginit(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  return SWIG_Python_InitShadowInstance(args);
+}
+
 SWIGINTERN PyObject *_wrap_delete_IFormFactorPolyhedron(PyObject *self, PyObject *args) {
   PyObject *resultobj = 0;
   IFormFactorPolyhedron *arg1 = (IFormFactorPolyhedron *) 0 ;
@@ -72145,8 +72520,8 @@ static PyMethodDef SwigMethods[] = {
 	 { "ParticleLayout_swigregister", ParticleLayout_swigregister, METH_O, NULL},
 	 { "ParticleLayout_swiginit", ParticleLayout_swiginit, METH_VARARGS, NULL},
 	 { "new_LayerRoughness", _wrap_new_LayerRoughness, METH_VARARGS, "\n"
-		"LayerRoughness(double sigma, double hurstParameter=0, double lateralCorrLength=0, RoughnessModel const & profileModel=RoughnessModel::DEFAULT)\n"
-		"LayerRoughness(double sigma, RoughnessModel const & profileModel)\n"
+		"LayerRoughness(double sigma, double hurstParameter=0, double lateralCorrLength=0, RoughnessModel roughnessModel=None)\n"
+		"LayerRoughness(double sigma, RoughnessModel roughnessModel)\n"
 		"new_LayerRoughness() -> LayerRoughness\n"
 		""},
 	 { "LayerRoughness_clone", _wrap_LayerRoughness_clone, METH_O, "LayerRoughness_clone(LayerRoughness self) -> LayerRoughness"},
@@ -72161,8 +72536,8 @@ static PyMethodDef SwigMethods[] = {
 	 { "LayerRoughness_setLatteralCorrLength", _wrap_LayerRoughness_setLatteralCorrLength, METH_VARARGS, "LayerRoughness_setLatteralCorrLength(LayerRoughness self, double lateralCorrLength)"},
 	 { "LayerRoughness_lateralCorrLength", _wrap_LayerRoughness_lateralCorrLength, METH_O, "LayerRoughness_lateralCorrLength(LayerRoughness self) -> double"},
 	 { "LayerRoughness_validate", _wrap_LayerRoughness_validate, METH_O, "LayerRoughness_validate(LayerRoughness self) -> std::string"},
-	 { "LayerRoughness_setProfileModel", _wrap_LayerRoughness_setProfileModel, METH_VARARGS, "LayerRoughness_setProfileModel(LayerRoughness self, RoughnessModel const & profileModel)"},
-	 { "LayerRoughness_profileModel", _wrap_LayerRoughness_profileModel, METH_O, "LayerRoughness_profileModel(LayerRoughness self) -> RoughnessModel"},
+	 { "LayerRoughness_setRoughnessModel", _wrap_LayerRoughness_setRoughnessModel, METH_VARARGS, "LayerRoughness_setRoughnessModel(LayerRoughness self, RoughnessModel roughnessModel)"},
+	 { "LayerRoughness_roughnessModel", _wrap_LayerRoughness_roughnessModel, METH_O, "LayerRoughness_roughnessModel(LayerRoughness self) -> RoughnessModel"},
 	 { "delete_LayerRoughness", _wrap_delete_LayerRoughness, METH_O, "delete_LayerRoughness(LayerRoughness self)"},
 	 { "LayerRoughness_swigregister", LayerRoughness_swigregister, METH_O, NULL},
 	 { "LayerRoughness_swiginit", LayerRoughness_swiginit, METH_VARARGS, NULL},
@@ -72186,8 +72561,22 @@ static PyMethodDef SwigMethods[] = {
 	 { "MultiLayer_setName", _wrap_MultiLayer_setName, METH_VARARGS, "MultiLayer_setName(MultiLayer self, std::string const & name)"},
 	 { "MultiLayer_swigregister", MultiLayer_swigregister, METH_O, NULL},
 	 { "MultiLayer_swiginit", MultiLayer_swiginit, METH_VARARGS, NULL},
+	 { "RoughnessModel_clone", _wrap_RoughnessModel_clone, METH_O, "RoughnessModel_clone(RoughnessModel self) -> RoughnessModel"},
+	 { "RoughnessModel_transient", _wrap_RoughnessModel_transient, METH_VARARGS, "RoughnessModel_transient(RoughnessModel self, double x, double sigma) -> double"},
 	 { "delete_RoughnessModel", _wrap_delete_RoughnessModel, METH_O, "delete_RoughnessModel(RoughnessModel self)"},
 	 { "RoughnessModel_swigregister", RoughnessModel_swigregister, METH_O, NULL},
+	 { "new_ErfRoughness", _wrap_new_ErfRoughness, METH_NOARGS, "new_ErfRoughness() -> ErfRoughness"},
+	 { "ErfRoughness_transient", _wrap_ErfRoughness_transient, METH_VARARGS, "ErfRoughness_transient(ErfRoughness self, double x, double sigma) -> double"},
+	 { "ErfRoughness_clone", _wrap_ErfRoughness_clone, METH_O, "ErfRoughness_clone(ErfRoughness self) -> ErfRoughness"},
+	 { "delete_ErfRoughness", _wrap_delete_ErfRoughness, METH_O, "delete_ErfRoughness(ErfRoughness self)"},
+	 { "ErfRoughness_swigregister", ErfRoughness_swigregister, METH_O, NULL},
+	 { "ErfRoughness_swiginit", ErfRoughness_swiginit, METH_VARARGS, NULL},
+	 { "new_TanhRoughness", _wrap_new_TanhRoughness, METH_NOARGS, "new_TanhRoughness() -> TanhRoughness"},
+	 { "TanhRoughness_transient", _wrap_TanhRoughness_transient, METH_VARARGS, "TanhRoughness_transient(TanhRoughness self, double x, double sigma) -> double"},
+	 { "TanhRoughness_clone", _wrap_TanhRoughness_clone, METH_O, "TanhRoughness_clone(TanhRoughness self) -> TanhRoughness"},
+	 { "delete_TanhRoughness", _wrap_delete_TanhRoughness, METH_O, "delete_TanhRoughness(TanhRoughness self)"},
+	 { "TanhRoughness_swigregister", TanhRoughness_swigregister, METH_O, NULL},
+	 { "TanhRoughness_swiginit", TanhRoughness_swiginit, METH_VARARGS, NULL},
 	 { "delete_IFormFactorPolyhedron", _wrap_delete_IFormFactorPolyhedron, METH_O, "delete_IFormFactorPolyhedron(IFormFactorPolyhedron self)"},
 	 { "IFormFactorPolyhedron_volume", _wrap_IFormFactorPolyhedron_volume, METH_O, "IFormFactorPolyhedron_volume(IFormFactorPolyhedron self) -> double"},
 	 { "IFormFactorPolyhedron_radialExtension", _wrap_IFormFactorPolyhedron_radialExtension, METH_O, "IFormFactorPolyhedron_radialExtension(IFormFactorPolyhedron self) -> double"},
@@ -72845,6 +73234,9 @@ static void *_p_DodecahedronTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemo
 static void *_p_EllipsoidalCylinderTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
     return (void *)((ICloneable *) (ISampleNode *)(IFormFactor *) ((EllipsoidalCylinder *) x));
 }
+static void *_p_ErfRoughnessTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((ICloneable *) (RoughnessModel *) ((ErfRoughness *) x));
+}
 static void *_p_FuzzySphereTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
     return (void *)((ICloneable *) (ISampleNode *)(IFormFactor *) ((FuzzySphere *) x));
 }
@@ -73046,6 +73438,9 @@ static void *_p_RotationYTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)
 static void *_p_RotationZTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
     return (void *)((ICloneable *) (IRotation *) ((RotationZ *) x));
 }
+static void *_p_RoughnessModelTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((ICloneable *)  ((RoughnessModel *) x));
+}
 static void *_p_SawtoothRippleBoxTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
     return (void *)((ICloneable *) (ISampleNode *)(IFormFactor *)(IProfileRipple *)(ISawtoothRipple *) ((SawtoothRippleBox *) x));
 }
@@ -73064,6 +73459,9 @@ static void *_p_SpheroidTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory))
 static void *_p_SquareLattice2DTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
     return (void *)((ICloneable *) (Lattice2D *) ((SquareLattice2D *) x));
 }
+static void *_p_TanhRoughnessTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((ICloneable *) (RoughnessModel *) ((TanhRoughness *) x));
+}
 static void *_p_TruncatedCubeTo_p_ICloneable(void *x, int *SWIGUNUSEDPARM(newmemory)) {
     return (void *)((ICloneable *) (ISampleNode *)(IFormFactor *)(IFormFactorPolyhedron *) ((TruncatedCube *) x));
 }
@@ -73862,6 +74260,12 @@ static void *_p_HexagonalLattice2DTo_p_Lattice2D(void *x, int *SWIGUNUSEDPARM(ne
 static void *_p_SquareLattice2DTo_p_Lattice2D(void *x, int *SWIGUNUSEDPARM(newmemory)) {
     return (void *)((Lattice2D *)  ((SquareLattice2D *) x));
 }
+static void *_p_ErfRoughnessTo_p_RoughnessModel(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((RoughnessModel *)  ((ErfRoughness *) x));
+}
+static void *_p_TanhRoughnessTo_p_RoughnessModel(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((RoughnessModel *)  ((TanhRoughness *) x));
+}
 static swig_type_info _swigt__p_BarGauss = {"_p_BarGauss", "BarGauss *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_BarLorentz = {"_p_BarLorentz", "BarLorentz *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_BasicLattice2D = {"_p_BasicLattice2D", "BasicLattice2D *", 0, 0, (void*)0, 0};
@@ -73878,6 +74282,7 @@ static swig_type_info _swigt__p_Crystal = {"_p_Crystal", "Crystal *", 0, 0, (voi
 static swig_type_info _swigt__p_Cylinder = {"_p_Cylinder", "Cylinder *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_Dodecahedron = {"_p_Dodecahedron", "Dodecahedron *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_EllipsoidalCylinder = {"_p_EllipsoidalCylinder", "EllipsoidalCylinder *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_ErfRoughness = {"_p_ErfRoughness", "ErfRoughness *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_FuzzySphere = {"_p_FuzzySphere", "FuzzySphere *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_GaussFisherPeakShape = {"_p_GaussFisherPeakShape", "GaussFisherPeakShape *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_GaussSphere = {"_p_GaussSphere", "GaussSphere *", 0, 0, (void*)0, 0};
@@ -73955,8 +74360,7 @@ static swig_type_info _swigt__p_RotationEuler = {"_p_RotationEuler", "RotationEu
 static swig_type_info _swigt__p_RotationX = {"_p_RotationX", "RotationX *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_RotationY = {"_p_RotationY", "RotationY *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_RotationZ = {"_p_RotationZ", "RotationZ *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_RoughnessModelWrap = {"_p_RoughnessModelWrap", "RoughnessModelWrap *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_RoughnessModelWrap__RoughnessModel = {"_p_RoughnessModelWrap__RoughnessModel", "RoughnessModel *|enum RoughnessModelWrap::RoughnessModel *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_RoughnessModel = {"_p_RoughnessModel", "RoughnessModel *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_SawtoothRippleBox = {"_p_SawtoothRippleBox", "SawtoothRippleBox *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_SawtoothRippleGauss = {"_p_SawtoothRippleGauss", "SawtoothRippleGauss *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_SawtoothRippleLorentz = {"_p_SawtoothRippleLorentz", "SawtoothRippleLorentz *", 0, 0, (void*)0, 0};
@@ -73966,6 +74370,7 @@ static swig_type_info _swigt__p_Sphere = {"_p_Sphere", "Sphere *", 0, 0, (void*)
 static swig_type_info _swigt__p_Spheroid = {"_p_Spheroid", "Spheroid *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_SpinMatrix = {"_p_SpinMatrix", "SpinMatrix *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_SquareLattice2D = {"_p_SquareLattice2D", "SquareLattice2D *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_TanhRoughness = {"_p_TanhRoughness", "DefaultRoughness *|TanhRoughness *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_TruncatedCube = {"_p_TruncatedCube", "TruncatedCube *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_TruncatedSphere = {"_p_TruncatedSphere", "TruncatedSphere *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_TruncatedSpheroid = {"_p_TruncatedSpheroid", "TruncatedSpheroid *", 0, 0, (void*)0, 0};
@@ -74038,6 +74443,7 @@ static swig_type_info *swig_type_initial[] = {
   &_swigt__p_Cylinder,
   &_swigt__p_Dodecahedron,
   &_swigt__p_EllipsoidalCylinder,
+  &_swigt__p_ErfRoughness,
   &_swigt__p_FuzzySphere,
   &_swigt__p_GaussFisherPeakShape,
   &_swigt__p_GaussSphere,
@@ -74115,8 +74521,7 @@ static swig_type_info *swig_type_initial[] = {
   &_swigt__p_RotationX,
   &_swigt__p_RotationY,
   &_swigt__p_RotationZ,
-  &_swigt__p_RoughnessModelWrap,
-  &_swigt__p_RoughnessModelWrap__RoughnessModel,
+  &_swigt__p_RoughnessModel,
   &_swigt__p_SawtoothRippleBox,
   &_swigt__p_SawtoothRippleGauss,
   &_swigt__p_SawtoothRippleLorentz,
@@ -74126,6 +74531,7 @@ static swig_type_info *swig_type_initial[] = {
   &_swigt__p_Spheroid,
   &_swigt__p_SpinMatrix,
   &_swigt__p_SquareLattice2D,
+  &_swigt__p_TanhRoughness,
   &_swigt__p_TruncatedCube,
   &_swigt__p_TruncatedSphere,
   &_swigt__p_TruncatedSpheroid,
@@ -74198,13 +74604,14 @@ static swig_cast_info _swigc__p_Crystal[] = {  {&_swigt__p_Crystal, 0, 0, 0},{0,
 static swig_cast_info _swigc__p_Cylinder[] = {  {&_swigt__p_Cylinder, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_Dodecahedron[] = {  {&_swigt__p_Dodecahedron, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_EllipsoidalCylinder[] = {  {&_swigt__p_EllipsoidalCylinder, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_ErfRoughness[] = {  {&_swigt__p_ErfRoughness, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_FuzzySphere[] = {  {&_swigt__p_FuzzySphere, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_GaussFisherPeakShape[] = {  {&_swigt__p_GaussFisherPeakShape, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_GaussSphere[] = {  {&_swigt__p_GaussSphere, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_HemiEllipsoid[] = {  {&_swigt__p_HemiEllipsoid, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_HexagonalLattice2D[] = {  {&_swigt__p_HexagonalLattice2D, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_HorizontalCylinder[] = {  {&_swigt__p_HorizontalCylinder, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_ICloneable[] = {  {&_swigt__p_ICloneable, 0, 0, 0},  {&_swigt__p_BarGauss, _p_BarGaussTo_p_ICloneable, 0, 0},  {&_swigt__p_BarLorentz, _p_BarLorentzTo_p_ICloneable, 0, 0},  {&_swigt__p_BasicLattice2D, _p_BasicLattice2DTo_p_ICloneable, 0, 0},  {&_swigt__p_Bipyramid4, _p_Bipyramid4To_p_ICloneable, 0, 0},  {&_swigt__p_Box, _p_BoxTo_p_ICloneable, 0, 0},  {&_swigt__p_CantellatedCube, _p_CantellatedCubeTo_p_ICloneable, 0, 0},  {&_swigt__p_Compound, _p_CompoundTo_p_ICloneable, 0, 0},  {&_swigt__p_Cone, _p_ConeTo_p_ICloneable, 0, 0},  {&_swigt__p_CoreAndShell, _p_CoreAndShellTo_p_ICloneable, 0, 0},  {&_swigt__p_CosineRippleBox, _p_CosineRippleBoxTo_p_ICloneable, 0, 0},  {&_swigt__p_CosineRippleGauss, _p_CosineRippleGaussTo_p_ICloneable, 0, 0},  {&_swigt__p_CosineRippleLorentz, _p_CosineRippleLorentzTo_p_ICloneable, 0, 0},  {&_swigt__p_Crystal, _p_CrystalTo_p_ICloneable, 0, 0},  {&_swigt__p_Cylinder, _p_CylinderTo_p_ICloneable, 0, 0},  {&_swigt__p_Dodecahedron, _p_DodecahedronTo_p_ICloneable, 0, 0},  {&_swigt__p_EllipsoidalCylinder, _p_EllipsoidalCylinderTo_p_ICloneable, 0, 0},  {&_swigt__p_FuzzySphere, _p_FuzzySphereTo_p_ICloneable, 0, 0},  {&_swigt__p_GaussFisherPeakShape, _p_GaussFisherPeakShapeTo_p_ICloneable, 0, 0},  {&_swigt__p_GaussSphere, _p_GaussSphereTo_p_ICloneable, 0, 0},  {&_swigt__p_HemiEllipsoid, _p_HemiEllipsoidTo_p_ICloneable, 0, 0},  {&_swigt__p_HexagonalLattice2D, _p_HexagonalLattice2DTo_p_ICloneable, 0, 0},  {&_swigt__p_HorizontalCylinder, _p_HorizontalCylinderTo_p_ICloneable, 0, 0},  {&_swigt__p_ICosineRipple, _p_ICosineRippleTo_p_ICloneable, 0, 0},  {&_swigt__p_IFormFactor, _p_IFormFactorTo_p_ICloneable, 0, 0},  {&_swigt__p_IFormFactorPolyhedron, _p_IFormFactorPolyhedronTo_p_ICloneable, 0, 0},  {&_swigt__p_IFormFactorPrism, _p_IFormFactorPrismTo_p_ICloneable, 0, 0},  {&_swigt__p_IInterference, _p_IInterferenceTo_p_ICloneable, 0, 0},  {&_swigt__p_IParticle, _p_IParticleTo_p_ICloneable, 0, 0},  {&_swigt__p_IPeakShape, _p_IPeakShapeTo_p_ICloneable, 0, 0},  {&_swigt__p_IProfile1D, _p_IProfile1DTo_p_ICloneable, 0, 0},  {&_swigt__p_IProfile2D, _p_IProfile2DTo_p_ICloneable, 0, 0},  {&_swigt__p_IProfileRectangularRipple, _p_IProfileRectangularRippleTo_p_ICloneable, 0, 0},  {&_swigt__p_IProfileRipple, _p_IProfileRippleTo_p_ICloneable, 0, 0},  {&_swigt__p_IRotation, _p_IRotationTo_p_ICloneable, 0, 0},  {&_swigt__p_ISampleNode, _p_ISampleNodeTo_p_ICloneable, 0, 0},  {&_swigt__p_ISawtoothRipple, _p_ISawtoothRippleTo_p_ICloneable, 0, 0},  {&_swigt__p_Icosahedron, _p_IcosahedronTo_p_ICloneable, 0, 0},  {&_swigt__p_IdentityRotation, _p_IdentityRotationTo_p_ICloneable, 0, 0},  {&_swigt__p_Interference1DLattice, _p_Interference1DLatticeTo_p_ICloneable, 0, 0},  {&_swigt__p_Interference2DLattice, _p_Interference2DLatticeTo_p_ICloneable, 0, 0},  {&_swigt__p_Interference2DParacrystal, _p_Interference2DParacrystalTo_p_ICloneable, 0, 0},  {&_swigt__p_Interference2DSuperLattice, _p_Interference2DSuperLatticeTo_p_ICloneable, 0, 0},  {&_swigt__p_InterferenceFinite2DLattice, _p_InterferenceFinite2DLatticeTo_p_ICloneable, 0, 0},  {&_swigt__p_InterferenceHardDisk, _p_InterferenceHardDiskTo_p_ICloneable, 0, 0},  {&_swigt__p_InterferenceNone, _p_InterferenceNoneTo_p_ICloneable, 0, 0},  {&_swigt__p_InterferenceRadialParacrystal, _p_InterferenceRadialParacrystalTo_p_ICloneable, 0, 0},  {&_swigt__p_IsotropicGaussPeakShape, _p_IsotropicGaussPeakShapeTo_p_ICloneable, 0, 0},  {&_swigt__p_IsotropicLorentzPeakShape, _p_IsotropicLorentzPeakShapeTo_p_ICloneable, 0, 0},  {&_swigt__p_Lattice2D, _p_Lattice2DTo_p_ICloneable, 0, 0},  {&_swigt__p_Layer, _p_LayerTo_p_ICloneable, 0, 0},  {&_swigt__p_LayerRoughness, _p_LayerRoughnessTo_p_ICloneable, 0, 0},  {&_swigt__p_LongBoxGauss, _p_LongBoxGaussTo_p_ICloneable, 0, 0},  {&_swigt__p_LongBoxLorentz, _p_LongBoxLorentzTo_p_ICloneable, 0, 0},  {&_swigt__p_LorentzFisherPeakShape, _p_LorentzFisherPeakShapeTo_p_ICloneable, 0, 0},  {&_swigt__p_Mesocrystal, _p_MesocrystalTo_p_ICloneable, 0, 0},  {&_swigt__p_MisesFisherGaussPeakShape, _p_MisesFisherGaussPeakShapeTo_p_ICloneable, 0, 0},  {&_swigt__p_MisesGaussPeakShape, _p_MisesGaussPeakShapeTo_p_ICloneable, 0, 0},  {&_swigt__p_MultiLayer, _p_MultiLayerTo_p_ICloneable, 0, 0},  {&_swigt__p_Particle, _p_ParticleTo_p_ICloneable, 0, 0},  {&_swigt__p_ParticleLayout, _p_ParticleLayoutTo_p_ICloneable, 0, 0},  {&_swigt__p_PlatonicOctahedron, _p_PlatonicOctahedronTo_p_ICloneable, 0, 0},  {&_swigt__p_PlatonicTetrahedron, _p_PlatonicTetrahedronTo_p_ICloneable, 0, 0},  {&_swigt__p_Prism3, _p_Prism3To_p_ICloneable, 0, 0},  {&_swigt__p_Prism6, _p_Prism6To_p_ICloneable, 0, 0},  {&_swigt__p_Profile1DCauchy, _p_Profile1DCauchyTo_p_ICloneable, 0, 0},  {&_swigt__p_Profile1DCosine, _p_Profile1DCosineTo_p_ICloneable, 0, 0},  {&_swigt__p_Profile1DGate, _p_Profile1DGateTo_p_ICloneable, 0, 0},  {&_swigt__p_Profile1DGauss, _p_Profile1DGaussTo_p_ICloneable, 0, 0},  {&_swigt__p_Profile1DTriangle, _p_Profile1DTriangleTo_p_ICloneable, 0, 0},  {&_swigt__p_Profile1DVoigt, _p_Profile1DVoigtTo_p_ICloneable, 0, 0},  {&_swigt__p_Profile2DCauchy, _p_Profile2DCauchyTo_p_ICloneable, 0, 0},  {&_swigt__p_Profile2DCone, _p_Profile2DConeTo_p_ICloneable, 0, 0},  {&_swigt__p_Profile2DGate, _p_Profile2DGateTo_p_ICloneable, 0, 0},  {&_swigt__p_Profile2DGauss, _p_Profile2DGaussTo_p_ICloneable, 0, 0},  {&_swigt__p_Profile2DVoigt, _p_Profile2DVoigtTo_p_ICloneable, 0, 0},  {&_swigt__p_Pyramid2, _p_Pyramid2To_p_ICloneable, 0, 0},  {&_swigt__p_Pyramid3, _p_Pyramid3To_p_ICloneable, 0, 0},  {&_swigt__p_Pyramid4, _p_Pyramid4To_p_ICloneable, 0, 0},  {&_swigt__p_Pyramid6, _p_Pyramid6To_p_ICloneable, 0, 0},  {&_swigt__p_RotationEuler, _p_RotationEulerTo_p_ICloneable, 0, 0},  {&_swigt__p_RotationX, _p_RotationXTo_p_ICloneable, 0, 0},  {&_swigt__p_RotationY, _p_RotationYTo_p_ICloneable, 0, 0},  {&_swigt__p_RotationZ, _p_RotationZTo_p_ICloneable, 0, 0},  {&_swigt__p_SawtoothRippleBox, _p_SawtoothRippleBoxTo_p_ICloneable, 0, 0},  {&_swigt__p_SawtoothRippleGauss, _p_SawtoothRippleGaussTo_p_ICloneable, 0, 0},  {&_swigt__p_SawtoothRippleLorentz, _p_SawtoothRippleLorentzTo_p_ICloneable, 0, 0},  {&_swigt__p_Sphere, _p_SphereTo_p_ICloneable, 0, 0},  {&_swigt__p_Spheroid, _p_SpheroidTo_p_ICloneable, 0, 0},  {&_swigt__p_SquareLattice2D, _p_SquareLattice2DTo_p_ICloneable, 0, 0},  {&_swigt__p_TruncatedCube, _p_TruncatedCubeTo_p_ICloneable, 0, 0},  {&_swigt__p_TruncatedSphere, _p_TruncatedSphereTo_p_ICloneable, 0, 0},  {&_swigt__p_TruncatedSpheroid, _p_TruncatedSpheroidTo_p_ICloneable, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_ICloneable[] = {  {&_swigt__p_ICloneable, 0, 0, 0},  {&_swigt__p_BarGauss, _p_BarGaussTo_p_ICloneable, 0, 0},  {&_swigt__p_BarLorentz, _p_BarLorentzTo_p_ICloneable, 0, 0},  {&_swigt__p_BasicLattice2D, _p_BasicLattice2DTo_p_ICloneable, 0, 0},  {&_swigt__p_Bipyramid4, _p_Bipyramid4To_p_ICloneable, 0, 0},  {&_swigt__p_Box, _p_BoxTo_p_ICloneable, 0, 0},  {&_swigt__p_CantellatedCube, _p_CantellatedCubeTo_p_ICloneable, 0, 0},  {&_swigt__p_Compound, _p_CompoundTo_p_ICloneable, 0, 0},  {&_swigt__p_Cone, _p_ConeTo_p_ICloneable, 0, 0},  {&_swigt__p_CoreAndShell, _p_CoreAndShellTo_p_ICloneable, 0, 0},  {&_swigt__p_CosineRippleBox, _p_CosineRippleBoxTo_p_ICloneable, 0, 0},  {&_swigt__p_CosineRippleGauss, _p_CosineRippleGaussTo_p_ICloneable, 0, 0},  {&_swigt__p_CosineRippleLorentz, _p_CosineRippleLorentzTo_p_ICloneable, 0, 0},  {&_swigt__p_Crystal, _p_CrystalTo_p_ICloneable, 0, 0},  {&_swigt__p_Cylinder, _p_CylinderTo_p_ICloneable, 0, 0},  {&_swigt__p_Dodecahedron, _p_DodecahedronTo_p_ICloneable, 0, 0},  {&_swigt__p_EllipsoidalCylinder, _p_EllipsoidalCylinderTo_p_ICloneable, 0, 0},  {&_swigt__p_ErfRoughness, _p_ErfRoughnessTo_p_ICloneable, 0, 0},  {&_swigt__p_FuzzySphere, _p_FuzzySphereTo_p_ICloneable, 0, 0},  {&_swigt__p_GaussFisherPeakShape, _p_GaussFisherPeakShapeTo_p_ICloneable, 0, 0},  {&_swigt__p_GaussSphere, _p_GaussSphereTo_p_ICloneable, 0, 0},  {&_swigt__p_HemiEllipsoid, _p_HemiEllipsoidTo_p_ICloneable, 0, 0},  {&_swigt__p_HexagonalLattice2D, _p_HexagonalLattice2DTo_p_ICloneable, 0, 0},  {&_swigt__p_HorizontalCylinder, _p_HorizontalCylinderTo_p_ICloneable, 0, 0},  {&_swigt__p_ICosineRipple, _p_ICosineRippleTo_p_ICloneable, 0, 0},  {&_swigt__p_IFormFactor, _p_IFormFactorTo_p_ICloneable, 0, 0},  {&_swigt__p_IFormFactorPolyhedron, _p_IFormFactorPolyhedronTo_p_ICloneable, 0, 0},  {&_swigt__p_IFormFactorPrism, _p_IFormFactorPrismTo_p_ICloneable, 0, 0},  {&_swigt__p_IInterference, _p_IInterferenceTo_p_ICloneable, 0, 0},  {&_swigt__p_IParticle, _p_IParticleTo_p_ICloneable, 0, 0},  {&_swigt__p_IPeakShape, _p_IPeakShapeTo_p_ICloneable, 0, 0},  {&_swigt__p_IProfile1D, _p_IProfile1DTo_p_ICloneable, 0, 0},  {&_swigt__p_IProfile2D, _p_IProfile2DTo_p_ICloneable, 0, 0},  {&_swigt__p_IProfileRectangularRipple, _p_IProfileRectangularRippleTo_p_ICloneable, 0, 0},  {&_swigt__p_IProfileRipple, _p_IProfileRippleTo_p_ICloneable, 0, 0},  {&_swigt__p_IRotation, _p_IRotationTo_p_ICloneable, 0, 0},  {&_swigt__p_ISampleNode, _p_ISampleNodeTo_p_ICloneable, 0, 0},  {&_swigt__p_ISawtoothRipple, _p_ISawtoothRippleTo_p_ICloneable, 0, 0},  {&_swigt__p_Icosahedron, _p_IcosahedronTo_p_ICloneable, 0, 0},  {&_swigt__p_IdentityRotation, _p_IdentityRotationTo_p_ICloneable, 0, 0},  {&_swigt__p_Interference1DLattice, _p_Interference1DLatticeTo_p_ICloneable, 0, 0},  {&_swigt__p_Interference2DLattice, _p_Interference2DLatticeTo_p_ICloneable, 0, 0},  {&_swigt__p_Interference2DParacrystal, _p_Interference2DParacrystalTo_p_ICloneable, 0, 0},  {&_swigt__p_Interference2DSuperLattice, _p_Interference2DSuperLatticeTo_p_ICloneable, 0, 0},  {&_swigt__p_InterferenceFinite2DLattice, _p_InterferenceFinite2DLatticeTo_p_ICloneable, 0, 0},  {&_swigt__p_InterferenceHardDisk, _p_InterferenceHardDiskTo_p_ICloneable, 0, 0},  {&_swigt__p_InterferenceNone, _p_InterferenceNoneTo_p_ICloneable, 0, 0},  {&_swigt__p_InterferenceRadialParacrystal, _p_InterferenceRadialParacrystalTo_p_ICloneable, 0, 0},  {&_swigt__p_IsotropicGaussPeakShape, _p_IsotropicGaussPeakShapeTo_p_ICloneable, 0, 0},  {&_swigt__p_IsotropicLorentzPeakShape, _p_IsotropicLorentzPeakShapeTo_p_ICloneable, 0, 0},  {&_swigt__p_Lattice2D, _p_Lattice2DTo_p_ICloneable, 0, 0},  {&_swigt__p_Layer, _p_LayerTo_p_ICloneable, 0, 0},  {&_swigt__p_LayerRoughness, _p_LayerRoughnessTo_p_ICloneable, 0, 0},  {&_swigt__p_LongBoxGauss, _p_LongBoxGaussTo_p_ICloneable, 0, 0},  {&_swigt__p_LongBoxLorentz, _p_LongBoxLorentzTo_p_ICloneable, 0, 0},  {&_swigt__p_LorentzFisherPeakShape, _p_LorentzFisherPeakShapeTo_p_ICloneable, 0, 0},  {&_swigt__p_Mesocrystal, _p_MesocrystalTo_p_ICloneable, 0, 0},  {&_swigt__p_MisesFisherGaussPeakShape, _p_MisesFisherGaussPeakShapeTo_p_ICloneable, 0, 0},  {&_swigt__p_MisesGaussPeakShape, _p_MisesGaussPeakShapeTo_p_ICloneable, 0, 0},  {&_swigt__p_MultiLayer, _p_MultiLayerTo_p_ICloneable, 0, 0},  {&_swigt__p_Particle, _p_ParticleTo_p_ICloneable, 0, 0},  {&_swigt__p_ParticleLayout, _p_ParticleLayoutTo_p_ICloneable, 0, 0},  {&_swigt__p_PlatonicOctahedron, _p_PlatonicOctahedronTo_p_ICloneable, 0, 0},  {&_swigt__p_PlatonicTetrahedron, _p_PlatonicTetrahedronTo_p_ICloneable, 0, 0},  {&_swigt__p_Prism3, _p_Prism3To_p_ICloneable, 0, 0},  {&_swigt__p_Prism6, _p_Prism6To_p_ICloneable, 0, 0},  {&_swigt__p_Profile1DCauchy, _p_Profile1DCauchyTo_p_ICloneable, 0, 0},  {&_swigt__p_Profile1DCosine, _p_Profile1DCosineTo_p_ICloneable, 0, 0},  {&_swigt__p_Profile1DGate, _p_Profile1DGateTo_p_ICloneable, 0, 0},  {&_swigt__p_Profile1DGauss, _p_Profile1DGaussTo_p_ICloneable, 0, 0},  {&_swigt__p_Profile1DTriangle, _p_Profile1DTriangleTo_p_ICloneable, 0, 0},  {&_swigt__p_Profile1DVoigt, _p_Profile1DVoigtTo_p_ICloneable, 0, 0},  {&_swigt__p_Profile2DCauchy, _p_Profile2DCauchyTo_p_ICloneable, 0, 0},  {&_swigt__p_Profile2DCone, _p_Profile2DConeTo_p_ICloneable, 0, 0},  {&_swigt__p_Profile2DGate, _p_Profile2DGateTo_p_ICloneable, 0, 0},  {&_swigt__p_Profile2DGauss, _p_Profile2DGaussTo_p_ICloneable, 0, 0},  {&_swigt__p_Profile2DVoigt, _p_Profile2DVoigtTo_p_ICloneable, 0, 0},  {&_swigt__p_Pyramid2, _p_Pyramid2To_p_ICloneable, 0, 0},  {&_swigt__p_Pyramid3, _p_Pyramid3To_p_ICloneable, 0, 0},  {&_swigt__p_Pyramid4, _p_Pyramid4To_p_ICloneable, 0, 0},  {&_swigt__p_Pyramid6, _p_Pyramid6To_p_ICloneable, 0, 0},  {&_swigt__p_RotationEuler, _p_RotationEulerTo_p_ICloneable, 0, 0},  {&_swigt__p_RotationX, _p_RotationXTo_p_ICloneable, 0, 0},  {&_swigt__p_RotationY, _p_RotationYTo_p_ICloneable, 0, 0},  {&_swigt__p_RotationZ, _p_RotationZTo_p_ICloneable, 0, 0},  {&_swigt__p_RoughnessModel, _p_RoughnessModelTo_p_ICloneable, 0, 0},  {&_swigt__p_SawtoothRippleBox, _p_SawtoothRippleBoxTo_p_ICloneable, 0, 0},  {&_swigt__p_SawtoothRippleGauss, _p_SawtoothRippleGaussTo_p_ICloneable, 0, 0},  {&_swigt__p_SawtoothRippleLorentz, _p_SawtoothRippleLorentzTo_p_ICloneable, 0, 0},  {&_swigt__p_Sphere, _p_SphereTo_p_ICloneable, 0, 0},  {&_swigt__p_Spheroid, _p_SpheroidTo_p_ICloneable, 0, 0},  {&_swigt__p_SquareLattice2D, _p_SquareLattice2DTo_p_ICloneable, 0, 0},  {&_swigt__p_TanhRoughness, _p_TanhRoughnessTo_p_ICloneable, 0, 0},  {&_swigt__p_TruncatedCube, _p_TruncatedCubeTo_p_ICloneable, 0, 0},  {&_swigt__p_TruncatedSphere, _p_TruncatedSphereTo_p_ICloneable, 0, 0},  {&_swigt__p_TruncatedSpheroid, _p_TruncatedSpheroidTo_p_ICloneable, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_ICosineRipple[] = {  {&_swigt__p_ICosineRipple, 0, 0, 0},  {&_swigt__p_CosineRippleBox, _p_CosineRippleBoxTo_p_ICosineRipple, 0, 0},  {&_swigt__p_CosineRippleGauss, _p_CosineRippleGaussTo_p_ICosineRipple, 0, 0},  {&_swigt__p_CosineRippleLorentz, _p_CosineRippleLorentzTo_p_ICosineRipple, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_IFormFactor[] = {  {&_swigt__p_IFormFactor, 0, 0, 0},  {&_swigt__p_BarGauss, _p_BarGaussTo_p_IFormFactor, 0, 0},  {&_swigt__p_BarLorentz, _p_BarLorentzTo_p_IFormFactor, 0, 0},  {&_swigt__p_Bipyramid4, _p_Bipyramid4To_p_IFormFactor, 0, 0},  {&_swigt__p_Box, _p_BoxTo_p_IFormFactor, 0, 0},  {&_swigt__p_CantellatedCube, _p_CantellatedCubeTo_p_IFormFactor, 0, 0},  {&_swigt__p_Cone, _p_ConeTo_p_IFormFactor, 0, 0},  {&_swigt__p_CosineRippleBox, _p_CosineRippleBoxTo_p_IFormFactor, 0, 0},  {&_swigt__p_CosineRippleGauss, _p_CosineRippleGaussTo_p_IFormFactor, 0, 0},  {&_swigt__p_CosineRippleLorentz, _p_CosineRippleLorentzTo_p_IFormFactor, 0, 0},  {&_swigt__p_Cylinder, _p_CylinderTo_p_IFormFactor, 0, 0},  {&_swigt__p_Dodecahedron, _p_DodecahedronTo_p_IFormFactor, 0, 0},  {&_swigt__p_EllipsoidalCylinder, _p_EllipsoidalCylinderTo_p_IFormFactor, 0, 0},  {&_swigt__p_FuzzySphere, _p_FuzzySphereTo_p_IFormFactor, 0, 0},  {&_swigt__p_GaussSphere, _p_GaussSphereTo_p_IFormFactor, 0, 0},  {&_swigt__p_HemiEllipsoid, _p_HemiEllipsoidTo_p_IFormFactor, 0, 0},  {&_swigt__p_HorizontalCylinder, _p_HorizontalCylinderTo_p_IFormFactor, 0, 0},  {&_swigt__p_ICosineRipple, _p_ICosineRippleTo_p_IFormFactor, 0, 0},  {&_swigt__p_IFormFactorPolyhedron, _p_IFormFactorPolyhedronTo_p_IFormFactor, 0, 0},  {&_swigt__p_IFormFactorPrism, _p_IFormFactorPrismTo_p_IFormFactor, 0, 0},  {&_swigt__p_IProfileRectangularRipple, _p_IProfileRectangularRippleTo_p_IFormFactor, 0, 0},  {&_swigt__p_IProfileRipple, _p_IProfileRippleTo_p_IFormFactor, 0, 0},  {&_swigt__p_ISawtoothRipple, _p_ISawtoothRippleTo_p_IFormFactor, 0, 0},  {&_swigt__p_Icosahedron, _p_IcosahedronTo_p_IFormFactor, 0, 0},  {&_swigt__p_LongBoxGauss, _p_LongBoxGaussTo_p_IFormFactor, 0, 0},  {&_swigt__p_LongBoxLorentz, _p_LongBoxLorentzTo_p_IFormFactor, 0, 0},  {&_swigt__p_PlatonicOctahedron, _p_PlatonicOctahedronTo_p_IFormFactor, 0, 0},  {&_swigt__p_PlatonicTetrahedron, _p_PlatonicTetrahedronTo_p_IFormFactor, 0, 0},  {&_swigt__p_Prism3, _p_Prism3To_p_IFormFactor, 0, 0},  {&_swigt__p_Prism6, _p_Prism6To_p_IFormFactor, 0, 0},  {&_swigt__p_Pyramid2, _p_Pyramid2To_p_IFormFactor, 0, 0},  {&_swigt__p_Pyramid3, _p_Pyramid3To_p_IFormFactor, 0, 0},  {&_swigt__p_Pyramid4, _p_Pyramid4To_p_IFormFactor, 0, 0},  {&_swigt__p_Pyramid6, _p_Pyramid6To_p_IFormFactor, 0, 0},  {&_swigt__p_SawtoothRippleBox, _p_SawtoothRippleBoxTo_p_IFormFactor, 0, 0},  {&_swigt__p_SawtoothRippleGauss, _p_SawtoothRippleGaussTo_p_IFormFactor, 0, 0},  {&_swigt__p_SawtoothRippleLorentz, _p_SawtoothRippleLorentzTo_p_IFormFactor, 0, 0},  {&_swigt__p_Sphere, _p_SphereTo_p_IFormFactor, 0, 0},  {&_swigt__p_Spheroid, _p_SpheroidTo_p_IFormFactor, 0, 0},  {&_swigt__p_TruncatedCube, _p_TruncatedCubeTo_p_IFormFactor, 0, 0},  {&_swigt__p_TruncatedSphere, _p_TruncatedSphereTo_p_IFormFactor, 0, 0},  {&_swigt__p_TruncatedSpheroid, _p_TruncatedSpheroidTo_p_IFormFactor, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_IFormFactorPolyhedron[] = {  {&_swigt__p_IFormFactorPolyhedron, 0, 0, 0},  {&_swigt__p_Bipyramid4, _p_Bipyramid4To_p_IFormFactorPolyhedron, 0, 0},  {&_swigt__p_Box, _p_BoxTo_p_IFormFactorPolyhedron, 0, 0},  {&_swigt__p_CantellatedCube, _p_CantellatedCubeTo_p_IFormFactorPolyhedron, 0, 0},  {&_swigt__p_Dodecahedron, _p_DodecahedronTo_p_IFormFactorPolyhedron, 0, 0},  {&_swigt__p_IFormFactorPrism, _p_IFormFactorPrismTo_p_IFormFactorPolyhedron, 0, 0},  {&_swigt__p_Icosahedron, _p_IcosahedronTo_p_IFormFactorPolyhedron, 0, 0},  {&_swigt__p_PlatonicOctahedron, _p_PlatonicOctahedronTo_p_IFormFactorPolyhedron, 0, 0},  {&_swigt__p_PlatonicTetrahedron, _p_PlatonicTetrahedronTo_p_IFormFactorPolyhedron, 0, 0},  {&_swigt__p_Prism3, _p_Prism3To_p_IFormFactorPolyhedron, 0, 0},  {&_swigt__p_Prism6, _p_Prism6To_p_IFormFactorPolyhedron, 0, 0},  {&_swigt__p_Pyramid2, _p_Pyramid2To_p_IFormFactorPolyhedron, 0, 0},  {&_swigt__p_Pyramid3, _p_Pyramid3To_p_IFormFactorPolyhedron, 0, 0},  {&_swigt__p_Pyramid4, _p_Pyramid4To_p_IFormFactorPolyhedron, 0, 0},  {&_swigt__p_Pyramid6, _p_Pyramid6To_p_IFormFactorPolyhedron, 0, 0},  {&_swigt__p_TruncatedCube, _p_TruncatedCubeTo_p_IFormFactorPolyhedron, 0, 0},{0, 0, 0, 0}};
@@ -74275,8 +74682,7 @@ static swig_cast_info _swigc__p_RotationEuler[] = {  {&_swigt__p_RotationEuler,
 static swig_cast_info _swigc__p_RotationX[] = {  {&_swigt__p_RotationX, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_RotationY[] = {  {&_swigt__p_RotationY, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_RotationZ[] = {  {&_swigt__p_RotationZ, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_RoughnessModelWrap[] = {  {&_swigt__p_RoughnessModelWrap, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_RoughnessModelWrap__RoughnessModel[] = {  {&_swigt__p_RoughnessModelWrap__RoughnessModel, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_RoughnessModel[] = {  {&_swigt__p_RoughnessModel, 0, 0, 0},  {&_swigt__p_ErfRoughness, _p_ErfRoughnessTo_p_RoughnessModel, 0, 0},  {&_swigt__p_TanhRoughness, _p_TanhRoughnessTo_p_RoughnessModel, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_SawtoothRippleBox[] = {  {&_swigt__p_SawtoothRippleBox, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_SawtoothRippleGauss[] = {  {&_swigt__p_SawtoothRippleGauss, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_SawtoothRippleLorentz[] = {  {&_swigt__p_SawtoothRippleLorentz, 0, 0, 0},{0, 0, 0, 0}};
@@ -74286,6 +74692,7 @@ static swig_cast_info _swigc__p_Sphere[] = {  {&_swigt__p_Sphere, 0, 0, 0},{0, 0
 static swig_cast_info _swigc__p_Spheroid[] = {  {&_swigt__p_Spheroid, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_SpinMatrix[] = {  {&_swigt__p_SpinMatrix, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_SquareLattice2D[] = {  {&_swigt__p_SquareLattice2D, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_TanhRoughness[] = {  {&_swigt__p_TanhRoughness, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_TruncatedCube[] = {  {&_swigt__p_TruncatedCube, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_TruncatedSphere[] = {  {&_swigt__p_TruncatedSphere, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_TruncatedSpheroid[] = {  {&_swigt__p_TruncatedSpheroid, 0, 0, 0},{0, 0, 0, 0}};
@@ -74358,6 +74765,7 @@ static swig_cast_info *swig_cast_initial[] = {
   _swigc__p_Cylinder,
   _swigc__p_Dodecahedron,
   _swigc__p_EllipsoidalCylinder,
+  _swigc__p_ErfRoughness,
   _swigc__p_FuzzySphere,
   _swigc__p_GaussFisherPeakShape,
   _swigc__p_GaussSphere,
@@ -74435,8 +74843,7 @@ static swig_cast_info *swig_cast_initial[] = {
   _swigc__p_RotationX,
   _swigc__p_RotationY,
   _swigc__p_RotationZ,
-  _swigc__p_RoughnessModelWrap,
-  _swigc__p_RoughnessModelWrap__RoughnessModel,
+  _swigc__p_RoughnessModel,
   _swigc__p_SawtoothRippleBox,
   _swigc__p_SawtoothRippleGauss,
   _swigc__p_SawtoothRippleLorentz,
@@ -74446,6 +74853,7 @@ static swig_cast_info *swig_cast_initial[] = {
   _swigc__p_Spheroid,
   _swigc__p_SpinMatrix,
   _swigc__p_SquareLattice2D,
+  _swigc__p_TanhRoughness,
   _swigc__p_TruncatedCube,
   _swigc__p_TruncatedSphere,
   _swigc__p_TruncatedSpheroid,
@@ -74979,9 +75387,6 @@ SWIG_init(void) {
   SWIG_Python_SetConstant(d, "MATERIAL_TYPES_InvalidMaterialType",SWIG_From_int(static_cast< int >(MATERIAL_TYPES::InvalidMaterialType)));
   SWIG_Python_SetConstant(d, "MATERIAL_TYPES_RefractiveMaterial",SWIG_From_int(static_cast< int >(MATERIAL_TYPES::RefractiveMaterial)));
   SWIG_Python_SetConstant(d, "MATERIAL_TYPES_MaterialBySLD",SWIG_From_int(static_cast< int >(MATERIAL_TYPES::MaterialBySLD)));
-  SWIG_Python_SetConstant(d, "RoughnessModel_DEFAULT",SWIG_From_int(static_cast< int >(RoughnessModelWrap::DEFAULT)));
-  SWIG_Python_SetConstant(d, "RoughnessModel_TANH",SWIG_From_int(static_cast< int >(RoughnessModelWrap::TANH)));
-  SWIG_Python_SetConstant(d, "RoughnessModel_NEVOT_CROCE",SWIG_From_int(static_cast< int >(RoughnessModelWrap::NEVOT_CROCE)));
 #if PY_VERSION_HEX >= 0x03000000
   return m;
 #else
diff --git a/rawEx/fit/specular/Honeycomb_fit.py b/rawEx/fit/specular/Honeycomb_fit.py
index d730662264c410544a6fd1839053165da47248ed..0ad0010ed020dc0780a8a8714a93026dae5ef503 100755
--- a/rawEx/fit/specular/Honeycomb_fit.py
+++ b/rawEx/fit/specular/Honeycomb_fit.py
@@ -48,7 +48,7 @@ def get_sample(P, sign, T):
     l_SiO2 = ba.Layer(material_SiO2, P["t_SiO2"]*angstrom)
     l_Si = ba.Layer(material_Si)
 
-    roughness_model = ba.RoughnessModel.NEVOT_CROCE
+    roughness_model = ba.ErfRoughness()
     rPyOx = ba.LayerRoughness(P["rPyOx"]*angstrom, roughness_model)
     rPy2 = ba.LayerRoughness(P["rPy2"]*angstrom, roughness_model)
     rPy1 = ba.LayerRoughness(P["rPy1"]*angstrom, roughness_model)
diff --git a/rawEx/specular/RoughnessModel.py b/rawEx/specular/RoughnessModel.py
index efde2e143a90d491ae30e67cd432c45258901870..e8ea7ba77964a43eca8e840fa1208d6ff0b9cd02 100755
--- a/rawEx/specular/RoughnessModel.py
+++ b/rawEx/specular/RoughnessModel.py
@@ -57,8 +57,8 @@ def simulate(roughness_model, title):
 
 if __name__ == '__main__':
     results = [
-        simulate(ba.RoughnessModel.NEVOT_CROCE, "Névot-Croce"),
-        simulate(ba.RoughnessModel.TANH, "Tanh"),
+        simulate(ba.ErfRoughness(), "Névot-Croce"),
+        simulate(ba.TanhRoughness(), "Tanh"),
     ]
 
     bp.plot_multicurve(results)
diff --git a/rawEx/varia/MaterialProfile.py b/rawEx/varia/MaterialProfile.py
index 11099b3a5ea8bff478f53f3695c18f7179ee45ce..bd7e7d0278d80d948eda1c44cc0150a4aea6216a 100755
--- a/rawEx/varia/MaterialProfile.py
+++ b/rawEx/varia/MaterialProfile.py
@@ -29,7 +29,8 @@ def get_sample():
     # sample
     sample = ba.MultiLayer()
     sample.addLayer(ambient_layer)
-    roughness = ba.LayerRoughness(5*angstrom, 0.5, 10*angstrom)
+    roughness_model = ba.TanhRoughness()
+    roughness = ba.LayerRoughness(5*angstrom, 0.5, 10*angstrom, roughness_model)
     for _ in range(4):
         sample.addLayerWithTopRoughness(ti_layer, roughness)
         sample.addLayerWithTopRoughness(ni_layer, roughness)