diff --git a/Base/Element/DiffuseElement.cpp b/Base/Element/DiffuseElement.cpp
index 5c468579d93fdecc90a57151bfd99f400205b561..d035d29f27a22c737cbd43ce08eeba974e9f56f0 100644
--- a/Base/Element/DiffuseElement.cpp
+++ b/Base/Element/DiffuseElement.cpp
@@ -23,7 +23,7 @@ DiffuseElement::DiffuseElement(double wavelength, double alpha_i, double phi_i,
                                const Eigen::Matrix2cd& beam_polpair,
                                const Eigen::Matrix2cd& analyzer, bool isSpecular_,
                                const Fluxes* const fluxes_in, const Fluxes* const fluxes_out)
-    : m_polpair(beam_polpair, analyzer)
+    : IElement({beam_polpair, analyzer})
     , m_wavelength(wavelength)
     , m_alpha_i(alpha_i)
     , m_phi_i(phi_i)
@@ -38,7 +38,7 @@ DiffuseElement::DiffuseElement(double wavelength, double alpha_i, double phi_i,
 }
 
 DiffuseElement::DiffuseElement(const DiffuseElement& other)
-    : m_polpair(other.m_polpair)
+    : IElement(other.m_polpair)
     , m_wavelength(other.m_wavelength)
     , m_alpha_i(other.m_alpha_i)
     , m_phi_i(other.m_phi_i)
diff --git a/Base/Element/DiffuseElement.h b/Base/Element/DiffuseElement.h
index b5a3e133559284623afbe4294469eebab0a640a2..1db54050899413b2a1ba6e6c7e6821e0422eb079 100644
--- a/Base/Element/DiffuseElement.h
+++ b/Base/Element/DiffuseElement.h
@@ -20,7 +20,7 @@
 #ifndef BORNAGAIN_BASE_ELEMENT_DIFFUSEELEMENT_H
 #define BORNAGAIN_BASE_ELEMENT_DIFFUSEELEMENT_H
 
-#include "Base/Element/PolarizerPair.h"
+#include "Base/Element/IElement.h"
 #include "Base/Vector/Vectors3D.h"
 #include <memory>
 
@@ -33,7 +33,7 @@ using Fluxes = std::vector<std::unique_ptr<const IFlux>>;
 //! Data stucture containing both input and output of a single detector cell.
 //! @ingroup simulation
 
