From 39e80d7bef4f27f592777a2fe2d210974da4b1ed Mon Sep 17 00:00:00 2001
From: Mikhail Svechnikov <m.svechnikov@fz-juelich.de>
Date: Mon, 2 Sep 2024 10:48:12 +0200
Subject: [PATCH] add max frequency

---
 GUI/Model/FromCore/ItemizeSample.cpp       |   3 +-
 GUI/Model/Sample/RoughnessItems.cpp        |  27 ++-
 GUI/Model/Sample/RoughnessItems.h          |  13 +-
 Sample/Interface/AutocorrelationModels.cpp |  48 ++++-
 Sample/Interface/AutocorrelationModels.h   |  58 +++---
 auto/Wrap/libBornAgainSample.py            |  18 +-
 auto/Wrap/libBornAgainSample_wrap.cpp      | 216 ++++++++++++++++++++-
 7 files changed, 318 insertions(+), 65 deletions(-)

diff --git a/GUI/Model/FromCore/ItemizeSample.cpp b/GUI/Model/FromCore/ItemizeSample.cpp
index c7f308439be..49503da25e9 100644
--- a/GUI/Model/FromCore/ItemizeSample.cpp
+++ b/GUI/Model/FromCore/ItemizeSample.cpp
@@ -322,7 +322,8 @@ void set_Roughness(LayerItem* parent, const LayerInterface* top_interface)
 
     if (const auto* autocorrItem = dynamic_cast<const K_CorrelationModel*>(autocorrelation)) {
         auto* k_corr = new K_CorrelationRoughnessItem(autocorrItem->sigma(), autocorrItem->hurst(),
-                                                      autocorrItem->lateralCorrLength());
+                                                      autocorrItem->lateralCorrLength(),
+                                                      autocorrItem->maxSpatialFrequency());
         set_InterlayerModel(k_corr, interlayer);
         set_CrosscorrelationModel(k_corr, crosscorrelation);
         parent->roughnessSelection().setCertainItem(k_corr);
diff --git a/GUI/Model/Sample/RoughnessItems.cpp b/GUI/Model/Sample/RoughnessItems.cpp
index 85509f13bf3..0d178b6ab23 100644
--- a/GUI/Model/Sample/RoughnessItems.cpp
+++ b/GUI/Model/Sample/RoughnessItems.cpp
@@ -22,6 +22,7 @@ namespace Tag {
 const QString BaseData("BaseData");
 const QString HeightDistributionModel("HeightDistributionModel");
 const QString CrosscorrelationModel("CrosscorrelationModel");
+const QString MaxSpatialFrequency("MaxSpatialFrequency");
 const QString Sigma("Sigma");
 const QString Hurst("Hurst");
 const QString LateralCorrelationLength("LateralCorrelationLength");
@@ -33,6 +34,7 @@ void RoughnessItem::writeTo(QXmlStreamWriter* w) const
 {
     XML::writeTaggedElement(w, Tag::HeightDistributionModel, m_interlayer_model);
     XML::writeTaggedElement(w, Tag::CrosscorrelationModel, m_crosscorr_model);
+    m_max_spatial_frequency.writeTo2(w, Tag::MaxSpatialFrequency);
 }
 
 void RoughnessItem::readFrom(QXmlStreamReader* r)
@@ -44,12 +46,14 @@ void RoughnessItem::readFrom(QXmlStreamReader* r)
             XML::readTaggedElement(r, tag, m_interlayer_model);
         else if (tag == Tag::CrosscorrelationModel)
             XML::readTaggedElement(r, tag, m_crosscorr_model);
+        else if (tag == Tag::MaxSpatialFrequency)
+            m_max_spatial_frequency.readFrom2(r, tag);
         else
             r->skipCurrentElement();
     }
 }
 
