diff --git a/Core/Multilayer/LayoutStrategyBuilder.cpp b/Core/Multilayer/LayoutStrategyBuilder.cpp
index 81859f16fb36a86899d51b2cbff2e944042f3277..1eb2bb2fab0a797c7b8c41cae7b80d099984e3a9 100644
--- a/Core/Multilayer/LayoutStrategyBuilder.cpp
+++ b/Core/Multilayer/LayoutStrategyBuilder.cpp
@@ -14,17 +14,18 @@
 // ************************************************************************** //
 
 #include "LayoutStrategyBuilder.h"
+#include "DecouplingApproximationStrategy.h"
 #include "Exceptions.h"
 #include "FormFactorCoherentSum.h"
 #include "FormFactorDWBA.h"
 #include "FormFactorDWBAPol.h"
+#include "IFresnelMap.h"
 #include "ILayout.h"
 #include "IParticle.h"
 #include "InterferenceFunctionNone.h"
 #include "MultiLayer.h"
 #include "Layer.h"
-#include "IFresnelMap.h"
-#include "DecouplingApproximationStrategy.h"
+#include "SlicedFormFactorList.h"
 #include "SSCApproximationStrategy.h"
 
 LayoutStrategyBuilder::LayoutStrategyBuilder(
@@ -82,8 +83,7 @@ SafePointerVector<class FormFactorCoherentSum> LayoutStrategyBuilder::collectFor
     SafePointerVector<class FormFactorCoherentSum> result;
     double layout_abundance = mp_layout->getTotalAbundance();
     for (const IParticle* particle: mp_layout->getParticles()) {
-        FormFactorCoherentSum* p_ff_coh;
-        p_ff_coh = createFormFactorCoherentSum(particle);
+        auto p_ff_coh = createFormFactorCoherentSum(particle);
         p_ff_coh->scaleRelativeAbundance(layout_abundance);
         result.push_back(p_ff_coh);
     }
@@ -94,33 +94,28 @@ SafePointerVector<class FormFactorCoherentSum> LayoutStrategyBuilder::collectFor
 FormFactorCoherentSum* LayoutStrategyBuilder::createFormFactorCoherentSum(
     const IParticle* particle) const
 {
-    const std::unique_ptr<IParticle> P_particle_clone{ particle->clone() };
-    const std::unique_ptr<IFormFactor> P_ff_particle{ P_particle_clone->createFormFactor() };
-    std::unique_ptr<IFormFactor> P_ff_framework;
-    if (mp_multilayer->getNumberOfLayers()>1) {
-        if (m_polarized)
-            P_ff_framework.reset(new FormFactorDWBAPol(*P_ff_particle));
-        else
-            P_ff_framework.reset(new FormFactorDWBA(*P_ff_particle));
-    } else
-        P_ff_framework.reset(P_ff_particle->clone());
+    std::unique_ptr<FormFactorCoherentSum> P_result(
+                new FormFactorCoherentSum(particle->getAbundance()));
+    auto sliced_ffs = CreateSlicedFormFactors(*particle, *mp_multilayer, m_layer_index);
+    for (size_t i=0; i < sliced_ffs.size(); ++i) {
+        auto ff_pair = sliced_ffs[i];
+        std::unique_ptr<IFormFactor> P_ff_framework;
+        if (mp_multilayer->getNumberOfLayers()>1) {
+            if (m_polarized)
+                P_ff_framework.reset(new FormFactorDWBAPol(*ff_pair.first));
+            else
+                P_ff_framework.reset(new FormFactorDWBA(*ff_pair.first));
+        } else
+            P_ff_framework.reset(ff_pair.first->clone());
 
-    size_t layer_index = findLayerIndex(*P_ff_framework);
-    const IMaterial* p_layer_material = mp_multilayer->getLayer(layer_index)->getMaterial();
-    P_ff_framework->setAmbientMaterial(*p_layer_material);
+        size_t layer_index = ff_pair.second;
+        const IMaterial* p_layer_material = mp_multilayer->getLayer(layer_index)->getMaterial();
+        P_ff_framework->setAmbientMaterial(*p_layer_material);
 
-    auto part = FormFactorCoherentPart(P_ff_framework.release());
-    part.setSpecularInfo(mp_fresnel_map, layer_index);
+        auto part = FormFactorCoherentPart(P_ff_framework.release());
+        part.setSpecularInfo(mp_fresnel_map, layer_index);
 
-    std::unique_ptr<FormFactorCoherentSum> P_result(
-                new FormFactorCoherentSum(particle->getAbundance()));
-    P_result->addCoherentPart(part);
+        P_result->addCoherentPart(part);
+    }
     return P_result.release();
 }
-
-size_t LayoutStrategyBuilder::findLayerIndex(const IFormFactor& ff) const
-{
-    std::unique_ptr<IRotation> P_rot(IRotation::createIdentity());
-    double zmin = ff.bottomZ(*P_rot) + mp_multilayer->getLayerTopZ(m_layer_index);
-    return mp_multilayer->zToLayerIndex(zmin);
-}
diff --git a/Core/Multilayer/LayoutStrategyBuilder.h b/Core/Multilayer/LayoutStrategyBuilder.h
index ac903413e1c07d60fa042f65a661d270f1d255b8..57bfa2969272fb3bf009896008689a89559f429b 100644
--- a/Core/Multilayer/LayoutStrategyBuilder.h
+++ b/Core/Multilayer/LayoutStrategyBuilder.h
@@ -47,7 +47,6 @@ public:
 private:
     SafePointerVector<class FormFactorCoherentSum> collectFormFactorList() const;
     FormFactorCoherentSum* createFormFactorCoherentSum(const IParticle* particle) const;
-    size_t findLayerIndex(const IFormFactor& ff) const;
 
     const MultiLayer* mp_multilayer;
     const ILayout* mp_layout;
diff --git a/Core/Multilayer/MultiLayer.cpp b/Core/Multilayer/MultiLayer.cpp
index 484d9ff1e0e315ad866602dfba196c108bd4d774..20791eff7580191def8702016f2faab670ad2fdb 100644
--- a/Core/Multilayer/MultiLayer.cpp
+++ b/Core/Multilayer/MultiLayer.cpp
@@ -317,7 +317,7 @@ bool MultiLayer::requiresMatrixRTCoefficients() const
     return false;
 }
 
-size_t MultiLayer::zToLayerIndex(double z_value) const
+size_t MultiLayer::bottomZToLayerIndex(double z_value) const
 {
     size_t n_layers = m_layers_z.size();
     if (n_layers < 2)
@@ -328,6 +328,17 @@ size_t MultiLayer::zToLayerIndex(double z_value) const
     return nbin;
 }
 
+size_t MultiLayer::topZToLayerIndex(double z_value) const
+{
+    size_t n_layers = m_layers_z.size();
+    if (n_layers < 2)
+        return 0;
+    if (z_value < m_layers_z[n_layers-2]) return m_layers_z.size()-1;
+    auto bottom_limit = std::lower_bound(m_layers_z.begin(), m_layers_z.end(), z_value);
+    size_t nbin = static_cast<size_t>(bottom_limit - m_layers_z.begin());
+    return nbin;
+}
+
 double MultiLayer::getLayerTopZ(size_t i_layer) const
 {
     if (i_layer==0)
diff --git a/Core/Multilayer/MultiLayer.h b/Core/Multilayer/MultiLayer.h
index 7f21f712cbfa132ed832130e8cfeda774db631dc..eb6fecfd7efd43ea603607f9f06e5d8ecd55b4d3 100644
--- a/Core/Multilayer/MultiLayer.h
+++ b/Core/Multilayer/MultiLayer.h
@@ -118,7 +118,11 @@ public:
 
     //! returns layer index corresponding to given global z coordinate
     //! The top interface position of a layer is considered to belong to the layer above
-    size_t zToLayerIndex(double z_value) const;
+    size_t bottomZToLayerIndex(double z_value) const;
+
+    //! returns layer index corresponding to given global z coordinate
+    //! The top interface position of a layer is considered to belong to the layer beneath
+    size_t topZToLayerIndex(double z_value) const;
 
     bool containsMagneticMaterial() const;
 
diff --git a/Core/Particle/IParticle.cpp b/Core/Particle/IParticle.cpp
index 34a229da239846afba83487444eade17aca83200..b9b077b54411c69a37264914cebced1bc3220d92 100644
--- a/Core/Particle/IParticle.cpp
+++ b/Core/Particle/IParticle.cpp
@@ -16,6 +16,7 @@
 #include "IParticle.h"
 #include "BornAgainNamespace.h"
 #include "FormFactorDecoratorPositionFactor.h"
+#include "MultiLayer.h"
 #include "RealParameter.h"
 
 IFormFactor* IParticle::createFormFactor() const
@@ -23,6 +24,16 @@ IFormFactor* IParticle::createFormFactor() const
     return createTransformedFormFactor(nullptr, kvector_t());
 }
 
+void IParticle::applyTranslation(kvector_t displacement)
+{
+    m_position += displacement;
+}
+
+const IRotation* IParticle::getRotation() const
+{
+    return mP_rotation.get();
+}
+
 void IParticle::setRotation(const IRotation& rotation)
 {
     mP_rotation.reset(rotation.clone());
@@ -40,11 +51,6 @@ void IParticle::applyRotation(const IRotation& rotation)
     registerChild(mP_rotation.get());
 }
 
-void IParticle::applyTranslation(kvector_t displacement)
-{
-    m_position += displacement;
-}
-
 std::vector<const INode*> IParticle::getChildren() const
 {
     return std::vector<const INode*>() << mP_rotation;
@@ -75,6 +81,13 @@ void IParticle::registerPosition(bool make_registered)
     }
 }
 
