From 584e8d60c9fb0e9e6edea150c97178836e4bf2e8 Mon Sep 17 00:00:00 2001
From: Walter Van Herck <w.van.herck@fz-juelich.de>
Date: Tue, 27 Nov 2012 14:33:18 +0100
Subject: [PATCH] Calculate form factor by using an approximation of the
 integral in case of large bin sizes

---
 App/src/FitSuiteHelper.cpp                    |   2 +-
 App/src/TestMesoCrystal1.cpp                  |   7 +-
 Core/Core.pro                                 |   3 +-
 Core/FormFactors/inc/FormFactorBigCylinder.h  |  61 ----------
 Core/FormFactors/inc/FormFactorCrystal.h      |   7 ++
 .../inc/FormFactorSphereGaussianRadius.h      |   4 +-
 Core/FormFactors/inc/FormFactorWeighted.h     |   3 +
 Core/FormFactors/inc/FormFactors.h            |   1 -
 Core/FormFactors/inc/IFormFactor.h            | 107 ++++++++++++++++--
 .../FormFactors/src/FormFactorBigCylinder.cpp |  86 --------------
 Core/FormFactors/src/FormFactorCylinder.cpp   |   7 +-
 Core/FormFactors/src/FormFactorFullSphere.cpp |   7 +-
 Core/FormFactors/src/FormFactorGauss.cpp      |  12 +-
 Core/FormFactors/src/FormFactorLorentz.cpp    |   7 +-
 .../src/FormFactorParallelepiped.cpp          |   4 +-
 Core/FormFactors/src/FormFactorPrism3.cpp     |   7 +-
 Core/FormFactors/src/FormFactorPyramid.cpp    |   8 +-
 Core/FormFactors/src/FormFactorWeighted.cpp   |   7 ++
 Core/FormFactors/src/IFormFactor.cpp          |  19 ++++
 Core/Tools/inc/MathFunctions.h                |  12 +-
 20 files changed, 175 insertions(+), 196 deletions(-)
 delete mode 100644 Core/FormFactors/inc/FormFactorBigCylinder.h
 delete mode 100644 Core/FormFactors/src/FormFactorBigCylinder.cpp
 create mode 100644 Core/FormFactors/src/IFormFactor.cpp

diff --git a/App/src/FitSuiteHelper.cpp b/App/src/FitSuiteHelper.cpp
index 2ea5dc01263..76209f477b8 100644
--- a/App/src/FitSuiteHelper.cpp
+++ b/App/src/FitSuiteHelper.cpp
@@ -117,7 +117,7 @@ void FitSuiteObserverDraw::update(IObservable *subject)
         data2draw.push_back( fitObject->getChiSquaredModule()->createChi2DifferenceMap() );
 
         // drawing