-class DiffuseElement {
+class DiffuseElement : public IElement {
 public:
     DiffuseElement(double wavelength, double alpha_i, double phi_i, std::unique_ptr<IPixel> pixel,
                    const Eigen::Matrix2cd& beam_polpair, const Eigen::Matrix2cd& analyzer,
@@ -81,7 +81,6 @@ public:
 private:
     kvector_t getKf(double x, double y) const;
 
-    const PolarizerPair m_polpair;
     const double m_wavelength; //!< wavelength of beam
     const double m_alpha_i;    //!< incident grazing angle
     const double m_phi_i;      //!< incident angle in xy plane
diff --git a/Core/Element/DepthProbeElement.cpp b/Core/Element/DepthProbeElement.cpp
index 1585e21b742f80528ebe0eeebb308bf7c2cf7dfc..c70888e1ff3f029c1f9b4fcba7d9de20b3428d2a 100644
--- a/Core/Element/DepthProbeElement.cpp
+++ b/Core/Element/DepthProbeElement.cpp
@@ -19,7 +19,8 @@
 const double phi_i_0 = 0.0;
 
 DepthProbeElement::DepthProbeElement(double wavelength, double alpha_i, const IAxis* z_positions)
-    : m_wavelength(wavelength)
+    : IElement(PolarizerPair())
+    , m_wavelength(wavelength)
     , m_alpha_i(alpha_i)
     , m_z_positions(z_positions)
     , m_calculation_flag(true)
@@ -31,7 +32,8 @@ DepthProbeElement::DepthProbeElement(double wavelength, double alpha_i, const IA
 }
 
 DepthProbeElement::DepthProbeElement(const DepthProbeElement& other)
-    : m_wavelength(other.m_wavelength)
+    : IElement(PolarizerPair())
+    , m_wavelength(other.m_wavelength)
     , m_alpha_i(other.m_alpha_i)
     , m_intensities(other.m_intensities)
     , m_z_positions(other.m_z_positions)
@@ -40,7 +42,8 @@ DepthProbeElement::DepthProbeElement(const DepthProbeElement& other)
 }
 
 DepthProbeElement::DepthProbeElement(DepthProbeElement&& other) noexcept
-    : m_wavelength(other.m_wavelength)
+    : IElement(PolarizerPair())
+    , m_wavelength(other.m_wavelength)
     , m_alpha_i(other.m_alpha_i)
     , m_intensities(std::move(other.m_intensities))
     , m_z_positions(other.m_z_positions)
diff --git a/Core/Element/DepthProbeElement.h b/Core/Element/DepthProbeElement.h
index b32fc77dd202d029ad875f2fcd65695ec8a95a0e..068a9200507337dd46cff73b8d5d927616e53a85 100644
--- a/Core/Element/DepthProbeElement.h
+++ b/Core/Element/DepthProbeElement.h
@@ -20,13 +20,13 @@
 #ifndef BORNAGAIN_CORE_ELEMENT_DEPTHPROBEELEMENT_H
 #define BORNAGAIN_CORE_ELEMENT_DEPTHPROBEELEMENT_H
 
-#include <valarray>
-
+#include "Base/Element/IElement.h"
 #include "Base/Vector/Vectors3D.h"
+#include <valarray>
 
 class IAxis;
 
-class DepthProbeElement {
+class DepthProbeElement : public IElement {
 public:
     DepthProbeElement(double wavelength, double alpha_i, const IAxis* z_positions);
     DepthProbeElement(const DepthProbeElement& other);
diff --git a/Core/Element/SpecularElement.cpp b/Core/Element/SpecularElement.cpp
index 856c6ab9e5d6272d2e18699873c2acb21b8c987d..d2fac539ad7147d3924cf8a6f6fb27e168176442 100644
--- a/Core/Element/SpecularElement.cpp
+++ b/Core/Element/SpecularElement.cpp
@@ -19,8 +19,8 @@
 #include "Resample/Slice/KzComputation.h"
 
 SpecularElement::SpecularElement(double kz, const Instrument& instrument, bool computable)
-    : m_polpair(instrument.beam().getPolarization(),
-                     instrument.detector().detectionProperties().analyzerOperator())
+    : IElement({instrument.beam().getPolarization(),
+            instrument.detector().detectionProperties().analyzerOperator()})
     , m_intensity(0.0)
     , m_computable(computable)
     , m_kz_computation(
@@ -30,8 +30,8 @@ SpecularElement::SpecularElement(double kz, const Instrument& instrument, bool c
 
 SpecularElement::SpecularElement(double wavelength, double alpha, const Instrument& instrument,
                                  bool computable)
-    : m_polpair(instrument.beam().getPolarization(),
-                     instrument.detector().detectionProperties().analyzerOperator())
+    : IElement({instrument.beam().getPolarization(),
+            instrument.detector().detectionProperties().analyzerOperator()})
     , m_intensity(0.0)
     , m_computable(computable)
     , m_kz_computation([k = vecOfLambdaAlphaPhi(wavelength, alpha, 0.0)](const SliceStack& slices) {
diff --git a/Core/Element/SpecularElement.h b/Core/Element/SpecularElement.h
index 9790b830763c5e875301d24e793fc6d72ed2ad19..a2cc90a5995e758d4b687279176f281602f1ffab 100644
--- a/Core/Element/SpecularElement.h
+++ b/Core/Element/SpecularElement.h
@@ -20,7 +20,7 @@
 #ifndef BORNAGAIN_CORE_ELEMENT_SPECULARELEMENT_H
 #define BORNAGAIN_CORE_ELEMENT_SPECULARELEMENT_H
 
-#include "Base/Element/PolarizerPair.h"
+#include "Base/Element/IElement.h"
 #include "Base/Vector/Vectors3D.h"
 #include <memory>
 #include <vector>
@@ -31,7 +31,7 @@ class SliceStack;
 //! Data stucture containing both input and output of a single image pixel for specular simulation.
 //! @ingroup simulation
 
-class SpecularElement {
+class SpecularElement : public IElement {
 public:
     SpecularElement(double kz, const Instrument& instrument, bool computable);
     SpecularElement(double wavelength, double alpha, const Instrument& instrument, bool computable);
@@ -54,7 +54,6 @@ public:
     std::vector<complex_t> produceKz(const SliceStack& slices);
 
 private:
-    const PolarizerPair m_polpair;
     double m_intensity; //!< simulated intensity for detector cell
     const bool m_computable;
     const std::function<std::vector<complex_t>(const SliceStack&)> m_kz_computation;