+SafePointerVector<IParticle> IParticle::decompose() const
+{
+    SafePointerVector<IParticle> result;
+    result.push_back(this->clone());
+    return result;
+}
+
 IRotation* IParticle::createComposedRotation(const IRotation* p_rotation) const
 {
     if (p_rotation) {
@@ -107,7 +120,3 @@ void IParticle::registerParticleProperties()
     registerPosition();
 }
 
-const IRotation* IParticle::getRotation() const
-{
-    return mP_rotation.get();
-}
diff --git a/Core/Particle/IParticle.h b/Core/Particle/IParticle.h
index a563edac27c9c8796c894f0b149f8a5940bb35d5..59ad62b73cd0790786e3c9016085b9674b056b6c 100644
--- a/Core/Particle/IParticle.h
+++ b/Core/Particle/IParticle.h
@@ -18,6 +18,7 @@
 
 #include "IAbstractParticle.h"
 #include "Rotations.h"
+#include "SafePointerVector.h"
 #include "Vectors3D.h"
 #include <memory>
 
@@ -33,7 +34,6 @@ public:
     virtual ~IParticle() {}
     virtual IParticle* clone() const =0;
 
-    //! Returns a clone with inverted magnetic fields
     virtual IParticle* cloneInvertB() const =0;
 
     virtual void accept(INodeVisitor* visitor) const { visitor->visit(this); }
@@ -54,6 +54,9 @@ public:
     //! Sets particle position.
     void setPosition(double x, double y, double z) { m_position = kvector_t(x, y, z); }
 
+    //! Applies extra translation by adding it to the current one
+    void applyTranslation(kvector_t displacement);
+
     //! Returns rotation object
     const IRotation* getRotation() const;
 
@@ -63,9 +66,6 @@ public:
     //! Applies transformation by composing it with the existing one
     void applyRotation(const IRotation& rotation);
 
-    //! Applies extra translation by adding it to the current one
-    void applyTranslation(kvector_t displacement);
-
     std::vector<const INode*> getChildren() const;
 
     void registerAbundance(bool make_registered = true);
@@ -73,6 +73,9 @@ public:
     //! Registers the three components of its position
     void registerPosition(bool make_registered = true);
 
+    //! Decompose in constituent IParticle objects
+    virtual SafePointerVector<IParticle> decompose() const;
+
 protected:
     //! Creates a composed IRotation object
     IRotation* createComposedRotation(const IRotation* p_rotation) const;
diff --git a/Core/Particle/ParticleComposition.cpp b/Core/Particle/ParticleComposition.cpp
index 0789ecf15b95371ff71c475c871de2ba0250da93..e4211b1853d52ebf5274d1c5a03a62158ba0318c 100644
--- a/Core/Particle/ParticleComposition.cpp
+++ b/Core/Particle/ParticleComposition.cpp
@@ -25,18 +25,6 @@ ParticleComposition::ParticleComposition()
     initialize();
 }
 