-        double maximum_of_real_signal(0);
+//        double maximum_of_real_signal(0);
         for(size_t i_hist=0; i_hist<data2draw.size(); ++i_hist)  {
             c1->cd(i_hist+1);
             gPad->SetLogz();
diff --git a/App/src/TestMesoCrystal1.cpp b/App/src/TestMesoCrystal1.cpp
index b8365a93141..4f6d66e1bff 100644
--- a/App/src/TestMesoCrystal1.cpp
+++ b/App/src/TestMesoCrystal1.cpp
@@ -132,10 +132,9 @@ ISample* MesoCrystalBuilder::buildSample() const
     complex_t n_avg = std::sqrt(m_surface_filling_ratio*avg_n_squared_meso + 1.0 - m_surface_filling_ratio);
     complex_t n_particle_adapted = std::sqrt(n_avg*n_avg + n_particle*n_particle - 1.0);
     FormFactorCylinder ff_cyl(m_meso_height, m_meso_radius);
-//    FormFactorBigCylinder ff_cyl(m_meso_height, m_meso_radius);
-//    double bin_size = FormFactorBigCylinder::calculateBinSize(1.77*Units::angstrom, 0.051, 80);
-//    std::cout << "Bin size: " << bin_size << std::endl;
-//    ff_cyl.setBinSize(bin_size);
+    double bin_size_qy = IFormFactor::CalculateBinSize(1.77*Units::angstrom, 0.051, 80);
+    double bin_size_qz = IFormFactor::CalculateBinSize(1.77*Units::angstrom, 0.05, 80);
+    ff_cyl.setBinSizes(bin_size_qy, bin_size_qz);
     FormFactorDecoratorDebyeWaller ff_meso(ff_cyl.clone(), m_sigma_meso_height*m_sigma_meso_height/2.0,
             m_sigma_meso_radius*m_sigma_meso_radius/2.0);
 
diff --git a/Core/Core.pro b/Core/Core.pro
index 38b301de89f..b812ea39e97 100644
--- a/Core/Core.pro
+++ b/Core/Core.pro
@@ -41,7 +41,6 @@ SOURCES += \
     Algorithms/src/OpticalFresnel.cpp \
     Algorithms/src/ResolutionFunction2DSimple.cpp \
     \
-    FormFactors/src/FormFactorBigCylinder.cpp \
     FormFactors/src/FormFactorDWBA.cpp \
     FormFactors/src/FormFactorDWBAConstZ.cpp \
     FormFactors/src/FormFactorDecoratorTransformation.cpp \
@@ -54,6 +53,7 @@ SOURCES += \
     FormFactors/src/FormFactorLorentz.cpp \
     FormFactors/src/FormFactorWeighted.cpp \
     FormFactors/src/FormFactorCrystal.cpp \
+    FormFactors/src/IFormFactor.cpp \
     \
     Geometry/src/BasicVector3D.cpp \
     Geometry/src/Normal3D.cpp \
@@ -157,7 +157,6 @@ HEADERS += \
     Algorithms/inc/ResolutionFunction2DSimple.h \
     Algorithms/inc/ThreadInfo.h \
     \
-    FormFactors/inc/FormFactorBigCylinder.h \
     FormFactors/inc/FormFactorDWBA.h \
     FormFactors/inc/FormFactorDWBAConstZ.h \
     FormFactors/inc/FormFactorDecoratorDebyeWaller.h \
diff --git a/Core/FormFactors/inc/FormFactorBigCylinder.h b/Core/FormFactors/inc/FormFactorBigCylinder.h
deleted file mode 100644
index 0713f1d5301..00000000000
--- a/Core/FormFactors/inc/FormFactorBigCylinder.h
+++ /dev/null
@@ -1,61 +0,0 @@
-#ifndef FORMFACTORBIGCYLINDER_H_
-#define FORMFACTORBIGCYLINDER_H_
-// ********************************************************************
-// * The BornAgain project                                            *
-// * Simulation of neutron and x-ray scattering at grazing incidence  *
-// *                                                                  *
-// * LICENSE AND DISCLAIMER                                           *
-// * Lorem ipsum dolor sit amet, consectetur adipiscing elit.  Mauris *
-// * eget quam orci. Quisque  porta  varius  dui,  quis  posuere nibh *
-// * mollis quis. Mauris commodo rhoncus porttitor.                   *
-// ********************************************************************
-//! @file   FormFactorBigCylinder.h
-//! @brief  Definition of FormFactorBigCylinder class
-//! @author Scientific Computing Group at FRM II
-//! @date   Nov 23, 2012
-
-#include "IFormFactor.h"
-#include "IStochasticParameter.h"
-
-
-class FormFactorBigCylinder : public IFormFactorBorn
-{
-public:
-    FormFactorBigCylinder(double height, double radius);
-
-    ~FormFactorBigCylinder();
-    virtual FormFactorBigCylinder *clone() const;
-
-    virtual int getNumberOfStochasticParameters() const { return 2; }
-
-    virtual double getHeight() const { return m_height; }
-
-    void setBinSize(double bin_size) { m_bin_size = bin_size; }
-
-    static double calculateBinSize(double lambda, double phi_range, size_t n_phi);
-
-protected:
-    virtual complex_t evaluate_for_q(const cvector_t &q) const;
-
-private:
-    //! copy constructor and assignment operator are hidden since there is a clone method
-    FormFactorBigCylinder(const FormFactorBigCylinder &);
-    FormFactorBigCylinder &operator=(const FormFactorBigCylinder &);
-
-    //! initialize pool parameters, i.e. register some of class members for later access via parameter pool
-    virtual void init_parameters();
-
-    //! approximation to radial function for integration
-    double iTilde(double qR, void *params) const;
-
-    //! print class
-    void print(std::ostream &ostr) const;
-
-//    StochasticParameter<double> *mp_height;
-//    StochasticParameter<double> *mp_radius;
-    double m_height;
-    double m_radius;
-    double m_bin_size;
-};
-
-#endif /* FORMFACTORBIGCYLINDER_H_ */
diff --git a/Core/FormFactors/inc/FormFactorCrystal.h b/Core/FormFactors/inc/FormFactorCrystal.h
index 22b490adb91..93338d9b3ea 100644
--- a/Core/FormFactors/inc/FormFactorCrystal.h
+++ b/Core/FormFactors/inc/FormFactorCrystal.h
@@ -33,6 +33,13 @@ public:
 
     virtual void setAmbientRefractiveIndex(complex_t refractive_index);
 
+    //! propagate the bin sizes to the form factor to possibly enable large bin size approximations
+    virtual void setBinSizes(double delta_qy, double delta_qz) {
+        IFormFactor::setBinSizes(delta_qy, delta_qz);
+        mp_basis_form_factor->setBinSizes(delta_qy, delta_qz);
+        mp_meso_form_factor->setBinSizes(delta_qy, delta_qz);
+    }
+
 protected:
     virtual complex_t evaluate_for_q(const cvector_t &q) const;
 private:
diff --git a/Core/FormFactors/inc/FormFactorSphereGaussianRadius.h b/Core/FormFactors/inc/FormFactorSphereGaussianRadius.h
index eb07a88b605..a8b83fcbecb 100644
--- a/Core/FormFactors/inc/FormFactorSphereGaussianRadius.h
+++ b/Core/FormFactors/inc/FormFactorSphereGaussianRadius.h
@@ -57,7 +57,9 @@ inline FormFactorSphereGaussianRadius::FormFactorSphereGaussianRadius(double mea
 
 inline FormFactorSphereGaussianRadius* FormFactorSphereGaussianRadius::clone() const
 {
-    return new FormFactorSphereGaussianRadius(m_mean, m_sigma);
+    FormFactorSphereGaussianRadius *p_clone = new FormFactorSphereGaussianRadius(m_mean, m_sigma);
+    p_clone->setBinSizes(m_bin_qy, m_bin_qz);
+    return p_clone;
 }
 
 inline FormFactorSphereGaussianRadius::~FormFactorSphereGaussianRadius()
diff --git a/Core/FormFactors/inc/FormFactorWeighted.h b/Core/FormFactors/inc/FormFactorWeighted.h
index d2a1240bf84..e4d9967882f 100644
--- a/Core/FormFactors/inc/FormFactorWeighted.h
+++ b/Core/FormFactors/inc/FormFactorWeighted.h
@@ -30,6 +30,9 @@ public:
     virtual complex_t evaluate(const cvector_t &k_i, const cvector_t &k_f, double alpha_i, double alpha_f) const;
 
     virtual int getNumberOfStochasticParameters() const;
+
+    //! propagate the bin sizes to the form factor to possibly enable large bin size approximations
+    virtual void setBinSizes(double delta_qy, double delta_qz);
 protected:
     std::vector<IFormFactor *> m_form_factors;
     std::vector<double> m_weights;
diff --git a/Core/FormFactors/inc/FormFactors.h b/Core/FormFactors/inc/FormFactors.h
index 1315bcdbf34..b58e7431798 100644
--- a/Core/FormFactors/inc/FormFactors.h
+++ b/Core/FormFactors/inc/FormFactors.h
@@ -14,7 +14,6 @@
 //! @author Scientific Computing Group at FRM II
 //! @date   Jun 27, 2012
 
-#include "FormFactorBigCylinder.h"
 #include "FormFactorPyramid.h"
 #include "FormFactorCylinder.h"
 #include "FormFactorPrism3.h"
diff --git a/Core/FormFactors/inc/IFormFactor.h b/Core/FormFactors/inc/IFormFactor.h
index 6a20d1027b3..fa28a520dc1 100644
--- a/Core/FormFactors/inc/IFormFactor.h
+++ b/Core/FormFactors/inc/IFormFactor.h
@@ -16,6 +16,8 @@
 
 #include "Types.h"
 #include "ISample.h"
+#include "MemberFunctionIntegrator.h"
+#include "MathFunctions.h"
 
 
 //- -------------------------------------------------------------------
@@ -25,24 +27,29 @@
 class IFormFactor : public ISample
 {
 public:
-    IFormFactor(){}
+    IFormFactor() : m_use_large_bin_approximation(false), m_bin_qy(0.0), m_bin_qz(0.0) {}
     virtual ~IFormFactor() {}
     virtual IFormFactor *clone() const=0;
 
     virtual void setAmbientRefractiveIndex(complex_t refractive_index) { (void)refractive_index; }
 
-    /// calculate scattering amplitude for complex wavevectors
-    /// @param k_i   incoming wavevector
-    /// @param k_f   outgoing wavevector
+    //! calculate scattering amplitude for complex wavevectors
+    //! @param k_i   incoming wavevector
+    //! @param k_f   outgoing wavevector
     virtual complex_t evaluate(const cvector_t &k_i, const cvector_t &k_f, double alpha_i, double alpha_f) const=0;
 
-    /// return number of variable/stochastic parameters
+    //! return number of variable/stochastic parameters
     virtual int getNumberOfStochasticParameters() const { return 0; }
 
+    //! propagate the bin sizes to the form factor to possibly enable large bin size approximations
+    virtual void setBinSizes(double delta_qy, double delta_qz);
+
     virtual double getVolume() const;
 
     virtual double getHeight() const;
 
+    virtual double getRadius() const;
+
     virtual bool isDistributedFormFactor() const { return false; }
 
     virtual void createDistributedFormFactors(std::vector<IFormFactor *> &form_factors,
@@ -52,8 +59,25 @@ public:
         (void)nbr_samples;
     }
 
+    static double CalculateBinSize(double lambda, double phi_range, size_t n_phi);
+
+protected:
+    bool m_use_large_bin_approximation;  //!< indicates if large bin size approximation should be used
+    double m_bin_qy, m_bin_qz;  //!< the sizes of the bins in q space
 };
 
+inline void IFormFactor::setBinSizes(double delta_qy, double delta_qz)
+{
+    m_bin_qy = delta_qy;
+    m_bin_qz = delta_qz;
+    if (m_bin_qy > M_PI/2.0/getRadius() || m_bin_qz > M_PI/2.0/getHeight()) {
+        m_use_large_bin_approximation = true;
+    }
+    else {
+        m_use_large_bin_approximation = false;
+    }
+}
+
 inline double IFormFactor::getVolume() const
 {
     cvector_t zero;
@@ -66,6 +90,19 @@ inline double IFormFactor::getHeight() const
     return result;
 }
 
+inline double IFormFactor::getRadius() const
+{
+    double result = std::sqrt(getVolume()/getHeight());
+    return result;
+}
+
+inline double IFormFactor::CalculateBinSize(double lambda, double phi_range,
+        size_t n_phi)
+{
+    double k = 2.0*M_PI/lambda;
+    return k*phi_range/(n_phi-1.0);
+}
+
 class IFormFactorDecorator : public IFormFactor
 {
 public:
@@ -75,6 +112,12 @@ public:
 
     virtual void setAmbientRefractiveIndex(complex_t refractive_index) { if (mp_form_factor) mp_form_factor->setAmbientRefractiveIndex(refractive_index); }
 
+    //! propagate the bin sizes to the form factor to possibly enable large bin size approximations
+    virtual void setBinSizes(double delta_qy, double delta_qz) {
+        IFormFactor::setBinSizes(delta_qy, delta_qz);
+        mp_form_factor->setBinSizes(delta_qy, delta_qz);
+    }
+
     virtual double getHeight() const { return mp_form_factor->getHeight(); }
 
 protected:
@@ -89,22 +132,70 @@ inline IFormFactorDecorator::~IFormFactorDecorator()
 class IFormFactorBorn : public IFormFactor
 {
 public:
-    IFormFactorBorn(){}
+    IFormFactorBorn() {}
     virtual ~IFormFactorBorn() {}
 	virtual IFormFactorBorn *clone() const=0;
 
 	virtual complex_t evaluate(const cvector_t &k_i, const cvector_t &k_f, double alpha_i, double alpha_f) const;
+
+	//! evaluate scattering amplitude for large bin sizes
+	virtual complex_t evaluateForLargeBins(const cvector_t &q) const;
 protected:
-    /// evaluate scattering amplitude for complex wavevector
-    /// @param q  wavevector transfer \f$q\equiv k_i-k_f\f$
+    //! evaluate scattering amplitude for complex wavevector
+    //! @param q  wavevector transfer \f$q\equiv k_i-k_f\f$
     virtual complex_t evaluate_for_q(const cvector_t &q) const=0;
+
+    //! override volume getter to avoid infinite loop caused by big bin approximation
+    virtual double getVolume() const;
+private:
+    double bigRadialPart(double qR, void *params) const;
+    double bigZPart(double qH2, void *params) const;
 };
 
 inline complex_t IFormFactorBorn::evaluate(const cvector_t &k_i, const cvector_t &k_f, double alpha_i, double alpha_f) const
 {
     (void)alpha_i;
     (void)alpha_f;
+    if (m_use_large_bin_approximation) {
+        return evaluateForLargeBins(k_i - k_f);
+    }
     return evaluate_for_q(k_i - k_f);
 }
 
+inline complex_t IFormFactorBorn::evaluateForLargeBins(const cvector_t& q) const
+{
+    // z parameters
+    complex_t qzH2 = q.z()*getHeight()/2.0;
+    double qzH2_d = std::abs(qzH2);
+    double effective_bin_size_h = m_bin_qz*getHeight();
+
+    // radial parameters
+    double qrR = std::abs(q.magxy())*getRadius();
+    double effective_bin_size_r = m_bin_qy*getRadius();
+    double qRmin = qrR - effective_bin_size_r/2.0;
+    double qRmax = qrR + effective_bin_size_r/2.0;
+
+    // phase from the height of the particle
+    complex_t z_phase = std::exp(complex_t(0.0, 1.0)*qzH2);
+
+    // modulus of the height of the particle
+    double z_average_intensity = (bigZPart(qzH2_d + effective_bin_size_h/2.0, (void *)0)
+            - bigZPart(qzH2_d - effective_bin_size_h/2.0, (void *)0))/effective_bin_size_h;
+    double z_modulus = std::sqrt(z_average_intensity);
+
+    // modulus of the radial part
+    MemberFunctionIntegrator<IFormFactorBorn>::mem_function p_mf = &IFormFactorBorn::bigRadialPart;
+    MemberFunctionIntegrator<IFormFactorBorn> integrator(p_mf, this);
+    double average_intensity = integrator.integrate(qRmin, qRmax, (void*)0)/effective_bin_size_r;
+    double radial_part = std::sqrt(average_intensity);
+
+    return getVolume()*radial_part*z_modulus*z_phase;
+}
+
+inline double IFormFactorBorn::getVolume() const
+{
+    cvector_t zero;
+    return std::abs(evaluate_for_q(zero));
+}
+
 #endif // IFORMFACTOR_H
diff --git a/Core/FormFactors/src/FormFactorBigCylinder.cpp b/Core/FormFactors/src/FormFactorBigCylinder.cpp
deleted file mode 100644
index 9037ab922e0..00000000000
--- a/Core/FormFactors/src/FormFactorBigCylinder.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-#include "FormFactorBigCylinder.h"
-#include "StochasticDiracDelta.h"
-
-#include "MathFunctions.h"
-#include "MemberFunctionIntegrator.h"
-#include "Numeric.h"
-
-FormFactorBigCylinder::FormFactorBigCylinder(double height, double radius)
-: m_bin_size(1.0)
-{
-    setName("FormFactorBigCylinder");
-    m_height = height;
-    m_radius = radius;
-    init_parameters();
-}
-
-FormFactorBigCylinder::~FormFactorBigCylinder()
-{
-}
-
-/* ************************************************************************* */
-// initialize pool parameters, i.e. register some of class members for later access via parameter pool
-/* ************************************************************************* */
-void FormFactorBigCylinder::init_parameters()
-{
-    getParameterPool()->clear();
-    getParameterPool()->registerParameter("height", &m_height);
-    getParameterPool()->registerParameter("radius", &m_radius);
-    getParameterPool()->registerParameter("bin_size", &m_bin_size);
-}
-
-
-FormFactorBigCylinder* FormFactorBigCylinder::clone() const
-{
-    FormFactorBigCylinder *p_clone = new FormFactorBigCylinder(m_height, m_radius);
-    p_clone->setBinSize(m_bin_size);
-    return p_clone;
-}
-
-double FormFactorBigCylinder::calculateBinSize(double lambda, double phi_range,
-        size_t n_phi)
-{
-    double k = 2.0*M_PI/lambda;
-    return k*phi_range/(n_phi-1.0);
-}
-
-complex_t FormFactorBigCylinder::evaluate_for_q(const cvector_t &q) const
-{
-    double R = m_radius;
-    double H = m_height;
-
-    complex_t qzH_half = q.z()*H/2.0;
-    complex_t z_part = H*MathFunctions::Sinc(qzH_half)*std::exp(complex_t(0.0, 1.0)*qzH_half);
-
-    double qrR = std::abs(q.magxy())*R;
-    double effective_bin_size = m_bin_size*R;
-    double qRmin = qrR - effective_bin_size/2.0;
-    double qRmax = qrR + effective_bin_size/2.0;
-
-    MemberFunctionIntegrator<FormFactorBigCylinder>::mem_function p_mf = &FormFactorBigCylinder::iTilde;
-    MemberFunctionIntegrator<FormFactorBigCylinder> integrator(p_mf, this);
-    double average_intensity = integrator.integrate(qRmin, qRmax, (void*)0);
-
-    double J1_qrR_div_qrR = std::sqrt(average_intensity);
-    double radial_part = 2.0*M_PI*R*R*J1_qrR_div_qrR;
-
-    return radial_part*z_part;
-}
-
-double FormFactorBigCylinder::iTilde(double qR, void *params) const
-{
-    (void)params;
-    static double a = 1.0/4.0;
-    static double b = std::sqrt(M_PI/3.0/std::sqrt(3.0));
-
-    return a/(1.0 + std::pow(std::abs(b*qR),3.0));
-}
-
-/* ************************************************************************* */
-// print class
-/* ************************************************************************* */
-void FormFactorBigCylinder::print(std::ostream &ostr) const
-{
-    ISample::print(ostr);
-//    ostr << " (height:"<<m_height << " radius:"<<m_radius << ")";
-}
diff --git a/Core/FormFactors/src/FormFactorCylinder.cpp b/Core/FormFactors/src/FormFactorCylinder.cpp
index 69ddd7094bb..15eb3fb2148 100644
--- a/Core/FormFactors/src/FormFactorCylinder.cpp
+++ b/Core/FormFactors/src/FormFactorCylinder.cpp
@@ -40,14 +40,13 @@ void FormFactorCylinder::init_parameters()
 
 FormFactorCylinder* FormFactorCylinder::clone() const
 {
-    return new FormFactorCylinder(m_height, m_radius);
-//    return new FormFactorCylinder(mp_height->clone(), mp_radius->clone());
+    FormFactorCylinder *p_clone = new FormFactorCylinder(m_height, m_radius);
+    p_clone->setBinSizes(m_bin_qy, m_bin_qz);
+    return p_clone;
 }
 
 complex_t FormFactorCylinder::evaluate_for_q(const cvector_t &q) const
 {
-//    double R = mp_radius->getCurrent();
-//    double H = mp_height->getCurrent();
     double R = m_radius;
     double H = m_height;
 
diff --git a/Core/FormFactors/src/FormFactorFullSphere.cpp b/Core/FormFactors/src/FormFactorFullSphere.cpp
index 150168d558d..71a9a3b5f1b 100644
--- a/Core/FormFactors/src/FormFactorFullSphere.cpp
+++ b/Core/FormFactors/src/FormFactorFullSphere.cpp
@@ -20,7 +20,6 @@ FormFactorFullSphere::FormFactorFullSphere(double radius)
 
 FormFactorFullSphere::~FormFactorFullSphere()
 {
-//    delete mp_radius;
 }
 
 /* ************************************************************************* */
@@ -35,13 +34,13 @@ void FormFactorFullSphere::init_parameters()
 
 FormFactorFullSphere* FormFactorFullSphere::clone() const
 {
-    return new FormFactorFullSphere(m_radius);
-//    return new FormFactorFullSphere(mp_radius->clone());
+    FormFactorFullSphere *p_clone = new FormFactorFullSphere(m_radius);
+    p_clone->setBinSizes(m_bin_qy, m_bin_qz);
+    return p_clone;
 }
 
 complex_t FormFactorFullSphere::evaluate_for_q(const cvector_t &q) const
 {
-//    double R = mp_radius->getCurrent();
     complex_t qz = q.z();
     double R = m_radius;
 
diff --git a/Core/FormFactors/src/FormFactorGauss.cpp b/Core/FormFactors/src/FormFactorGauss.cpp
index a1db00a1818..6bc841db1b0 100644
--- a/Core/FormFactors/src/FormFactorGauss.cpp
+++ b/Core/FormFactors/src/FormFactorGauss.cpp
@@ -20,8 +20,6 @@ FormFactorGauss::FormFactorGauss(double height, double width)
     m_height = height;
     m_width = width;
     init_parameters();
-    //    mp_height = new StochasticDiracDelta<double>(height);
-    //    mp_width = new StochasticDiracDelta<double>(width);
 }
 
 //FormFactorGauss::FormFactorGauss(StochasticParameter<double> *p_height, StochasticParameter<double> *p_width)
@@ -32,8 +30,6 @@ FormFactorGauss::FormFactorGauss(double height, double width)
 
 FormFactorGauss::~FormFactorGauss()
 {
-//    delete mp_height;
-//    delete mp_width;
 }
 
 
@@ -50,18 +46,16 @@ void FormFactorGauss::init_parameters()
 
 FormFactorGauss* FormFactorGauss::clone() const
 {
-    return new FormFactorGauss(m_height, m_width);
-//    return new FormFactorGauss(mp_height->clone(), mp_radius->clone());
+    FormFactorGauss *p_clone = new FormFactorGauss(m_height, m_width);
+    p_clone->setBinSizes(m_bin_qy, m_bin_qz);
+    return p_clone;
 }
 
 complex_t FormFactorGauss::evaluate_for_q(const cvector_t &q) const
 {
-//    double R = mp_width->getCurrent();
-//    double H = mp_height->getCurrent();
     double R = m_width;
     double H = m_height;
 
-//    complex_t z_phase = std::exp(complex_t(0.0, 1.0)*q.z()*H/2.0);
     complex_t z_part = H*std::exp(-q.z()*q.z()*H*H/8.0/M_PI);
 
     complex_t radial_part = R*R*std::exp(-(q.x()*q.x()+q.y()*q.y())*R*R/8.0/M_PI);
diff --git a/Core/FormFactors/src/FormFactorLorentz.cpp b/Core/FormFactors/src/FormFactorLorentz.cpp
index 2770146df3f..fc5c8eb36ae 100644
--- a/Core/FormFactors/src/FormFactorLorentz.cpp
+++ b/Core/FormFactors/src/FormFactorLorentz.cpp
@@ -50,14 +50,13 @@ void FormFactorLorentz::init_parameters()
 
 FormFactorLorentz* FormFactorLorentz::clone() const
 {
-    return new FormFactorLorentz(m_height, m_width);
-//    return new FormFactorLorentz(mp_height->clone(), mp_radius->clone());
+    FormFactorLorentz *p_clone = new FormFactorLorentz(m_height, m_width);
+    p_clone->setBinSizes(m_bin_qy, m_bin_qz);
+    return p_clone;
 }
 
 complex_t FormFactorLorentz::evaluate_for_q(const cvector_t &q) const
 {
-//    double R = mp_radius->getCurrent();
-//    double H = mp_height->getCurrent();
     static const double sigma2 = 4.0*std::pow(M_PI, 2.0/3.0);
     double R = m_width;
     double H = m_height;
diff --git a/Core/FormFactors/src/FormFactorParallelepiped.cpp b/Core/FormFactors/src/FormFactorParallelepiped.cpp
index a16fe912a6a..3e36f063d91 100644
--- a/Core/FormFactors/src/FormFactorParallelepiped.cpp
+++ b/Core/FormFactors/src/FormFactorParallelepiped.cpp
@@ -13,7 +13,9 @@ FormFactorParallelepiped::~FormFactorParallelepiped()
 
 FormFactorParallelepiped* FormFactorParallelepiped::clone() const
 {
-    return new FormFactorParallelepiped(m_height, m_radius);
+    FormFactorParallelepiped *p_clone = new FormFactorParallelepiped(m_height, m_radius);
+    p_clone->setBinSizes(m_bin_qy, m_bin_qz);
+    return p_clone;
 }
 
 complex_t FormFactorParallelepiped::evaluate_for_q(const cvector_t& q) const
diff --git a/Core/FormFactors/src/FormFactorPrism3.cpp b/Core/FormFactors/src/FormFactorPrism3.cpp
index 3974e75af22..6e90ac5a705 100644
--- a/Core/FormFactors/src/FormFactorPrism3.cpp
+++ b/Core/FormFactors/src/FormFactorPrism3.cpp
@@ -41,14 +41,13 @@ void FormFactorPrism3::init_parameters()
 
 FormFactorPrism3* FormFactorPrism3::clone() const
 {
-    return new FormFactorPrism3(m_height, m_half_side );
-//    return new FormFactorPrism3(mp_height->clone(), mp_half_side->clone());
+    FormFactorPrism3 *p_clone = new FormFactorPrism3(m_height, m_half_side );
+    p_clone->setBinSizes(m_bin_qy, m_bin_qz);
+    return p_clone;
 }
 
 complex_t FormFactorPrism3::evaluate_for_q(const cvector_t &q) const
 {
-//    double R = mp_half_side->getCurrent();
-//    double H = mp_height->getCurrent();
     complex_t qz = q.z();
     double R = m_half_side;
     double H = m_height;
diff --git a/Core/FormFactors/src/FormFactorPyramid.cpp b/Core/FormFactors/src/FormFactorPyramid.cpp
index 2359d39cd8a..1914cd6034d 100644
--- a/Core/FormFactors/src/FormFactorPyramid.cpp
+++ b/Core/FormFactors/src/FormFactorPyramid.cpp
@@ -47,15 +47,13 @@ void FormFactorPyramid::init_parameters()
 
 FormFactorPyramid* FormFactorPyramid::clone() const
 {
-    return new FormFactorPyramid(m_height, m_half_side, m_alpha);
-//    return new FormFactorPyramid(mp_height->clone(), mp_half_side->clone(), mp_alpha->clone());
+    FormFactorPyramid *p_clone = new FormFactorPyramid(m_height, m_half_side, m_alpha);
+    p_clone->setBinSizes(m_bin_qy, m_bin_qz);
+    return p_clone;
 }
 
 complex_t FormFactorPyramid::evaluate_for_q(const cvector_t &q) const
 {
-//    double H = mp_height->getCurrent();
-//    double R = mp_half_side->getCurrent();
-//    double tga = std::tan(mp_alpha->getCurrent());
 
     double H = m_height;
     double R = m_half_side;
diff --git a/Core/FormFactors/src/FormFactorWeighted.cpp b/Core/FormFactors/src/FormFactorWeighted.cpp
index ad403301aef..5ad7499d63f 100644
--- a/Core/FormFactors/src/FormFactorWeighted.cpp
+++ b/Core/FormFactors/src/FormFactorWeighted.cpp
@@ -53,3 +53,10 @@ int FormFactorWeighted::getNumberOfStochasticParameters() const
     }
     return result;
 }
+
+void FormFactorWeighted::setBinSizes(double delta_qy, double delta_qz)
+{
+    for (size_t index=0; index<m_form_factors.size(); ++index) {
+        m_form_factors[index]->setBinSizes(delta_qy, delta_qz);
+    }
+}
diff --git a/Core/FormFactors/src/IFormFactor.cpp b/Core/FormFactors/src/IFormFactor.cpp
new file mode 100644
index 00000000000..3c9c5dbfc82
--- /dev/null
+++ b/Core/FormFactors/src/IFormFactor.cpp
@@ -0,0 +1,19 @@
+#include "IFormFactor.h"
+
+double IFormFactorBorn::bigRadialPart(double qR, void *params) const
+{
+    (void)params;
+    static double a = 1.0/4.0;
+    static double b = std::sqrt(M_PI/3.0/std::sqrt(3.0));
+
+    return a/(1.0 + std::pow(std::abs(b*qR),3.0));
+}
+
+double IFormFactorBorn::bigZPart(double qH2, void* params) const
+{
+    (void)params;
+    if (qH2<Numeric::double_epsilon) return qH2;
+    double qH = 2.0*qH2;
+    return (qH*MathFunctions::Si(qH) + std::cos(qH) - 1.0)/qH;
+}
+
diff --git a/Core/Tools/inc/MathFunctions.h b/Core/Tools/inc/MathFunctions.h
index 83011e34a2f..ab376bdc67a 100644
--- a/Core/Tools/inc/MathFunctions.h
+++ b/Core/Tools/inc/MathFunctions.h
@@ -23,6 +23,7 @@
 
 #include "gsl/gsl_sf_bessel.h"
 #include "gsl/gsl_sf_trig.h"
+#include "gsl/gsl_sf_expint.h"
 #include "gsl/gsl_integration.h"
 
 namespace MathFunctions
@@ -39,12 +40,16 @@ double GenerateStandardNormalRandom();
 
 double GenerateUniformRandom();
 
+//! Bessel function of the first kind and order 1
 double Bessel_J1(double value);
 
-//complex_t Bessel_J1(complex_t value);
+//! Sine integral function: \f$Si(x)\equiv\int_0^x du \sin(u)/u\f$
+double Si(double value);
 
+//! Sinc function: \f$Sinc(x)\equiv\sin(x)/x\f$
 double Sinc(double value);
 
+//! Complex Sinc function: \f$Sinc(x)\equiv\sin(x)/x\f$
 complex_t Sinc(complex_t value);
 
 complex_t Laue(complex_t value, size_t N);
@@ -92,6 +97,11 @@ inline double MathFunctions::Bessel_J1(double value)
     return gsl_sf_bessel_J1(value);
 }
 
+inline double MathFunctions::Si(double value)  // int_0^x du Sin(u)/u
+{
+    return gsl_sf_Si(value);
+}
+
 inline double MathFunctions::Sinc(double value)  // Sin(x)/x
 {
     return gsl_sf_sinc(value/M_PI);
-- 
GitLab