-RoughnessItem::RoughnessItem()
+RoughnessItem::RoughnessItem(double max_spat_frequency)
 {
     m_interlayer_model.simpleInit("Interlayer profile",
                                   "Laterally averaged profile of the interlayer transition (or "
@@ -58,12 +62,19 @@ RoughnessItem::RoughnessItem()
     m_crosscorr_model.simpleInit("Crosscorrelation",
                                  "Model of roughness crosscorrelation between interfaces",
                                  CrosscorrelationCatalog::Type::None);
+    m_max_spatial_frequency.init("Max spatial frequency (1/nm)",
+                                 "The upper limit of the roughness spatial frequency.\n "
+                                 "Minimum spatial scale of relief (in nm) is 1/max_frequency.",
+                                 max_spat_frequency, 3, RealLimits::positive(),
+                                 "maxSpatialFrequency");
 }
 
 //------------------------------------------------------------------------------------------------
 
 K_CorrelationRoughnessItem::K_CorrelationRoughnessItem(double sigma, double hurst,
-                                                       double corr_length)
+                                                       double corr_length,
+                                                       double max_spat_frequency)
+    : RoughnessItem(max_spat_frequency)
 {
     m_sigma.init("Sigma (nm)", "rms of the roughness", sigma, "sigma");
     m_hurst.init("Hurst",
@@ -104,5 +115,15 @@ void K_CorrelationRoughnessItem::readFrom(QXmlStreamReader* r)
 std::unique_ptr<AutocorrelationModel> K_CorrelationRoughnessItem::createModel() const
 {
     return std::make_unique<K_CorrelationModel>(m_sigma.dVal(), m_hurst.dVal(),
-                                                m_lateral_correlation_length.dVal());
+                                                m_lateral_correlation_length.dVal(),
+                                                m_max_spatial_frequency.dVal());
+}
+
+DoubleProperties K_CorrelationRoughnessItem::lateralProperties()
+{
+    DoubleProperties result = {&m_sigma, &m_hurst, &m_lateral_correlation_length};
+    const auto base_pars = RoughnessItem::lateralProperties();
+    for (const auto base_par : base_pars)
+        result.push_back(base_par);
+    return result;
 }
diff --git a/GUI/Model/Sample/RoughnessItems.h b/GUI/Model/Sample/RoughnessItems.h
index d65f782c698..c756a3b9d71 100644
--- a/GUI/Model/Sample/RoughnessItems.h
+++ b/GUI/Model/Sample/RoughnessItems.h
@@ -30,7 +30,7 @@ public:
     virtual void writeTo(QXmlStreamWriter* w) const;
     virtual void readFrom(QXmlStreamReader* r);
     virtual std::unique_ptr<AutocorrelationModel> createModel() const = 0;
-    virtual DoubleProperties lateralProperties() = 0;
+    virtual DoubleProperties lateralProperties() { return {&m_max_spatial_frequency}; }
 
     PolyPtr<InterlayerItem, InterlayerCatalog>& interlayerModelSelection()
     {
@@ -47,14 +47,16 @@ public:
     void setCrosscorrModelType(CrosscorrelationItem* p) { m_crosscorr_model.setCertainItem(p); }
 
 protected:
-    RoughnessItem();
+    RoughnessItem(double max_spat_frequency);
     PolyPtr<InterlayerItem, InterlayerCatalog> m_interlayer_model;
     PolyPtr<CrosscorrelationItem, CrosscorrelationCatalog> m_crosscorr_model;
+    DoubleProperty m_max_spatial_frequency;
 };
 
 class K_CorrelationRoughnessItem : public RoughnessItem {
 public:
-    K_CorrelationRoughnessItem(double sigma, double hurst, double corr_length);
+    K_CorrelationRoughnessItem(double sigma, double hurst, double corr_length,
+                               double max_spat_frequency = 0.5);
 
     DoubleProperty& sigma() { return m_sigma; }
     const DoubleProperty& sigma() const { return m_sigma; }
@@ -72,10 +74,7 @@ public:
     void readFrom(QXmlStreamReader* r) override;
     std::unique_ptr<AutocorrelationModel> createModel() const override;
 
-    DoubleProperties lateralProperties() override
-    {
-        return {&m_sigma, &m_hurst, &m_lateral_correlation_length};
-    }
+    DoubleProperties lateralProperties() override;
 
 private:
     DoubleProperty m_sigma;
diff --git a/Sample/Interface/AutocorrelationModels.cpp b/Sample/Interface/AutocorrelationModels.cpp
index f148c7c5477..78d7877b5d5 100644
--- a/Sample/Interface/AutocorrelationModels.cpp
+++ b/Sample/Interface/AutocorrelationModels.cpp
@@ -1,4 +1,4 @@
-//  ************************************************************************************************
+//  ************************************************************************************************
 //
 //  BornAgain: simulate and fit reflection and scattering
 //
@@ -20,12 +20,34 @@
 
 using std::numbers::pi;
 
+AutocorrelationModel::AutocorrelationModel(double maxSpatFrequency)
+    : m_max_spatial_frequency(maxSpatFrequency)
+{
+}
+
+std::vector<std::string> AutocorrelationModel::validationErrs() const
+{
+    std::vector<std::string> errs;
+    requestGt0(errs, m_max_spatial_frequency, "maxSpatFrequency");
+    return errs;
+}
+
+std::string AutocorrelationModel::pythonArguments() const
+{
+    return Py::Fmt::printArguments(
+        {{m_max_spatial_frequency, AutocorrelationModel::parDefs()[0].unit}});
+}
+
+//-------------------------------------------------------------------------------------------------
+
 //! @param sigma: rms of the roughness in nanometers
 //! @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
-K_CorrelationModel::K_CorrelationModel(double sigma, double hurst, double lateralCorrLength)
-    : m_sigma(sigma)
+K_CorrelationModel::K_CorrelationModel(double sigma, double hurst, double lateralCorrLength,
+                                       double maxSpatFrequency)
+    : AutocorrelationModel(maxSpatFrequency)
+    , m_sigma(sigma)
     , m_hurst_parameter(hurst)
     , m_lateral_corr_length(lateralCorrLength)
 {
@@ -34,12 +56,21 @@ K_CorrelationModel::K_CorrelationModel(double sigma, double hurst, double latera
 
 K_CorrelationModel* K_CorrelationModel::clone() const
 {
-    return new K_CorrelationModel(m_sigma, m_hurst_parameter, m_lateral_corr_length);
+    return new K_CorrelationModel(m_sigma, m_hurst_parameter, m_lateral_corr_length,
+                                  m_max_spatial_frequency);
+}
+
+std::vector<ParaMeta> K_CorrelationModel::parDefs() const
+{
+    std::vector<ParaMeta> result = {{"Sigma", "nm"}, {"Hurst", ""}, {"CorrLength", "nm"}};
+    const auto base_pars = AutocorrelationModel::parDefs();
+    result.insert(result.end(), base_pars.begin(), base_pars.end());
+    return result;
 }
 
 std::string K_CorrelationModel::validate() const
 {
-    std::vector<std::string> errs;
+    std::vector<std::string> errs = AutocorrelationModel::validationErrs();
     requestGe0(errs, m_sigma, "sigma");
     if (m_sigma > 0) {
         requestIn(errs, m_hurst_parameter, "hurst", 0, 1);
@@ -55,7 +86,8 @@ std::string K_CorrelationModel::pythonArguments() const
 {
     return Py::Fmt::printArguments({{m_sigma, parDefs()[0].unit},
                                     {m_hurst_parameter, parDefs()[1].unit},
-                                    {m_lateral_corr_length, parDefs()[2].unit}});
+                                    {m_lateral_corr_length, parDefs()[2].unit}})
+           + ", " + AutocorrelationModel::pythonArguments();
 }
 
 //! Power spectral density of the surface roughness is a result of two-dimensional
@@ -65,9 +97,11 @@ std::string K_CorrelationModel::pythonArguments() const
 double K_CorrelationModel::spectralFunction(const R3& q) const
 {
     ASSERT(m_validated);
+    const double Qpar2 = q.magxy2();
+    if (Qpar2 > 4 * pi * pi * m_max_spatial_frequency * m_max_spatial_frequency)
+        return 0;
     const double H = m_hurst_parameter;
     const double clength2 = m_lateral_corr_length * m_lateral_corr_length;
-    const double Qpar2 = q.magxy2();
     return 4.0 * pi * H * m_sigma * m_sigma * clength2 * std::pow(1 + Qpar2 * clength2, -1 - H);
 }
 
diff --git a/Sample/Interface/AutocorrelationModels.h b/Sample/Interface/AutocorrelationModels.h
index 6f2595588df..dc2a99961f1 100644
--- a/Sample/Interface/AutocorrelationModels.h
+++ b/Sample/Interface/AutocorrelationModels.h
@@ -27,9 +27,19 @@ public:
     virtual double spectralFunction(const R3& k) const = 0;
     virtual double corrFunction(const R3& k) const = 0;
 
+    void setMaxSpatialFrequency(double val) { m_max_spatial_frequency = val; }
+    double maxSpatialFrequency() const { return m_max_spatial_frequency; }
+
+    std::vector<ParaMeta> parDefs() const override { return {{"MaxSpatialFrequency", "1/nm"}}; }
+
 #ifndef SWIG
     //! Used to create the Python constructor of this class
-    virtual std::string pythonArguments() const = 0;
+    virtual std::string pythonArguments() const;
+
+protected:
+    std::vector<std::string> validationErrs() const;
+    AutocorrelationModel(double maxSpatFrequency);
+    double m_max_spatial_frequency; // nm^-1
 #endif
 };
 
@@ -38,56 +48,36 @@ public:
 //! 14472-14478 (1993)
 class K_CorrelationModel : public AutocorrelationModel {
 public:
-    K_CorrelationModel(double sigma = 0, double hurst = 0, double lateralCorrLength = 0);
+    K_CorrelationModel(double sigma = 0, double hurst = 0, double lateralCorrLength = 0,
+                       double maxSpatFrequency = 0.5);
     K_CorrelationModel* clone() const override;
     std::string className() const override { return "K_CorrelationModel"; }
-    std::vector<ParaMeta> parDefs() const final
-    {
-        return {{"Sigma", "nm"}, {"Hurst", ""}, {"CorrLength", "nm"}};
-    }
+    std::vector<ParaMeta> parDefs() const final;
     std::string validate() const override;
 
-#ifndef SWIG
-    std::string pythonArguments() const override;
-#endif
-
     //! Returns power spectral density of the surface roughness
     double spectralFunction(const R3& q) const override;
 
     double corrFunction(const R3& r) const override;
 
     //! Sets rms of roughness
-    void setSigma(double sigma)
-    {
-        m_sigma = sigma;
-    }
+    void setSigma(double sigma) { m_sigma = sigma; }
     //! Returns rms of roughness
-    double sigma() const override
-    {
-        return m_sigma;
-    }
+    double sigma() const override { return m_sigma; }
 
     //! Sets hurst parameter. It describes how jagged the surface is.
-    void setHurstParameter(double hurstParameter)
-    {
-        m_hurst_parameter = hurstParameter;
-    }
+    void setHurstParameter(double hurstParameter) { m_hurst_parameter = hurstParameter; }
     //! Returns hurst parameter
-    double hurst() const
-    {
-        return m_hurst_parameter;
-    }
+    double hurst() const { return m_hurst_parameter; }
 
     //! Sets lateral correlation length
-    void setLatteralCorrLength(double lateralCorrLen)
-    {
-        m_lateral_corr_length = lateralCorrLen;
-    }
+    void setLatteralCorrLength(double lateralCorrLen) { m_lateral_corr_length = lateralCorrLen; }
     //! Returns lateral correlation length
-    double lateralCorrLength() const
-    {
-        return m_lateral_corr_length;
-    }
+    double lateralCorrLength() const { return m_lateral_corr_length; }
+
+#ifndef SWIG
+    std::string pythonArguments() const override;
+#endif
 
 private:
     double m_sigma;           //!< rms of roughness
diff --git a/auto/Wrap/libBornAgainSample.py b/auto/Wrap/libBornAgainSample.py
index 9f35ceb0dcb..716bd55a525 100644
--- a/auto/Wrap/libBornAgainSample.py
+++ b/auto/Wrap/libBornAgainSample.py
@@ -4337,6 +4337,18 @@ class AutocorrelationModel(libBornAgainBase.ICloneable, libBornAgainParam.INode)
     def corrFunction(self, k):
         r"""corrFunction(AutocorrelationModel self, R3 k) -> double"""
         return _libBornAgainSample.AutocorrelationModel_corrFunction(self, k)
+
+    def setMaxSpatialFrequency(self, val):
+        r"""setMaxSpatialFrequency(AutocorrelationModel self, double val)"""
+        return _libBornAgainSample.AutocorrelationModel_setMaxSpatialFrequency(self, val)
+
+    def maxSpatialFrequency(self):
+        r"""maxSpatialFrequency(AutocorrelationModel self) -> double"""
+        return _libBornAgainSample.AutocorrelationModel_maxSpatialFrequency(self)
+
+    def parDefs(self):
+        r"""parDefs(AutocorrelationModel self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >"""
+        return _libBornAgainSample.AutocorrelationModel_parDefs(self)
     __swig_destroy__ = _libBornAgainSample.delete_AutocorrelationModel
 
 # Register AutocorrelationModel in _libBornAgainSample:
@@ -4347,9 +4359,9 @@ class K_CorrelationModel(AutocorrelationModel):
     thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
     __repr__ = _swig_repr
 
-    def __init__(self, sigma=0, hurst=0, lateralCorrLength=0):
-        r"""__init__(K_CorrelationModel self, double sigma=0, double hurst=0, double lateralCorrLength=0) -> K_CorrelationModel"""
-        _libBornAgainSample.K_CorrelationModel_swiginit(self, _libBornAgainSample.new_K_CorrelationModel(sigma, hurst, lateralCorrLength))
+    def __init__(self, sigma=0, hurst=0, lateralCorrLength=0, maxSpatFrequency=0.5):
+        r"""__init__(K_CorrelationModel self, double sigma=0, double hurst=0, double lateralCorrLength=0, double maxSpatFrequency=0.5) -> K_CorrelationModel"""
+        _libBornAgainSample.K_CorrelationModel_swiginit(self, _libBornAgainSample.new_K_CorrelationModel(sigma, hurst, lateralCorrLength, maxSpatFrequency))
 
     def clone(self):
         r"""clone(K_CorrelationModel self) -> K_CorrelationModel"""
diff --git a/auto/Wrap/libBornAgainSample_wrap.cpp b/auto/Wrap/libBornAgainSample_wrap.cpp
index c2f75f61b9f..07d646c2cfb 100644
--- a/auto/Wrap/libBornAgainSample_wrap.cpp
+++ b/auto/Wrap/libBornAgainSample_wrap.cpp
@@ -52207,6 +52207,114 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_AutocorrelationModel_setMaxSpatialFrequency(PyObject *self, PyObject *args) {
+  PyObject *resultobj = 0;
+  AutocorrelationModel *arg1 = (AutocorrelationModel *) 0 ;
+  double arg2 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  double val2 ;
+  int ecode2 = 0 ;
+  PyObject *swig_obj[2] ;
+  
+  (void)self;
+  if (!SWIG_Python_UnpackTuple(args, "AutocorrelationModel_setMaxSpatialFrequency", 2, 2, swig_obj)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_AutocorrelationModel, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "AutocorrelationModel_setMaxSpatialFrequency" "', argument " "1"" of type '" "AutocorrelationModel *""'"); 
+  }
+  arg1 = reinterpret_cast< AutocorrelationModel * >(argp1);
+  ecode2 = SWIG_AsVal_double(swig_obj[1], &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "AutocorrelationModel_setMaxSpatialFrequency" "', argument " "2"" of type '" "double""'");
+  } 
+  arg2 = static_cast< double >(val2);
+  {
+    try {
+      (arg1)->setMaxSpatialFrequency(arg2);
+    } 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 *_wrap_AutocorrelationModel_maxSpatialFrequency(PyObject *self, PyObject *args) {
+  PyObject *resultobj = 0;
+  AutocorrelationModel *arg1 = (AutocorrelationModel *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject *swig_obj[1] ;
+  double result;
+  
+  (void)self;
+  if (!args) SWIG_fail;
+  swig_obj[0] = args;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_AutocorrelationModel, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "AutocorrelationModel_maxSpatialFrequency" "', argument " "1"" of type '" "AutocorrelationModel const *""'"); 
+  }
+  arg1 = reinterpret_cast< AutocorrelationModel * >(argp1);
+  {
+    try {
+      result = (double)((AutocorrelationModel const *)arg1)->maxSpatialFrequency();
+    } 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_AutocorrelationModel_parDefs(PyObject *self, PyObject *args) {
+  PyObject *resultobj = 0;
+  AutocorrelationModel *arg1 = (AutocorrelationModel *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject *swig_obj[1] ;
+  SwigValueWrapper< std::vector< ParaMeta,std::allocator< ParaMeta > > > result;
+  
+  (void)self;
+  if (!args) SWIG_fail;
+  swig_obj[0] = args;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_AutocorrelationModel, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "AutocorrelationModel_parDefs" "', argument " "1"" of type '" "AutocorrelationModel const *""'"); 
+  }
+  arg1 = reinterpret_cast< AutocorrelationModel * >(argp1);
+  {
+    try {
+      result = ((AutocorrelationModel const *)arg1)->parDefs();
+    } 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((new std::vector< ParaMeta,std::allocator< ParaMeta > >(result)), SWIGTYPE_p_std__vectorT_ParaMeta_std__allocatorT_ParaMeta_t_t, SWIG_POINTER_OWN |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_delete_AutocorrelationModel(PyObject *self, PyObject *args) {
   PyObject *resultobj = 0;
   AutocorrelationModel *arg1 = (AutocorrelationModel *) 0 ;
@@ -52248,6 +52356,62 @@ SWIGINTERN PyObject *AutocorrelationModel_swigregister(PyObject *SWIGUNUSEDPARM(
 }
 
 SWIGINTERN PyObject *_wrap_new_K_CorrelationModel__SWIG_0(PyObject *self, Py_ssize_t nobjs, PyObject **swig_obj) {
+  PyObject *resultobj = 0;
+  double arg1 ;
+  double arg2 ;
+  double arg3 ;
+  double arg4 ;
+  double val1 ;
+  int ecode1 = 0 ;
+  double val2 ;
+  int ecode2 = 0 ;
+  double val3 ;
+  int ecode3 = 0 ;
+  double val4 ;
+  int ecode4 = 0 ;
+  K_CorrelationModel *result = 0 ;
+  
+  (void)self;
+  if ((nobjs < 4) || (nobjs > 4)) SWIG_fail;
+  ecode1 = SWIG_AsVal_double(swig_obj[0], &val1);
+  if (!SWIG_IsOK(ecode1)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode1), "in method '" "new_K_CorrelationModel" "', argument " "1"" of type '" "double""'");
+  } 
+  arg1 = static_cast< double >(val1);
+  ecode2 = SWIG_AsVal_double(swig_obj[1], &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "new_K_CorrelationModel" "', 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 '" "new_K_CorrelationModel" "', argument " "3"" of type '" "double""'");
+  } 
+  arg3 = static_cast< double >(val3);
+  ecode4 = SWIG_AsVal_double(swig_obj[3], &val4);
+  if (!SWIG_IsOK(ecode4)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "new_K_CorrelationModel" "', argument " "4"" of type '" "double""'");
+  } 
+  arg4 = static_cast< double >(val4);
+  {
+    try {
+      result = (K_CorrelationModel *)new K_CorrelationModel(arg1,arg2,arg3,arg4);
+    } 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_K_CorrelationModel, SWIG_POINTER_NEW |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_new_K_CorrelationModel__SWIG_1(PyObject *self, Py_ssize_t nobjs, PyObject **swig_obj) {
   PyObject *resultobj = 0;
   double arg1 ;
   double arg2 ;
@@ -52295,7 +52459,7 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_new_K_CorrelationModel__SWIG_1(PyObject *self, Py_ssize_t nobjs, PyObject **swig_obj) {
+SWIGINTERN PyObject *_wrap_new_K_CorrelationModel__SWIG_2(PyObject *self, Py_ssize_t nobjs, PyObject **swig_obj) {
   PyObject *resultobj = 0;
   double arg1 ;
   double arg2 ;
@@ -52335,7 +52499,7 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_new_K_CorrelationModel__SWIG_2(PyObject *self, Py_ssize_t nobjs, PyObject **swig_obj) {
+SWIGINTERN PyObject *_wrap_new_K_CorrelationModel__SWIG_3(PyObject *self, Py_ssize_t nobjs, PyObject **swig_obj) {
   PyObject *resultobj = 0;
   double arg1 ;
   double val1 ;
@@ -52367,7 +52531,7 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_new_K_CorrelationModel__SWIG_3(PyObject *self, Py_ssize_t nobjs, PyObject **SWIGUNUSEDPARM(swig_obj)) {
+SWIGINTERN PyObject *_wrap_new_K_CorrelationModel__SWIG_4(PyObject *self, Py_ssize_t nobjs, PyObject **SWIGUNUSEDPARM(swig_obj)) {
   PyObject *resultobj = 0;
   K_CorrelationModel *result = 0 ;
   
@@ -52393,14 +52557,14 @@ fail:
 
 SWIGINTERN PyObject *_wrap_new_K_CorrelationModel(PyObject *self, PyObject *args) {
   Py_ssize_t argc;
-  PyObject *argv[4] = {
+  PyObject *argv[5] = {
     0
   };
   
-  if (!(argc = SWIG_Python_UnpackTuple(args, "new_K_CorrelationModel", 0, 3, argv))) SWIG_fail;
+  if (!(argc = SWIG_Python_UnpackTuple(args, "new_K_CorrelationModel", 0, 4, argv))) SWIG_fail;
   --argc;
   if (argc == 0) {
-    return _wrap_new_K_CorrelationModel__SWIG_3(self, argc, argv);
+    return _wrap_new_K_CorrelationModel__SWIG_4(self, argc, argv);
   }
   if (argc == 1) {
     int _v = 0;
@@ -52409,7 +52573,7 @@ SWIGINTERN PyObject *_wrap_new_K_CorrelationModel(PyObject *self, PyObject *args
       _v = SWIG_CheckState(res);
     }
     if (_v) {
-      return _wrap_new_K_CorrelationModel__SWIG_2(self, argc, argv);
+      return _wrap_new_K_CorrelationModel__SWIG_3(self, argc, argv);
     }
   }
   if (argc == 2) {
@@ -52424,7 +52588,7 @@ SWIGINTERN PyObject *_wrap_new_K_CorrelationModel(PyObject *self, PyObject *args
         _v = SWIG_CheckState(res);
       }
       if (_v) {
-        return _wrap_new_K_CorrelationModel__SWIG_1(self, argc, argv);
+        return _wrap_new_K_CorrelationModel__SWIG_2(self, argc, argv);
       }
     }
   }
@@ -52445,7 +52609,35 @@ SWIGINTERN PyObject *_wrap_new_K_CorrelationModel(PyObject *self, PyObject *args
           _v = SWIG_CheckState(res);
         }
         if (_v) {
-          return _wrap_new_K_CorrelationModel__SWIG_0(self, argc, argv);
+          return _wrap_new_K_CorrelationModel__SWIG_1(self, argc, argv);
+        }
+      }
+    }
+  }
+  if (argc == 4) {
+    int _v = 0;
+    {
+      int res = SWIG_AsVal_double(argv[0], NULL);
+      _v = SWIG_CheckState(res);
+    }
+    if (_v) {
+      {
+        int res = SWIG_AsVal_double(argv[1], NULL);
+        _v = SWIG_CheckState(res);
+      }
+      if (_v) {
+        {
+          int res = SWIG_AsVal_double(argv[2], NULL);
+          _v = SWIG_CheckState(res);
+        }
+        if (_v) {
+          {
+            int res = SWIG_AsVal_double(argv[3], NULL);
+            _v = SWIG_CheckState(res);
+          }
+          if (_v) {
+            return _wrap_new_K_CorrelationModel__SWIG_0(self, argc, argv);
+          }
         }
       }
     }
@@ -52454,6 +52646,7 @@ SWIGINTERN PyObject *_wrap_new_K_CorrelationModel(PyObject *self, PyObject *args
 fail:
   SWIG_Python_RaiseOrModifyTypeError("Wrong number or type of arguments for overloaded function 'new_K_CorrelationModel'.\n"
     "  Possible C/C++ prototypes are:\n"
+    "    K_CorrelationModel::K_CorrelationModel(double,double,double,double)\n"
     "    K_CorrelationModel::K_CorrelationModel(double,double,double)\n"
     "    K_CorrelationModel::K_CorrelationModel(double,double)\n"
     "    K_CorrelationModel::K_CorrelationModel(double)\n"
@@ -74438,9 +74631,12 @@ static PyMethodDef SwigMethods[] = {
 	 { "AutocorrelationModel_sigma", _wrap_AutocorrelationModel_sigma, METH_O, "AutocorrelationModel_sigma(AutocorrelationModel self) -> double"},
 	 { "AutocorrelationModel_spectralFunction", _wrap_AutocorrelationModel_spectralFunction, METH_VARARGS, "AutocorrelationModel_spectralFunction(AutocorrelationModel self, R3 k) -> double"},
 	 { "AutocorrelationModel_corrFunction", _wrap_AutocorrelationModel_corrFunction, METH_VARARGS, "AutocorrelationModel_corrFunction(AutocorrelationModel self, R3 k) -> double"},
+	 { "AutocorrelationModel_setMaxSpatialFrequency", _wrap_AutocorrelationModel_setMaxSpatialFrequency, METH_VARARGS, "AutocorrelationModel_setMaxSpatialFrequency(AutocorrelationModel self, double val)"},
+	 { "AutocorrelationModel_maxSpatialFrequency", _wrap_AutocorrelationModel_maxSpatialFrequency, METH_O, "AutocorrelationModel_maxSpatialFrequency(AutocorrelationModel self) -> double"},
+	 { "AutocorrelationModel_parDefs", _wrap_AutocorrelationModel_parDefs, METH_O, "AutocorrelationModel_parDefs(AutocorrelationModel self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >"},
 	 { "delete_AutocorrelationModel", _wrap_delete_AutocorrelationModel, METH_O, "delete_AutocorrelationModel(AutocorrelationModel self)"},
 	 { "AutocorrelationModel_swigregister", AutocorrelationModel_swigregister, METH_O, NULL},
-	 { "new_K_CorrelationModel", _wrap_new_K_CorrelationModel, METH_VARARGS, "K_CorrelationModel(double sigma=0, double hurst=0, double lateralCorrLength=0)"},
+	 { "new_K_CorrelationModel", _wrap_new_K_CorrelationModel, METH_VARARGS, "K_CorrelationModel(double sigma=0, double hurst=0, double lateralCorrLength=0, double maxSpatFrequency=0.5)"},
 	 { "K_CorrelationModel_clone", _wrap_K_CorrelationModel_clone, METH_O, "K_CorrelationModel_clone(K_CorrelationModel self) -> K_CorrelationModel"},
 	 { "K_CorrelationModel_className", _wrap_K_CorrelationModel_className, METH_O, "K_CorrelationModel_className(K_CorrelationModel self) -> std::string"},
 	 { "K_CorrelationModel_parDefs", _wrap_K_CorrelationModel_parDefs, METH_O, "K_CorrelationModel_parDefs(K_CorrelationModel self) -> std::vector< ParaMeta,std::allocator< ParaMeta > >"},
-- 
GitLab