diff --git a/Base/Types/OwningVector.h b/Base/Types/OwningVector.h
index a9e63628631e66406799950f37c699c5b6326ea5..90a4860fa23c34ba536e8d134c1fb69a681c7572 100644
--- a/Base/Types/OwningVector.h
+++ b/Base/Types/OwningVector.h
@@ -29,7 +29,8 @@
 //! Equips vector<unique_ptr<T>> with copy constructor.
 //! For use with polymorphic objects, or in pimpl idiom.
 
-//! The objects pointed to must posses a clone() function.
+//! If the copy constructor or the copy assignment operator is used,
+//! then there must be a function T::clone().
 
 template <class T>
 class OwningVector {
@@ -49,6 +50,7 @@ public:
         for (T* e : other)
             m_v.emplace_back(e->clone());
     }
+    OwningVector(OwningVector&& other) = default;
     ~OwningVector() { clear(); }
     OwningVector& operator=(const OwningVector& other)
     {
@@ -58,7 +60,9 @@ public:
         std::swap(m_v, ret.m_v);
         return *this;
     }
+    OwningVector& operator=(OwningVector&& other) = default;
 
+    void reserve(size_t n) { m_v.reserve(n); }
     void emplace_back(T* e) { m_v.emplace_back(e); }
     void clear()
     {
diff --git a/Device/Detector/DetectorContext.h b/Device/Detector/DetectorContext.h
index d7f7f97f5f8dbec77a10e88346df395dab494bcb..6b634cd749ae43835be1d2b5a9167f8e43ef858f 100644
--- a/Device/Detector/DetectorContext.h
+++ b/Device/Detector/DetectorContext.h
@@ -18,6 +18,7 @@
 
 #include "Base/Pixel/IPixel.h"
 #include "Base/Spin/SpinMatrix.h"
+#include "Base/Types/OwningVector.h"
 #include <memory>
 #include <vector>
 
@@ -43,7 +44,7 @@ private:
     void setup_context(const IDetector* detector);
 
     SpinMatrix m_analyzer_operator;
-    std::vector<std::unique_ptr<IPixel>> m_pixels; //! All unmasked pixels inside ROI.
+    OwningVector<IPixel> m_pixels; //! All unmasked pixels inside ROI.
     std::vector<size_t> m_active_indices; //! The sequence of bin indices (unmasked, in ROI)
 };
 
diff --git a/GUI/View/Realspace/RealSpaceBuilderUtils.cpp b/GUI/View/Realspace/RealSpaceBuilderUtils.cpp
index b2182695e2cc3c61d4367d78acc09a00bb6f1ed8..9ba157a7e7b4d4d6e3587a467dc6234e3ae57b23 100644
--- a/GUI/View/Realspace/RealSpaceBuilderUtils.cpp
+++ b/GUI/View/Realspace/RealSpaceBuilderUtils.cpp
@@ -315,20 +315,20 @@ Particle3DContainer GUI::RealSpace::BuilderUtils::particleComposition3DContainer
 
     Particle3DContainer result;
 