-ParticleComposition::ParticleComposition(const IParticle& particle)
-{
-    initialize();
-    addParticle( particle, kvector_t(0.0, 0.0, 0.0) );
-}
-
-ParticleComposition::ParticleComposition(const IParticle &particle, kvector_t position)
-{
-    initialize();
-    addParticle(particle, position);
-}
-
 ParticleComposition::ParticleComposition(const IParticle& particle,
         std::vector<kvector_t> positions)
 {
@@ -45,10 +33,7 @@ ParticleComposition::ParticleComposition(const IParticle& particle,
 }
 
 ParticleComposition::~ParticleComposition()
-{
-    for (size_t index=0; index<m_particles.size(); ++index)
-        delete m_particles[index];
-}
+{}
 
 ParticleComposition* ParticleComposition::clone() const
 {
@@ -90,10 +75,9 @@ void ParticleComposition::addParticle(const IParticle& particle, kvector_t posit
     addParticlePointer(np);
 }
 
-// Please note, that positions is not const reference here. This is intentionally to
-// python lists to std::vector
-void ParticleComposition::addParticles(const IParticle& particle,
-        std::vector<kvector_t > positions)
+// Please note, that positions is not const reference here. This is intentional, to
+// enable python lists to std::vector conversion
+void ParticleComposition::addParticles(const IParticle& particle, std::vector<kvector_t> positions)
 {
     for (size_t i=0; i<positions.size(); ++i)
         addParticle(particle, positions[i]);
@@ -118,7 +102,7 @@ IFormFactor* ParticleComposition::createTransformedFormFactor(
 
 const IParticle* ParticleComposition::getParticle(size_t index) const
 {
-    return m_particles[check_index(index)];
+    return m_particles[check_index(index)].get();
 }
 
 kvector_t ParticleComposition::getParticlePosition(size_t index) const
@@ -129,8 +113,26 @@ kvector_t ParticleComposition::getParticlePosition(size_t index) const
 std::vector<const INode*> ParticleComposition::getChildren() const
 {
     std::vector<const INode*> result = IParticle::getChildren();
-    for(auto particle : m_particles)
-        result.push_back(particle);
+    for (auto& P_particle : m_particles)
+        result.push_back(P_particle.get());
+    return result;
+}
+
+SafePointerVector<IParticle> ParticleComposition::decompose() const
+{
+    SafePointerVector<IParticle> result;
+    auto p_rotation = getRotation();
+    auto translation = getPosition();
+    for (auto& P_particle : m_particles)
+    {
+        auto sublist = P_particle->decompose();
+        for (auto p_subparticle : sublist) {
+            if (p_rotation)
+                p_subparticle->applyRotation(*p_rotation);
+            p_subparticle->applyTranslation(translation);
+            result.push_back(p_subparticle->clone());
+        }
+    }
     return result;
 }
 
@@ -152,7 +154,7 @@ void ParticleComposition::addParticlePointer(IParticle* p_particle)
 {
     p_particle->registerAbundance(false);
     registerChild(p_particle);
-    m_particles.push_back(p_particle);
+    m_particles.emplace_back(p_particle);
 }
 
 void ParticleComposition::initialize()
diff --git a/Core/Particle/ParticleComposition.h b/Core/Particle/ParticleComposition.h
index 9bcc7e81a880d2035f0dacdde2cb03f3a33faeb7..a980a7dc5c59a7b83342d2c9d43e500a5c256ffb 100644
--- a/Core/Particle/ParticleComposition.h
+++ b/Core/Particle/ParticleComposition.h
@@ -17,6 +17,7 @@
 #define PARTICLECOMPOSITION_H
 
 #include "IParticle.h"
+#include <memory>
 
 class IMaterial;
 
@@ -27,25 +28,21 @@ class BA_CORE_API_ ParticleComposition : public IParticle
 {
 public:
     ParticleComposition();
-    explicit ParticleComposition(const IParticle& particle);
-    ParticleComposition(const IParticle& particle, kvector_t position);
     ParticleComposition(const IParticle& particle, std::vector<kvector_t > positions);
 
-    virtual ~ParticleComposition();
-    virtual ParticleComposition* clone() const;
+    ~ParticleComposition();
+    ParticleComposition* clone() const override;
 
-    //! Returns a clone with inverted magnetic fields
-    virtual ParticleComposition* cloneInvertB() const;
+    ParticleComposition* cloneInvertB() const override;
 
-    virtual void accept(INodeVisitor* visitor) const { visitor->visit(this); }
+    void accept(INodeVisitor* visitor) const override { visitor->visit(this); }
 
     void addParticle(const IParticle& particle);
     void addParticle(const IParticle& particle, kvector_t  position);
     void addParticles(const IParticle& particle, std::vector<kvector_t > positions);
 
-    //! Create a form factor for this particle with an extra scattering factor
-    virtual IFormFactor* createTransformedFormFactor(const IRotation* p_rotation,
-                                                     kvector_t translation) const;
+    IFormFactor* createTransformedFormFactor(const IRotation* p_rotation,
+                                                     kvector_t translation) const override;
 
     //! Returns number of different particles
     size_t getNbrParticles() const { return m_particles.size(); }
@@ -55,7 +52,9 @@ public:
 
     kvector_t getParticlePosition(size_t index) const;
 
-    std::vector<const INode*> getChildren() const;
+    std::vector<const INode*> getChildren() const override;
+
+    SafePointerVector<IParticle> decompose() const override;
 
 private:
     size_t check_index(size_t index) const;
@@ -66,7 +65,7 @@ private:
     //! For internal use in cloneInvertB():
     void addParticlePointer(IParticle* p_particle);
 
-    std::vector<IParticle*> m_particles;
+    std::vector<std::unique_ptr<IParticle>> m_particles;
     void initialize();
 };
 
diff --git a/Core/Particle/SlicedFormFactorList.cpp b/Core/Particle/SlicedFormFactorList.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0a5abf37982fefb18b9be4e3e141d0f713d757c6
--- /dev/null
+++ b/Core/Particle/SlicedFormFactorList.cpp
@@ -0,0 +1,89 @@
+// ************************************************************************** //
+//
+//  BornAgain: simulate and fit scattering at grazing incidence
+//
+//! @file      Core/Shapes/SlicedFormFactorList.cpp
+//! @brief     Defines class SlicedFormFactorList.
+//!
+//! @homepage  http://www.bornagainproject.org
+//! @license   GNU General Public License v3 or higher (see COPYING)
+//! @copyright Forschungszentrum Jülich GmbH 2017
+//! @authors   Scientific Computing Group at MLZ Garching
+//! @authors   J. Burle, J. M. Fisher, M. Ganeva, G. Pospelov, W. Van Herck, J. Wuttke
+//
+// ************************************************************************** //
+
+
+#include "SlicedFormFactorList.h"
+#include "IParticle.h"
+#include "MultiLayer.h"
+#include "Rotations.h"
+
+namespace {
+size_t LayerIndexBottom(const IParticle& particle, const MultiLayer& multilayer,
+                        size_t ref_layer_index);
+size_t LayerIndexTop(const IParticle& particle, const MultiLayer& multilayer,
+                        size_t ref_layer_index);
+double ZDifference(const MultiLayer& multilayer, size_t layer_index, size_t ref_layer_index);
+}
+
+void SlicedFormFactorList::addParticle(IParticle& particle,
+                                       const MultiLayer& multilayer, size_t ref_layer_index)
+{
+    size_t layer_index = LayerIndexBottom(particle, multilayer, ref_layer_index);
+    kvector_t translation(0.0, 0.0, -ZDifference(multilayer, layer_index, ref_layer_index));
+    particle.applyTranslation(translation);
+    m_ff_list.emplace_back(std::unique_ptr<IFormFactor>(particle.createFormFactor()), layer_index);
+}
+
+size_t SlicedFormFactorList::size() const
+{
+    return m_ff_list.size();
+}
+
+std::pair<const IFormFactor*, size_t> SlicedFormFactorList::operator[](size_t index) const
+{
+    if (index >= size())
+        throw std::out_of_range("SlicedFormFactorList::operator[] error: "
+                                "index out of range");
+    return { m_ff_list[index].first.get(), m_ff_list[index].second };
+}
+
+SlicedFormFactorList CreateSlicedFormFactors(const IParticle& particle,
+                                             const MultiLayer& multilayer, size_t ref_layer_index)
+{
+    SlicedFormFactorList result;
+    auto particles = particle.decompose();
+    for (auto p_particle : particles) {
+        result.addParticle(*p_particle, multilayer, ref_layer_index);
+    }
+    return result;
+}
+
+namespace {
+size_t LayerIndexBottom(const IParticle& particle, const MultiLayer& multilayer,
+                        size_t ref_layer_index)
+{
+    std::unique_ptr<IFormFactor> P_ff(particle.createFormFactor());
+    std::unique_ptr<IRotation> P_rot(IRotation::createIdentity());
+    double position_offset = multilayer.getLayerTopZ(ref_layer_index);
+    double zmin = P_ff->bottomZ(*P_rot) + position_offset;
+    return multilayer.bottomZToLayerIndex(zmin);
+}
+
+size_t LayerIndexTop(const IParticle& particle, const MultiLayer& multilayer,
+                     size_t ref_layer_index)
+{
+    std::unique_ptr<IFormFactor> P_ff(particle.createFormFactor());
+    std::unique_ptr<IRotation> P_rot(IRotation::createIdentity());
+    double position_offset = multilayer.getLayerTopZ(ref_layer_index);
+    double zmin = P_ff->topZ(*P_rot) + position_offset;
+    return multilayer.topZToLayerIndex(zmin);
+}
+
+double ZDifference(const MultiLayer& multilayer, size_t layer_index, size_t ref_layer_index)
+{
+    return multilayer.getLayerTopZ(layer_index) - multilayer.getLayerTopZ(ref_layer_index);
+}
+}
+
diff --git a/Core/Particle/SlicedFormFactorList.h b/Core/Particle/SlicedFormFactorList.h
new file mode 100644
index 0000000000000000000000000000000000000000..7050b45acc73406560f44874d3610e3cbcc3dbdb
--- /dev/null
+++ b/Core/Particle/SlicedFormFactorList.h
@@ -0,0 +1,55 @@
+// ************************************************************************** //
+//
+//  BornAgain: simulate and fit scattering at grazing incidence
+//
+//! @file      Core/Shapes/SlicedFormFactorList.h
+//! @brief     Defines class SlicedFormFactorList.
+//!
+//! @homepage  http://www.bornagainproject.org
+//! @license   GNU General Public License v3 or higher (see COPYING)
+//! @copyright Forschungszentrum Jülich GmbH 2017
+//! @authors   Scientific Computing Group at MLZ Garching
+//! @authors   J. Burle, J. M. Fisher, M. Ganeva, G. Pospelov, W. Van Herck, J. Wuttke
+//
+// ************************************************************************** //
+
+#ifndef SLICEDFORMFACTORLIST_H
+#define SLICEDFORMFACTORLIST_H
+
+#include "IFormFactor.h"
+#include <memory>
+
+class MultiLayer;
+
+//! Class that contains and owns a list of form factors and the index of their containing layer.
+//! This class also handles the slicing of form factors if they cross layer interfaces.
+//!
+//! @ingroup intern
+
+class SlicedFormFactorList
+{
+public:
+    SlicedFormFactorList() = default;
+    SlicedFormFactorList(SlicedFormFactorList&& other) = default;
+    SlicedFormFactorList& operator=(SlicedFormFactorList&& other) = default;
+    ~SlicedFormFactorList() = default;
+
+    void addParticle(IParticle& particle, const MultiLayer& multilayer,
+                       size_t ref_layer_index);
+
+    size_t size() const;
+
+    std::pair<const IFormFactor*, size_t> operator[](size_t index) const;
+private:
+    std::vector<std::pair<std::unique_ptr<IFormFactor>, size_t>> m_ff_list;
+};
+
+//! Global function that creates a SlicedFormFactorList from an IParticle in a multilayer
+//!
+//! @ingroup intern
+SlicedFormFactorList CreateSlicedFormFactors(const IParticle& particle,
+                                             const MultiLayer& multilayer,
+                                             size_t ref_layer_index);
+
+
+#endif // SLICEDFORMFACTORLIST_H
diff --git a/Tests/UnitTests/Core/Sample/MultiLayerTest.h b/Tests/UnitTests/Core/Sample/MultiLayerTest.h
index 63b77ce3eadf81bbb38e4ea02d7f595881ca1f2c..5df535b334d447f48ee16aadaec213a293f1249d 100644
--- a/Tests/UnitTests/Core/Sample/MultiLayerTest.h
+++ b/Tests/UnitTests/Core/Sample/MultiLayerTest.h
@@ -565,14 +565,14 @@ TEST_F(MultiLayerTest, MultiLayerZtoIndex)
     mLayer.addLayer(layer3);
     mLayer.addLayer(layer4);
 
-    EXPECT_EQ(size_t(0), mLayer.zToLayerIndex(1.0));
-    EXPECT_EQ(size_t(0), mLayer.zToLayerIndex(0.0));
-    EXPECT_EQ(size_t(1), mLayer.zToLayerIndex(-1.0));
-    EXPECT_EQ(size_t(1), mLayer.zToLayerIndex(-9.0));
-    EXPECT_EQ(size_t(1), mLayer.zToLayerIndex(-10.0));
-    EXPECT_EQ(size_t(2), mLayer.zToLayerIndex(-11.0));
-    EXPECT_EQ(size_t(2), mLayer.zToLayerIndex(-30.0));
-    EXPECT_EQ(size_t(3), mLayer.zToLayerIndex(-31.0));
-    EXPECT_EQ(size_t(3), mLayer.zToLayerIndex(-60.0));
-    EXPECT_EQ(size_t(4), mLayer.zToLayerIndex(-61.0));
+    EXPECT_EQ(size_t(0), mLayer.bottomZToLayerIndex(1.0));
+    EXPECT_EQ(size_t(0), mLayer.bottomZToLayerIndex(0.0));
+    EXPECT_EQ(size_t(1), mLayer.bottomZToLayerIndex(-1.0));
+    EXPECT_EQ(size_t(1), mLayer.bottomZToLayerIndex(-9.0));
+    EXPECT_EQ(size_t(1), mLayer.bottomZToLayerIndex(-10.0));
+    EXPECT_EQ(size_t(2), mLayer.bottomZToLayerIndex(-11.0));
+    EXPECT_EQ(size_t(2), mLayer.bottomZToLayerIndex(-30.0));
+    EXPECT_EQ(size_t(3), mLayer.bottomZToLayerIndex(-31.0));
+    EXPECT_EQ(size_t(3), mLayer.bottomZToLayerIndex(-60.0));
+    EXPECT_EQ(size_t(4), mLayer.bottomZToLayerIndex(-61.0));
 }
diff --git a/Tests/UnitTests/Core/Sample/ParticleCompositionTest.h b/Tests/UnitTests/Core/Sample/ParticleCompositionTest.h
index 7cd7985c643c507f02cd07f00c75b1f1c8863524..81c63758572813960272bddf0349dac900414f9f 100644
--- a/Tests/UnitTests/Core/Sample/ParticleCompositionTest.h
+++ b/Tests/UnitTests/Core/Sample/ParticleCompositionTest.h
@@ -22,42 +22,6 @@ TEST_F(ParticleCompositionTest, ParticleCompositionDefaultConstructor)
     EXPECT_EQ(0u, composition->getNbrParticles());
 }
 
-TEST_F(ParticleCompositionTest, ParticleCompositionConstructorWithOneParameter)
-{
-    kvector_t position0(0.0, 0.0, 0.0);
-    kvector_t position1(4.0, 5.0, 6.0);
-
-    Particle particle;
-    std::unique_ptr<ParticleComposition> composition(new ParticleComposition(particle));
-
-    EXPECT_EQ(BornAgain::ParticleCompositionType, composition->getName());
-    composition->addParticle(particle, position1);
-
-    EXPECT_EQ(particle.getName(), composition->getParticle(0)->getName());
-    EXPECT_EQ(particle.getRotation(), composition->getParticle(0)->getRotation());
-    EXPECT_EQ(particle.getName(), composition->getParticle(1)->getName());
-    EXPECT_EQ(particle.getRotation(), composition->getParticle(1)->getRotation());
-    EXPECT_EQ(position0, composition->getParticlePosition(0));
-    EXPECT_EQ(position1, composition->getParticlePosition(1));
-}
-
-TEST_F(ParticleCompositionTest, ParticleCompositionConstructorWithTwoParameter)
-{
-    Particle particle;
-    kvector_t position = kvector_t(1.0, 1.0, 1.0);
-    std::unique_ptr<ParticleComposition> composition(new ParticleComposition(particle, position));
-
-    EXPECT_EQ(BornAgain::ParticleCompositionType, composition->getName());
-    composition->addParticle(particle, position);
-    EXPECT_EQ(particle.getName(), composition->getParticle(0)->getName());
-    EXPECT_EQ(particle.getRotation(), composition->getParticle(0)->getRotation());
-    EXPECT_EQ(particle.getName(), composition->getParticle(1)->getName());
-    EXPECT_EQ(particle.getRotation(), composition->getParticle(1)->getRotation());
-    EXPECT_EQ(position, composition->getParticlePosition(0));
-    EXPECT_EQ(position, composition->getParticlePosition(1));
-
-}
-
 TEST_F(ParticleCompositionTest, ParticleCompositionClone)
 {
     ParticleComposition composition;
diff --git a/Wrap/swig/ignores.i b/Wrap/swig/ignores.i
index 833e3521eb105b27670e6808ec3bdd964a49331b..e4b0d042f2ebba8e8fab35a314dab831dc993e4a 100644
--- a/Wrap/swig/ignores.i
+++ b/Wrap/swig/ignores.i
@@ -55,6 +55,7 @@
 %ignore DecoratedLayerComputation;
 %ignore RoughMultiLayerComputation;
 %ignore SpecularComputation;
+%ignore SlicedFormFactorList;
 
 %ignore Lattice2D::ReciprocalBases;
 %ignore Lattice2D::reciprocalBases();
diff --git a/auto/Wrap/libBornAgainCore.py b/auto/Wrap/libBornAgainCore.py
index 79e493e97ccbcfe7fdeb2095a25813445e7e943e..fabffca75b85868fd7ccd1b7239782a244a1f2dd 100644
--- a/auto/Wrap/libBornAgainCore.py
+++ b/auto/Wrap/libBornAgainCore.py
@@ -18631,6 +18631,18 @@ class IParticle(IAbstractParticle):
         return _libBornAgainCore.IParticle_setPosition(self, *args)
 
 
+    def applyTranslation(self, displacement):
+        """
+        applyTranslation(IParticle self, kvector_t displacement)
+
+        void IParticle::applyTranslation(kvector_t displacement)
+
+        Applies extra translation by adding it to the current one. 
+
+        """
+        return _libBornAgainCore.IParticle_applyTranslation(self, displacement)
+
+
     def getRotation(self):
         """
         getRotation(IParticle self) -> IRotation
@@ -18667,18 +18679,6 @@ class IParticle(IAbstractParticle):
         return _libBornAgainCore.IParticle_applyRotation(self, rotation)
 
 
-    def applyTranslation(self, displacement):
-        """
-        applyTranslation(IParticle self, kvector_t displacement)
-
-        void IParticle::applyTranslation(kvector_t displacement)
-
-        Applies extra translation by adding it to the current one. 
-
-        """
-        return _libBornAgainCore.IParticle_applyTranslation(self, displacement)
-
-
     def getChildren(self):
         """
         getChildren(IParticle self) -> swig_dummy_type_const_inode_vector
@@ -18714,6 +18714,11 @@ class IParticle(IAbstractParticle):
         """
         return _libBornAgainCore.IParticle_registerPosition(self, make_registered)
 
+
+    def decompose(self):
+        """decompose(IParticle self) -> SafePointerVector< IParticle >"""
+        return _libBornAgainCore.IParticle_decompose(self)
+
 IParticle_swigregister = _libBornAgainCore.IParticle_swigregister
 IParticle_swigregister(IParticle)
 
@@ -22501,16 +22506,14 @@ class MultiLayer(ISample):
         return _libBornAgainCore.MultiLayer_requiresMatrixRTCoefficients(self)
 
 
-    def zToLayerIndex(self, z_value):
-        """
-        zToLayerIndex(MultiLayer self, double z_value) -> size_t
+    def bottomZToLayerIndex(self, z_value):
+        """bottomZToLayerIndex(MultiLayer self, double z_value) -> size_t"""
+        return _libBornAgainCore.MultiLayer_bottomZToLayerIndex(self, z_value)
 
-        size_t MultiLayer::zToLayerIndex(double z_value) const
 
-        returns layer index corresponding to given global z coordinate The top interface position of a layer is considered to belong to the layer above 
-
-        """
-        return _libBornAgainCore.MultiLayer_zToLayerIndex(self, z_value)
+    def topZToLayerIndex(self, z_value):
+        """topZToLayerIndex(MultiLayer self, double z_value) -> size_t"""
+        return _libBornAgainCore.MultiLayer_topZToLayerIndex(self, z_value)
 
 
     def containsMagneticMaterial(self):
@@ -23956,8 +23959,6 @@ class ParticleComposition(IParticle):
     def __init__(self, *args):
         """
         __init__(ParticleComposition self) -> ParticleComposition
-        __init__(ParticleComposition self, IParticle particle) -> ParticleComposition
-        __init__(ParticleComposition self, IParticle particle, kvector_t position) -> ParticleComposition
         __init__(ParticleComposition self, IParticle particle, vector_kvector_t positions) -> ParticleComposition
 
         ParticleComposition::ParticleComposition(const IParticle &particle, std::vector< kvector_t > positions)
@@ -24085,6 +24086,11 @@ class ParticleComposition(IParticle):
         """
         return _libBornAgainCore.ParticleComposition_getChildren(self)
 
+
+    def decompose(self):
+        """decompose(ParticleComposition self) -> SafePointerVector< IParticle >"""
+        return _libBornAgainCore.ParticleComposition_decompose(self)
+
 ParticleComposition_swigregister = _libBornAgainCore.ParticleComposition_swigregister
 ParticleComposition_swigregister(ParticleComposition)
 
diff --git a/auto/Wrap/libBornAgainCore_wrap.cpp b/auto/Wrap/libBornAgainCore_wrap.cpp
index 528345f89ad2e872cac6329336903c4f2d0536a8..1930c107aebfdf6d2fd7dc60bce1998d03c86492 100644
--- a/auto/Wrap/libBornAgainCore_wrap.cpp
+++ b/auto/Wrap/libBornAgainCore_wrap.cpp
@@ -3665,98 +3665,99 @@ namespace Swig {
 #define SWIGTYPE_p_RotationZ swig_types[208]
 #define SWIGTYPE_p_SafePointerVectorT_FitObject_t__iterator swig_types[209]
 #define SWIGTYPE_p_SafePointerVectorT_IParticle_const_t swig_types[210]
-#define SWIGTYPE_p_SampleBuilderFactory swig_types[211]
-#define SWIGTYPE_p_SimpleSelectionRule swig_types[212]
-#define SWIGTYPE_p_Simulation swig_types[213]
-#define SWIGTYPE_p_SimulationFactory swig_types[214]
-#define SWIGTYPE_p_SimulationOptions swig_types[215]
-#define SWIGTYPE_p_SpecularSimulation swig_types[216]
-#define SWIGTYPE_p_SphericalDetector swig_types[217]
-#define SWIGTYPE_p_SphericalPixel swig_types[218]
-#define SWIGTYPE_p_SquareLattice swig_types[219]
-#define SWIGTYPE_p_SquaredFunctionDefault swig_types[220]
-#define SWIGTYPE_p_SquaredFunctionGaussianError swig_types[221]
-#define SWIGTYPE_p_SquaredFunctionMeanSquaredError swig_types[222]
-#define SWIGTYPE_p_SquaredFunctionSimError swig_types[223]
-#define SWIGTYPE_p_SquaredFunctionSystematicError swig_types[224]
-#define SWIGTYPE_p_ThreadInfo swig_types[225]
-#define SWIGTYPE_p_Transform3D swig_types[226]
-#define SWIGTYPE_p_VariableBinAxis swig_types[227]
-#define SWIGTYPE_p_VerticalLine swig_types[228]
-#define SWIGTYPE_p_WavevectorInfo swig_types[229]
-#define SWIGTYPE_p__object swig_types[230]
-#define SWIGTYPE_p_allocator_type swig_types[231]
-#define SWIGTYPE_p_bool swig_types[232]
-#define SWIGTYPE_p_char swig_types[233]
-#define SWIGTYPE_p_const_iterator swig_types[234]
-#define SWIGTYPE_p_const_reference swig_types[235]
-#define SWIGTYPE_p_difference_type swig_types[236]
-#define SWIGTYPE_p_double swig_types[237]
-#define SWIGTYPE_p_int swig_types[238]
-#define SWIGTYPE_p_iterator swig_types[239]
-#define SWIGTYPE_p_long_long swig_types[240]
-#define SWIGTYPE_p_observer_t swig_types[241]
-#define SWIGTYPE_p_observerlist_t swig_types[242]
-#define SWIGTYPE_p_p__object swig_types[243]
-#define SWIGTYPE_p_reference swig_types[244]
-#define SWIGTYPE_p_short swig_types[245]
-#define SWIGTYPE_p_signed_char swig_types[246]
-#define SWIGTYPE_p_size_type swig_types[247]
-#define SWIGTYPE_p_std__allocatorT_BasicVector3DT_double_t_t swig_types[248]
-#define SWIGTYPE_p_std__allocatorT_BasicVector3DT_std__complexT_double_t_t_t swig_types[249]
-#define SWIGTYPE_p_std__allocatorT_IFormFactor_p_t swig_types[250]
-#define SWIGTYPE_p_std__allocatorT_INode_const_p_t swig_types[251]
-#define SWIGTYPE_p_std__allocatorT_INode_p_t swig_types[252]
-#define SWIGTYPE_p_std__allocatorT_ParameterSample_t swig_types[253]
-#define SWIGTYPE_p_std__allocatorT_double_t swig_types[254]
-#define SWIGTYPE_p_std__allocatorT_int_t swig_types[255]
-#define SWIGTYPE_p_std__allocatorT_std__complexT_double_t_t swig_types[256]
-#define SWIGTYPE_p_std__allocatorT_std__string_t swig_types[257]
-#define SWIGTYPE_p_std__allocatorT_std__vectorT_double_std__allocatorT_double_t_t_t swig_types[258]
-#define SWIGTYPE_p_std__allocatorT_std__vectorT_int_std__allocatorT_int_t_t_t swig_types[259]
-#define SWIGTYPE_p_std__allocatorT_unsigned_long_t swig_types[260]
-#define SWIGTYPE_p_std__complexT_double_t swig_types[261]
-#define SWIGTYPE_p_std__functionT_GISASSimulation_pfF_t swig_types[262]
-#define SWIGTYPE_p_std__functionT_IMultiLayerBuilder_pfF_t swig_types[263]
-#define SWIGTYPE_p_std__functionT_void_fF_t swig_types[264]
-#define SWIGTYPE_p_std__invalid_argument swig_types[265]
-#define SWIGTYPE_p_std__mapT_std__string_std__string_t__const_iterator swig_types[266]
-#define SWIGTYPE_p_std__shared_ptrT_IFitObserver_t swig_types[267]
-#define SWIGTYPE_p_std__shared_ptrT_ILayerRTCoefficients_const_t swig_types[268]
-#define SWIGTYPE_p_std__shared_ptrT_IMultiLayerBuilder_t swig_types[269]
-#define SWIGTYPE_p_std__shared_ptrT_IObserver_t swig_types[270]
-#define SWIGTYPE_p_std__vectorT_BasicVector3DT_double_t_std__allocatorT_BasicVector3DT_double_t_t_t swig_types[271]
-#define SWIGTYPE_p_std__vectorT_BasicVector3DT_std__complexT_double_t_t_std__allocatorT_BasicVector3DT_std__complexT_double_t_t_t_t swig_types[272]
-#define SWIGTYPE_p_std__vectorT_FitElement_std__allocatorT_FitElement_t_t swig_types[273]
-#define SWIGTYPE_p_std__vectorT_FitElement_std__allocatorT_FitElement_t_t__const_iterator swig_types[274]
-#define SWIGTYPE_p_std__vectorT_FitElement_std__allocatorT_FitElement_t_t__iterator swig_types[275]
-#define SWIGTYPE_p_std__vectorT_IDetector2D__EAxesUnits_std__allocatorT_IDetector2D__EAxesUnits_t_t swig_types[276]
-#define SWIGTYPE_p_std__vectorT_IFTDistribution2D_const_p_std__allocatorT_IFTDistribution2D_const_p_t_t swig_types[277]
-#define SWIGTYPE_p_std__vectorT_IFormFactor_p_std__allocatorT_IFormFactor_p_t_t swig_types[278]
-#define SWIGTYPE_p_std__vectorT_IMaterial_const_p_std__allocatorT_IMaterial_const_p_t_t swig_types[279]
-#define SWIGTYPE_p_std__vectorT_INode_const_p_std__allocatorT_INode_const_p_t_t swig_types[280]
-#define SWIGTYPE_p_std__vectorT_INode_p_std__allocatorT_INode_p_t_t swig_types[281]
-#define SWIGTYPE_p_std__vectorT_IParticle_const_p_std__allocatorT_IParticle_const_p_t_t swig_types[282]
-#define SWIGTYPE_p_std__vectorT_ParameterSample_std__allocatorT_ParameterSample_t_t swig_types[283]
-#define SWIGTYPE_p_std__vectorT_PolygonalTopology_std__allocatorT_PolygonalTopology_t_t swig_types[284]
-#define SWIGTYPE_p_std__vectorT_RealParameter_p_std__allocatorT_RealParameter_p_t_t swig_types[285]
-#define SWIGTYPE_p_std__vectorT_SimulationElement_std__allocatorT_SimulationElement_t_t swig_types[286]
-#define SWIGTYPE_p_std__vectorT_double_std__allocatorT_double_t_t swig_types[287]
-#define SWIGTYPE_p_std__vectorT_int_std__allocatorT_int_t_t swig_types[288]
-#define SWIGTYPE_p_std__vectorT_size_t_std__allocatorT_size_t_t_t swig_types[289]
-#define SWIGTYPE_p_std__vectorT_std__complexT_double_t_std__allocatorT_std__complexT_double_t_t_t swig_types[290]
-#define SWIGTYPE_p_std__vectorT_std__string_std__allocatorT_std__string_t_t swig_types[291]
-#define SWIGTYPE_p_std__vectorT_std__vectorT_double_std__allocatorT_double_t_t_std__allocatorT_std__vectorT_double_std__allocatorT_double_t_t_t_t swig_types[292]
-#define SWIGTYPE_p_std__vectorT_std__vectorT_int_std__allocatorT_int_t_t_std__allocatorT_std__vectorT_int_std__allocatorT_int_t_t_t_t swig_types[293]
-#define SWIGTYPE_p_std__vectorT_unsigned_long_std__allocatorT_unsigned_long_t_t swig_types[294]
-#define SWIGTYPE_p_swig__SwigPyIterator swig_types[295]
-#define SWIGTYPE_p_unsigned_char swig_types[296]
-#define SWIGTYPE_p_unsigned_int swig_types[297]
-#define SWIGTYPE_p_unsigned_long_long swig_types[298]
-#define SWIGTYPE_p_unsigned_short swig_types[299]
-#define SWIGTYPE_p_value_type swig_types[300]
-static swig_type_info *swig_types[302];
-static swig_module_info swig_module = {swig_types, 301, 0, 0, 0, 0};
+#define SWIGTYPE_p_SafePointerVectorT_IParticle_t swig_types[211]
+#define SWIGTYPE_p_SampleBuilderFactory swig_types[212]
+#define SWIGTYPE_p_SimpleSelectionRule swig_types[213]
+#define SWIGTYPE_p_Simulation swig_types[214]
+#define SWIGTYPE_p_SimulationFactory swig_types[215]
+#define SWIGTYPE_p_SimulationOptions swig_types[216]
+#define SWIGTYPE_p_SpecularSimulation swig_types[217]
+#define SWIGTYPE_p_SphericalDetector swig_types[218]
+#define SWIGTYPE_p_SphericalPixel swig_types[219]
+#define SWIGTYPE_p_SquareLattice swig_types[220]
+#define SWIGTYPE_p_SquaredFunctionDefault swig_types[221]
+#define SWIGTYPE_p_SquaredFunctionGaussianError swig_types[222]
+#define SWIGTYPE_p_SquaredFunctionMeanSquaredError swig_types[223]
+#define SWIGTYPE_p_SquaredFunctionSimError swig_types[224]
+#define SWIGTYPE_p_SquaredFunctionSystematicError swig_types[225]
+#define SWIGTYPE_p_ThreadInfo swig_types[226]
+#define SWIGTYPE_p_Transform3D swig_types[227]
+#define SWIGTYPE_p_VariableBinAxis swig_types[228]
+#define SWIGTYPE_p_VerticalLine swig_types[229]
+#define SWIGTYPE_p_WavevectorInfo swig_types[230]
+#define SWIGTYPE_p__object swig_types[231]
+#define SWIGTYPE_p_allocator_type swig_types[232]
+#define SWIGTYPE_p_bool swig_types[233]
+#define SWIGTYPE_p_char swig_types[234]
+#define SWIGTYPE_p_const_iterator swig_types[235]
+#define SWIGTYPE_p_const_reference swig_types[236]
+#define SWIGTYPE_p_difference_type swig_types[237]
+#define SWIGTYPE_p_double swig_types[238]
+#define SWIGTYPE_p_int swig_types[239]
+#define SWIGTYPE_p_iterator swig_types[240]
+#define SWIGTYPE_p_long_long swig_types[241]
+#define SWIGTYPE_p_observer_t swig_types[242]
+#define SWIGTYPE_p_observerlist_t swig_types[243]
+#define SWIGTYPE_p_p__object swig_types[244]
+#define SWIGTYPE_p_reference swig_types[245]
+#define SWIGTYPE_p_short swig_types[246]
+#define SWIGTYPE_p_signed_char swig_types[247]
+#define SWIGTYPE_p_size_type swig_types[248]
+#define SWIGTYPE_p_std__allocatorT_BasicVector3DT_double_t_t swig_types[249]
+#define SWIGTYPE_p_std__allocatorT_BasicVector3DT_std__complexT_double_t_t_t swig_types[250]
+#define SWIGTYPE_p_std__allocatorT_IFormFactor_p_t swig_types[251]
+#define SWIGTYPE_p_std__allocatorT_INode_const_p_t swig_types[252]
+#define SWIGTYPE_p_std__allocatorT_INode_p_t swig_types[253]
+#define SWIGTYPE_p_std__allocatorT_ParameterSample_t swig_types[254]
+#define SWIGTYPE_p_std__allocatorT_double_t swig_types[255]
+#define SWIGTYPE_p_std__allocatorT_int_t swig_types[256]
+#define SWIGTYPE_p_std__allocatorT_std__complexT_double_t_t swig_types[257]
+#define SWIGTYPE_p_std__allocatorT_std__string_t swig_types[258]
+#define SWIGTYPE_p_std__allocatorT_std__vectorT_double_std__allocatorT_double_t_t_t swig_types[259]
+#define SWIGTYPE_p_std__allocatorT_std__vectorT_int_std__allocatorT_int_t_t_t swig_types[260]
+#define SWIGTYPE_p_std__allocatorT_unsigned_long_t swig_types[261]
+#define SWIGTYPE_p_std__complexT_double_t swig_types[262]
+#define SWIGTYPE_p_std__functionT_GISASSimulation_pfF_t swig_types[263]
+#define SWIGTYPE_p_std__functionT_IMultiLayerBuilder_pfF_t swig_types[264]
+#define SWIGTYPE_p_std__functionT_void_fF_t swig_types[265]
+#define SWIGTYPE_p_std__invalid_argument swig_types[266]
+#define SWIGTYPE_p_std__mapT_std__string_std__string_t__const_iterator swig_types[267]
+#define SWIGTYPE_p_std__shared_ptrT_IFitObserver_t swig_types[268]
+#define SWIGTYPE_p_std__shared_ptrT_ILayerRTCoefficients_const_t swig_types[269]
+#define SWIGTYPE_p_std__shared_ptrT_IMultiLayerBuilder_t swig_types[270]
+#define SWIGTYPE_p_std__shared_ptrT_IObserver_t swig_types[271]
+#define SWIGTYPE_p_std__vectorT_BasicVector3DT_double_t_std__allocatorT_BasicVector3DT_double_t_t_t swig_types[272]
+#define SWIGTYPE_p_std__vectorT_BasicVector3DT_std__complexT_double_t_t_std__allocatorT_BasicVector3DT_std__complexT_double_t_t_t_t swig_types[273]
+#define SWIGTYPE_p_std__vectorT_FitElement_std__allocatorT_FitElement_t_t swig_types[274]
+#define SWIGTYPE_p_std__vectorT_FitElement_std__allocatorT_FitElement_t_t__const_iterator swig_types[275]
+#define SWIGTYPE_p_std__vectorT_FitElement_std__allocatorT_FitElement_t_t__iterator swig_types[276]
+#define SWIGTYPE_p_std__vectorT_IDetector2D__EAxesUnits_std__allocatorT_IDetector2D__EAxesUnits_t_t swig_types[277]
+#define SWIGTYPE_p_std__vectorT_IFTDistribution2D_const_p_std__allocatorT_IFTDistribution2D_const_p_t_t swig_types[278]
+#define SWIGTYPE_p_std__vectorT_IFormFactor_p_std__allocatorT_IFormFactor_p_t_t swig_types[279]
+#define SWIGTYPE_p_std__vectorT_IMaterial_const_p_std__allocatorT_IMaterial_const_p_t_t swig_types[280]
+#define SWIGTYPE_p_std__vectorT_INode_const_p_std__allocatorT_INode_const_p_t_t swig_types[281]
+#define SWIGTYPE_p_std__vectorT_INode_p_std__allocatorT_INode_p_t_t swig_types[282]
+#define SWIGTYPE_p_std__vectorT_IParticle_const_p_std__allocatorT_IParticle_const_p_t_t swig_types[283]
+#define SWIGTYPE_p_std__vectorT_ParameterSample_std__allocatorT_ParameterSample_t_t swig_types[284]
+#define SWIGTYPE_p_std__vectorT_PolygonalTopology_std__allocatorT_PolygonalTopology_t_t swig_types[285]
+#define SWIGTYPE_p_std__vectorT_RealParameter_p_std__allocatorT_RealParameter_p_t_t swig_types[286]
+#define SWIGTYPE_p_std__vectorT_SimulationElement_std__allocatorT_SimulationElement_t_t swig_types[287]
+#define SWIGTYPE_p_std__vectorT_double_std__allocatorT_double_t_t swig_types[288]
+#define SWIGTYPE_p_std__vectorT_int_std__allocatorT_int_t_t swig_types[289]
+#define SWIGTYPE_p_std__vectorT_size_t_std__allocatorT_size_t_t_t swig_types[290]
+#define SWIGTYPE_p_std__vectorT_std__complexT_double_t_std__allocatorT_std__complexT_double_t_t_t swig_types[291]
+#define SWIGTYPE_p_std__vectorT_std__string_std__allocatorT_std__string_t_t swig_types[292]
+#define SWIGTYPE_p_std__vectorT_std__vectorT_double_std__allocatorT_double_t_t_std__allocatorT_std__vectorT_double_std__allocatorT_double_t_t_t_t swig_types[293]
+#define SWIGTYPE_p_std__vectorT_std__vectorT_int_std__allocatorT_int_t_t_std__allocatorT_std__vectorT_int_std__allocatorT_int_t_t_t_t swig_types[294]
+#define SWIGTYPE_p_std__vectorT_unsigned_long_std__allocatorT_unsigned_long_t_t swig_types[295]
+#define SWIGTYPE_p_swig__SwigPyIterator swig_types[296]
+#define SWIGTYPE_p_unsigned_char swig_types[297]
+#define SWIGTYPE_p_unsigned_int swig_types[298]
+#define SWIGTYPE_p_unsigned_long_long swig_types[299]
+#define SWIGTYPE_p_unsigned_short swig_types[300]
+#define SWIGTYPE_p_value_type swig_types[301]
+static swig_type_info *swig_types[303];
+static swig_module_info swig_module = {swig_types, 302, 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)
 
@@ -5983,7 +5984,7 @@ SWIG_AsVal_std_complex_Sl_double_Sg_  (PyObject *o, std::complex<double>* val)
 
 
 SWIGINTERNINLINE PyObject*
-SWIG_From_std_complex_Sl_double_Sg_  (/*@SWIG:/home/pospelov/software/local/share/swig/3.0.8/typemaps/swigmacros.swg,104,%ifcplusplus@*/
+SWIG_From_std_complex_Sl_double_Sg_  (/*@SWIG:/usr/share/swig3.0/typemaps/swigmacros.swg,104,%ifcplusplus@*/
 
 const std::complex<double>&
 
@@ -83273,6 +83274,44 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_IParticle_applyTranslation(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  IParticle *arg1 = (IParticle *) 0 ;
+  kvector_t arg2 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  void *argp2 ;
+  int res2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:IParticle_applyTranslation",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_IParticle, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "IParticle_applyTranslation" "', argument " "1"" of type '" "IParticle *""'"); 
+  }
+  arg1 = reinterpret_cast< IParticle * >(argp1);
+  {
+    res2 = SWIG_ConvertPtr(obj1, &argp2, SWIGTYPE_p_BasicVector3DT_double_t,  0  | 0);
+    if (!SWIG_IsOK(res2)) {
+      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "IParticle_applyTranslation" "', argument " "2"" of type '" "kvector_t""'"); 
+    }  
+    if (!argp2) {
+      SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "IParticle_applyTranslation" "', argument " "2"" of type '" "kvector_t""'");
+    } else {
+      kvector_t * temp = reinterpret_cast< kvector_t * >(argp2);
+      arg2 = *temp;
+      if (SWIG_IsNewObj(res2)) delete temp;
+    }
+  }
+  (arg1)->applyTranslation(arg2);
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_IParticle_getRotation(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   IParticle *arg1 = (IParticle *) 0 ;
@@ -83361,44 +83400,6 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_IParticle_applyTranslation(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  IParticle *arg1 = (IParticle *) 0 ;
-  kvector_t arg2 ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  void *argp2 ;
-  int res2 = 0 ;
-  PyObject * obj0 = 0 ;
-  PyObject * obj1 = 0 ;
-  
-  if (!PyArg_ParseTuple(args,(char *)"OO:IParticle_applyTranslation",&obj0,&obj1)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_IParticle, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "IParticle_applyTranslation" "', argument " "1"" of type '" "IParticle *""'"); 
-  }
-  arg1 = reinterpret_cast< IParticle * >(argp1);
-  {
-    res2 = SWIG_ConvertPtr(obj1, &argp2, SWIGTYPE_p_BasicVector3DT_double_t,  0  | 0);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "IParticle_applyTranslation" "', argument " "2"" of type '" "kvector_t""'"); 
-    }  
-    if (!argp2) {
-      SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "IParticle_applyTranslation" "', argument " "2"" of type '" "kvector_t""'");
-    } else {
-      kvector_t * temp = reinterpret_cast< kvector_t * >(argp2);
-      arg2 = *temp;
-      if (SWIG_IsNewObj(res2)) delete temp;
-    }
-  }
-  (arg1)->applyTranslation(arg2);
-  resultobj = SWIG_Py_Void();
-  return resultobj;
-fail:
-  return NULL;
-}
-
-
 SWIGINTERN PyObject *_wrap_IParticle_getChildren(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   IParticle *arg1 = (IParticle *) 0 ;
@@ -83615,6 +83616,28 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_IParticle_decompose(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  IParticle *arg1 = (IParticle *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  SwigValueWrapper< SafePointerVector< IParticle > > result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:IParticle_decompose",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_IParticle, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "IParticle_decompose" "', argument " "1"" of type '" "IParticle const *""'"); 
+  }
+  arg1 = reinterpret_cast< IParticle * >(argp1);
+  result = ((IParticle const *)arg1)->decompose();
+  resultobj = SWIG_NewPointerObj((new SafePointerVector< IParticle >(static_cast< const SafePointerVector< IParticle >& >(result))), SWIGTYPE_p_SafePointerVectorT_IParticle_t, SWIG_POINTER_OWN |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *IParticle_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *obj;
   if (!PyArg_ParseTuple(args,(char*)"O:swigregister", &obj)) return NULL;
@@ -95057,7 +95080,7 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_MultiLayer_zToLayerIndex(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+SWIGINTERN PyObject *_wrap_MultiLayer_bottomZToLayerIndex(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   MultiLayer *arg1 = (MultiLayer *) 0 ;
   double arg2 ;
@@ -95069,18 +95092,49 @@ SWIGINTERN PyObject *_wrap_MultiLayer_zToLayerIndex(PyObject *SWIGUNUSEDPARM(sel
   PyObject * obj1 = 0 ;
   size_t result;
   
-  if (!PyArg_ParseTuple(args,(char *)"OO:MultiLayer_zToLayerIndex",&obj0,&obj1)) SWIG_fail;
+  if (!PyArg_ParseTuple(args,(char *)"OO:MultiLayer_bottomZToLayerIndex",&obj0,&obj1)) SWIG_fail;
   res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_MultiLayer, 0 |  0 );
   if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "MultiLayer_zToLayerIndex" "', argument " "1"" of type '" "MultiLayer const *""'"); 
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "MultiLayer_bottomZToLayerIndex" "', argument " "1"" of type '" "MultiLayer const *""'"); 
   }
   arg1 = reinterpret_cast< MultiLayer * >(argp1);
   ecode2 = SWIG_AsVal_double(obj1, &val2);
   if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "MultiLayer_zToLayerIndex" "', argument " "2"" of type '" "double""'");
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "MultiLayer_bottomZToLayerIndex" "', argument " "2"" of type '" "double""'");
   } 
   arg2 = static_cast< double >(val2);
-  result = ((MultiLayer const *)arg1)->zToLayerIndex(arg2);
+  result = ((MultiLayer const *)arg1)->bottomZToLayerIndex(arg2);
+  resultobj = SWIG_From_size_t(static_cast< size_t >(result));
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_MultiLayer_topZToLayerIndex(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  MultiLayer *arg1 = (MultiLayer *) 0 ;
+  double arg2 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  double val2 ;
+  int ecode2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  size_t result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:MultiLayer_topZToLayerIndex",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_MultiLayer, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "MultiLayer_topZToLayerIndex" "', argument " "1"" of type '" "MultiLayer const *""'"); 
+  }
+  arg1 = reinterpret_cast< MultiLayer * >(argp1);
+  ecode2 = SWIG_AsVal_double(obj1, &val2);
+  if (!SWIG_IsOK(ecode2)) {
+    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "MultiLayer_topZToLayerIndex" "', argument " "2"" of type '" "double""'");
+  } 
+  arg2 = static_cast< double >(val2);
+  result = ((MultiLayer const *)arg1)->topZToLayerIndex(arg2);
   resultobj = SWIG_From_size_t(static_cast< size_t >(result));
   return resultobj;
 fail:
@@ -101461,73 +101515,6 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_new_ParticleComposition__SWIG_1(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  IParticle *arg1 = 0 ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  PyObject * obj0 = 0 ;
-  ParticleComposition *result = 0 ;
-  
-  if (!PyArg_ParseTuple(args,(char *)"O:new_ParticleComposition",&obj0)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1, SWIGTYPE_p_IParticle,  0  | 0);
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "new_ParticleComposition" "', argument " "1"" of type '" "IParticle const &""'"); 
-  }
-  if (!argp1) {
-    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "new_ParticleComposition" "', argument " "1"" of type '" "IParticle const &""'"); 
-  }
-  arg1 = reinterpret_cast< IParticle * >(argp1);
-  result = (ParticleComposition *)new ParticleComposition((IParticle const &)*arg1);
-  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_ParticleComposition, SWIG_POINTER_NEW |  0 );
-  return resultobj;
-fail:
-  return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_new_ParticleComposition__SWIG_2(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  IParticle *arg1 = 0 ;
-  kvector_t arg2 ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  void *argp2 ;
-  int res2 = 0 ;
-  PyObject * obj0 = 0 ;
-  PyObject * obj1 = 0 ;
-  ParticleComposition *result = 0 ;
-  
-  if (!PyArg_ParseTuple(args,(char *)"OO:new_ParticleComposition",&obj0,&obj1)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1, SWIGTYPE_p_IParticle,  0  | 0);
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "new_ParticleComposition" "', argument " "1"" of type '" "IParticle const &""'"); 
-  }
-  if (!argp1) {
-    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "new_ParticleComposition" "', argument " "1"" of type '" "IParticle const &""'"); 
-  }
-  arg1 = reinterpret_cast< IParticle * >(argp1);
-  {
-    res2 = SWIG_ConvertPtr(obj1, &argp2, SWIGTYPE_p_BasicVector3DT_double_t,  0  | 0);
-    if (!SWIG_IsOK(res2)) {
-      SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "new_ParticleComposition" "', argument " "2"" of type '" "kvector_t""'"); 
-    }  
-    if (!argp2) {
-      SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "new_ParticleComposition" "', argument " "2"" of type '" "kvector_t""'");
-    } else {
-      kvector_t * temp = reinterpret_cast< kvector_t * >(argp2);
-      arg2 = *temp;
-      if (SWIG_IsNewObj(res2)) delete temp;
-    }
-  }
-  result = (ParticleComposition *)new ParticleComposition((IParticle const &)*arg1,arg2);
-  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_ParticleComposition, SWIG_POINTER_NEW |  0 );
-  return resultobj;
-fail:
-  return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_new_ParticleComposition__SWIG_3(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   IParticle *arg1 = 0 ;
   std::vector< kvector_t,std::allocator< kvector_t > > arg2 ;
@@ -101578,26 +101565,6 @@ SWIGINTERN PyObject *_wrap_new_ParticleComposition(PyObject *self, PyObject *arg
   if (argc == 0) {
     return _wrap_new_ParticleComposition__SWIG_0(self, args);
   }
-  if (argc == 1) {
-    int _v;
-    int res = SWIG_ConvertPtr(argv[0], 0, SWIGTYPE_p_IParticle, 0);
-    _v = SWIG_CheckState(res);
-    if (_v) {
-      return _wrap_new_ParticleComposition__SWIG_1(self, args);
-    }
-  }
-  if (argc == 2) {
-    int _v;
-    int res = SWIG_ConvertPtr(argv[0], 0, SWIGTYPE_p_IParticle, 0);
-    _v = SWIG_CheckState(res);
-    if (_v) {
-      int res = SWIG_ConvertPtr(argv[1], 0, SWIGTYPE_p_BasicVector3DT_double_t, 0);
-      _v = SWIG_CheckState(res);
-      if (_v) {
-        return _wrap_new_ParticleComposition__SWIG_2(self, args);
-      }
-    }
-  }
   if (argc == 2) {
     int _v;
     int res = SWIG_ConvertPtr(argv[0], 0, SWIGTYPE_p_IParticle, 0);
@@ -101606,7 +101573,7 @@ SWIGINTERN PyObject *_wrap_new_ParticleComposition(PyObject *self, PyObject *arg
       int res = swig::asptr(argv[1], (std::vector< BasicVector3D< double >,std::allocator< BasicVector3D< double > > >**)(0));
       _v = SWIG_CheckState(res);
       if (_v) {
-        return _wrap_new_ParticleComposition__SWIG_3(self, args);
+        return _wrap_new_ParticleComposition__SWIG_1(self, args);
       }
     }
   }
@@ -101615,8 +101582,6 @@ fail:
   SWIG_SetErrorMsg(PyExc_NotImplementedError,"Wrong number or type of arguments for overloaded function 'new_ParticleComposition'.\n"
     "  Possible C/C++ prototypes are:\n"
     "    ParticleComposition::ParticleComposition()\n"
-    "    ParticleComposition::ParticleComposition(IParticle const &)\n"
-    "    ParticleComposition::ParticleComposition(IParticle const &,kvector_t)\n"
     "    ParticleComposition::ParticleComposition(IParticle const &,std::vector< kvector_t,std::allocator< kvector_t > >)\n");
   return 0;
 }
@@ -102057,6 +102022,28 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_ParticleComposition_decompose(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  ParticleComposition *arg1 = (ParticleComposition *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  PyObject * obj0 = 0 ;
+  SwigValueWrapper< SafePointerVector< IParticle > > result;
+  
+  if (!PyArg_ParseTuple(args,(char *)"O:ParticleComposition_decompose",&obj0)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ParticleComposition, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ParticleComposition_decompose" "', argument " "1"" of type '" "ParticleComposition const *""'"); 
+  }
+  arg1 = reinterpret_cast< ParticleComposition * >(argp1);
+  result = ((ParticleComposition const *)arg1)->decompose();
+  resultobj = SWIG_NewPointerObj((new SafePointerVector< IParticle >(static_cast< const SafePointerVector< IParticle >& >(result))), SWIGTYPE_p_SafePointerVectorT_IParticle_t, SWIG_POINTER_OWN |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *ParticleComposition_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *obj;
   if (!PyArg_ParseTuple(args,(char*)"O:swigregister", &obj)) return NULL;
@@ -117774,6 +117761,14 @@ static PyMethodDef SwigMethods[] = {
 		"Sets particle position. \n"
 		"\n"
 		""},
+	 { (char *)"IParticle_applyTranslation", _wrap_IParticle_applyTranslation, METH_VARARGS, (char *)"\n"
+		"IParticle_applyTranslation(IParticle self, kvector_t displacement)\n"
+		"\n"
+		"void IParticle::applyTranslation(kvector_t displacement)\n"
+		"\n"
+		"Applies extra translation by adding it to the current one. \n"
+		"\n"
+		""},
 	 { (char *)"IParticle_getRotation", _wrap_IParticle_getRotation, METH_VARARGS, (char *)"\n"
 		"IParticle_getRotation(IParticle self) -> IRotation\n"
 		"\n"
@@ -117798,14 +117793,6 @@ static PyMethodDef SwigMethods[] = {
 		"Applies transformation by composing it with the existing one. \n"
 		"\n"
 		""},
-	 { (char *)"IParticle_applyTranslation", _wrap_IParticle_applyTranslation, METH_VARARGS, (char *)"\n"
-		"IParticle_applyTranslation(IParticle self, kvector_t displacement)\n"
-		"\n"
-		"void IParticle::applyTranslation(kvector_t displacement)\n"
-		"\n"
-		"Applies extra translation by adding it to the current one. \n"
-		"\n"
-		""},
 	 { (char *)"IParticle_getChildren", _wrap_IParticle_getChildren, METH_VARARGS, (char *)"\n"
 		"IParticle_getChildren(IParticle self) -> swig_dummy_type_const_inode_vector\n"
 		"\n"
@@ -117830,6 +117817,7 @@ static PyMethodDef SwigMethods[] = {
 		"Registers the three components of its position. \n"
 		"\n"
 		""},
+	 { (char *)"IParticle_decompose", _wrap_IParticle_decompose, METH_VARARGS, (char *)"IParticle_decompose(IParticle self) -> SafePointerVector< IParticle >"},
 	 { (char *)"IParticle_swigregister", IParticle_swigregister, METH_VARARGS, NULL},
 	 { (char *)"delete_IResolutionFunction2D", _wrap_delete_IResolutionFunction2D, METH_VARARGS, (char *)"\n"
 		"delete_IResolutionFunction2D(IResolutionFunction2D self)\n"
@@ -119857,14 +119845,8 @@ static PyMethodDef SwigMethods[] = {
 		"returns true if contains magnetic materials and matrix calculations are required \n"
 		"\n"
 		""},
-	 { (char *)"MultiLayer_zToLayerIndex", _wrap_MultiLayer_zToLayerIndex, METH_VARARGS, (char *)"\n"
-		"MultiLayer_zToLayerIndex(MultiLayer self, double z_value) -> size_t\n"
-		"\n"
-		"size_t MultiLayer::zToLayerIndex(double z_value) const\n"
-		"\n"
-		"returns layer index corresponding to given global z coordinate The top interface position of a layer is considered to belong to the layer above \n"
-		"\n"
-		""},
+	 { (char *)"MultiLayer_bottomZToLayerIndex", _wrap_MultiLayer_bottomZToLayerIndex, METH_VARARGS, (char *)"MultiLayer_bottomZToLayerIndex(MultiLayer self, double z_value) -> size_t"},
+	 { (char *)"MultiLayer_topZToLayerIndex", _wrap_MultiLayer_topZToLayerIndex, METH_VARARGS, (char *)"MultiLayer_topZToLayerIndex(MultiLayer self, double z_value) -> size_t"},
 	 { (char *)"MultiLayer_containsMagneticMaterial", _wrap_MultiLayer_containsMagneticMaterial, METH_VARARGS, (char *)"\n"
 		"MultiLayer_containsMagneticMaterial(MultiLayer self) -> bool\n"
 		"\n"
@@ -120671,8 +120653,6 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"Particle_swigregister", Particle_swigregister, METH_VARARGS, NULL},
 	 { (char *)"new_ParticleComposition", _wrap_new_ParticleComposition, METH_VARARGS, (char *)"\n"
 		"ParticleComposition()\n"
-		"ParticleComposition(IParticle particle)\n"
-		"ParticleComposition(IParticle particle, kvector_t position)\n"
 		"new_ParticleComposition(IParticle particle, vector_kvector_t positions) -> ParticleComposition\n"
 		"\n"
 		"ParticleComposition::ParticleComposition(const IParticle &particle, std::vector< kvector_t > positions)\n"
@@ -120759,6 +120739,7 @@ static PyMethodDef SwigMethods[] = {
 		"Returns a vector of children (const). \n"
 		"\n"
 		""},
+	 { (char *)"ParticleComposition_decompose", _wrap_ParticleComposition_decompose, METH_VARARGS, (char *)"ParticleComposition_decompose(ParticleComposition self) -> SafePointerVector< IParticle >"},
 	 { (char *)"ParticleComposition_swigregister", ParticleComposition_swigregister, METH_VARARGS, NULL},
 	 { (char *)"new_ParticleCoreShell", _wrap_new_ParticleCoreShell, METH_VARARGS, (char *)"\n"
 		"ParticleCoreShell(Particle shell, Particle core, kvector_t relative_core_position)\n"
@@ -124569,6 +124550,7 @@ static swig_type_info _swigt__p_RotationY = {"_p_RotationY", "RotationY *", 0, 0
 static swig_type_info _swigt__p_RotationZ = {"_p_RotationZ", "RotationZ *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_SafePointerVectorT_FitObject_t__iterator = {"_p_SafePointerVectorT_FitObject_t__iterator", "SafePointerVector< FitObject >::iterator *|FitSuiteObjects::iterator *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_SafePointerVectorT_IParticle_const_t = {"_p_SafePointerVectorT_IParticle_const_t", "SafePointerVector< IParticle const > *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_SafePointerVectorT_IParticle_t = {"_p_SafePointerVectorT_IParticle_t", "SafePointerVector< IParticle > *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_SampleBuilderFactory = {"_p_SampleBuilderFactory", "SampleBuilderFactory *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_SimpleSelectionRule = {"_p_SimpleSelectionRule", "SimpleSelectionRule *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_Simulation = {"_p_Simulation", "Simulation *", 0, 0, (void*)0, 0};
@@ -124872,6 +124854,7 @@ static swig_type_info *swig_type_initial[] = {
   &_swigt__p_RotationZ,
   &_swigt__p_SafePointerVectorT_FitObject_t__iterator,
   &_swigt__p_SafePointerVectorT_IParticle_const_t,
+  &_swigt__p_SafePointerVectorT_IParticle_t,
   &_swigt__p_SampleBuilderFactory,
   &_swigt__p_SimpleSelectionRule,
   &_swigt__p_Simulation,
@@ -125175,6 +125158,7 @@ static swig_cast_info _swigc__p_RotationY[] = {  {&_swigt__p_RotationY, 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_SafePointerVectorT_FitObject_t__iterator[] = {  {&_swigt__p_SafePointerVectorT_FitObject_t__iterator, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_SafePointerVectorT_IParticle_const_t[] = {  {&_swigt__p_SafePointerVectorT_IParticle_const_t, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_SafePointerVectorT_IParticle_t[] = {  {&_swigt__p_SafePointerVectorT_IParticle_t, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_SampleBuilderFactory[] = {  {&_swigt__p_SampleBuilderFactory, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_SimpleSelectionRule[] = {  {&_swigt__p_SimpleSelectionRule, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_Simulation[] = {  {&_swigt__p_Simulation, 0, 0, 0},  {&_swigt__p_GISASSimulation, _p_GISASSimulationTo_p_Simulation, 0, 0},  {&_swigt__p_OffSpecSimulation, _p_OffSpecSimulationTo_p_Simulation, 0, 0},{0, 0, 0, 0}};
@@ -125478,6 +125462,7 @@ static swig_cast_info *swig_cast_initial[] = {
   _swigc__p_RotationZ,
   _swigc__p_SafePointerVectorT_FitObject_t__iterator,
   _swigc__p_SafePointerVectorT_IParticle_const_t,
+  _swigc__p_SafePointerVectorT_IParticle_t,
   _swigc__p_SampleBuilderFactory,
   _swigc__p_SimpleSelectionRule,
   _swigc__p_Simulation,
diff --git a/auto/Wrap/libBornAgainFit_wrap.cpp b/auto/Wrap/libBornAgainFit_wrap.cpp
index 980a19744c597e8ce4355eef1f3bbad544cc94ca..182abc5541c99f92f98a78439a7f630a79c6657c 100644
--- a/auto/Wrap/libBornAgainFit_wrap.cpp
+++ b/auto/Wrap/libBornAgainFit_wrap.cpp
@@ -5627,7 +5627,7 @@ SWIG_AsVal_std_complex_Sl_double_Sg_  (PyObject *o, std::complex<double>* val)
 
 
 SWIGINTERNINLINE PyObject*
-SWIG_From_std_complex_Sl_double_Sg_  (/*@SWIG:/home/pospelov/software/local/share/swig/3.0.8/typemaps/swigmacros.swg,104,%ifcplusplus@*/
+SWIG_From_std_complex_Sl_double_Sg_  (/*@SWIG:/usr/share/swig3.0/typemaps/swigmacros.swg,104,%ifcplusplus@*/
 
 const std::complex<double>&