-    for (const auto& pc_particle : PC_clone->decompose()) {
+    for (const auto* pc_particle : PC_clone->decompose()) {
         ASSERT(pc_particle);
         Particle3DContainer particle3DContainer;
         // no abundances are associated with the individual components of ParticleComposition
-        if (const auto* p = dynamic_cast<const ParticleCoreShell*>(pc_particle.get())) {
+        if (const auto* p = dynamic_cast<const ParticleCoreShell*>(pc_particle)) {
             particle3DContainer = particleCoreShell3DContainer(*p, 1.0, origin);
-        } else if (dynamic_cast<const MesoCrystal*>(pc_particle.get())) {
+        } else if (dynamic_cast<const MesoCrystal*>(pc_particle)) {
             // TODO: Implement method to populate MesoCrystal from CORE and NOT from MesoCrystalItem
             // as it is done currently in GUI::RealSpace::BuilderUtils::mesoCrystal3DContainer
             std::ostringstream ostr;
             ostr << "Sorry, MesoCrystal inside ParticleComposition not yet implemented";
             ostr << "\n\nStay tuned!";
             throw std::runtime_error(ostr.str());
-        } else if (const auto* p = dynamic_cast<const Particle*>(pc_particle.get()))
+        } else if (const auto* p = dynamic_cast<const Particle*>(pc_particle))
             particle3DContainer = singleParticle3DContainer(*p, 1.0, origin);
         else
             ASSERT(0);
diff --git a/Resample/Element/DiffuseElement.cpp b/Resample/Element/DiffuseElement.cpp
index 2f8b3b4acebcff2986814b42cde79cac9da86253..bc35ca3f69f58b1a74b37832836014f6d4b7bfd6 100644
--- a/Resample/Element/DiffuseElement.cpp
+++ b/Resample/Element/DiffuseElement.cpp
@@ -61,12 +61,12 @@ void DiffuseElement::setFluxes(const Fluxes* fluxes_in, const Fluxes* fluxes_out
 
 const IFlux* DiffuseElement::fluxIn(size_t i_layer) const
 {
-    return (*m_fluxes_in)[i_layer].get();
+    return (*m_fluxes_in)[i_layer];
 }
 
 const IFlux* DiffuseElement::fluxOut(size_t i_layer) const
 {
-    return (*m_fluxes_out)[i_layer].get();
+    return (*m_fluxes_out)[i_layer];
 }
 
 DiffuseElement DiffuseElement::pointElement(double x, double y) const
diff --git a/Resample/Element/DiffuseElement.h b/Resample/Element/DiffuseElement.h
index d110d3122d30268280bde8f4168c6d392a99e5c7..6b088549e6bbf6c8025f5cbe9ad57d51c7efa7c9 100644
--- a/Resample/Element/DiffuseElement.h
+++ b/Resample/Element/DiffuseElement.h
@@ -25,12 +25,11 @@
 #include <memory>
 #include <vector>
 
+class Fluxes;
 class IFlux;
 class IPixel;
 class WavevectorInfo;
 
-using Fluxes = std::vector<std::unique_ptr<const IFlux>>;
-
 //! Data stucture containing both input and output of a single detector cell.
 //! @ingroup simulation
 
diff --git a/Resample/Flux/IFlux.h b/Resample/Flux/IFlux.h
index 27c0dfc399b51e94320bfcea459653456ed72a4a..dd8e96a71c2655222ed370ada1f5762fc6b82ddf 100644
--- a/Resample/Flux/IFlux.h
+++ b/Resample/Flux/IFlux.h
@@ -21,8 +21,7 @@
 #define BORNAGAIN_RESAMPLE_FLUX_IFLUX_H
 
 #include "Base/Spin/Spinor.h"
-#include <memory>
-#include <vector>
+#include "Base/Types/OwningVector.h"
 
 //! Interface to access reflection/transmission coefficients.
 //! Realized by ScalarFlux and MatrixFlux.
@@ -45,5 +44,7 @@ public:
     virtual Spinor getKz() const = 0;
 };
 
+class Fluxes : public OwningVector<IFlux> {};
+
 #endif // BORNAGAIN_RESAMPLE_FLUX_IFLUX_H
 #endif // USER_API
diff --git a/Resample/Interparticle/DecouplingApproximationStrategy.cpp b/Resample/Interparticle/DecouplingApproximationStrategy.cpp
index 2039518c18444675d216b1baa32dc916e51eb267..79605fe4964f468e595d0176e6c4cc4ce0bd1980 100644
--- a/Resample/Interparticle/DecouplingApproximationStrategy.cpp
+++ b/Resample/Interparticle/DecouplingApproximationStrategy.cpp
@@ -19,7 +19,7 @@
 #include "Sample/Aggregate/InterferenceNone.h"
 
 DecouplingApproximationStrategy::DecouplingApproximationStrategy(
-    const std::vector<std::unique_ptr<const CoherentFFSum>>& weighted_formfactors,
+    const OwningVector<const CoherentFFSum>& weighted_formfactors,
     const IInterference* iff, SimulationOptions sim_params, bool polarized)
     : IInterparticleStrategy(weighted_formfactors, sim_params, polarized)
     , m_iff(iff ? iff->clone() : new InterferenceNone())
@@ -27,13 +27,10 @@ DecouplingApproximationStrategy::DecouplingApproximationStrategy(
 {
 }
 
-//! Returns the total incoherent and coherent scattering intensity for given kf and
-//! for one particle layout (implied by the given particle form factors).
-//! This is the scalar version
 double DecouplingApproximationStrategy::scalarCalculation(const DiffuseElement& ele) const
 {
     double intensity = 0.0;
-    complex_t amplitude = complex_t(0.0, 0.0);
+    complex_t amplitude = 0;
     for (const auto& ffw : m_weighted_formfactors) {
         const complex_t ff = ffw->summedFF(ele);
         if (std::isnan(ff.real()))
@@ -43,12 +40,12 @@ double DecouplingApproximationStrategy::scalarCalculation(const DiffuseElement&
         amplitude += fraction * ff;
         intensity += fraction * std::norm(ff);
     }
-    const double amplitude_norm = std::norm(amplitude); // squared magnitude
-    const double coherence_factor = m_iff->structureFactor(ele.meanQ());
-    return intensity + amplitude_norm * (coherence_factor - 1.0);
+    // Renaud, Lazzari, Leroy 2009, eq. (160).
+    // Incoherent cross section is intensity - norm(amplitude).
+    // Coherent cross section is S_q*norm(amplitude).
+    return intensity + (m_iff->structureFactor(ele.meanQ()) - 1) * std::norm(amplitude);
 }
 
-//! This is the polarized version
 double DecouplingApproximationStrategy::polarizedCalculation(const DiffuseElement& ele) const
 {
     SpinMatrix mean_intensity;
@@ -70,6 +67,5 @@ double DecouplingApproximationStrategy::polarizedCalculation(const DiffuseElemen
     const SpinMatrix intensity_matrix = polarization_handler.analyzerMatrix() * mean_intensity;
     const double amplitude_trace = std::abs(amplitude_matrix.trace());
     const double intensity_trace = std::abs(intensity_matrix.trace());
-    const double coherence_factor = m_iff->structureFactor(ele.meanQ());
-    return intensity_trace + amplitude_trace * (coherence_factor - 1.0);
+    return intensity_trace + (m_iff->structureFactor(ele.meanQ()) - 1) * amplitude_trace;
 }
diff --git a/Resample/Interparticle/DecouplingApproximationStrategy.h b/Resample/Interparticle/DecouplingApproximationStrategy.h
index 204aea17ee07f84c16023184c48b295953f62f15..f0a2385f80e9ce95dc1a512ae39d5c8b22dcb3fd 100644
--- a/Resample/Interparticle/DecouplingApproximationStrategy.h
+++ b/Resample/Interparticle/DecouplingApproximationStrategy.h
@@ -30,11 +30,15 @@ class DiffuseElement;
 class DecouplingApproximationStrategy : public IInterparticleStrategy {
 public:
     DecouplingApproximationStrategy(
-        const std::vector<std::unique_ptr<const CoherentFFSum>>& weighted_formfactors,
+        const OwningVector<const CoherentFFSum>& weighted_formfactors,
         const IInterference* iff, SimulationOptions sim_params, bool polarized);
 
 private:
+    //! Returns the total scalar incoherent and coherent scattering intensity
+    //! for given kf and for one particle layout (implied by the given particle form factors).
     double scalarCalculation(const DiffuseElement& ele) const override;
+    //! Returns the total polarized incoherent and coherent scattering intensity
+    //! for given kf and for one particle layout (implied by the given particle form factors).
     double polarizedCalculation(const DiffuseElement& ele) const override;
 
     const std::unique_ptr<IInterference> m_iff;
diff --git a/Resample/Interparticle/IInterparticleStrategy.cpp b/Resample/Interparticle/IInterparticleStrategy.cpp
index 50ec272d56698f1a973d450561cc6775dac0a43e..fb29f866fd35f0b919410cc985eb83a2a7bc0e8f 100644
--- a/Resample/Interparticle/IInterparticleStrategy.cpp
+++ b/Resample/Interparticle/IInterparticleStrategy.cpp
@@ -19,7 +19,7 @@
 #include "Resample/Element/DiffuseElement.h"
 
 IInterparticleStrategy::IInterparticleStrategy(
-    const std::vector<std::unique_ptr<const CoherentFFSum>>& weighted_formfactors,
+    const OwningVector<const CoherentFFSum>& weighted_formfactors,
     const SimulationOptions& sim_params, bool polarized)
     : m_weighted_formfactors(weighted_formfactors)
     , m_options(sim_params)
diff --git a/Resample/Interparticle/IInterparticleStrategy.h b/Resample/Interparticle/IInterparticleStrategy.h
index 12c7afca000459294b772abf45668c3f42902bc8..82911cce2442ca2ae1f5ff6fab4f455a9fdfeb71 100644
--- a/Resample/Interparticle/IInterparticleStrategy.h
+++ b/Resample/Interparticle/IInterparticleStrategy.h
@@ -21,6 +21,7 @@
 #define BORNAGAIN_RESAMPLE_INTERPARTICLE_IINTERPARTICLESTRATEGY_H
 
 #include "Resample/Options/SimulationOptions.h"
+#include "Base/Types/OwningVector.h"
 #include <heinz/Complex.h>
 #include <memory>
 #include <vector>
@@ -41,7 +42,7 @@ class DiffuseElement;
 class IInterparticleStrategy {
 public:
     IInterparticleStrategy(
-        const std::vector<std::unique_ptr<const CoherentFFSum>>& weighted_formfactors,
+        const OwningVector<const CoherentFFSum>& weighted_formfactors,
         const SimulationOptions& sim_params, bool polarized);
     virtual ~IInterparticleStrategy();
 
@@ -49,7 +50,7 @@ public:
     double evaluate(const DiffuseElement& ele) const;
 
 protected:
-    const std::vector<std::unique_ptr<const CoherentFFSum>>& m_weighted_formfactors;
+    const OwningVector<const CoherentFFSum>& m_weighted_formfactors;
     const SimulationOptions m_options;
 
 private:
diff --git a/Resample/Interparticle/SSCAStrategy.cpp b/Resample/Interparticle/SSCAStrategy.cpp
index 9677f6cb308340485b7c0f28477645430d8a146f..17d6eadb922959c22e451589c84509515450954d 100644
--- a/Resample/Interparticle/SSCAStrategy.cpp
+++ b/Resample/Interparticle/SSCAStrategy.cpp
@@ -19,7 +19,7 @@
 
 namespace {
 
-double meanRadius(const std::vector<std::unique_ptr<const CoherentFFSum>>& weighted_formfactors)
+double meanRadius(const OwningVector<const CoherentFFSum>& weighted_formfactors)
 {
     double result = 0.0;
     for (const auto& ffw : weighted_formfactors)
@@ -31,7 +31,7 @@ double meanRadius(const std::vector<std::unique_ptr<const CoherentFFSum>>& weigh
 
 
 SSCAStrategy::SSCAStrategy(
-    const std::vector<std::unique_ptr<const CoherentFFSum>>& weighted_formfactors,
+    const OwningVector<const CoherentFFSum>& weighted_formfactors,
     const InterferenceRadialParaCrystal* iff, SimulationOptions sim_params, bool polarized,
     double kappa)
     : IInterparticleStrategy(weighted_formfactors, sim_params, polarized)
@@ -98,7 +98,7 @@ double SSCAStrategy::polarizedCalculation(const DiffuseElement& ele) const
 }
 
 complex_t SSCAStrategy::getCharacteristicSizeCoupling(
-    double qp, const std::vector<std::unique_ptr<const CoherentFFSum>>& ff_wrappers) const
+    double qp, const OwningVector<const CoherentFFSum>& ff_wrappers) const
 {
     complex_t result = 0;
     for (const auto& ffw : ff_wrappers)
diff --git a/Resample/Interparticle/SSCAStrategy.h b/Resample/Interparticle/SSCAStrategy.h
index 856b2727a5aa6e02301d4cf4670c98c36143639f..d8b38d3cd4d4a5ed4fb7eee494af707b056ce36f 100644
--- a/Resample/Interparticle/SSCAStrategy.h
+++ b/Resample/Interparticle/SSCAStrategy.h
@@ -30,7 +30,7 @@ class DiffuseElement;
 
 class SSCAStrategy : public IInterparticleStrategy {
 public:
-    SSCAStrategy(const std::vector<std::unique_ptr<const CoherentFFSum>>& weighted_formfactors,
+    SSCAStrategy(const OwningVector<const CoherentFFSum>& weighted_formfactors,
                  const InterferenceRadialParaCrystal* iff, SimulationOptions sim_params,
                  bool polarized, double kappa);
 
@@ -39,7 +39,7 @@ private:
     double polarizedCalculation(const DiffuseElement& ele) const override;
 
     complex_t getCharacteristicSizeCoupling(
-        double qp, const std::vector<std::unique_ptr<const CoherentFFSum>>& ff_wrappers) const;
+        double qp, const OwningVector<const CoherentFFSum>& ff_wrappers) const;
     complex_t calculatePositionOffsetPhase(double qp, double radial_extension) const;
 
     const std::unique_ptr<InterferenceRadialParaCrystal> m_iff;
diff --git a/Resample/Processed/ReLayout.cpp b/Resample/Processed/ReLayout.cpp
index c1bdb5cda9ec3374085f02bd4d4e277b91bfaaea..b5f801ab14bcd0bc7eb8d963ab335b9681dc2027 100644
--- a/Resample/Processed/ReLayout.cpp
+++ b/Resample/Processed/ReLayout.cpp
@@ -26,7 +26,7 @@ namespace {
 //  ************************************************************************************************
 
 reLayout::reLayout(double surface_density,
-                   std::vector<std::unique_ptr<const CoherentFFSum>>&& formfactors,
+                   OwningVector<const CoherentFFSum>&& formfactors,
                    const IInterference* iff, std::map<size_t, Admixtures>&& slice2admixtures)
     : m_surface_density(surface_density)
     , m_formfactors(std::move(formfactors))
diff --git a/Resample/Processed/ReLayout.h b/Resample/Processed/ReLayout.h
index fcda652b5440663747f60f7bb4d5c82fa018d994..85cbbb17be29c00afe4ccea1c83684f4c2b32922 100644
--- a/Resample/Processed/ReLayout.h
+++ b/Resample/Processed/ReLayout.h
@@ -20,6 +20,7 @@
 #ifndef BORNAGAIN_RESAMPLE_PROCESSED_RELAYOUT_H
 #define BORNAGAIN_RESAMPLE_PROCESSED_RELAYOUT_H
 
+#include "Base/Types/OwningVector.h"
 #include <map>
 #include <memory>
 #include <vector>
@@ -35,23 +36,20 @@ class Admixtures;
 class reLayout {
 public:
     reLayout(double surface_density,
-             std::vector<std::unique_ptr<const CoherentFFSum>>&& formfactors,
+             OwningVector<const CoherentFFSum>&& formfactors,
              const IInterference* iff, std::map<size_t, Admixtures>&& slice2admixtures);
     reLayout(reLayout&& other);
 
     ~reLayout();
 
     double surfaceDensity() const { return m_surface_density; }
-    const std::vector<std::unique_ptr<const CoherentFFSum>>& formfactorList() const
-    {
-        return m_formfactors;
-    }
+    const OwningVector<const CoherentFFSum>& formfactorList() const { return m_formfactors; }
     const IInterference* interferenceFunction() const { return m_iff.get(); }
     const std::map<size_t, Admixtures>& regionMap() const { return m_slice2admixtures; }
 
 private:
     const double m_surface_density;
-    std::vector<std::unique_ptr<const CoherentFFSum>> m_formfactors;
+    OwningVector<const CoherentFFSum> m_formfactors;
     std::unique_ptr<const IInterference> m_iff;
     std::map<size_t, Admixtures> m_slice2admixtures;
 };
diff --git a/Resample/Processed/ReSample.cpp b/Resample/Processed/ReSample.cpp
index 9a97c3614227b2956d1f834769aa389c56a5c51f..35c8589c5b7e6acb38d11f41bcd88f4880cd8ae5 100644
--- a/Resample/Processed/ReSample.cpp
+++ b/Resample/Processed/ReSample.cpp
@@ -82,15 +82,13 @@ Material createAveragedMaterial(const Material& layer_mat, const Admixtures& adm
         return RefractiveMaterial(avge_name, avr_mat_data.real(), avr_mat_data.imag(),
                                   avge_magnetization);
     }
-    if (common_type == MATERIAL_TYPES::MaterialBySLD) {
-        complex_t (*avrData)(const Material&) = [](const Material& mat) {
-            return mat.materialData();
-        };
-        const auto avr_mat_data = averageData<complex_t>(layer_mat, admixtures, avrData);
-        return MaterialBySLD(avge_name, avr_mat_data.real(), avr_mat_data.imag(),
-                             avge_magnetization);
-    }
-    ASSERT(0);
+    ASSERT(common_type == MATERIAL_TYPES::MaterialBySLD);
+    complex_t (*avrData)(const Material&) = [](const Material& mat) {
+        return mat.materialData();
+    };
+    const auto avr_mat_data = averageData<complex_t>(layer_mat, admixtures, avrData);
+    return MaterialBySLD(avge_name, avr_mat_data.real(), avr_mat_data.imag(),
+                         avge_magnetization);
 }
 
 void checkVolumeFractions(const Admixtures& admixtures)
@@ -225,23 +223,24 @@ reLayout makereLayout(const ParticleLayout& layout, const SliceStack& slices, do
     ASSERT(layout_abundance > 0);
     const double surface_density = layout.weightedParticleSurfaceDensity();
 
-    std::vector<std::unique_ptr<const CoherentFFSum>> formfactors;
+    OwningVector<const CoherentFFSum> formfactors;
     std::map<size_t, Admixtures> slice2admixtures;
 
     for (const auto& particle : layout.particles()) {
 
         std::vector<std::shared_ptr<const SumDWBA>> terms;
 
-        for (const auto& subparticle : particle->decompose()) {
+        for (const auto* subparticle : particle->decompose()) {
             const auto slice_indices = SliceIndexSpan(*subparticle, slices, z_ref);
             bool single_layer = (slice_indices.first == slice_indices.second);
             double z0 = slices.at(0).zBottom();
+            std::unique_ptr<IParticle> myparticle(subparticle->clone());
             for (size_t iSlice = slice_indices.first; iSlice < slice_indices.second + 1; ++iSlice) {
                 const Slice& slice = slices[iSlice];
                 double z_top_i = iSlice == 0 ? 0 : slice.zTop() - z0;
                 R3 translation(0.0, 0.0, z_ref - z_top_i);
                 z_ref = z_top_i; // subparticle now has coordinates relative to z_top_i
-                subparticle->translate(translation);
+                myparticle->translate(translation);
                 // if subparticle is contained in this layer, set limits to infinite:
                 ZLimits limits;
                 if (!single_layer) {
@@ -249,7 +248,7 @@ reLayout makereLayout(const ParticleLayout& layout, const SliceStack& slices, do
                     limits = {slice.zBottom() - z1, slice.zTop() - z1};
                 }
                 ParticleInSlice pis =
-                    Compute::Slicing::createParticleInSlice(subparticle.get(), limits);
+                    Compute::Slicing::createParticleInSlice(myparticle.get(), limits);
                 pis.particleSlice->setAmbientMaterial(slices.at(iSlice).material());
 
                 std::unique_ptr<SumDWBA> computer;
@@ -270,8 +269,8 @@ reLayout makereLayout(const ParticleLayout& layout, const SliceStack& slices, do
             }
         }
 
-        formfactors.emplace_back(
-            std::make_unique<CoherentFFSum>(particle->abundance() / layout_abundance, terms));
+        formfactors.emplace_back(new CoherentFFSum(
+                                     particle->abundance() / layout_abundance, terms));
     }
 
     const auto* iff = layout.interferenceFunction();
diff --git a/Resample/Processed/ReSample.h b/Resample/Processed/ReSample.h
index a9596c5ede56aec42568e00f132dfb1e4f613b0f..2b71f47c6c1f8d321c5e101516488909ff63b765 100644
--- a/Resample/Processed/ReSample.h
+++ b/Resample/Processed/ReSample.h
@@ -25,14 +25,12 @@
 #include <memory>
 #include <vector>
 
-class IFlux;
+class Fluxes;
 class Material;
 class MultiLayer;
 class reLayout;
 class SimulationOptions;
 
-using Fluxes = std::vector<std::unique_ptr<const IFlux>>;
-
 //! Data structure that contains all the necessary data for scattering calculations.
 //!
 //! If the usage of average materials is requested, layers and particles are sliced into multiple
diff --git a/Resample/Processed/Slicer.cpp b/Resample/Processed/Slicer.cpp
index 10a9be5fccd12ee1f9430d4e8ced10b08937c642..014ceb02012526187db6bbabf99dc8a6dbbd0670 100644
--- a/Resample/Processed/Slicer.cpp
+++ b/Resample/Processed/Slicer.cpp
@@ -236,8 +236,8 @@ IReParticle* processBasis(const IParticle* basis)
         const auto& particles = b->decompose();
         ASSERT(!particles.empty());
         auto* result = new ReCompound;
-        for (const auto& particle : particles) {
-            std::unique_ptr<IReParticle> re(processBasis(particle.get()));
+        for (const auto* particle : particles) {
+            std::unique_ptr<IReParticle> re(processBasis(particle));
             result->addFormFactor(*re);
         }
         return result;
@@ -335,8 +335,8 @@ ParticleInSlice Compute::Slicing::createParticleInSlice(const IParticle* particl
 
         Admixtures& regions = result.admixtures;
         ASSERT(regions.empty());
-        for (const auto& particle : crystal->basis()->decompose()) {
-            ParticleInSlice pis = createParticleInSlice(particle.get(), {});
+        for (const auto* particle : crystal->basis()->decompose()) {
+            ParticleInSlice pis = createParticleInSlice(particle, {});
             regions.insert(regions.end(), pis.admixtures.begin(), pis.admixtures.end());
         }
         for (auto& region : regions)
@@ -353,9 +353,9 @@ ZLimits Compute::Slicing::zSpan(const IParticle* particle)
     if (const auto* p = dynamic_cast<const ParticleComposition*>(particle)) {
         const auto subparticles = p->decompose();
         ASSERT(subparticles.size() > 0);
-        ZLimits result = zSpan(subparticles[0].get());
-        for (const auto& subparticle : subparticles)
-            result = ZLimits::enclosingInterval(result, zSpan(subparticle.get()));
+        ZLimits result = zSpan(subparticles[0]);
+        for (const auto* subparticle : subparticles)
+            result = ZLimits::enclosingInterval(result, zSpan(subparticle));
         return result;
     }
     const ParticleInSlice pis = createParticleInSlice(particle, ZLimits{});
diff --git a/Resample/Specular/ComputeFluxMagnetic.cpp b/Resample/Specular/ComputeFluxMagnetic.cpp
index 470c9c2e1421f4bd2e675ca54d0136fed79c6482..e15980dcd9d95dc0b375e7d5d3d10d1332547026 100644
--- a/Resample/Specular/ComputeFluxMagnetic.cpp
+++ b/Resample/Specular/ComputeFluxMagnetic.cpp
@@ -183,7 +183,7 @@ Fluxes Compute::SpecularMagnetic::fluxes(const SliceStack& slices, const R3& k,
 
     Fluxes result;
     for (auto& coeff : computeFlux(slices, kz, slices.roughnessModel(), forward))
-        result.emplace_back(std::make_unique<const MatrixFlux>(coeff));
+        result.emplace_back(new MatrixFlux(coeff));
 
     return result;
 }
diff --git a/Resample/Specular/ComputeFluxMagnetic.h b/Resample/Specular/ComputeFluxMagnetic.h
index da3201d69ba39f16f9e04563df882c424cebf44f..256cac3e3b7930e9916599c08e0acfd1f64529fb 100644
--- a/Resample/Specular/ComputeFluxMagnetic.h
+++ b/Resample/Specular/ComputeFluxMagnetic.h
@@ -21,15 +21,12 @@
 #define BORNAGAIN_RESAMPLE_SPECULAR_COMPUTEFLUXMAGNETIC_H
 
 #include "Base/Spin/SpinMatrix.h"
-#include "Sample/Multilayer/RoughnessModels.h"
 #include <heinz/Complex.h>
 #include <heinz/Vectors3D.h>
-#include <memory>
 #include <vector>
 
-class IFlux;
+class Fluxes;
 class SliceStack;
-using Fluxes = std::vector<std::unique_ptr<const IFlux>>;
 
 //! Methods to compute polarized propagation directions and fluxes as function of slice.
 //!
diff --git a/Resample/Specular/ComputeFluxScalar.cpp b/Resample/Specular/ComputeFluxScalar.cpp
index 450fd80e76a17c2dea73e0e23aa2c3a192bbc6b9..8ee5f1d983361489009a6c35e60110b49b733083 100644
--- a/Resample/Specular/ComputeFluxScalar.cpp
+++ b/Resample/Specular/ComputeFluxScalar.cpp
@@ -129,7 +129,7 @@ Fluxes Compute::SpecularScalar::fluxes(const SliceStack& slices, const R3& k)
 
     Fluxes result;
     for (size_t i = 0; i < kz.size(); ++i)
-        result.emplace_back(std::make_unique<const ScalarFlux>(kz[i], TR[i]));
+        result.emplace_back(new ScalarFlux(kz[i], TR[i]));
     return result;
 }
 
diff --git a/Resample/Specular/ComputeFluxScalar.h b/Resample/Specular/ComputeFluxScalar.h
index f434dfd8a5cc2aec2e9829dff854eb8e7dc32b15..49683c1821669fe0e09722e35c320606908b393b 100644
--- a/Resample/Specular/ComputeFluxScalar.h
+++ b/Resample/Specular/ComputeFluxScalar.h
@@ -23,12 +23,10 @@
 #include "Sample/Multilayer/RoughnessModels.h"
 #include <heinz/Complex.h>
 #include <heinz/Vectors3D.h>
-#include <memory>
 #include <vector>
 
-class IFlux;
+class Fluxes;
 class SliceStack;
-using Fluxes = std::vector<std::unique_ptr<const IFlux>>;
 
 //! Methods to compute scalar propagation directions and fluxes as function of slice.
 
diff --git a/Sample/Multilayer/Layer.cpp b/Sample/Multilayer/Layer.cpp
index 739a3d12f1e61f5ef2c1dd8edf5c5b69b1243882..1b4082caf68b6bf02b0dfbd4c9f4d42f3c8e44a0 100644
--- a/Sample/Multilayer/Layer.cpp
+++ b/Sample/Multilayer/Layer.cpp
@@ -42,8 +42,8 @@ Layer* Layer::clone() const
 std::vector<const INode*> Layer::nodeChildren() const
 {
     std::vector<const INode*> result;
-    for (const auto& layout : m_layouts)
-        result.push_back(layout.get());
+    for (const auto* layout : m_layouts)
+        result.push_back(layout);
     return result;
 }
 
@@ -55,8 +55,8 @@ void Layer::addLayout(const ParticleLayout& layout)
 std::vector<const ParticleLayout*> Layer::layouts() const
 {
     std::vector<const ParticleLayout*> result;
-    for (const auto& layout : m_layouts)
-        result.push_back(layout.get());
+    for (const auto* layout : m_layouts)
+        result.push_back(layout);
     return result;
 }
 
diff --git a/Sample/Multilayer/Layer.h b/Sample/Multilayer/Layer.h
index 4d09e9eed21bcb96af8a0ab8b14f15d6f923aec9..9f01c2fcb4223c8857d7b1bb4081e40ff3d28e28 100644
--- a/Sample/Multilayer/Layer.h
+++ b/Sample/Multilayer/Layer.h
@@ -16,6 +16,7 @@
 #define BORNAGAIN_SAMPLE_MULTILAYER_LAYER_H
 
 #include "Sample/Material/Material.h"
+#include "Base/Types/OwningVector.h"
 #include "Sample/Scattering/ISampleNode.h"
 
 class ParticleLayout;
@@ -47,10 +48,10 @@ public:
     std::string validate() const override;
 
 private:
-    Material m_material;                                    //!< material
-    R3 m_B_field;                                           //!< cached value of magnetic induction
-    double m_thickness;                                     //!< layer thickness in nanometers
-    std::vector<std::unique_ptr<ParticleLayout>> m_layouts; //!< independent layouts in this layer
+    Material m_material;                    //!< material
+    R3 m_B_field;                           //!< cached value of magnetic induction
+    double m_thickness;                     //!< layer thickness in nanometers
+    OwningVector<ParticleLayout> m_layouts; //!< independent layouts in this layer
     unsigned int m_n_slices = 1; //!< number of slices to create for graded layer approach
 };
 
diff --git a/Sample/Particle/IParticle.cpp b/Sample/Particle/IParticle.cpp
index 500a5b7966355e7d35a7f0c6ea8c43dfda6f8871..ae8cd87089cd2d157e7cc4d7a7b5ae87a4da8e35 100644
--- a/Sample/Particle/IParticle.cpp
+++ b/Sample/Particle/IParticle.cpp
@@ -49,9 +49,9 @@ IParticle* IParticle::rotate(const IRotation& rotation)
 }
 
 #ifndef SWIG
-std::vector<std::unique_ptr<IParticle>> IParticle::decompose() const
+OwningVector<IParticle> IParticle::decompose() const
 {
-    std::vector<std::unique_ptr<IParticle>> result;
+    OwningVector<IParticle> result;
     result.emplace_back(this->clone());
     return result;
 }
diff --git a/Sample/Particle/IParticle.h b/Sample/Particle/IParticle.h
index 456922472ad64805e1527693b838164931eb8664..5fbc0a3a150a90ee2efd58714ce1b83ee3039da2 100644
--- a/Sample/Particle/IParticle.h
+++ b/Sample/Particle/IParticle.h
@@ -17,6 +17,7 @@
 #define BORNAGAIN_SAMPLE_PARTICLE_IPARTICLE_H
 
 #include "Sample/Scattering/ISampleNode.h"
+#include "Base/Types/OwningVector.h"
 #include <heinz/Vectors3D.h>
 #include <memory>
 #include <vector>
@@ -71,7 +72,7 @@ public:
 
 #ifndef SWIG
     //! Decompose in constituent IParticle objects
-    virtual std::vector<std::unique_ptr<IParticle>> decompose() const;
+    virtual OwningVector<IParticle> decompose() const;
 #endif
 
     std::string validate() const override = 0;
diff --git a/Sample/Particle/ParticleComposition.cpp b/Sample/Particle/ParticleComposition.cpp
index 64aa65c20129672e4822fd447fc45ac7592f4907..1d775b22ecb2009bfc162178bc2125485335fa73 100644
--- a/Sample/Particle/ParticleComposition.cpp
+++ b/Sample/Particle/ParticleComposition.cpp
@@ -41,9 +41,9 @@ std::vector<const INode*> ParticleComposition::nodeChildren() const
 }
 
 #ifndef SWIG
-std::vector<std::unique_ptr<IParticle>> ParticleComposition::decompose() const
+OwningVector<IParticle> ParticleComposition::decompose() const
 {
-    std::vector<std::unique_ptr<IParticle>> result;
+    OwningVector<IParticle> result;
     const auto* rot = rotation();
     const auto& translation = particlePosition();
     for (const auto& particle : m_particles) {
diff --git a/Sample/Particle/ParticleComposition.h b/Sample/Particle/ParticleComposition.h
index 543e7e41af879d6a8122702ca2a53fdb2b506ef6..e44937de47d279a81d9b8c69bb7624b329980923 100644
--- a/Sample/Particle/ParticleComposition.h
+++ b/Sample/Particle/ParticleComposition.h
@@ -15,7 +15,6 @@
 #ifndef BORNAGAIN_SAMPLE_PARTICLE_PARTICLECOMPOSITION_H
 #define BORNAGAIN_SAMPLE_PARTICLE_PARTICLECOMPOSITION_H
 
-#include "Base/Types/OwningVector.h"
 #include "Sample/Particle/IParticle.h"
 
 //! A composition of particles at fixed positions
@@ -32,7 +31,7 @@ public:
     std::vector<const INode*> nodeChildren() const override;
 
 #ifndef SWIG
-    std::vector<std::unique_ptr<IParticle>> decompose() const override;
+    OwningVector<IParticle> decompose() const override;
 #endif
 
     void addParticle(const IParticle& particle);
diff --git a/Sim/Computation/DWBAComputation.cpp b/Sim/Computation/DWBAComputation.cpp
index eda9af78687fc8a8fe8a51649e9ee71901aa1ae0..541bb30ff7b0c6f5dacfe69e7235b91e18c40be7 100644
--- a/Sim/Computation/DWBAComputation.cpp
+++ b/Sim/Computation/DWBAComputation.cpp
@@ -26,11 +26,11 @@
 
 namespace {
 
-std::vector<std::unique_ptr<const ParticleLayoutContribution>>
+OwningVector<const ParticleLayoutContribution>
 makeLayoutComputation(const std::vector<reLayout>& layouts, const SimulationOptions& options,
                       bool polarized)
 {
-    std::vector<std::unique_ptr<const ParticleLayoutContribution>> result;
+    OwningVector<const ParticleLayoutContribution> result;
 
     for (const reLayout& layout : layouts)
         result.emplace_back(new ParticleLayoutContribution(layout, options, polarized));
diff --git a/Sim/Computation/DWBAComputation.h b/Sim/Computation/DWBAComputation.h
index c7195c1afb39cb914ce69ecbf714a798c31e95ae..d0edf7bb560902e58887de00dd1f04e0bf836944 100644
--- a/Sim/Computation/DWBAComputation.h
+++ b/Sim/Computation/DWBAComputation.h
@@ -21,6 +21,7 @@
 #define BORNAGAIN_SIM_COMPUTATION_DWBACOMPUTATION_H
 
 #include "Sim/Computation/IComputation.h"
+#include "Base/Types/OwningVector.h"
 #include <vector>
 
 class DiffuseElement;
@@ -53,7 +54,7 @@ private:
     std::vector<DiffuseElement>::iterator m_begin_it, m_end_it;
     const std::unique_ptr<const GISASSpecularContribution> m_specular_contrib;
     const std::unique_ptr<const RoughMultiLayerContribution> m_roughness_contrib;
-    const std::vector<std::unique_ptr<const ParticleLayoutContribution>> m_layout_contribs;
+    const OwningVector<const ParticleLayoutContribution> m_layout_contribs;
 };
 
 #endif // BORNAGAIN_SIM_COMPUTATION_DWBACOMPUTATION_H
diff --git a/Sim/Computation/DepthProbeComputation.cpp b/Sim/Computation/DepthProbeComputation.cpp
index 75ae8e4b58e8e8618403dd552bf250ec80b93566..0b37ab54655bdb45356940627d6302f201f3d06a 100644
--- a/Sim/Computation/DepthProbeComputation.cpp
+++ b/Sim/Computation/DepthProbeComputation.cpp
@@ -55,7 +55,7 @@ void DepthProbeComputation::runProtected()
             z_layer_top = i_layer ? m_re_sample.sliceTopZ(i_layer) : 0;
 
             // get R & T coefficients for current layer
-            const auto* flux = dynamic_cast<const ScalarFlux*>(fluxes[i_layer].get());
+            const auto* flux = dynamic_cast<const ScalarFlux*>(fluxes[i_layer]);
             ASSERT(flux);
             const complex_t R = flux->getScalarR();
             const complex_t T = flux->getScalarT();
diff --git a/Sim/Contrib/ParticleLayoutContribution.cpp b/Sim/Contrib/ParticleLayoutContribution.cpp
index 5a1b8385035323bbda9c498368bf86ded19651ea..cd3f9e446c43914cfe7e896b05303b15244ac238 100644
--- a/Sim/Contrib/ParticleLayoutContribution.cpp
+++ b/Sim/Contrib/ParticleLayoutContribution.cpp
@@ -27,8 +27,7 @@ std::unique_ptr<IInterparticleStrategy> processedInterference(const reLayout& re
 {
     const IInterference* iff = re_layout.interferenceFunction();
 
-    const std::vector<std::unique_ptr<const CoherentFFSum>>& weighted_formfactors =
-        re_layout.formfactorList();
+    const OwningVector<const CoherentFFSum>& weighted_formfactors = re_layout.formfactorList();
 
     const auto* radial_para = dynamic_cast<const InterferenceRadialParaCrystal*>(iff);
     if (radial_para)
diff --git a/Tests/Unit/Resample/RTTest.cpp b/Tests/Unit/Resample/RTTest.cpp
index 12a3d9a1a33aface6a917b26b30bca5cd53ac54b..1f8cb77fa4f8d735e8d4c6626d26b782a0583310 100644
--- a/Tests/Unit/Resample/RTTest.cpp
+++ b/Tests/Unit/Resample/RTTest.cpp
@@ -33,7 +33,7 @@ protected:
     {
         std::vector<ScalarFlux> result;
         for (auto& flux : fluxes)
-            result.push_back(*dynamic_cast<const ScalarFlux*>(flux.get()));
+            result.push_back(*dynamic_cast<const ScalarFlux*>(flux));
         return result;
     }
     const Material air = RefractiveMaterial("Air", 1e-8, 1e-8);
diff --git a/auto/Wrap/doxygenBase.i b/auto/Wrap/doxygenBase.i
index 55d236e7eaf9c7559e3ba3551e0f95f0be54d490..27c75850c3ab198ffbca0c4f4846c5a975f92b29 100644
--- a/auto/Wrap/doxygenBase.i
+++ b/auto/Wrap/doxygenBase.i
@@ -693,9 +693,15 @@ OwningVector::OwningVector
 Constructor that clones elements in given vector. 
 ";
 
+%feature("docstring")  OwningVector::OwningVector "OwningVector< T >::OwningVector(OwningVector &&other)=default
+OwningVector::OwningVector";
+
 %feature("docstring")  OwningVector::~OwningVector "OwningVector< T >::~OwningVector()
 OwningVector::~OwningVector";
 
+%feature("docstring")  OwningVector::reserve "void OwningVector< T >::reserve(size_t n)
+OwningVector::reserve";
+
 %feature("docstring")  OwningVector::emplace_back "void OwningVector< T >::emplace_back(T *e)
 OwningVector::emplace_back";
 
diff --git a/auto/Wrap/doxygenResample.i b/auto/Wrap/doxygenResample.i
index 7424642f075bf12ccf0e0cd8ae9da01574fabc27..34aea93e9609666f76abea53af011eaedaa01c2c 100644
--- a/auto/Wrap/doxygenResample.i
+++ b/auto/Wrap/doxygenResample.i
@@ -33,7 +33,7 @@ Strategy class to compute the total scattering from a particle layout in the dec
 C++ includes: DecouplingApproximationStrategy.h
 ";
 
-%feature("docstring")  DecouplingApproximationStrategy::DecouplingApproximationStrategy "DecouplingApproximationStrategy::DecouplingApproximationStrategy(const std::vector< std::unique_ptr< const CoherentFFSum > > &weighted_formfactors, const IInterference *iff, SimulationOptions sim_params, bool polarized)
+%feature("docstring")  DecouplingApproximationStrategy::DecouplingApproximationStrategy "DecouplingApproximationStrategy::DecouplingApproximationStrategy(const OwningVector< const CoherentFFSum > &weighted_formfactors, const IInterference *iff, SimulationOptions sim_params, bool polarized)
 DecouplingApproximationStrategy::DecouplingApproximationStrategy";
 
 
@@ -130,6 +130,10 @@ Tells if simulation element corresponds to a specular peak.
 ";
 
 
+// File: classFluxes.xml
+%feature("docstring") Fluxes "";
+
+
 // File: classIFlux.xml
 %feature("docstring") IFlux "
 
@@ -183,7 +187,7 @@ Instantiation of child classes takes place in LayoutStrategyBuilder::createStrat
 C++ includes: IInterparticleStrategy.h
 ";
 
-%feature("docstring")  IInterparticleStrategy::IInterparticleStrategy "IInterparticleStrategy::IInterparticleStrategy(const std::vector< std::unique_ptr< const CoherentFFSum > > &weighted_formfactors, const SimulationOptions &sim_params, bool polarized)
+%feature("docstring")  IInterparticleStrategy::IInterparticleStrategy "IInterparticleStrategy::IInterparticleStrategy(const OwningVector< const CoherentFFSum > &weighted_formfactors, const SimulationOptions &sim_params, bool polarized)
 IInterparticleStrategy::IInterparticleStrategy";
 
 %feature("docstring")  IInterparticleStrategy::~IInterparticleStrategy "IInterparticleStrategy::~IInterparticleStrategy()
@@ -467,12 +471,12 @@ Returns scattering amplitude for matrix interactions.
 
 Data structure that contains preprocessed data for a single layout.
 
-If particles in the layout crossed the limits of the layer slices, these particles will be sliced themselves.
+It is set by the preprocessor makereLayout in  ReSample.cpp.
 
 C++ includes: ReLayout.h
 ";
 
-%feature("docstring")  reLayout::reLayout "reLayout::reLayout(double surface_density, std::vector< std::unique_ptr< const CoherentFFSum > > &&formfactors, const IInterference *iff, std::map< size_t, Admixtures > &&slice2admixtures)
+%feature("docstring")  reLayout::reLayout "reLayout::reLayout(double surface_density, OwningVector< const CoherentFFSum > &&formfactors, const IInterference *iff, std::map< size_t, Admixtures > &&slice2admixtures)
 reLayout::reLayout";
 
 %feature("docstring")  reLayout::reLayout "reLayout::reLayout(reLayout &&other)
@@ -484,7 +488,7 @@ reLayout::~reLayout";
 %feature("docstring")  reLayout::surfaceDensity "double reLayout::surfaceDensity() const
 reLayout::surfaceDensity";
 
-%feature("docstring")  reLayout::formfactorList "const std::vector< std::unique_ptr< const CoherentFFSum > > & reLayout::formfactorList() const
+%feature("docstring")  reLayout::formfactorList "const OwningVector< const CoherentFFSum > & reLayout::formfactorList() const
 reLayout::formfactorList";
 
 %feature("docstring")  reLayout::interferenceFunction "const IInterference * reLayout::interferenceFunction() const
@@ -945,7 +949,7 @@ Strategy class to compute the total scattering from a particle layout in the siz
 C++ includes: SSCAStrategy.h
 ";
 
-%feature("docstring")  SSCAStrategy::SSCAStrategy "SSCAStrategy::SSCAStrategy(const std::vector< std::unique_ptr< const CoherentFFSum > > &weighted_formfactors, const InterferenceRadialParaCrystal *iff, SimulationOptions sim_params, bool polarized, double kappa)
+%feature("docstring")  SSCAStrategy::SSCAStrategy "SSCAStrategy::SSCAStrategy(const OwningVector< const CoherentFFSum > &weighted_formfactors, const InterferenceRadialParaCrystal *iff, SimulationOptions sim_params, bool polarized, double kappa)
 SSCAStrategy::SSCAStrategy";
 
 
diff --git a/auto/Wrap/doxygenSample.i b/auto/Wrap/doxygenSample.i
index 346dd16543a9846c06993c30c52d916c87a36bcf..412b3ba86c7a36a7da683130b407e4fbbd1c8ce6 100644
--- a/auto/Wrap/doxygenSample.i
+++ b/auto/Wrap/doxygenSample.i
@@ -1993,7 +1993,7 @@ IParticle::rotate
 Rotates the particle, and returns this. 
 ";
 
-%feature("docstring")  IParticle::decompose "std::vector< std::unique_ptr< IParticle > > IParticle::decompose() const
+%feature("docstring")  IParticle::decompose "OwningVector< IParticle > IParticle::decompose() const
 IParticle::decompose
 Decompose in constituent  IParticle objects. 
 ";
@@ -3277,7 +3277,7 @@ ParticleComposition::className";
 %feature("docstring")  ParticleComposition::nodeChildren "std::vector< const INode * > ParticleComposition::nodeChildren() const override
 ParticleComposition::nodeChildren";
 
-%feature("docstring")  ParticleComposition::decompose "std::vector< std::unique_ptr< IParticle > > ParticleComposition::decompose() const override
+%feature("docstring")  ParticleComposition::decompose "OwningVector< IParticle > ParticleComposition::decompose() const override
 ParticleComposition::decompose
 Decompose in constituent  IParticle objects. 
 ";