From 00417b16ebf8e8dea750c0d8ac52e18cc75fa6ca Mon Sep 17 00:00:00 2001
From: ralfulrich <ralf.ulrich@kit.edu>
Date: Tue, 1 Dec 2020 12:38:32 +0100
Subject: [PATCH] first round of makeing this actually work

---
 corsika/framework/stack/CombinedStack.hpp     |  72 +-
 corsika/framework/stack/ParticleBase.hpp      |   8 +-
 corsika/framework/stack/SecondaryView.hpp     | 309 ++++----
 corsika/framework/stack/Stack.hpp             |  44 +-
 .../stack/StackIteratorInterface.hpp          | 283 +++----
 corsika/stack/DummyStack.hpp                  | 103 ++-
 corsika/stack/GeometryNodeStackExtension.hpp  |  20 +-
 corsika/stack/NuclearStackExtension.hpp       | 713 +++++++++---------
 corsika/stack/SuperStupidStack.hpp            | 458 +++++------
 examples/stack_example.cpp                    |  30 +-
 tests/framework/CMakeLists.txt                |   8 +-
 tests/framework/testCombinedStack.cpp         | 262 +++----
 tests/framework/testSecondaryView.cpp         | 140 ++--
 tests/framework/testStackInterface.cpp        | 112 +--
 tests/framework/testTestStack.h               |  53 +-
 tests/stack/testDummyStack.cpp                |  13 +-
 .../stack/testGeometryNodeStackExtension.cpp  |  40 +-
 tests/stack/testNuclearStackExtension.cpp     | 250 +++---
 tests/stack/testSuperStupidStack.cpp          |  40 +-
 19 files changed, 1427 insertions(+), 1531 deletions(-)

diff --git a/corsika/framework/stack/CombinedStack.hpp b/corsika/framework/stack/CombinedStack.hpp
index 10b2f903c..0df3532f4 100644
--- a/corsika/framework/stack/CombinedStack.hpp
+++ b/corsika/framework/stack/CombinedStack.hpp
@@ -8,7 +8,7 @@
 
 #pragma once
 
-//#include <corsika/logging/Logging.h>
+#include <corsika/framework/logging/Logging.hpp>
 #include <corsika/framework/core/ParticleProperties.hpp>
 #include <corsika/framework/stack/Stack.hpp>
 #include <corsika/framework/core/PhysicalUnits.hpp>
@@ -16,7 +16,8 @@
 namespace corsika {
 
   /**
-   * @class CombinedParticleInterface
+   * CombinedParticleInterface can be used to combine the data of several StackData
+   * objects.
    *
    * You may combine two StackData object, see class CombinedStackImpl
    * below, into one Stack, using a combined StackIterator (aka
@@ -33,49 +34,61 @@ namespace corsika {
    * ParticleInterface classes.
    *
    */
-  template <template <typename> typename ParticleInterfaceA,
-            template <typename> class ParticleInterfaceB, typename StackIterator>
+  template <template <typename> typename TParticleInterfaceA,
+            template <typename> class TParticleInterfaceB, typename TStackIterator>
   struct CombinedParticleInterface
-      : public ParticleInterfaceB<ParticleInterfaceA<StackIterator>> {
+      : public TParticleInterfaceB<TParticleInterfaceA<TStackIterator>> {
 
+    typedef CombinedParticleInterface<TParticleInterfaceA, TParticleInterfaceB,
+                                      TStackIterator>
+        pi_c_type;
+    typedef TParticleInterfaceA<TStackIterator> pi_a_type;
+    typedef TParticleInterfaceB<TParticleInterfaceA<TStackIterator>> pi_b_type;
+
+  protected:
+    using pi_b_type::getIndex;     // choose B, A would also work
+    using pi_b_type::getStackData; // choose B, A would also work
+
+  public:
     /**
      * @name wrapper for user functions
      * @{
      *
      * In this set of functions we call the user-provide
-     * ParticleInterface setParticleData(...) methods, either with
+     * TParticleInterface setParticleData(...) methods, either with
      * parent particle reference, or w/o.
      *
      * There is one implicit assumption here: if only one data tuple
      * is provided for setParticleData, the data is passed on to
-     * ParticleInterfaceA and the ParticleInterfaceB is
+     * TParticleInterfaceA and the TParticleInterfaceB is
      * default-initialized. There are many occasions where this is the
      * desired behaviour, e.g. for thinning etc.
      *
      */
 
-    template <typename... Args1>
-    void setParticleData(const std::tuple<Args1...> vA) {
-    	pi_a_type::setParticleData(vA);
-    	pi_b_type::setParticleData();
+    template <typename... TArgs1>
+    void setParticleData(std::tuple<TArgs1...> const vA) {
+      pi_a_type::setParticleData(vA);
+      pi_b_type::setParticleData();
     }
-    template <typename... Args1, typename... Args2>
-    void setParticleData(const std::tuple<Args1...> vA, const std::tuple<Args2...> vB) {
-    	pi_a_type::setParticleData(vA);
-        pi_b_type::setParticleData(vB);
+    template <typename... TArgs1, typename... TArgs2>
+    void setParticleData(std::tuple<TArgs1...> const vA, std::tuple<TArgs2...> const vB) {
+      pi_a_type::setParticleData(vA);
+      pi_b_type::setParticleData(vB);
     }
 
-    template <typename... Args1>
-    void setParticleData(pi_a_type& p, const std::tuple<Args1...> vA) {
+    template <typename... TArgs1>
+    void setParticleData(pi_a_type& p, std::tuple<TArgs1...> const vA) {
       // static_assert(MT<I>::has_not, "error");
-    	pi_a_type::setParticleData(static_cast<pi_a_type&>(p), vA); // original stack
-        pi_b_type::setParticleData(static_cast<pi_b_type&>(p));     // addon stack
+      pi_a_type::setParticleData(static_cast<pi_a_type&>(p), vA); // original stack
+      pi_b_type::setParticleData(static_cast<pi_b_type&>(p));     // addon stack
     }
-    template <typename... Args1, typename... Args2>
-    void setParticleData(pi_c_type& p, const std::tuple<Args1...> vA, const std::tuple<Args2...> vB) {
+    template <typename... TArgs1, typename... TArgs2>
+    void setParticleData(pi_c_type& p, std::tuple<TArgs1...> const vA,
+                         std::tuple<TArgs2...> const vB) {
 
-    	pi_a_type::setParticleData(static_cast<pi_a_type&>(p), vA);
-        pi_b_type::setParticleData(static_cast<pi_b_type&>(p), vB);
+      pi_a_type::setParticleData(static_cast<pi_a_type&>(p), vA);
+      pi_b_type::setParticleData(static_cast<pi_b_type&>(p), vB);
     }
     ///@}
 
@@ -84,14 +97,7 @@ namespace corsika {
     }
 
   private:
-    typedef CombinedParticleInterface<ParticleInterfaceA, ParticleInterfaceB, StackIterator> pi_c_type ;
-    typedef ParticleInterfaceA<StackIterator> pi_a_type;
-    typedef ParticleInterfaceB<ParticleInterfaceA<StackIterator>> pi_b_type;
-
   protected:
-    using pi_b_type::getIndex;     // choose B, A would also work
-    using pi_b_type::getStackData; // choose B, A would also work
-
   };
 
   /**
@@ -162,9 +168,9 @@ namespace corsika {
    * initialization are forwarded to Stack1Impl (first).
    */
 
-  template <typename Stack1Impl, typename Stack2Impl, template <typename> typename _Pi>
-  typedef  Stack<CombinedStackImpl<Stack1Impl, Stack2Impl>, Pi> combined_stack_type;
-
+  template <typename Stack1Impl, typename Stack2Impl, template <typename> typename _PI>
+  using CombinedStack = Stack<CombinedStackImpl<Stack1Impl, Stack2Impl>, _PI>;
+  
 } // namespace corsika
 
 //#include <corsika/detail/framework/stack/CombinedStack.inl>
diff --git a/corsika/framework/stack/ParticleBase.hpp b/corsika/framework/stack/ParticleBase.hpp
index 5e0a2ae1d..1a051f80b 100644
--- a/corsika/framework/stack/ParticleBase.hpp
+++ b/corsika/framework/stack/ParticleBase.hpp
@@ -50,13 +50,11 @@ namespace corsika {
     ParticleBase() = default;
 
      // those copy constructors and assigments should never be implemented
-    ParticleBase(ParticleBase&)       = delete;
     ParticleBase(ParticleBase&&)      = delete;
-    ParticleBase(const ParticleBase&) = delete;
+    ParticleBase(ParticleBase const&) = delete;
 
-    ParticleBase operator=(ParticleBase&)       = delete;
     ParticleBase operator=(ParticleBase&&)      = delete;
-    ParticleBase operator=(const ParticleBase&) = delete;
+    ParticleBase operator=(ParticleBase const&) = delete;
 
 
     /**
@@ -68,7 +66,7 @@ namespace corsika {
     /**
      * Method to retrieve the status of the Particle. Is it already deleted? Or not.
      */
-    bool isDeleted() const { return this->getIterator().getStack().isDeleted(this->getIterator()); }
+    bool isErased() const { return this->getIterator().getStack().isErased(this->getIterator()); }
 
     /**
      * Add a secondary particle based on *this on the stack @param
diff --git a/corsika/framework/stack/SecondaryView.hpp b/corsika/framework/stack/SecondaryView.hpp
index 7986159db..79abc168f 100644
--- a/corsika/framework/stack/SecondaryView.hpp
+++ b/corsika/framework/stack/SecondaryView.hpp
@@ -8,8 +8,7 @@
 #pragma once
 
 #include <corsika/framework/stack/Stack.hpp>
-
-//#include <corsika/logging/Logging.h>
+#include <corsika/framework/logging/Logging.hpp>
 
 #include <stdexcept>
 #include <vector>
@@ -58,121 +57,116 @@ namespace corsika {
      getIndexFromIterator.
    */
 
-  template <typename StackDataType,
-            template <typename> typename ParticleInterface,
-            template <typename T1, template <class> class T2> class MSecondaryProducer = DefaultSecondaryProducer>
-  class SecondaryView : public Stack<StackDataType&, ParticleInterface>,
-                        public MSecondaryProducer<StackDataType, ParticleInterface>
-  {
+  template <typename TStackDataType, template <typename> typename TParticleInterface,
+            template <typename T1, template <class> class T2> class MSecondaryProducer =
+                DefaultSecondaryProducer>
+  class SecondaryView : public Stack<TStackDataType&, TParticleInterface>,
+                        public MSecondaryProducer<TStackDataType, TParticleInterface> {
 
-	//using ViewType = SecondaryView<StackDataType, ParticleInterface, MSecondaryProducer>;
-    typedef SecondaryView<StackDataType, ParticleInterface, MSecondaryProducer> view_type;
+    // using ViewType = SecondaryView<TStackDataType, TParticleInterface,
+    // MSecondaryProducer>;
+    typedef SecondaryView<TStackDataType, TParticleInterface, MSecondaryProducer>
+        view_type;
     /**
      * Helper type for inside this class
      */
-    //using InnerStackTypeRef = Stack<StackDataType&, ParticleInterface>;
-    typedef Stack<StackDataType&, ParticleInterface> inner_stack_reference_type;
-
-    //using InnerStackTypeValue = Stack<StackDataType, ParticleInterface>;
-    typedef Stack<StackDataType, ParticleInterface>  inner_stack_value_type;
-
-    using inner_stack_reference_type::getDeleted;
+    // using InnerStackTypeRef = Stack<TStackDataType&, TParticleInterface>;
+    typedef Stack<TStackDataType&, TParticleInterface> inner_stack_reference_type;
 
     /**
-     * @name We need this "special" types with non-reference StackData for
+     * @name We need this "value" types with non-reference TStackData for
      * the constructor of the SecondaryView class
      * @{
      */
-
+    // using InnerStackTypeValue = Stack<TStackDataType, TParticleInterface>;
+    typedef Stack<TStackDataType, TParticleInterface> inner_stack_value_type;
 
   public:
+    //    using StackIteratorValue =
+    //        StackIteratorInterface<typename std::remove_reference<TStackDataType>::type,
+    //                               TParticleInterface, InnerStackTypeValue>;
+    typedef StackIteratorInterface<typename std::remove_reference<TStackDataType>::type,
+                                   TParticleInterface, inner_stack_value_type>
+        stack_value_iterator;
+
+    //    using ConstStackIteratorValue =
+    //        ConstStackIteratorInterface<typename
+    //        std::remove_reference<TStackDataType>::type,
+    //                                    TParticleInterface, inner_stack_value_type>;
+
+    typedef ConstStackIteratorInterface<
+        typename std::remove_reference<TStackDataType>::type, TParticleInterface,
+        inner_stack_value_type>
+        const_stack_value_iterator;
+    /// @}
 
-//    using StackIteratorValue =
-//        StackIteratorInterface<typename std::remove_reference<StackDataType>::type,
-//                               ParticleInterface, InnerStackTypeValue>;
-   typedef  StackIteratorInterface<typename std::remove_reference<StackDataType>::type,
-                                   ParticleInterface, inner_stack_value_type> stack_value_iterator;
-
-//    using ConstStackIteratorValue =
-//        ConstStackIteratorInterface<typename std::remove_reference<StackDataType>::type,
-//                                    ParticleInterface, inner_stack_value_type>;
-
-   typedef ConstStackIteratorInterface<typename std::remove_reference<StackDataType>::type,
-                                       ParticleInterface, inner_stack_value_type> const_stack_value_iterator;
-       /// @}
-
-//    using StackIterator =
-//        StackIteratorInterface<typename std::remove_reference<StackDataType>::type,
-//                               ParticleInterface, view_type>;
+    //    using StackIterator =
+    //        StackIteratorInterface<typename std::remove_reference<TStackDataType>::type,
+    //                               TParticleInterface, view_type>;
 
-    typedef  StackIteratorInterface<typename std::remove_reference<StackDataType>::type,
-                               ParticleInterface, view_type> stack_view_iterator;
+    typedef StackIteratorInterface<typename std::remove_reference<TStackDataType>::type,
+                                   TParticleInterface, view_type>
+        stack_view_iterator;
 
-//    using ConstStackIterator =
-//        ConstStackIteratorInterface<typename std::remove_reference<StackDataType>::type,
-//                                    ParticleInterface, view_type>;
+    //    using ConstStackIterator =
+    //        ConstStackIteratorInterface<typename
+    //        std::remove_reference<TStackDataType>::type,
+    //                                    TParticleInterface, view_type>;
 
-    typedef ConstStackIteratorInterface<typename std::remove_reference<StackDataType>::type,
-                                    ParticleInterface, view_type> const_stack_view_iterator;
+    typedef ConstStackIteratorInterface<
+        typename std::remove_reference<TStackDataType>::type, TParticleInterface,
+        view_type>
+        const_stack_view_iterator;
 
     /**
-     * this is the full type of the declared ParticleInterface: typedef typename
+     * this is the full type of the declared TParticleInterface:
      */
-    using ParticleType = StackIterator;
-    using ParticleInterfaceType = typename StackIterator::ParticleInterfaceType;
-
-    friend class StackIteratorInterface<
-        typename std::remove_reference<StackDataType>::type, ParticleInterface, view_type>;
-
-    friend class ConstStackIteratorInterface<
-        typename std::remove_reference<StackDataType>::type, ParticleInterface, view_type>;
-
-    friend class ParticleBase<StackIterator>;
-
+    using ParticleType = stack_view_iterator;
+    using ParticleInterfaceType = typename stack_view_iterator::particle_interface_type;
 
     /**
      * This is not accessible, since we don't want to allow creating a
      * new stack.
      */
-    template <typename... Args>
-    SecondaryView(Args... args) = delete;
+    template <typename... TArgs>
+    SecondaryView(TArgs... args) = delete;
     SecondaryView() = delete;
 
-   /**
-       SecondaryView can only be constructed passing it a valid
-       StackIterator to another Stack object (here: lvalue)
-     **/
+    /**
+        SecondaryView can only be constructed passing it a valid
+        stack_view_iterator to another Stack object (here: lvalue)
+      **/
     SecondaryView(stack_value_iterator& particle)
-        : Stack<StackDataType&, ParticleInterface>(particle.getStackData())
-        , MSecondaryProducer<StackDataType, ParticleInterface>{particle}
+        : Stack<TStackDataType&, TParticleInterface>(particle.getStackData())
+        , MSecondaryProducer<TStackDataType, TParticleInterface>{particle}
         , inner_stack_(particle.getStack())
         , projectile_index_(particle.getIndex()) {
-      C8LOG_TRACE("SecondaryView::SecondaryView(particle&)");
+      CORSIKA_LOG_TRACE("SecondaryView::SecondaryView(particle&)");
     }
     /**
        SecondaryView can only be constructed passing it a valid
-       StackIterator to another Stack object (here: rvalue)
+       stack_view_iterator to another Stack object (here: rvalue)
      **/
     SecondaryView(stack_value_iterator&& particle)
-        : Stack<StackDataType&, ParticleInterface>(particle.getStackData())
-        , MSecondaryProducer<StackDataType, ParticleInterface>{particle}
+        : Stack<TStackDataType&, TParticleInterface>(particle.getStackData())
+        , MSecondaryProducer<TStackDataType, TParticleInterface>{particle}
         , inner_stack_(particle.getStack())
         , projectile_index_(particle.getIndex()) {
-      C8LOG_TRACE("SecondaryView::SecondaryView(particle&&)");
+      CORSIKA_LOG_TRACE("SecondaryView::SecondaryView(particle&&)");
     }
     /**
-     * Also allow to create a new View from a Projectile (StackIterator on View)
+     * Also allow to create a new View from a Projectile (stack_view_iterator on View)
      *
      * Note, the view generated this way will be equivalent to the orignal view in
      * terms of reference to the underlying data stack. It is not a "view to a view".
      */
     SecondaryView(view_type& view, stack_view_iterator& projectile)
-        : Stack<StackDataType&, ParticleInterface>{view.getStackData()}
-        , MSecondaryProducer<StackDataType, ParticleInterface>{stack_value_iterator{
+        : Stack<TStackDataType&, TParticleInterface>{view.getStackData()}
+        , MSecondaryProducer<TStackDataType, TParticleInterface>{stack_value_iterator{
               view.inner_stack_, view.getIndexFromIterator(projectile.getIndex())}}
         , inner_stack_{view.inner_stack_}
         , projectile_index_{view.getIndexFromIterator(projectile.getIndex())} {
-      C8LOG_TRACE("SecondaryView::SecondaryView(view, projectile)");
+      CORSIKA_LOG_TRACE("SecondaryView::SecondaryView(view, projectile)");
     }
 
     /**
@@ -207,24 +201,20 @@ namespace corsika {
      */
     template <typename... Args>
     stack_view_iterator addSecondary(const Args... v) {
-      C8LOG_TRACE("SecondaryView::addSecondary(Args&&)");
+      CORSIKA_LOG_TRACE("SecondaryView::addSecondary(Args&&)");
       stack_view_iterator proj = getProjectile(); // make this const
       return addSecondary(proj, v...);
     }
     /**
      * overwrite Stack::getSize to return actual number of secondaries
      */
-    unsigned int getSize() const {
-    	return indices_.size();
-    }
+    unsigned int getSize() const { return indices_.size(); }
 
     unsigned int getEntries() const {
-    	return getSize() - getDeleted();
+      return getSize() - inner_stack_reference_type::getErased();
     }
 
-    bool IsEmpty() const {
-    	return getEntries() == 0;
-    }
+    bool isEmpty() const { return getEntries() == 0; }
 
     /**
      * @name These are functions required by std containers and std loops
@@ -237,19 +227,17 @@ namespace corsika {
     stack_view_iterator begin() {
       unsigned int i = 0;
       for (; i < getSize(); ++i) {
-        if (!isDeleted(i)) break;
+        if (!isErased(i)) break;
       }
       return stack_view_iterator(*this, i + 1);
     }
 
-    auto end() {
-    	return stack_view_iterator(*this, getSize() + 1);
-    }
+    auto end() { return stack_view_iterator(*this, getSize() + 1); }
 
     auto last() {
       unsigned int i = 0;
       for (; i < getSize(); ++i) {
-        if (!isDeleted(getSize() - 1 - i)) break;
+        if (!isErased(getSize() - 1 - i)) break;
       }
       return stack_view_iterator(*this, getSize() - 1 - i + 1);
     }
@@ -257,20 +245,18 @@ namespace corsika {
     auto begin() const {
       unsigned int i = 0;
       for (; i < getSize(); ++i) {
-        if (!isDeleted(i)) break;
+        if (!isErased(i)) break;
       }
 
       return const_stack_view_iterator(*this, i + 1);
     }
 
-    auto end() const {
-    	return const_stack_view_iterator(*this, getSize() + 1);
-    }
+    auto end() const { return const_stack_view_iterator(*this, getSize() + 1); }
 
     auto last() const {
       unsigned int i = 0;
       for (; i < getSize(); ++i) {
-        if (!isDeleted(getSize() - 1 - i)) break;
+        if (!isErased(getSize() - 1 - i)) break;
       }
       return const_stack_view_iterator(*this, getSize() - 1 - i + 1);
     }
@@ -278,52 +264,46 @@ namespace corsika {
     auto cbegin() const {
       unsigned int i = 0;
       for (; i < getSize(); ++i) {
-        if (!isDeleted(i)) break;
+        if (!isErased(i)) break;
       }
       return const_stack_view_iterator(*this, i + 1);
     }
 
-    auto cend() const {
-    	return const_stack_view_iterator(*this, getSize());
-    }
+    auto cend() const { return const_stack_view_iterator(*this, getSize()); }
 
     auto clast() const {
       unsigned int i = 0;
       for (; i < getSize(); ++i) {
-        if (!isDeleted(getSize() - 1 - i)) break;
+        if (!isErased(getSize() - 1 - i)) break;
       }
       return const_stack_view_iterator(*this, getSize() - 1 - i + 1);
     }
 
-    stack_view_iterator at(unsigned int i) {
-    	return stack_view_iterator(*this, i);
-    }
+    stack_view_iterator at(unsigned int i) { return stack_view_iterator(*this, i); }
 
     const_stack_view_iterator at(unsigned int i) const {
-    	return const_stack_view_iterator(*this, i);
+      return const_stack_view_iterator(*this, i);
     }
 
-    stack_view_iterator first() {
-    	return stack_view_iterator{*this, 0};
-    }
+    stack_view_iterator first() { return stack_view_iterator{*this, 0}; }
 
     const_stack_view_iterator cfirst() const {
-    	return const_stack_view_iterator{*this, 0};
+      return const_stack_view_iterator{*this, 0};
     }
     /// @}
 
     void swap(stack_view_iterator a, stack_view_iterator b) {
-      C8LOG_TRACE("View::swap");
+      CORSIKA_LOG_TRACE("View::swap");
       inner_stack_.swap(getIndexFromIterator(a.getIndex()),
                         getIndexFromIterator(b.getIndex()));
     }
     void copy(stack_view_iterator a, stack_view_iterator b) {
-      C8LOG_TRACE("View::copy");
+      CORSIKA_LOG_TRACE("View::copy");
       inner_stack_.copy(getIndexFromIterator(a.getIndex()),
                         getIndexFromIterator(b.getIndex()));
     }
     void copy(const_stack_view_iterator a, stack_view_iterator b) {
-      C8LOG_TRACE("View::copy");
+      CORSIKA_LOG_TRACE("View::copy");
       inner_stack_.copy(getIndexFromIterator(a.getIndex()),
                         getIndexFromIterator(b.getIndex()));
     }
@@ -341,14 +321,14 @@ namespace corsika {
      *
      */
     void erase(stack_view_iterator p) {
-      C8LOG_TRACE("SecondaryView::Delete");
-      if (IsEmpty()) { /*error*/
+      CORSIKA_LOG_TRACE("SecondaryView::Delete");
+      if (isEmpty()) { /*error*/
         throw std::runtime_error("Stack, cannot delete entry since size is zero");
       }
-      if (isDeleted(p.getIndex() - 1)) { /*error*/
+      if (isErased(p.getIndex() - 1)) { /*error*/
         throw std::runtime_error("Stack, cannot delete entry since already deleted");
       }
-      inner_stack_.Delete(getIndexFromIterator(p.getIndex()));
+      inner_stack_.erase(getIndexFromIterator(p.getIndex()));
       inner_stack_reference_type::nDeleted_++; // also count in SecondaryView
     }
 
@@ -364,21 +344,21 @@ namespace corsika {
     /**
      * check if this particle was already deleted
      *
-     * need to re-implement for SecondaryView since StackIterator types are a bit
+     * need to re-implement for SecondaryView since stack_view_iterator types are a bit
      * different
      */
-    bool isDeleted(const stack_view_iterator& p) const {
-    	return isDeleted(p.getIndex() - 1);
+    bool isErased(const stack_view_iterator& p) const {
+      return isErased(p.getIndex() - 1);
     }
 
-    bool isDeleted(const const_stack_view_iterator& p) const {
-      return isDeleted(p.getIndex() - 1);
+    bool isErased(const const_stack_view_iterator& p) const {
+      return isErased(p.getIndex() - 1);
     }
     /**
      * delete this particle
      */
-    bool isDeleted(const ParticleInterfaceType& p) const {
-      return isDeleted(p.getIterator());
+    bool isErased(const ParticleInterfaceType& p) const {
+      return isErased(p.getIterator());
     }
 
     /**
@@ -387,8 +367,8 @@ namespace corsika {
      * the function will just return false and do nothing.
      */
     bool purgeLastIfDeleted() {
-      C8LOG_TRACE("SecondaryView::purgeLastIfDeleted");
-      if (!isDeleted(getSize() - 1))
+      CORSIKA_LOG_TRACE("SecondaryView::purgeLastIfDeleted");
+      if (!isErased(getSize() - 1))
         return false; // the last particle is not marked for deletion. Do nothing.
       inner_stack_.purge(getIndexFromIterator(getSize()));
       inner_stack_reference_type::nDeleted_--;
@@ -408,7 +388,7 @@ namespace corsika {
       unsigned int iStack = 0;
       unsigned int size = getSize();
       while (iStack < size) {
-        if (isDeleted(iStack)) {
+        if (isErased(iStack)) {
           inner_stack_.purge(iStack);
           indices_.erase(indices_.begin() + iStack);
         }
@@ -423,7 +403,7 @@ namespace corsika {
       // we make our own begin/end since we want ALL entries
       std::string new_line = "     ";
       for (unsigned int iPart = 0; iPart != getSize(); ++iPart) {
-    	  const_stack_view_iterator itPart(*this, iPart);
+        const_stack_view_iterator itPart(*this, iPart);
         str += fmt::format(
             "{}{}{}", new_line, itPart.as_string(),
             (inner_stack_.deleted_[getIndexFromIterator(itPart.getIndex())] ? " [deleted]"
@@ -434,39 +414,48 @@ namespace corsika {
     }
 
   protected:
+    friend class StackIteratorInterface<
+        typename std::remove_reference<TStackDataType>::type, TParticleInterface,
+        view_type>;
+
+    friend class ConstStackIteratorInterface<
+        typename std::remove_reference<TStackDataType>::type, TParticleInterface,
+        view_type>;
 
-     /**
-      * Overwrite of Stack::StackIterator
-      *
-      * increase stack size, create new particle at end of stack,
-      * related to parent particle/projectile
-      *
-      * This should only get internally called from a
-      * StackIterator::addSecondary via ParticleBase
-      */
-     template <typename... Args>
-     stack_view_iterator addSecondary(stack_view_iterator& proj, const Args... v) {
-       C8LOG_TRACE("SecondaryView::addSecondary(StackIterator&, Args&&)");
-       // make space on stack
-       inner_stack_reference_type::getStackData().IncrementSize();
-       inner_stack_.deleted_.push_back(false);
-       // get current number of secondaries on stack
-       const unsigned int idSec = getSize();
-       // determine index on (inner) stack where new particle will be located
-       const unsigned int index = inner_stack_reference_type::getStackData().getSize() - 1;
-       indices_.push_back(index);
-       // NOTE: "+1" is since "0" is special marker here for PROJECTILE, see
-       // getIndexFromIterator
-       auto sec = stack_view_iterator(*this, idSec + 1, proj, v...);
-       MSecondaryProducer<StackDataType, ParticleInterface>::new_secondary(sec);
-       return sec;
-     }
+    friend class ParticleBase<stack_view_iterator>;
+
+    /**
+     * Overwrite of Stack::stack_view_iterator
+     *
+     * increase stack size, create new particle at end of stack,
+     * related to parent particle/projectile
+     *
+     * This should only get internally called from a
+     * stack_view_iterator::addSecondary via ParticleBase
+     */
+    template <typename... Args>
+    stack_view_iterator addSecondary(stack_view_iterator& proj, const Args... v) {
+      CORSIKA_LOG_TRACE("SecondaryView::addSecondary(stack_view_iterator&, Args&&)");
+      // make space on stack
+      inner_stack_reference_type::getStackData().incrementSize();
+      inner_stack_.deleted_.push_back(false);
+      // get current number of secondaries on stack
+      const unsigned int idSec = getSize();
+      // determine index on (inner) stack where new particle will be located
+      const unsigned int index = inner_stack_reference_type::getStackData().getSize() - 1;
+      indices_.push_back(index);
+      // NOTE: "+1" is since "0" is special marker here for PROJECTILE, see
+      // getIndexFromIterator
+      auto sec = stack_view_iterator(*this, idSec + 1, proj, v...);
+      MSecondaryProducer<TStackDataType, TParticleInterface>::new_secondary(sec);
+      return sec;
+    }
 
     // forward to inner stack
     // this also checks the allowed bounds of 'i'
-    bool isDeleted(unsigned int i) const {
+    bool isErased(unsigned int i) const {
       if (i >= indices_.size()) return false;
-      return inner_stack_.isDeleted(getIndexFromIterator(i + 1));
+      return inner_stack_.isErased(getIndexFromIterator(i + 1));
     }
 
     /**
@@ -475,8 +464,8 @@ namespace corsika {
      * performed.
      */
     unsigned int getIndexFromIterator(const unsigned int vI) const {
-      // this is too much: C8LOG_TRACE("SecondaryView::getIndexFromIterator({})={}", vI,
-      // (vI?indices_[vI-1]:projectile_index_));
+      // this is too much: CORSIKA_LOG_TRACE("SecondaryView::getIndexFromIterator({})={}",
+      // vI, (vI?indices_[vI-1]:projectile_index_));
       if (vI == 0) return projectile_index_;
       return indices_[vI - 1];
     }
@@ -487,8 +476,6 @@ namespace corsika {
     std::vector<unsigned int> indices_;
   };
 
-
-
   /**
    * Class to handle the generation of new secondaries. Used as default mix-in for
    * SecondaryView.
@@ -509,7 +496,7 @@ namespace corsika {
      */
     template <typename Particle>
     auto new_secondary(Particle&&) const {
-      C8LOG_TRACE("DefaultSecondaryProducer::new_secondary(Particle&&)");
+      CORSIKA_LOG_TRACE("DefaultSecondaryProducer::new_secondary(Particle&&)");
     }
 
     /**
@@ -522,10 +509,8 @@ namespace corsika {
      */
     template <typename Particle>
     DefaultSecondaryProducer(Particle const&) {
-      C8LOG_TRACE("DefaultSecondaryProducer::DefaultSecondaryProducer(Particle&)");
+      CORSIKA_LOG_TRACE("DefaultSecondaryProducer::DefaultSecondaryProducer(Particle&)");
     }
-
-
   };
 
   /*
@@ -538,15 +523,15 @@ namespace corsika {
   */
 #if not defined(__clang__) && defined(__GNUC__) || defined(__GNUG__)
   template <typename TStack,
-            template <class TStack_, template <class> class MPIType_>
-            class MSecondaryProducer = corsika::stack::DefaultSecondaryProducer,
-            template <typename> typename MPIType_ = TStack::template MPIType>
+            template <class TStack_, template <class> class pi_type_>
+            class MSecondaryProducer = corsika::DefaultSecondaryProducer,
+            template <typename> typename pi_type_ = TStack::template pi_type>
   struct MakeView {
-    using type = corsika::stack::SecondaryView<typename TStack::StackImpl, MPIType_, MSecondaryProducer>;
+    using type = corsika::SecondaryView<typename TStack::stack_implementation_type,
+                                        pi_type_, MSecondaryProducer>;
   };
 #endif
 
 } // namespace corsika
 
-
 //#include <corsika/detail/framework/stack/SecondaryView.inl>
diff --git a/corsika/framework/stack/Stack.hpp b/corsika/framework/stack/Stack.hpp
index 408af2035..e30e4e7c5 100644
--- a/corsika/framework/stack/Stack.hpp
+++ b/corsika/framework/stack/Stack.hpp
@@ -10,7 +10,6 @@
 
 #include <corsika/framework/logging/Logging.hpp>
 #include <corsika/framework/stack/StackIteratorInterface.hpp>
-#include <corsika/framework/utility/MetaProgramming.hpp>
 
 #include <stdexcept>
 #include <string>
@@ -18,7 +17,6 @@
 #include <utility>
 #include <type_traits>
 
-
 namespace corsika {
 
   /**
@@ -60,7 +58,7 @@ namespace corsika {
                                                  ///< user-provided data structure
 
     template <typename TSI>
-    using mpi_type = MParticleInterface<TSI>;
+    using pi_type = MParticleInterface<TSI>;
 
     /**
      * Via the StackIteratorInterface and ConstStackIteratorInterface
@@ -78,7 +76,7 @@ namespace corsika {
     /**
      * this is the full type of the user-declared MParticleInterface
      */
-    typedef typename stack_iterator_type::ParticleInterfaceType particle_interface_type;
+    typedef typename stack_iterator_type::particle_interface_type particle_interface_type;
     /**
      * In all programming context, the object to access, copy, and
      * transport particle data is via the stack_iterator_type
@@ -101,9 +99,9 @@ namespace corsika {
     template <typename UType = StackData,
               typename = typename std::enable_if<std::is_reference<UType>::value>::type>
     Stack(StackData vD)
-        : data_(vD)
-        , deleted_(std::vector<bool>(data_.getSize(), false))
-        , nDeleted_(0) {}
+        : nDeleted_(0)
+        , data_(vD)
+        , deleted_(std::vector<bool>(data_.getSize(), false)) {}
 
     /**
      * This constructor takes any argument and passes it on to the
@@ -117,9 +115,9 @@ namespace corsika {
     template <typename... TArgs, typename UType = StackData,
               typename = typename std::enable_if<std::is_reference<UType>::value>::type>
     Stack(TArgs... args)
-        : data_(args...)
-        , deleted_(std::vector<bool>(data_.getSize(), false))
-        , nDeleted_(0) {}
+        : nDeleted_(0)
+        , data_(args...)
+        , deleted_(std::vector<bool>(data_.getSize(), false)) {}
 
     /**
      * @name Most generic proxy methods for StackData data_
@@ -127,9 +125,9 @@ namespace corsika {
      */
     unsigned int getCapacity() const { return data_.getCapacity(); }
 
-    unsigned int getDeleted() const { return nDeleted_; }
+    unsigned int getErased() const { return nDeleted_; }
 
-    unsigned int getEntries() const { return getSize() - getDeleted(); }
+    unsigned int getEntries() const { return getSize() - getErased(); }
 
     template <typename... TArgs>
     void clear(TArgs... args) {
@@ -271,14 +269,14 @@ namespace corsika {
     /**
      * check if this particle was already deleted
      */
-    bool isDeleted(const stack_iterator_type& p) const { return isDeleted(p.getIndex()); }
+    bool isErased(const stack_iterator_type& p) const { return isErased(p.getIndex()); }
 
-    bool isDeleted(const const_stack_iterator_type& p) const {
-      return isDeleted(p.getIndex());
+    bool isErased(const const_stack_iterator_type& p) const {
+      return isErased(p.getIndex());
     }
 
-    bool isDeleted(const particle_interface_type& p) const {
-      return isDeleted(p.getIterator());
+    bool isErased(const particle_interface_type& p) const {
+      return isErased(p.getIterator());
     }
 
     /**
@@ -307,7 +305,7 @@ namespace corsika {
     void purge() {
       unsigned int iStackFront = 0;
       unsigned int iStackBack = getSize() - 1;
-      for (unsigned int iDeleted = 0; iDeleted < getDeleted(); ++iDeleted) {
+      for (unsigned int iDeleted = 0; iDeleted < getErased(); ++iDeleted) {
         // search first delete entry on stack
         while (!deleted_[iStackFront]) { iStackFront++; }
         // search for last non-deleted particle on stack
@@ -324,7 +322,7 @@ namespace corsika {
 
     std::string as_string() const {
       std::string str(fmt::format("size {}, entries {}, deleted {} \n", getSize(),
-                                  getEntries(), getDeleted()));
+                                  getEntries(), getErased()));
       // we make our own begin/end since we want ALL entries
       std::string new_line = "     ";
       for (unsigned int iPart = 0; iPart != getSize(); ++iPart) {
@@ -352,12 +350,12 @@ namespace corsika {
       return stack_iterator_type(*this, getSize() - 1, parent, v...);
     }
 
-    void swap(unsigned int a, unsigned int b) {
+    void swap(unsigned int const a, unsigned int const b) {
       // C8LOG_TRACE("Stack::Swap(unsigned int)");
       data_.swap(a, b);
       std::swap(deleted_[a], deleted_[b]);
     }
-    void copy(unsigned int a, unsigned int b) {
+    void copy(unsigned int const a, unsigned int const b) {
       // C8LOG_TRACE("Stack::Copy");
       data_.copy(a, b);
       if (deleted_[b] && !deleted_[a]) nDeleted_--;
@@ -365,12 +363,12 @@ namespace corsika {
       deleted_[b] = deleted_[a];
     }
 
-    bool isDeleted(unsigned int i) const {
+    bool isErased(unsigned int const i) const {
       if (i >= deleted_.size()) return false;
       return deleted_.at(i);
     }
 
-    void erase(unsigned int i) {
+    void erase(unsigned int const i) {
       deleted_[i] = true;
       nDeleted_++;
     }
diff --git a/corsika/framework/stack/StackIteratorInterface.hpp b/corsika/framework/stack/StackIteratorInterface.hpp
index 7d3c7a4f3..6a64e8534 100644
--- a/corsika/framework/stack/StackIteratorInterface.hpp
+++ b/corsika/framework/stack/StackIteratorInterface.hpp
@@ -10,6 +10,11 @@
 
 #include <corsika/framework/stack/ParticleBase.hpp>
 
+namespace corsika::history {
+  template <typename T, template <typename> typename TParticleInterface>
+  class HistorySecondaryProducer; // forward decl.
+}
+
 namespace corsika {
 
   template <typename TStackData, template <typename> typename TParticleInterface>
@@ -24,10 +29,10 @@ namespace corsika {
   class ConstStackIteratorInterface; // forward decl
 
   /**
-     @class StackIteratorInterface
-
      The StackIteratorInterface is the main interface to iterator over
-     particles on a stack. At the same time StackIteratorInterface is a
+     particles on a stack.
+
+     At the same time StackIteratorInterface is a
      Particle object by itself, thus there is no difference between
      type and ref_type for convenience of the physicist.
 
@@ -47,14 +52,14 @@ namespace corsika {
      for a particle entry at any index index_.
 
      The TParticleInterface class must be written and provided by the
-     user, it contains methods like <code> auto GetData() const {
-     return GetStackData().GetData(GetIndex()); }</code>, where
-     StackIteratorInterface::GetStackData() return a reference to the
+     user, it contains methods like <code> auto getData() const {
+     return getStackData().getData(getIndex()); }</code>, where
+     StackIteratorInterface::getStackData() return a reference to the
      object storing the particle data of type TStackData. And
-     StackIteratorInterface::GetIndex() provides the iterator index to
+     StackIteratorInterface::getIndex() provides the iterator index to
      be readout. The TStackData is another user-provided class to
      store data and must implement functions compatible with
-     TParticleInterface, in this example TStackData::GetData(const unsigned int
+     TParticleInterface, in this example TStackData::getData(const unsigned int
      vIndex).
 
      For two examples see stack_example.cc, or the
@@ -62,43 +67,22 @@ namespace corsika {
   */
 
   template <typename TStackData, template <typename> typename TParticleInterface,
-            typename StackType = Stack<TStackData, TParticleInterface>>
+            typename TStackType = Stack<TStackData, TParticleInterface>>
   class StackIteratorInterface
       : public TParticleInterface<
-            StackIteratorInterface<TStackData, TParticleInterface, StackType>> {
+            StackIteratorInterface<TStackData, TParticleInterface, TStackType>> {
 
   public:
-    using ParticleInterfaceType = ParticleInterface<
-        corsika::StackIteratorInterface<StackDataType, ParticleInterface, StackType>>;
-
-    // friends are needed for access to protected methods
-    friend class Stack<TStackData,
-                       TParticleInterface>; // for access to GetIndex for Stack
-    friend class Stack<TStackData&, TParticleInterface>; // for access to GetIndex
-                                                         // SecondaryView : public Stack
-    friend class ParticleBase<StackIteratorInterface>;   // for access to GetStackData
-
-    template <typename T1,                     // best fix this to: TStackData,
-              template <typename> typename M1, // best fix this to: TParticleInterface,
-              template <typename T, template <typename> typename T3> typename M2>
-    friend class SecondaryView; // access grant for SecondaryView
-
-    template <typename T, template <typename> typename ParticleInterface>
-    friend class corsika::history::HistorySecondaryProducer;
-
-    friend class ConstStackIteratorInterface<TStackData, TParticleInterface, StackType>;
-
-  protected:
-    unsigned int index_ = 0;
+    typedef TParticleInterface<
+        corsika::StackIteratorInterface<TStackData, TParticleInterface, TStackType>>
+        particle_interface_type;
 
-  private:
-    StackType* data_ = 0; // info: Particles and StackIterators become invalid when parent
-                          // Stack is copied or deleted!
+    // using ParticleInterfaceType = TParticleInterface<
+    //  corsika::StackIteratorInterface<TStackData, TParticleInterface, TStackType>>;
 
     // it is not allowed to create a "dangling" stack iterator
-    StackIteratorInterface() = delete;
+    StackIteratorInterface() = delete; //! \todo check rule of five
 
-  public:
     StackIteratorInterface(StackIteratorInterface&& rhs)
         : index_(std::move(rhs.index_))
         , data_(std::move(rhs.data_)) {}
@@ -108,16 +92,18 @@ namespace corsika {
         , data_(vR.data_) {}
 
     StackIteratorInterface& operator=(StackIteratorInterface const& vR) {
-      index_ = vR.index_;
-      data_ = vR.data_;
+      if (&vR != this) {
+        index_ = vR.index_;
+        data_ = vR.data_;
+      }
       return *this;
     }
 
     /** iterator must always point to data, with an index:
           @param data reference to the stack [rw]
           @param index index on stack
-    **/
-    StackIteratorInterface(StackType& data, const unsigned int index)
+       */
+    StackIteratorInterface(TStackType& data, unsigned int const index)
         : index_(index)
         , data_(&data) {}
 
@@ -126,13 +112,14 @@ namespace corsika {
         @param index index on stack
         @param args variadic list of data to initialize stack entry, this must be
        consistent with the definition of the user-provided
-       ParticleInterfaceType::SetParticleData(...) function
-    **/
-    template <typename... Args>
-    StackIteratorInterface(StackType& data, const unsigned int index, const Args... args)
+       particle_interface_type::SetParticleData(...) function
+     */
+    template <typename... TArgs>
+    StackIteratorInterface(TStackType& data, unsigned int const index,
+                           const TArgs... args)
         : index_(index)
         , data_(&data) {
-      (**this).SetParticleData(args...);
+      (**this).setParticleData(args...);
     }
 
     /** constructor that also sets new values on particle data object, including reference
@@ -143,17 +130,17 @@ namespace corsika {
        counting, history, etc.
         @param args variadic list of data to initialize stack entry, this must be
        consistent with the definition of the user-provided
-       ParticleInterfaceType::SetParticleData(...) function
-    **/
+       particle_interface_type::SetParticleData(...) function
+    */
     template <typename... Args>
-    StackIteratorInterface(StackType& data, const unsigned int index,
+    StackIteratorInterface(TStackType& data, unsigned int const index,
                            StackIteratorInterface& parent, const Args... args)
         : index_(index)
         , data_(&data) {
-      (**this).SetParticleData(*parent, args...);
+      (**this).setParticleData(*parent, args...);
     }
 
-    bool isDeleted() const { return GetStack().isDeleted(*this); }
+    bool isErased() const { return getStack().isErased(*this); }
 
   public:
     /** @name Iterator interface
@@ -163,7 +150,7 @@ namespace corsika {
       do {
         ++index_;
       } while (
-          GetStack().isDeleted(*this)); // this also check the allowed bounds of index_
+          getStack().isErased(*this)); // this also check the allowed bounds of index_
       return *this;
     }
     StackIteratorInterface operator++(int) {
@@ -171,39 +158,39 @@ namespace corsika {
       do {
         ++index_;
       } while (
-          GetStack().isDeleted(*this)); // this also check the allowed bounds of index_
+          getStack().isErased(*this)); // this also check the allowed bounds of index_
       return tmp;
     }
     StackIteratorInterface operator+(int delta) const {
       return StackIteratorInterface(*data_, index_ + delta);
     }
-    bool operator==(const StackIteratorInterface& rhs) const {
+    bool operator==(StackIteratorInterface const& rhs) const {
       return index_ == rhs.index_;
     }
-    bool operator!=(const StackIteratorInterface& rhs) const {
+    bool operator!=(StackIteratorInterface const& rhs) const {
       return index_ != rhs.index_;
     }
     bool operator==(
-        const ConstStackIteratorInterface<TStackData, TParticleInterface, StackType>& rhs)
-        const; // implement below
+        const ConstStackIteratorInterface<TStackData, TParticleInterface, TStackType>&
+            rhs) const; // implemented below
     bool operator!=(
-        const ConstStackIteratorInterface<TStackData, TParticleInterface, StackType>& rhs)
-        const; // implement below
+        const ConstStackIteratorInterface<TStackData, TParticleInterface, TStackType>&
+            rhs) const; // implemented below
 
     /**
      * Convert iterator to value type, where value type is the user-provided particle
      * readout class
      **/
-    ParticleInterfaceType& operator*() {
-      return static_cast<ParticleInterfaceType&>(*this);
+    particle_interface_type& operator*() {
+      return static_cast<particle_interface_type&>(*this);
     }
 
     /**
      * Convert iterator to const value type, where value type is the user-provided
      * particle readout class
      **/
-    const ParticleInterfaceType& operator*() const {
-      return static_cast<const ParticleInterfaceType&>(*this);
+    particle_interface_type const& operator*() const {
+      return static_cast<particle_interface_type const&>(*this);
     }
     ///@}
 
@@ -213,99 +200,94 @@ namespace corsika {
      * @{
      **/
     /// Get current particle index
-    inline unsigned int GetIndex() const { return index_; }
+    inline unsigned int getIndex() const { return index_; }
     /// Get current particle Stack object
-    inline StackType& GetStack() { return *data_; }
+    inline TStackType& getStack() { return *data_; }
     /// Get current particle const Stack object
-    inline const StackType& GetStack() const { return *data_; }
+    inline TStackType const& getStack() const { return *data_; }
     /// Get current user particle TStackData object
-    inline TStackData& GetStackData() { return data_->GetStackData(); }
+    inline TStackData& getStackData() { return data_->getStackData(); }
     /// Get current const user particle TStackData object
-    inline const TStackData& GetStackData() const { return data_->GetStackData(); }
+    inline TStackData const& getStackData() const { return data_->getStackData(); }
     /// Get data index as mapped in Stack class
-    inline unsigned int GetIndexFromIterator() const {
-      return data_->GetIndexFromIterator(index_);
+    inline unsigned int getIndexFromIterator() const {
+      return data_->getIndexFromIterator(index_);
     }
     ///@}
-  }; // end class StackIterator
-
-  /**
-     @class ConstStackIteratorInterface
-
-     This is the iterator class for const-access to stack data
-  **/
-
-  template <typename TStackData, template <typename> typename TParticleInterface,
-            typename StackType = Stack<TStackData, TParticleInterface>>
-  class ConstStackIteratorInterface
-      : public TParticleInterface<
-            ConstStackIteratorInterface<TStackData, TParticleInterface, StackType>> {
-
-  public:
-    typedef TParticleInterface<
-        ConstStackIteratorInterface<TStackData, TParticleInterface, StackType>>
-        ParticleInterfaceType;
 
     // friends are needed for access to protected methods
     friend class Stack<TStackData,
-                       TParticleInterface>; // for access to GetIndex for Stack
-    friend class Stack<TStackData&, TParticleInterface>; // for access to GetIndex
-
-    friend class ParticleBase<ConstStackIteratorInterface>; // for access to GetStackData
-
-    template <typename T1,                     // best fix to: TStackData,
-              template <typename> typename M1, // best fix to: TParticleInterface,
-              template <class T2, template <class> class T3> class MSecondaryProducer>
-    friend class SecondaryView; // access for SecondaryView
+                       TParticleInterface>; // for access to getIndex for Stack
+    friend class Stack<TStackData&, TParticleInterface>; // for access to getIndex
+                                                         // SecondaryView : public Stack
+    friend class ParticleBase<StackIteratorInterface>;   // for access to getStackDataType
 
-    friend class StackIteratorInterface<TStackData, TParticleInterface, StackType>;
+    template <typename T1,                     // best fix this to: TStackData,
+              template <typename> typename M1, // best fix this to: TParticleInterface,
+              template <typename T, template <typename> typename T3> typename M2>
+    friend class SecondaryView; // access grant for SecondaryView
 
-    template <typename T, template <typename> typename ParticleInterface>
+    template <typename T, template <typename> typename TParticleInterface_>
     friend class corsika::history::HistorySecondaryProducer;
 
+    friend class ConstStackIteratorInterface<TStackData, TParticleInterface, TStackType>;
+
   protected:
     unsigned int index_ = 0;
 
   private:
-    const StackType* data_ = 0; // info: Particles and StackIterators become invalid when
-                                // parent Stack is copied or deleted!
+    TStackType* data_ = 0; // info: Particles and StackIterators become invalid when
+                           // parent Stack is copied or deleted!
+
+  }; // end class StackIterator
+
+  /**
+     This is the iterator class for const-access to stack data.
+
+     The const counterpart of StackIteratorInterface, which is used
+     for read-only iterator access on particle stack:
+
+     \verbatim
+     for (auto const& p : theStack) { E += p.getEnergy(); }
+     \endverbatim
+
+     See documentation of StackIteratorInterface for more details:
+     \sa StackIteratorInterface
+   */
+
+  template <typename TStackData, template <typename> typename TParticleInterface,
+            typename TStackType = Stack<TStackData, TParticleInterface>>
+  class ConstStackIteratorInterface
+      : public TParticleInterface<
+            ConstStackIteratorInterface<TStackData, TParticleInterface, TStackType>> {
+
+  public:
+    typedef TParticleInterface<
+        ConstStackIteratorInterface<TStackData, TParticleInterface, TStackType>>
+        particle_interface_type;
 
     // we don't want to allow dangling iterators to exist
-    ConstStackIteratorInterface() = delete;
+    ConstStackIteratorInterface() = delete; //! \todo check rule of five
 
   public:
     ConstStackIteratorInterface(ConstStackIteratorInterface&& rhs)
         : index_(std::move(rhs.index_))
         , data_(std::move(rhs.data_)) {}
 
-    ConstStackIteratorInterface(const StackType& data, const unsigned int index)
+    ConstStackIteratorInterface(TStackType const& data, unsigned int const index)
         : index_(index)
         , data_(&data) {}
 
-    /**
-       @class ConstStackIteratorInterface
-
-       The const counterpart of StackIteratorInterface, which is used
-       for read-only iterator access on particle stack:
-
-       \verbatim
-       for (const auto& p : theStack) { E += p.GetEnergy(); }
-       \endverbatim
-
-       See documentation of StackIteratorInterface for more details.
-    **/
-
-    bool isDeleted() const { return GetStack().isDeleted(*this); }
+    bool isErased() const { return getStack().isErased(*this); }
 
-  public:
     /** @name Iterator interface
-     **/
-    ///@{
+        @{
+     */
     ConstStackIteratorInterface& operator++() {
       do {
         ++index_;
       } while (
-          GetStack().isDeleted(*this)); // this also check the allowed bounds of index_
+          getStack().isErased(*this)); // this also check the allowed bounds of index_
       return *this;
     }
     ConstStackIteratorInterface operator++(int) {
@@ -313,45 +295,70 @@ namespace corsika {
       do {
         ++index_;
       } while (
-          GetStack().isDeleted(*this)); // this also check the allowed bounds of index_
+          getStack().isErased(*this)); // this also check the allowed bounds of index_
       return tmp;
     }
-    ConstStackIteratorInterface operator+(const int delta) const {
+    ConstStackIteratorInterface operator+(int const delta) const {
       return ConstStackIteratorInterface(*data_, index_ + delta);
     }
-    bool operator==(const ConstStackIteratorInterface& rhs) const {
+    bool operator==(ConstStackIteratorInterface const& rhs) const {
       return index_ == rhs.index_;
     }
-    bool operator!=(const ConstStackIteratorInterface& rhs) const {
+    bool operator!=(ConstStackIteratorInterface const& rhs) const {
       return index_ != rhs.index_;
     }
-    bool operator==(const StackIteratorInterface<TStackData, TParticleInterface,
-                                                 StackType>& rhs) const {
+    bool operator==(StackIteratorInterface<TStackData, TParticleInterface,
+                                           TStackType> const& rhs) const {
       return index_ == rhs.index_;
     }
-    bool operator!=(const StackIteratorInterface<TStackData, TParticleInterface,
-                                                 StackType>& rhs) const {
+    bool operator!=(StackIteratorInterface<TStackData, TParticleInterface,
+                                           TStackType> const& rhs) const {
       return index_ != rhs.index_;
     }
 
-    const ParticleInterfaceType& operator*() const {
-      return static_cast<const ParticleInterfaceType&>(*this);
+    particle_interface_type const& operator*() const {
+      return static_cast<particle_interface_type const&>(*this);
     }
     ///@}
 
   protected:
     /** @name Stack data access
         Only the const versions for read-only access
-    **/
-    ///@{
-    inline unsigned int GetIndex() const { return index_; }
-    inline const StackType& GetStack() const { return *data_; }
-    inline const TStackData& GetStackData() const { return data_->GetStackData(); }
+        @{
+     */
+    inline unsigned int getIndex() const { return index_; }
+    inline TStackType const& getStack() const { return *data_; }
+    inline TStackData const& getStackData() const { return data_->getStackData(); }
     /// Get data index as mapped in Stack class
-    inline unsigned int GetIndexFromIterator() const {
-      return data_->GetIndexFromIterator(index_);
+    inline unsigned int getIndexFromIterator() const {
+      return data_->getIndexFromIterator(index_);
     }
     ///@}
+
+    // friends are needed for access to protected methods
+    friend class Stack<TStackData,
+                       TParticleInterface>; // for access to GetIndex for Stack
+    friend class Stack<TStackData&, TParticleInterface>; // for access to GetIndex
+
+    friend class ParticleBase<ConstStackIteratorInterface>; // for access to GetStackData
+
+    template <typename T1,                     // best fix to: TStackData,
+              template <typename> typename M1, // best fix to: TParticleInterface,
+              template <class T2, template <class> class T3> class MSecondaryProducer>
+    friend class SecondaryView; // access for SecondaryView
+
+    friend class StackIteratorInterface<TStackData, TParticleInterface, TStackType>;
+
+    template <typename T, template <typename> typename TParticleInterface_>
+    friend class corsika::history::HistorySecondaryProducer;
+
+  protected:
+    unsigned int index_ = 0;
+
+  private:
+    TStackType const* data_ = 0; // info: Particles and StackIterators become invalid when
+                                 // parent Stack is copied or deleted!
+
   }; // end class ConstStackIterator
 
 } // namespace corsika
diff --git a/corsika/stack/DummyStack.hpp b/corsika/stack/DummyStack.hpp
index af2169843..d2f8323e8 100644
--- a/corsika/stack/DummyStack.hpp
+++ b/corsika/stack/DummyStack.hpp
@@ -8,7 +8,6 @@
 
 #pragma once
 
-
 #include <corsika/framework/core/ParticleProperties.hpp>
 #include <corsika/framework/core/PhysicalUnits.hpp>
 #include <corsika/framework/stack/Stack.hpp>
@@ -16,82 +15,74 @@
 #include <string>
 #include <tuple>
 
-namespace corsika {
-
-
-    /**
-     * Example of a particle object on the stack, with NO DATA.
-     */
-
-    /**
-       however, conceptually we need to provide fake data. A stack without data does not
-       work...
-     */
+namespace corsika::dummy_stack {
 
-    struct NoData { /* nothing */
-      int nothing = 0;
-    };
+  /**
+   * Example of a particle object on the stack, with NO DATA.
+   */
 
-    template <typename StackIteratorInterface>
-    struct ParticleInterface : public corsika::ParticleBase<StackIteratorInterface> {
+  /**
+     however, conceptually we need to provide fake data. A stack without data does not
+     work...
+   */
 
-    	typedef corsika::ParticleBase<StackIteratorInterface> super_type;
+  struct NoData { /* nothing */
+    int nothing = 0;
+  };
 
-    public:
-      void SetParticleData(const std::tuple<NoData>& /*v*/) {}
-      void SetParticleData(super_type& /*parent*/,
-                           const std::tuple<NoData>& /*v*/) {}
+  template <typename StackIteratorInterface>
+  struct ParticleInterface : public corsika::ParticleBase<StackIteratorInterface> {
 
-      std::string as_string() const { return "dummy-data"; }
-    };
+    typedef corsika::ParticleBase<StackIteratorInterface> super_type;
 
-    /**
-     *
-     * Memory implementation of the most simple (no-data) particle stack object.
-     */
+  public:
+    void setParticleData(const std::tuple<NoData>& /*v*/) {}
+    void setParticleData(super_type& /*parent*/, const std::tuple<NoData>& /*v*/) {}
 
-    class DummyStackImpl {
+    std::string as_string() const { return "dummy-data"; }
+  };
 
-    public:
-    DummyStackImpl()=default;
+  /**
+   *
+   * Memory implementation of the most simple (no-data) particle stack object.
+   */
 
-    DummyStackImpl( DummyStackImpl const&)=default;
+  class DummyStackImpl {
 
-    DummyStackImpl(DummyStackImpl &&)=default;
+  public:
+    DummyStackImpl() = default;
 
-    DummyStackImpl& operator=( DummyStackImpl const& )=default;
-    DummyStackImpl& operator=( DummyStackImpl && )=default;
+    DummyStackImpl(DummyStackImpl const&) = default;
 
+    DummyStackImpl(DummyStackImpl&&) = default;
 
-      void init() { entries_ = 0; }
+    DummyStackImpl& operator=(DummyStackImpl const&) = default;
+    DummyStackImpl& operator=(DummyStackImpl&&) = default;
 
-      void clear() { entries_ = 0; }
+    void init() { entries_ = 0; }
 
-      int getSize() const { return entries_; }
-      int getCapacity() const { return entries_; }
+    void clear() { entries_ = 0; }
 
-      /**
-       *   Function to copy particle at location i2 in stack to i1
-       */
-      void copy(const int /*i1*/, const int /*i2*/) {}
+    int getSize() const { return entries_; }
+    int getCapacity() const { return entries_; }
 
-      void incrementSize() { entries_++; }
-      void decrementSize() { entries_--; }
+    /**
+     *   Function to copy particle at location i2 in stack to i1
+     */
+    void copy(const int /*i1*/, const int /*i2*/) {}
 
-	int getEntries() const {
-		return entries_;
-	}
+    void incrementSize() { entries_++; }
+    void decrementSize() { entries_--; }
 
-	void setEntries(int entries = 0) {
-		entries_ = entries;
-	}
+    int getEntries() const { return entries_; }
 
-    private:
-      int entries_ = 0;
+    void setEntries(int entries = 0) { entries_ = entries; }
 
-    }; // end class DummyStackImpl
+  private:
+    int entries_ = 0;
 
-    typedef Stack<DummyStackImpl, ParticleInterface> DummyStack;
+  }; // end class DummyStackImpl
 
+  typedef Stack<DummyStackImpl, ParticleInterface> DummyStack;
 
-} // namespace corsika
+} // namespace corsika::dummy_stack
diff --git a/corsika/stack/GeometryNodeStackExtension.hpp b/corsika/stack/GeometryNodeStackExtension.hpp
index 6c0c89b74..fe88d6f04 100644
--- a/corsika/stack/GeometryNodeStackExtension.hpp
+++ b/corsika/stack/GeometryNodeStackExtension.hpp
@@ -8,26 +8,26 @@
 
 #pragma once
 
-//#include <corsika/framework/logging/Logging.hpp>
+#include <corsika/framework/logging/Logging.hpp>
 #include <corsika/framework/stack/Stack.hpp>
 
 #include <tuple>
 #include <utility>
 #include <vector>
 
-namespace corsika::stack::node {
+namespace corsika::node {
 
   /**
-   * @class GeometryDataInterface
-   *
-   * corresponding defintion of a stack-readout object, the iteractor
+   * Describe "volume node" data on a Stack.
+   * 
+   * Corresponding defintion of a stack-readout object, the iteractor
    * dereference operator will deliver access to these function
-  // defintion of a stack-readout object, the iteractor dereference
-  // operator will deliver access to these function
+   * defintion of a stack-readout object, the iteractor dereference
+   * operator will deliver access to these function
    */
 
   /**
-   * \fixme Document type T
+   * \todo fixme: Document type T
    */
   template <typename T, typename TEnvType>
   struct GeometryDataInterface : public T {
@@ -56,11 +56,11 @@ namespace corsika::stack::node {
     }
 
     void setNode(node_type const* v) {
-    	super_type::GetStackData().setNode(super_type::GetIndex(), v);
+    	super_type::getStackData().setNode(super_type::getIndex(), v);
     }
 
     node_type const* getNode() const {
-    	return super_type::GetStackData().getNode(super_type::GetIndex());
+    	return super_type::getStackData().getNode(super_type::getIndex());
     }
   };
 
diff --git a/corsika/stack/NuclearStackExtension.hpp b/corsika/stack/NuclearStackExtension.hpp
index 46809532a..520accc5b 100644
--- a/corsika/stack/NuclearStackExtension.hpp
+++ b/corsika/stack/NuclearStackExtension.hpp
@@ -19,374 +19,345 @@
 #include <tuple>
 #include <vector>
 
-namespace corsika {
-
-/**
- * @namespace nuclear_extension
- *
- * Add A and Z data to existing stack (currently SuperStupidStack) of particle
- * properties. This is done via inheritance, not via CombinedStack since the nuclear
- * data is stored ONLY when needed (for nuclei) and not for all particles. Thus, this is
- * a new, derived Stack object.
- *
- * Only for Code::Nucleus particles A and Z are stored, not for all
- * normal elementary particles.
- *
- * Thus in your code, make sure to always check <code>
- * particle.GetPID()==Code::Nucleus </code> before attempting to
- * read any nuclear information.
- *
- *
- */
-
-
-/**
- * @class NuclearParticleInterface
- *
- * Define ParticleInterface for NuclearStackExtension Stack derived from
- * ParticleInterface of Inner stack class
- */
-template < template <typename> class InnerParticleInterface, typename StackIteratorInterface>
-struct NuclearParticleInterface : public  InnerParticleInterface<StackIteratorInterface>  {
-
-	typedef  InnerParticleInterface<StackIteratorInterface>  super_type;
-
-
-
-public:
-
-
-	typedef std::tuple<
-			corsika::Code, corsika::units::si::HEPEnergyType,
-			momentum_type, corsika::Point,
-		    corsika::units::si::TimeType> particle_data_type;
-
-	typedef std::tuple<
-			corsika::Code, corsika::units::si::HEPEnergyType,
-			momentum_type, corsika::Point,
-			corsika::units::si::TimeType,
-			unsigned short, unsigned short> altenative_particle_data_type;
-
-
-	typedef corsika::Vector<corsika::units::si::hepmomentum_d> momentum_type;
-
-	void setParticleData(particle_data_type const& v) {
-
-		if (std::get<0>(v) == corsika::Code::Nucleus) {
-			std::ostringstream err;
-			err << "NuclearStackExtension: no A and Z specified for new Nucleus!";
-			throw std::runtime_error(err.str());
-		}
-
-		super_type::setParticleData(v);
-		setNucleusRef(-1); // this is not a nucleus
-	}
-
-	void setParticleData( altenative_particle_data_type const& v)
-	{
-		const unsigned short A = std::get<5>(v);
-		const unsigned short Z = std::get<6>(v);
-		if (std::get<0>(v) != corsika::Code::Nucleus || A == 0 || Z == 0) {
-			std::ostringstream err;
-			err << "NuclearStackExtension: no A and Z specified for new Nucleus!";
-			throw std::runtime_error(err.str());
-		}
-		setNucleusRef(super_type::GetStackData().getNucleusNextRef()); // store this nucleus data ref
-		setNuclearA(A);
-		setNuclearZ(Z);
-		super_type::setParticleData(particle_data_type{std::get<0>(v), std::get<1>(v),
-			std::get<2>(v), std::get<3>(v),	std::get<4>(v)});
-	}
-
-	void setParticleData( super_type& p, particle_data_type const& v)
-	{
-		if (std::get<0>(v) == corsika::Code::Nucleus) {
-			std::ostringstream err;
-			err << "NuclearStackExtension: no A and Z specified for new Nucleus!";
-			throw std::runtime_error(err.str());
-		}
-
-		super_type::setParticleData(p, particle_data_type{std::get<0>(v), std::get<1>(v),
-			std::get<2>(v), std::get<3>(v),	std::get<4>(v)});
-
-		setNucleusRef(-1); // this is not a nucleus
-	}
-
-	void setParticleData( super_type& p, altenative_particle_data_type const& v) {
-
-		const unsigned short A = std::get<5>(v);
-		const unsigned short Z = std::get<6>(v);
-
-		if (std::get<0>(v) != corsika::Code::Nucleus || A == 0 || Z == 0) {
-			std::ostringstream err;
-			err << "NuclearStackExtension: no A and Z specified for new Nucleus!";
-			throw std::runtime_error(err.str());
-		}
-
-		setNucleusRef(super_type::GetStackData().getNucleusNextRef()); // store this nucleus data ref
-		setNuclearA(A);
-		setNuclearZ(Z);
-		super_type::setParticleData(p, particle_data_type{std::get<0>(v), std::get<1>(v),
-			std::get<2>(v), std::get<3>(v),
-			std::get<4>(v)});
-	}
-
-	std::string as_string() const {
-		return fmt::format(
-				"{}, nuc({})", super_type::as_string(),
-				(isNucleus() ? fmt::format("A={}, Z={}", getNuclearA(), getNuclearZ())
-						: "n/a"));
-	}
-
-	/**
-	 * @name individual setters
-	 * @{
-	 */
-	void setNuclearA(const unsigned short vA) {
-		super_type::GetStackData().setNuclearA(super_type::GetIndex(), vA);
-	}
-	void setNuclearZ(const unsigned short vZ) {
-		super_type::GetStackData().setNuclearZ(super_type::GetIndex(), vZ);
-	}
-	/// @}
-
-	/**
-	 * @name individual getters
-	 * @{
-	 */
-	int getNuclearA() const { return super_type::GetStackData().getNuclearA(super_type::GetIndex()); }
-	int getNuclearZ() const { return super_type::GetStackData().getNuclearZ(super_type::GetIndex()); }
-	/// @}
-
-	/**
-	 * Overwrite normal GetParticleMass function with nuclear version
-	 */
-	corsika::units::si::HEPMassType getMass() const {
-		if (super_type::GetPID() ==
-				corsika::Code::Nucleus)
-			return corsika::GetNucleusMass(getNuclearA(), getNuclearZ());
-		return super_type::getMass();
-	}
-	/**
-	 * Overwirte normal GetChargeNumber function with nuclear version
-	 **/
-	int16_t getChargeNumber() const {
-		if (super_type::GetPID() ==
-				corsika::Code::Nucleus)
-			return getNuclearZ();
-		return super_type::getChargeNumber();
-	}
-
-	int getNucleusRef() const {
-		return super_type::GetStackData().getNucleusRef(GetIndex());
-	} // LCOV_EXCL_LINE
-
-protected:
-
-	void setNucleusRef(const int vR) {
-		super_type::GetStackData().setNucleusRef(super_type::GetIndex(), vR);
-	}
-
-	bool isNucleus() const {
-		return super_type::GetStackData().isNucleus(super_type::GetIndex());
-	}
-};
-
-/**
- * @class NuclearStackExtension
- *
- * Memory implementation of adding nuclear inforamtion to the
- * existing particle stack defined in class InnerStackImpl.
- *
- * Inside the NuclearStackExtension class there is a dedicated
- * fNucleusRef index, where fNucleusRef[i] is referring to the
- * correct A and Z for a specific particle index i. fNucleusRef[i]
- * == -1 means that this is not a nucleus, and a subsequent call to
- * GetNucleusA would produce an exception.
- */
-template <typename InnerStackImpl>
-class NuclearStackExtensionImpl : public InnerStackImpl {
-
-	typedef InnerStackImpl super_type;
-
-public:
-
-	typedef std::vector<int>            nucleus_ref_type;
-	typedef std::vector<unsigned short>   nuclear_a_type;
-	typedef std::vector<unsigned short>   nuclear_z_type;
-
-
-	NuclearStackExtensionImpl()= default;
-
-	NuclearStackExtensionImpl( NuclearStackExtensionImpl<InnerStackImpl> const&)= default;
-
-	NuclearStackExtensionImpl( NuclearStackExtensionImpl<InnerStackImpl> &&)= default;
-
-	NuclearStackExtensionImpl<InnerStackImpl>&
-	operator=( NuclearStackExtensionImpl<InnerStackImpl> const&)= default;
-
-	NuclearStackExtensionImpl<InnerStackImpl>&
-	operator=( NuclearStackExtensionImpl<InnerStackImpl> &&)= default;
-
-	void init() {
-		super_type::init();
-	}
-
-	void dump() {
-		super_type::dump();
-	}
-
-	void clear() {
-		super_type::clear();
-		nucleusRef_.clear();
-		nuclearA_.clear();
-		nuclearZ_.clear();
-	}
-
-	unsigned int getSize() const {
-		return nucleusRef_.size();
-	}
-
-	unsigned int getCapacity() const {
-		return nucleusRef_.capacity();
-	}
-
-	void setNuclearA(const unsigned int i, const unsigned short vA) {
-		nuclearA_[getNucleusRef(i)] = vA;
-	}
-
-	void setNuclearZ(const unsigned int i, const unsigned short vZ) {
-		nuclearZ_[getNucleusRef(i)] = vZ;
-	}
-
-	void setNucleusRef(const unsigned int i, const int v) {
-		nucleusRef_[i] = v;
-	}
-
-	int getNuclearA(const unsigned int i) const {
-		return nuclearA_[getNucleusRef(i)];
-	}
-
-	int getNuclearZ(const unsigned int i) const {
-		return nuclearZ_[getNucleusRef(i)];
-	}
-	// this function will create new storage for Nuclear Properties, and return the
-			// reference to it
-	int getNucleusNextRef() {
-		nuclearA_.push_back(0);
-		nuclearZ_.push_back(0);
-		return nuclearA_.size() - 1;
-	}
-
-	int getNucleusRef(const unsigned int i) const {
-		if (nucleusRef_[i] >= 0) return nucleusRef_[i];
-		std::ostringstream err;
-		err << "NuclearStackExtension: no nucleus at ref=" << i;
-		throw std::runtime_error(err.str());
-	}
-
-	bool isNucleus(const unsigned int i) const { return nucleusRef_[i] >= 0; }
-
-	/**
-	 *   Function to copy particle at location i1 in stack to i2
-	 */
-	void copy(const unsigned int i1, const unsigned int i2) {
-		// index range check
-		if (i1 >= getSize() || i2 >= getSize()) {
-			std::ostringstream err;
-			err << "NuclearStackExtension: trying to access data beyond size of stack!";
-			throw std::runtime_error(err.str());
-		}
-		// copy internal particle data p[i2] = p[i1]
-		super_type::copy(i1, i2);
-		// check if any of p[i1] or p[i2] was a Code::Nucleus
-		const int ref1 = nucleusRef_[i1];
-		const int ref2 = nucleusRef_[i2];
-		if (ref2 < 0) {
-			if (ref1 >= 0) {
-				// i1 is nucleus, i2 is not
-				nucleusRef_[i2] = getNucleusNextRef();
-				nuclearA_[nucleusRef_[i2]] = nuclearA_[ref1];
-				nuclearZ_[nucleusRef_[i2]] = nuclearZ_[ref1];
-			} else {
-				// neither i1 nor i2 are nuclei
-			}
-		} else {
-			if (ref1 >= 0) {
-				// both are nuclei, i2 is overwritten with nucleus i1
-				// fNucleusRef stays the same, but A and Z data is overwritten
-				nuclearA_[ref2] = nuclearA_[ref1];
-				nuclearZ_[ref2] = nuclearZ_[ref1];
-			} else {
-				// i2 is overwritten with non-nucleus i1
-				nucleusRef_[i2] = -1;                       // flag as non-nucleus
-				nuclearA_.erase(nuclearA_.cbegin() + ref2); // remove data for i2
-				nuclearZ_.erase(nuclearZ_.cbegin() + ref2); // remove data for i2
-				const int n = nucleusRef_.size(); // update fNucleusRef: indices above ref2
-				// must be decremented by 1
-				for (int i = 0; i < n; ++i) {
-					if (nucleusRef_[i] > ref2) { nucleusRef_[i] -= 1; }
-				}
-			}
-		}
-	}
-
-	/**
-	 *   Function to copy particle at location i2 in stack to i1
-	 */
-	void swap(const unsigned int i1, const unsigned int i2) {
-		// index range check
-		if (i1 >= getSize() || i2 >= getSize()) {
-			std::ostringstream err;
-			err << "NuclearStackExtension: trying to access data beyond size of stack!";
-			throw std::runtime_error(err.str());
-		}
-		// swap original particle data
-		super_type::swap(i1, i2);
-		// swap corresponding nuclear reference data
-		std::swap(nucleusRef_[i2], nucleusRef_[i1]);
-	}
-
-	void incrementSize() {
-		super_type::incrementSize();
-		nucleusRef_.push_back(-1);
-	}
-
-	void decrementSize() {
-		super_type::decrementSize();
-		if (nucleusRef_.size() > 0) {
-			const int ref = nucleusRef_.back();
-			nucleusRef_.pop_back();
-			if (ref >= 0) {
-				nuclearA_.erase(nuclearA_.begin() + ref);
-				nuclearZ_.erase(nuclearZ_.begin() + ref);
-				const int n = nucleusRef_.size();
-				for (int i = 0; i < n; ++i) {
-					if (nucleusRef_[i] >= ref) { nucleusRef_[i] -= 1; }
-				}
-			}
-		}
-	}
-
-private:
-	/// the actual memory to store particle data
-
-	nucleus_ref_type nucleusRef_;
-	nuclear_a_type     nuclearA_;
-	nuclear_z_type     nuclearZ_;
-
-}; // end class NuclearStackExtensionImpl
-
-template <typename InnerStack, template <typename> typename _PI>
-using NuclearStackExtension =
-		Stack<NuclearStackExtensionImpl<typename InnerStack::StackImpl>, _PI> ;
-
-//
-template <typename StackIter>
-using ExtendedParticleInterfaceType = NuclearParticleInterface<SuperStupidStack, StackIter>;
-
-// the particle data stack with extra nuclear information:
-using ParticleDataStack = NuclearStackExtension<SuperStupidStack, ExtendedParticleInterfaceType>;
-
-
-} // namespace corsika
+namespace corsika::nuclear_stack {
+
+  /**
+   *
+   * Define ParticleInterface for NuclearStackExtension Stack derived from
+   * ParticleInterface of Inner stack class
+   *
+   * Add A and Z data to existing stack (currently SuperStupidStack) of particle
+   * properties. This is done via inheritance, not via CombinedStack since the nuclear
+   * data is stored ONLY when needed (for nuclei) and not for all particles. Thus, this is
+   * a new, derived Stack object.
+   *
+   * Only for Code::Nucleus particles A and Z are stored, not for all
+   * normal elementary particles.
+   *
+   * Thus in your code, make sure to always check <code>
+   * particle.getPID()==Code::Nucleus </code> before attempting to
+   * read any nuclear information.
+   */
+  template <template <typename> class InnerParticleInterface,
+            typename StackIteratorInterface>
+  struct NuclearParticleInterface
+      : public InnerParticleInterface<StackIteratorInterface> {
+
+    typedef InnerParticleInterface<StackIteratorInterface> super_type;
+
+  public:
+    typedef std::tuple<Code, HEPEnergyType, simple_stack::MomentumVector, Point, TimeType>
+        particle_data_type;
+
+    typedef std::tuple<Code, HEPEnergyType, simple_stack::MomentumVector, Point, TimeType,
+                       unsigned short, unsigned short>
+        altenative_particle_data_type;
+
+    void setParticleData(particle_data_type const& v) {
+
+      if (std::get<0>(v) == Code::Nucleus) {
+        std::ostringstream err;
+        err << "NuclearStackExtension: no A and Z specified for new Nucleus!";
+        throw std::runtime_error(err.str());
+      }
+
+      super_type::setParticleData(v);
+      setNucleusRef(-1); // this is not a nucleus
+    }
+
+    void setParticleData(altenative_particle_data_type const& v) {
+      const unsigned short A = std::get<5>(v);
+      const unsigned short Z = std::get<6>(v);
+      if (std::get<0>(v) != Code::Nucleus || A == 0 || Z == 0) {
+        std::ostringstream err;
+        err << "NuclearStackExtension: no A and Z specified for new Nucleus!";
+        throw std::runtime_error(err.str());
+      }
+      setNucleusRef(
+          super_type::getStackData().getNucleusNextRef()); // store this nucleus data ref
+      setNuclearA(A);
+      setNuclearZ(Z);
+      super_type::setParticleData(particle_data_type{std::get<0>(v), std::get<1>(v),
+                                                     std::get<2>(v), std::get<3>(v),
+                                                     std::get<4>(v)});
+    }
+
+    void setParticleData(super_type& p, particle_data_type const& v) {
+      if (std::get<0>(v) == Code::Nucleus) {
+        std::ostringstream err;
+        err << "NuclearStackExtension: no A and Z specified for new Nucleus!";
+        throw std::runtime_error(err.str());
+      }
+
+      super_type::setParticleData(
+          p, particle_data_type{std::get<0>(v), std::get<1>(v), std::get<2>(v),
+                                std::get<3>(v), std::get<4>(v)});
+
+      setNucleusRef(-1); // this is not a nucleus
+    }
+
+    void setParticleData(super_type& p, altenative_particle_data_type const& v) {
+
+      const unsigned short A = std::get<5>(v);
+      const unsigned short Z = std::get<6>(v);
+
+      if (std::get<0>(v) != Code::Nucleus || A == 0 || Z == 0) {
+        std::ostringstream err;
+        err << "NuclearStackExtension: no A and Z specified for new Nucleus!";
+        throw std::runtime_error(err.str());
+      }
+
+      setNucleusRef(
+          super_type::getStackData().getNucleusNextRef()); // store this nucleus data ref
+      setNuclearA(A);
+      setNuclearZ(Z);
+      super_type::setParticleData(
+          p, particle_data_type{std::get<0>(v), std::get<1>(v), std::get<2>(v),
+                                std::get<3>(v), std::get<4>(v)});
+    }
+
+    std::string as_string() const {
+      return fmt::format(
+          "{}, nuc({})", super_type::as_string(),
+          (isNucleus() ? fmt::format("A={}, Z={}", getNuclearA(), getNuclearZ())
+                       : "n/a"));
+    }
+
+    /**
+     * @name individual setters
+     * @{
+     */
+    void setNuclearA(const unsigned short vA) {
+      super_type::getStackData().setNuclearA(super_type::getIndex(), vA);
+    }
+    void setNuclearZ(const unsigned short vZ) {
+      super_type::getStackData().setNuclearZ(super_type::getIndex(), vZ);
+    }
+    /// @}
+
+    /**
+     * @name individual getters
+     * @{
+     */
+    int getNuclearA() const {
+      return super_type::getStackData().getNuclearA(super_type::getIndex());
+    }
+    int getNuclearZ() const {
+      return super_type::getStackData().getNuclearZ(super_type::getIndex());
+    }
+    /// @}
+
+    /**
+     * Overwrite normal getParticleMass function with nuclear version
+     */
+    HEPMassType getMass() const {
+      if (super_type::getPID() == Code::Nucleus)
+        return getNucleusMass(getNuclearA(), getNuclearZ());
+      return super_type::getMass();
+    }
+    /**
+     * Overwirte normal getChargeNumber function with nuclear version
+     **/
+    int16_t getChargeNumber() const {
+      if (super_type::getPID() == Code::Nucleus) return getNuclearZ();
+      return super_type::getChargeNumber();
+    }
+
+    int getNucleusRef() const {
+      return super_type::getStackData().getNucleusRef(super_type::getIndex());
+    } // LCOV_EXCL_LINE
+
+  protected:
+    void setNucleusRef(const int vR) {
+      super_type::getStackData().setNucleusRef(super_type::getIndex(), vR);
+    }
+
+    bool isNucleus() const {
+      return super_type::getStackData().isNucleus(super_type::getIndex());
+    }
+  };
+
+  /**
+   * @class NuclearStackExtension
+   *
+   * Memory implementation of adding nuclear inforamtion to the
+   * existing particle stack defined in class InnerStackImpl.
+   *
+   * Inside the NuclearStackExtension class there is a dedicated
+   * fNucleusRef index, where fNucleusRef[i] is referring to the
+   * correct A and Z for a specific particle index i. fNucleusRef[i]
+   * == -1 means that this is not a nucleus, and a subsequent call to
+   * getNucleusA would produce an exception.
+   */
+  template <typename InnerStackImpl>
+  class NuclearStackExtensionImpl : public InnerStackImpl {
+
+    typedef InnerStackImpl super_type;
+
+  public:
+    typedef std::vector<int> nucleus_ref_type;
+    typedef std::vector<unsigned short> nuclear_a_type;
+    typedef std::vector<unsigned short> nuclear_z_type;
+
+    NuclearStackExtensionImpl() = default;
+
+    NuclearStackExtensionImpl(NuclearStackExtensionImpl<InnerStackImpl> const&) = default;
+
+    NuclearStackExtensionImpl(NuclearStackExtensionImpl<InnerStackImpl>&&) = default;
+
+    NuclearStackExtensionImpl<InnerStackImpl>& operator=(
+        NuclearStackExtensionImpl<InnerStackImpl> const&) = default;
+
+    NuclearStackExtensionImpl<InnerStackImpl>& operator=(
+        NuclearStackExtensionImpl<InnerStackImpl>&&) = default;
+
+    void init() { super_type::init(); }
+
+    void dump() { super_type::dump(); }
+
+    void clear() {
+      super_type::clear();
+      nucleusRef_.clear();
+      nuclearA_.clear();
+      nuclearZ_.clear();
+    }
+
+    unsigned int getSize() const { return nucleusRef_.size(); }
+
+    unsigned int getCapacity() const { return nucleusRef_.capacity(); }
+
+    void setNuclearA(const unsigned int i, const unsigned short vA) {
+      nuclearA_[getNucleusRef(i)] = vA;
+    }
+
+    void setNuclearZ(const unsigned int i, const unsigned short vZ) {
+      nuclearZ_[getNucleusRef(i)] = vZ;
+    }
+
+    void setNucleusRef(const unsigned int i, const int v) { nucleusRef_[i] = v; }
+
+    int getNuclearA(const unsigned int i) const { return nuclearA_[getNucleusRef(i)]; }
+
+    int getNuclearZ(const unsigned int i) const { return nuclearZ_[getNucleusRef(i)]; }
+    // this function will create new storage for Nuclear Properties, and return the
+    // reference to it
+    int getNucleusNextRef() {
+      nuclearA_.push_back(0);
+      nuclearZ_.push_back(0);
+      return nuclearA_.size() - 1;
+    }
+
+    int getNucleusRef(const unsigned int i) const {
+      if (nucleusRef_[i] >= 0) return nucleusRef_[i];
+      std::ostringstream err;
+      err << "NuclearStackExtension: no nucleus at ref=" << i;
+      throw std::runtime_error(err.str());
+    }
+
+    bool isNucleus(const unsigned int i) const { return nucleusRef_[i] >= 0; }
+
+    /**
+     *   Function to copy particle at location i1 in stack to i2
+     */
+    void copy(const unsigned int i1, const unsigned int i2) {
+      // index range check
+      if (i1 >= getSize() || i2 >= getSize()) {
+        std::ostringstream err;
+        err << "NuclearStackExtension: trying to access data beyond size of stack!";
+        throw std::runtime_error(err.str());
+      }
+      // copy internal particle data p[i2] = p[i1]
+      super_type::copy(i1, i2);
+      // check if any of p[i1] or p[i2] was a Code::Nucleus
+      const int ref1 = nucleusRef_[i1];
+      const int ref2 = nucleusRef_[i2];
+      if (ref2 < 0) {
+        if (ref1 >= 0) {
+          // i1 is nucleus, i2 is not
+          nucleusRef_[i2] = getNucleusNextRef();
+          nuclearA_[nucleusRef_[i2]] = nuclearA_[ref1];
+          nuclearZ_[nucleusRef_[i2]] = nuclearZ_[ref1];
+        } else {
+          // neither i1 nor i2 are nuclei
+        }
+      } else {
+        if (ref1 >= 0) {
+          // both are nuclei, i2 is overwritten with nucleus i1
+          // fNucleusRef stays the same, but A and Z data is overwritten
+          nuclearA_[ref2] = nuclearA_[ref1];
+          nuclearZ_[ref2] = nuclearZ_[ref1];
+        } else {
+          // i2 is overwritten with non-nucleus i1
+          nucleusRef_[i2] = -1;                       // flag as non-nucleus
+          nuclearA_.erase(nuclearA_.cbegin() + ref2); // remove data for i2
+          nuclearZ_.erase(nuclearZ_.cbegin() + ref2); // remove data for i2
+          const int n = nucleusRef_.size(); // update fNucleusRef: indices above ref2
+          // must be decremented by 1
+          for (int i = 0; i < n; ++i) {
+            if (nucleusRef_[i] > ref2) { nucleusRef_[i] -= 1; }
+          }
+        }
+      }
+    }
+
+    /**
+     *   Function to copy particle at location i2 in stack to i1
+     */
+    void swap(const unsigned int i1, const unsigned int i2) {
+      // index range check
+      if (i1 >= getSize() || i2 >= getSize()) {
+        std::ostringstream err;
+        err << "NuclearStackExtension: trying to access data beyond size of stack!";
+        throw std::runtime_error(err.str());
+      }
+      // swap original particle data
+      super_type::swap(i1, i2);
+      // swap corresponding nuclear reference data
+      std::swap(nucleusRef_[i2], nucleusRef_[i1]);
+    }
+
+    void incrementSize() {
+      super_type::incrementSize();
+      nucleusRef_.push_back(-1);
+    }
+
+    void decrementSize() {
+      super_type::decrementSize();
+      if (nucleusRef_.size() > 0) {
+        const int ref = nucleusRef_.back();
+        nucleusRef_.pop_back();
+        if (ref >= 0) {
+          nuclearA_.erase(nuclearA_.begin() + ref);
+          nuclearZ_.erase(nuclearZ_.begin() + ref);
+          const int n = nucleusRef_.size();
+          for (int i = 0; i < n; ++i) {
+            if (nucleusRef_[i] >= ref) { nucleusRef_[i] -= 1; }
+          }
+        }
+      }
+    }
+
+  private:
+    /// the actual memory to store particle data
+
+    nucleus_ref_type nucleusRef_;
+    nuclear_a_type nuclearA_;
+    nuclear_z_type nuclearZ_;
+
+  }; // end class NuclearStackExtensionImpl
+
+  template <typename TInnerStack, template <typename> typename PI_>
+  using NuclearStackExtension =
+      Stack<NuclearStackExtensionImpl<typename TInnerStack::stack_implementation_type>,
+            PI_>;
+
+  //
+  template <typename TStackIter>
+  using ExtendedParticleInterfaceType =
+      NuclearParticleInterface<simple_stack::SuperStupidStack::pi_type, TStackIter>;
+
+  // the particle data stack with extra nuclear information:
+  using ParticleDataStack = NuclearStackExtension<simple_stack::SuperStupidStack,
+                                                  ExtendedParticleInterfaceType>;
+
+} // namespace corsika::nuclear_stack
diff --git a/corsika/stack/SuperStupidStack.hpp b/corsika/stack/SuperStupidStack.hpp
index 34251a82b..a32ec7de6 100644
--- a/corsika/stack/SuperStupidStack.hpp
+++ b/corsika/stack/SuperStupidStack.hpp
@@ -20,261 +20,215 @@
 #include <tuple>
 #include <vector>
 
-namespace corsika {
+namespace corsika::simple_stack {
+
+  typedef corsika::Vector<hepmomentum_d>
+      MomentumVector; //! \todo this has to move to PhysicalUnits.hpp
+
+  /**
+   * Example of a particle object on the stack.
+   */
+
+  template <typename StackIteratorInterface>
+  struct ParticleInterface : public ParticleBase<StackIteratorInterface> {
+
+  private:
+    typedef corsika::ParticleBase<StackIteratorInterface> super_type;
+
+  public:
+    std::string as_string() const {
+      using namespace corsika::units::si;
+      return fmt::format("particle: i={}, PID={}, E={}GeV", super_type::getIndex(),
+                         corsika::get_name(this->getPID()), this->getEnergy() / 1_GeV);
+    }
+
+    void setParticleData(std::tuple<corsika::Code, HEPEnergyType, MomentumVector,
+                                    corsika::Point, TimeType> const& v) {
+      this->setPID(std::get<0>(v));
+      this->setEnergy(std::get<1>(v));
+      this->setMomentum(std::get<2>(v));
+      this->setPosition(std::get<3>(v));
+      this->setTime(std::get<4>(v));
+    }
+
+    void setParticleData(ParticleInterface<StackIteratorInterface> const&,
+                         std::tuple<corsika::Code, HEPEnergyType, MomentumVector,
+                                    corsika::Point, TimeType> const& v) {
+      this->setPID(std::get<0>(v));
+      this->setEnergy(std::get<1>(v));
+      this->setMomentum(std::get<2>(v));
+      this->setPosition(std::get<3>(v));
+      this->setTime(std::get<4>(v));
+    }
+
+    /// individual setters
+    void setPID(corsika::Code const id) {
+      super_type::getStackData().setPID(super_type::getIndex(), id);
+    }
+    void setEnergy(HEPEnergyType const& e) {
+      super_type::getStackData().setEnergy(super_type::getIndex(), e);
+    }
+    void setMomentum(MomentumVector const& v) {
+      super_type::getStackData().setMomentum(super_type::getIndex(), v);
+    }
+    void setPosition(corsika::Point const& v) {
+      super_type::getStackData().setPosition(super_type::getIndex(), v);
+    }
+    void setTime(TimeType const& v) {
+      super_type::getStackData().setTime(super_type::getIndex(), v);
+    }
+
+    /// individual getters
+    corsika::Code getPID() const {
+      return super_type::getStackData().getPID(super_type::getIndex());
+    }
+    HEPEnergyType getEnergy() const {
+      return super_type::getStackData().getEnergy(super_type::getIndex());
+    }
+    MomentumVector getMomentum() const {
+      return super_type::getStackData().getMomentum(super_type::getIndex());
+    }
+    corsika::Point getPosition() const {
+      return super_type::getStackData().getPosition(super_type::getIndex());
+    }
+    TimeType getTime() const {
+      return super_type::getStackData().getTime(super_type::getIndex());
+    }
+    /**
+     * @name derived quantities
+     *
+     * @{
+     */
+    corsika::Vector<dimensionless_d> getDirection() const {
+      return this->getMomentum() / this->getEnergy();
+    }
+
+    HEPMassType getMass() const { return corsika::get_mass(this->getPID()); }
+
+    int16_t getChargeNumber() const { return corsika::get_charge_number(this->getPID()); }
+    ///@}
+  };
+
+  /**
+   * Memory implementation of the most simple (stupid) particle stack object.
+   *
+   */
+
+  class SuperStupidStackImpl {
+
+  public:
+    typedef corsika::Vector<hepmomentum_d> momentum_type;
+    typedef std::vector<corsika::Code> code_vector_type;
+    typedef std::vector<HEPEnergyType> energy_vector_type;
+    typedef std::vector<corsika::Point> point_vector_type;
+    typedef std::vector<TimeType> time_vector_type;
+    typedef std::vector<MomentumVector> momentum_vector_type;
+
+    SuperStupidStackImpl() = default;
+
+    SuperStupidStackImpl(SuperStupidStackImpl const& other) = default;
+
+    SuperStupidStackImpl(SuperStupidStackImpl&& other) = default;
+
+    SuperStupidStackImpl& operator=(SuperStupidStackImpl const& other) = default;
+
+    SuperStupidStackImpl& operator=(SuperStupidStackImpl&& other) = default;
+
+    void init() {}
+    void dump() const {}
+
+    void clear() {
+      dataPID_.clear();
+      dataE_.clear();
+      momentum_.clear();
+      position_.clear();
+      time_.clear();
+    }
+
+    unsigned int getSize() const { return dataPID_.size(); }
+    unsigned int getCapacity() const { return dataPID_.size(); }
+
+    void setPID(size_t i, corsika::Code const id) { dataPID_[i] = id; }
+    void setEnergy(size_t i, HEPEnergyType const& e) { dataE_[i] = e; }
+    void setMomentum(size_t i, momentum_type const& v) { momentum_[i] = v; }
+    void setPosition(size_t i, corsika::Point const& v) { position_[i] = v; }
+    void setTime(size_t i, TimeType const& v) { time_[i] = v; }
+
+    corsika::Code getPID(size_t i) const { return dataPID_[i]; }
+
+    HEPEnergyType getEnergy(size_t i) const { return dataE_[i]; }
+
+    momentum_type getMomentum(size_t i) const { return momentum_[i]; }
+
+    corsika::Point getPosition(size_t i) const { return position_[i]; }
+    TimeType getTime(size_t i) const { return time_[i]; }
+
+    HEPEnergyType getDataE(size_t i) const { return dataE_[i]; }
+
+    void setDataE(size_t i, HEPEnergyType const& dataE) { dataE_[i] = dataE; }
+
+    corsika::Code getDataPid(size_t i) const { return dataPID_[i]; }
+
+    void setDataPid(size_t i, corsika::Code const& dataPid) { dataPID_[i] = dataPid; }
+    /**
+     *   Function to copy particle at location i2 in stack to i1
+     */
+    void copy(size_t i1, size_t i2) {
+      dataPID_[i2] = dataPID_[i1];
+      dataE_[i2] = dataE_[i1];
+      momentum_[i2] = momentum_[i1];
+      position_[i2] = position_[i1];
+      time_[i2] = time_[i1];
+    }
+
+    /**
+     *   FIXME: change to iterators.
+     *   Function to copy particle at location i2 in stack to i1
+     */
+    void swap(size_t i1, size_t i2) {
+      std::swap(dataPID_[i2], dataPID_[i1]);
+      std::swap(dataE_[i2], dataE_[i1]);
+      std::swap(momentum_[i2], momentum_[i1]);
+      std::swap(position_[i2], position_[i1]);
+      std::swap(time_[i2], time_[i1]);
+    }
+
+    void incrementSize() {
+      using corsika::Code;
+      using corsika::Point;
+
+      dataPID_.push_back(Code::Unknown);
+      dataE_.push_back(0 * electronvolt);
 
+      CoordinateSystemPtr const& dummyCS = get_root_CoordinateSystem();
 
-/**
- * Example of a particle object on the stack.
- */
-
-template <typename StackIteratorInterface>
-struct ParticleInterface : public ParticleBase<StackIteratorInterface> {
-
-private:
-
-	typedef corsika::ParticleBase<StackIteratorInterface> super_type;
-
-public:
-
-	typedef corsika::Vector<corsika::units::si::hepmomentum_d> momentum_vector_type;
-
-	std::string as_string() const {
-		using namespace corsika::units::si;
-		return fmt::format("particle: i={}, PID={}, E={}GeV", super_type::GetIndex(),
-				particles::GetName(this->getPID()), this->getEnergy() / 1_GeV);
-	}
-
-	void setParticleData( std::tuple<corsika::Code, corsika::units::si::HEPEnergyType,
-			momentum_vector_type, corsika::Point, corsika::units::si::TimeType> const& v) {
-		this->setPID(std::get<0>(v));
-		this->setEnergy(std::get<1>(v));
-		this->setMomentum(std::get<2>(v));
-		this->setPosition(std::get<3>(v));
-		this->setTime(std::get<4>(v));
-	}
-
-	void setParticleData( ParticleInterface<StackIteratorInterface> const&,
-			std::tuple<corsika::Code, corsika::units::si::HEPEnergyType,
-			momentum_vector_type, corsika::Point, corsika::units::si::TimeType> const& v) {
-		this->setPID(std::get<0>(v));
-		this->setEnergy(std::get<1>(v));
-		this->setMomentum(std::get<2>(v));
-		this->setPosition(std::get<3>(v));
-		this->setTime(std::get<4>(v));
-	}
-
-	/// individual setters
-	void setPID(const corsika::Code id) {
-		super_type::GetStackData().setPID(super_type::GetIndex(), id);
-	}
-	void setEnergy(const corsika::units::si::HEPEnergyType& e) {
-		super_type::GetStackData().setEnergy(super_type::GetIndex(), e);
-	}
-	void setMomentum(const momentum_vector_type& v) {
-		super_type::GetStackData().setMomentum(super_type::GetIndex(), v);
-	}
-	void setPosition(const corsika::Point& v) {
-		super_type::GetStackData().setPosition(super_type::GetIndex(), v);
-	}
-	void setTime(const corsika::units::si::TimeType& v) {
-		super_type::GetStackData().setTime(super_type::GetIndex(), v);
-	}
-
-	/// individual getters
-	corsika::Code getPID() const {
-		return super_type::GetStackData().getPID(super_type::GetIndex());
-	}
-	corsika::units::si::HEPEnergyType getEnergy() const {
-		return super_type::GetStackData().getEnergy(super_type::GetIndex());
-	}
-	momentum_vector_type getMomentum() const {
-		return super_type::GetStackData().getMomentum(super_type::GetIndex());
-	}
-	corsika::Point getPosition() const {
-		return super_type::GetStackData().getPosition(super_type::GetIndex());
-	}
-	corsika::units::si::TimeType getTime() const {
-		return super_type::GetStackData().getTime(super_type::GetIndex());
-	}
-	/**
-	 * @name derived quantities
-	 *
-	 * @{
-	 */
-	corsika::Vector<corsika::units::si::dimensionless_d> getDirection() const {
-		return  this->getMomentum() /  this->getEnergy();
-	}
-
-	corsika::units::si::HEPMassType getMass() const {
-		return corsika::GetMass(this->getPID());
-	}
-
-	int16_t getChargeNumber() const {
-		return corsika::GetChargeNumber(this->getPID());
-	}
-	///@}
-};
-
-/**
- * Memory implementation of the most simple (stupid) particle stack object.
- *
- */
-
-class SuperStupidStackImpl {
-
-public:
-
-	typedef  corsika::Vector<corsika::units::si::hepmomentum_d>        momentum_type;
-	typedef  std::vector<corsika::Code>                             code_vector_type;
-	typedef  std::vector<corsika::units::si::HEPEnergyType>       energy_vector_type;
-	typedef  std::vector<corsika::Point>                           point_vector_type;
-	typedef  std::vector<corsika::units::si::TimeType>              time_vector_type;
-	typedef  std::vector<momentum_type>                         momentum_vector_type;
-
-	SuperStupidStackImpl()=default;
-
-	SuperStupidStackImpl( SuperStupidStackImpl const& other)=default;
-
-	SuperStupidStackImpl( SuperStupidStackImpl && other)=default;
-
-
-	SuperStupidStackImpl& operator=( SuperStupidStackImpl const& other)=default;
-
-	SuperStupidStackImpl& operator=( SuperStupidStackImpl && other)=default;
-
-
-	void init() {}
-	void dump() const {}
-
-	void clear() {
-		dataPID_.clear();
-		dataE_.clear();
-		momentum_.clear();
-		position_.clear();
-		time_.clear();
-	}
-
-	unsigned int getSize() const { return dataPID_.size(); }
-	unsigned int getCapacity() const { return dataPID_.size(); }
-
-	void setPID(size_t i, const corsika::Code id) {
-		dataPID_[i] = id;
-	}
-	void setEnergy(size_t i,  corsika::units::si::HEPEnergyType  const& e) {
-		dataE_[i] = e;
-	}
-	void setMomentum(size_t i, momentum_type const& v) {
-		momentum_[i] = v;
-	}
-	void setPosition(size_t i, corsika::Point const& v) {
-		position_[i] = v;
-	}
-	void setTime(size_t i, corsika::units::si::TimeType const& v) {
-		time_[i] = v;
-	}
-
-	corsika::Code getPID(size_t i) const {
-		return dataPID_[i];
-	}
-
-	corsika::units::si::HEPEnergyType getEnergy(size_t i) const {
-		return dataE_[i];
-	}
-
-	momentum_type getMomentum(size_t i) const {
-		return momentum_[i];
-	}
-
-	corsika::Point getPosition(size_t i) const {
-		return position_[i];
-	}
-	corsika::units::si::TimeType getTime(size_t i) const {
-		return time_[i];
-	}
-
-	corsika::units::si::HEPEnergyType getDataE(size_t i) const {
-		return dataE_[i];
-	}
-
-	void setDataE(size_t i, corsika::units::si::HEPEnergyType const& dataE) {
-		dataE_[i] = dataE;
-	}
-
-	corsika::Code getDataPid(size_t i) const {
-		return dataPID_;
-	}
+      momentum_.push_back(
+          momentum_type(dummyCS, {0 * electronvolt, 0 * electronvolt, 0 * electronvolt}));
 
-	void setDataPid(size_t i, corsika::Code  const& dataPid) {
-		dataPID_[i] = dataPid;
-	}
-	/**
-	 *   Function to copy particle at location i2 in stack to i1
-	 */
-	 void copy(size_t i1, size_t i2) {
-		dataPID_[i2]  = dataPID_[i1];
-		dataE_[i2]    = dataE_[i1];
-		momentum_[i2] = momentum_[i1];
-		position_[i2] = position_[i1];
-		time_[i2]     = time_[i1];
-	 }
+      position_.push_back(Point(dummyCS, {0 * meter, 0 * meter, 0 * meter}));
+      time_.push_back(0 * second);
+    }
 
+    void decrementSize() {
+      if (dataE_.size() > 0) {
+        dataPID_.pop_back();
+        dataE_.pop_back();
+        momentum_.pop_back();
+        position_.pop_back();
+        time_.pop_back();
+      }
+    }
 
-	 /**
-	  *   FIXME: change to iterators.
-	  *   Function to copy particle at location i2 in stack to i1
-	  */
-	 void swap(size_t i1, size_t i2) {
-		 std::swap(dataPID_[i2] , dataPID_[i1]);
-		 std::swap(dataE_[i2]   , dataE_[i1]);
-		 std::swap(momentum_[i2], momentum_[i1]);
-		 std::swap(position_[i2], position_[i1]);
-		 std::swap(time_[i2]    , time_[i1]);
-	 }
-
-	 void incrementSize() {
-		 using corsika::Point;
-		 using corsika::Code;
-
-		 dataPID_.push_back(Code::Unknown);
-		 dataE_.push_back(0 * corsika::units::si::electronvolt);
-
-		 CoordinateSystem& dummyCS = RootCoordinateSystem::GetInstance().GetRootCoordinateSystem();
-
-		 momentum_.push_back(momentum_type( dummyCS,
-				 {0 * corsika::units::si::electronvolt, 0 * corsika::units::si::electronvolt,
-						 0 * corsika::units::si::electronvolt}));
-
-		 position_.push_back(
-				 Point(dummyCS, {0 * corsika::units::si::meter, 0 * corsika::units::si::meter,
-						 0 * corsika::units::si::meter}));
-		 time_.push_back(0 * corsika::units::si::second);
-	 }
-
-	 void decrementSize() {
-		 if (dataE_.size() > 0) {
-			 dataPID_.pop_back();
-			 dataE_.pop_back();
-			 momentum_.pop_back();
-			 position_.pop_back();
-			 time_.pop_back();
-		 }
-	 }
-
-
-private:
-
-	 /// the actual memory to store particle data
-	 code_vector_type dataPID_;
-	 energy_vector_type dataE_;
-	 momentum_vector_type momentum_;
-	 point_vector_type position_;
-	 time_vector_type time_;
-
-}; // end class SuperStupidStackImpl
-
-
-typedef Stack<SuperStupidStackImpl, ParticleInterface> SuperStupidStack;
-
-
-} // namespace corsika
+  private:
+    /// the actual memory to store particle data
+    code_vector_type dataPID_;
+    energy_vector_type dataE_;
+    momentum_vector_type momentum_;
+    point_vector_type position_;
+    time_vector_type time_;
 
+  }; // end class SuperStupidStackImpl
+
+  typedef Stack<SuperStupidStackImpl, ParticleInterface> SuperStupidStack;
+
+} // namespace corsika::simple_stack
diff --git a/examples/stack_example.cpp b/examples/stack_example.cpp
index 0279df865..19db8018a 100644
--- a/examples/stack_example.cpp
+++ b/examples/stack_example.cpp
@@ -7,6 +7,7 @@
  */
 
 #include <corsika/framework/core/ParticleProperties.hpp>
+#include <corsika/framework/core/PhysicalUnits.hpp>
 #include <corsika/stack/SuperStupidStack.hpp>
 
 #include <corsika/framework/geometry/Point.hpp>
@@ -17,37 +18,34 @@
 #include <iostream>
 
 using namespace corsika;
-using namespace corsika::units::si;
 using namespace std;
 
-void fill(corsika::super_stupid::SuperStupidStack& s) {
-  const corsika::CoordinateSystem& rootCS =
-      corsika::RootCoordinateSystem::getInstance().GetRootCoordinateSystem();
+void fill(simple_stack::SuperStupidStack& s) {
+  const CoordinateSystemPtr& rootCS = get_root_CoordinateSystem();
   for (int i = 0; i < 11; ++i) {
-    s.AddParticle(
-        std::tuple<corsika::Code, units::si::HEPEnergyType, corsika::MomentumVector,
-                   corsika::Point, units::si::TimeType>{
-            corsika::Code::Electron, 1.5_GeV * i,
-            corsika::MomentumVector(rootCS, {0_GeV, 0_GeV, 1_GeV}),
-            corsika::Point(rootCS, 0_m, 0_m, 0_m), 0_ns});
+    s.addParticle(
+        std::tuple<Code, HEPEnergyType, simple_stack::MomentumVector, Point,
+                   TimeType>{Code::Electron, 1.5_GeV * i,
+                             simple_stack::MomentumVector(rootCS, {0_GeV, 0_GeV, 1_GeV}),
+                             Point(rootCS, 0_m, 0_m, 0_m), 0_ns});
   }
 }
 
-void read(corsika::super_stupid::SuperStupidStack& s) {
-  assert(s.GetSize() == 11); // stack has 11 particles
+void read(simple_stack::SuperStupidStack& s) {
+  assert(s.getSize() == 11); // stack has 11 particles
 
   HEPEnergyType total_energy;
   [[maybe_unused]] int i = 0;
   for (const auto& p : s) {
-    total_energy += p.GetEnergy();
+    total_energy += p.getEnergy();
     // particles are electrons with 1.5 GeV energy times i
-    assert(p.GetPID() == corsika::Code::Electron);
-    assert(p.GetEnergy() == 1.5_GeV * (i++));
+    assert(p.getPID() == Code::Electron);
+    assert(p.getEnergy() == 1.5_GeV * (i++));
   }
 }
 
 int main() {
-  corsika::super_stupid::SuperStupidStack s;
+  simple_stack::SuperStupidStack s;
   fill(s);
   read(s);
   return 0;
diff --git a/tests/framework/CMakeLists.txt b/tests/framework/CMakeLists.txt
index 5b345ba58..3def966d1 100644
--- a/tests/framework/CMakeLists.txt
+++ b/tests/framework/CMakeLists.txt
@@ -2,8 +2,8 @@
 set (test_framework_sources  
   # testCascade.cpp this is most important, but whole content of former Processes folder missing yet
   testClassTimer.cpp
-  #testCombinedStack.cpp #FIXME: reenable this
-  testCOMBoost.cpp #FIXME: reenable this
+  testCombinedStack.cpp
+  testCOMBoost.cpp
   #testCorsikaFenv.cpp # does not work because of use of exceptions in catch2
   testFourVector.cpp
   testHelix.cpp
@@ -14,8 +14,8 @@ set (test_framework_sources
   testParticles.cpp
   #testProcessSequence.cpp #FIXME: reenable this
   testRandom.cpp
-  #testSecondaryView.cpp #FIXME: reenable this
-  #testStackInterface.cpp #FIXME: reenable this
+  testSecondaryView.cpp
+  testStackInterface.cpp
   testUnits.cpp
   )
 
diff --git a/tests/framework/testCombinedStack.cpp b/tests/framework/testCombinedStack.cpp
index a50be568b..5ea982873 100644
--- a/tests/framework/testCombinedStack.cpp
+++ b/tests/framework/testCombinedStack.cpp
@@ -32,29 +32,29 @@ class TestStackData2 {
 
 public:
   // these functions are needed for the Stack interface
-  void Clear() { fData2.clear(); }
-  unsigned int GetSize() const { return fData2.size(); }
-  unsigned int GetCapacity() const { return fData2.size(); }
-  void Copy(const int i1, const int i2) { fData2[i2] = fData2[i1]; }
-  void Swap(const int i1, const int i2) {
-    double tmp0 = fData2[i1];
-    fData2[i1] = fData2[i2];
-    fData2[i2] = tmp0;
+  void clear() { data2_.clear(); }
+  unsigned int getSize() const { return data2_.size(); }
+  unsigned int getCapacity() const { return data2_.size(); }
+  void copy(const int i1, const int i2) { data2_[i2] = data2_[i1]; }
+  void swap(const int i1, const int i2) {
+    double tmp0 = data2_[i1];
+    data2_[i1] = data2_[i2];
+    data2_[i2] = tmp0;
   }
 
   // custom data access function
-  void SetData2(const int i, const double v) { fData2[i] = v; }
-  double GetData2(const int i) const { return fData2[i]; }
+  void setData2(const int i, const double v) { data2_[i] = v; }
+  double getData2(const int i) const { return data2_[i]; }
 
   // these functions are also needed by the Stack interface
-  void IncrementSize() { fData2.push_back(0.); }
-  void DecrementSize() {
-    if (fData2.size() > 0) { fData2.pop_back(); }
+  void incrementSize() { data2_.push_back(0.); }
+  void decrementSize() {
+    if (data2_.size() > 0) { data2_.pop_back(); }
   }
 
   // custom private data section
 private:
-  std::vector<double> fData2;
+  std::vector<double> data2_;
 };
 
 // defintion of a stack-readout object, the iteractor dereference
@@ -63,25 +63,25 @@ template <typename T>
 class TestParticleInterface2 : public T {
 
 public:
-  using T::GetIndex;
-  using T::GetStackData;
-  using T::SetParticleData;
+  using T::getIndex;
+  using T::getStackData;
+  using T::setParticleData;
 
   // default version for particle-creation from input data
-  void SetParticleData(const std::tuple<double> v = {0.}) { SetData2(std::get<0>(v)); }
-  void SetParticleData(TestParticleInterface2<T>& parent,
-                       const std::tuple<double> v = {0.}) {
-    SetData2(parent.GetData2() + std::get<0>(v));
+  void setParticleData(std::tuple<double> const v = {0.}) { setData2(std::get<0>(v)); }
+  void setParticleData(TestParticleInterface2<T>& parent,
+                       std::tuple<double> const v = {0.}) {
+    setData2(parent.getData2() + std::get<0>(v));
   }
-  void SetData2(const double v) { GetStackData().SetData2(GetIndex(), v); }
-  double GetData2() const { return GetStackData().GetData2(GetIndex()); }
+  void setData2(const double v) { getStackData().setData2(getIndex(), v); }
+  double getData2() const { return getStackData().getData2(getIndex()); }
 };
 
 // combined stack: StackTest = (TestStackData + TestStackData2)
-template <typename StackIter>
+template <typename TStackIter>
 using CombinedTestInterfaceType =
-    corsika::CombinedParticleInterface<TestParticleInterface,
-                                              TestParticleInterface2, StackIter>;
+    corsika::CombinedParticleInterface<TestParticleInterface, TestParticleInterface2,
+                                       TStackIter>;
 
 using StackTest = CombinedStack<TestStackData, TestStackData2, CombinedTestInterfaceType>;
 
@@ -90,12 +90,12 @@ TEST_CASE("Combined Stack", "[stack]") {
   // helper function for sum over stack data
   auto sum = [](const StackTest& stack) {
     double v = 0;
-    for (const auto& p : stack) v += p.GetData();
+    for (const auto& p : stack) v += p.getData();
     return v;
   };
   auto sum2 = [](const StackTest& stack) {
     double v = 0;
-    for (const auto& p : stack) v += p.GetData2();
+    for (const auto& p : stack) v += p.getData2();
     return v;
   };
 
@@ -103,10 +103,10 @@ TEST_CASE("Combined Stack", "[stack]") {
 
     // construct a valid Stack object
     StackTest s;
-    s.Clear();
-    s.AddParticle(std::tuple{0.});
-    s.Copy(s.cbegin(), s.begin());
-    s.Swap(s.begin(), s.begin());
+    s.clear();
+    s.addParticle(std::tuple{0.});
+    s.copy(s.cbegin(), s.begin());
+    s.swap(s.begin(), s.begin());
     CHECK(s.getSize() == 1);
   }
 
@@ -119,7 +119,7 @@ TEST_CASE("Combined Stack", "[stack]") {
   SECTION("write and read") {
 
     StackTest s;
-    s.AddParticle(std::tuple{9.9});
+    s.addParticle(std::tuple{9.9});
     CHECK(sum2(s) == 0.);
     CHECK(sum(s) == 9.9);
   }
@@ -128,15 +128,15 @@ TEST_CASE("Combined Stack", "[stack]") {
 
     StackTest s;
     CHECK(s.getSize() == 0);
-    StackTest::StackIterator p =
-        s.AddParticle(std::tuple{0.}); // valid way to access particle data
-    p.SetData(8.9);
-    p.SetData2(3.);
+    StackTest::stack_iterator_type p =
+        s.addParticle(std::tuple{0.}); // valid way to access particle data
+    p.setData(8.9);
+    p.setData2(3.);
     CHECK(sum2(s) == 3.);
     CHECK(sum(s) == 8.9);
     CHECK(s.getSize() == 1);
     CHECK(s.getEntries() == 1);
-    s.Delete(p);
+    s.erase(p);
     CHECK(s.getSize() == 1);
     CHECK(s.getEntries() == 0);
   }
@@ -145,11 +145,11 @@ TEST_CASE("Combined Stack", "[stack]") {
 
     StackTest s;
     CHECK(s.getSize() == 0);
-    auto p = s.AddParticle(
+    auto p = s.addParticle(
         std::tuple{9.9}); // also valid way to access particle data, identical to above
     CHECK(s.getSize() == 1);
     CHECK(s.getEntries() == 1);
-    p.Delete();
+    p.erase();
     CHECK(s.getSize() == 1);
     CHECK(s.getEntries() == 0);
   }
@@ -157,19 +157,19 @@ TEST_CASE("Combined Stack", "[stack]") {
   SECTION("create secondaries") {
     StackTest s;
     CHECK(s.getSize() == 0);
-    auto iter = s.AddParticle(std::tuple{9.9});
-    iter.SetData2(2);
+    auto iter = s.addParticle(std::tuple{9.9});
+    iter.setData2(2);
     CHECK(s.getSize() == 1);
     CHECK(s.getEntries() == 1);
-    iter.AddSecondary(std::tuple{4.4});
+    iter.addSecondary(std::tuple{4.4});
     CHECK(s.getSize() == 2);
     CHECK(s.getEntries() == 2);
-    // p.AddSecondary(3.3, 2.2, 1.);
+    // p.addSecondary(3.3, 2.2, 1.);
     // CHECK(s.getSize() == 3);
     double v = 0;
     for (const auto& i : s) {
-      v += i.GetData();
-      CHECK(i.GetData2() == 2);
+      v += i.getData();
+      CHECK(i.getData2() == 2);
     }
     CHECK(v == 9.9 + 4.4);
   }
@@ -178,41 +178,41 @@ TEST_CASE("Combined Stack", "[stack]") {
     StackTest s;
     CHECK(s.getSize() == 0);
     CHECK(s.getEntries() == 0);
-    CHECK(s.IsEmpty());
+    CHECK(s.isEmpty());
 
-    auto p1 = s.AddParticle(std::tuple{9.9});
-    auto p2 = s.AddParticle(std::tuple{8.8});
-    p1.SetData2(20.2);
-    p2.SetData2(20.3);
+    auto p1 = s.addParticle(std::tuple{9.9});
+    auto p2 = s.addParticle(std::tuple{8.8});
+    p1.setData2(20.2);
+    p2.setData2(20.3);
     CHECK(s.getSize() == 2);
     CHECK(s.getEntries() == 2);
-    CHECK(!s.IsEmpty());
+    CHECK(!s.isEmpty());
 
-    auto particle = s.GetNextParticle(); // first particle
-    CHECK(particle.GetData() == 8.8);
-    CHECK(particle.GetData2() == 20.3);
+    auto particle = s.getNextParticle(); // first particle
+    CHECK(particle.getData() == 8.8);
+    CHECK(particle.getData2() == 20.3);
 
-    particle.Delete(); // only marks (last) particle as "deleted"
+    particle.erase(); // only marks (last) particle as "deleted"
     CHECK(s.getSize() == 2);
     CHECK(s.getEntries() == 1);
-    CHECK(!s.IsEmpty());
+    CHECK(!s.isEmpty());
 
     /*
       This following call to GetNextParticle will realize that the
       current last particle on the stack was marked "deleted" and will
       purge it: stack size is reduced by one.
      */
-    auto particle2 = s.GetNextParticle(); // first particle
+    auto particle2 = s.getNextParticle(); // first particle
     CHECK(s.getSize() == 1);
     CHECK(s.getEntries() == 1);
-    CHECK(!s.IsEmpty());
-    CHECK(particle2.GetData() == 9.9);
-    CHECK(particle2.GetData2() == 20.2);
+    CHECK(!s.isEmpty());
+    CHECK(particle2.getData() == 9.9);
+    CHECK(particle2.getData2() == 20.2);
 
-    particle2.Delete(); // also mark this particle as "deleted"
+    particle2.erase(); // also mark this particle as "deleted"
     CHECK(s.getSize() == 1);
     CHECK(s.getEntries() == 0);
-    CHECK(s.IsEmpty());
+    CHECK(s.isEmpty());
   }
 }
 
@@ -225,29 +225,29 @@ class TestStackData3 {
 
 public:
   // these functions are needed for the Stack interface
-  void Clear() { fData3.clear(); }
-  unsigned int getSize() const { return fData3.size(); }
-  unsigned int GetCapacity() const { return fData3.size(); }
-  void Copy(const int i1, const int i2) { fData3[i2] = fData3[i1]; }
-  void Swap(const int i1, const int i2) {
-    double tmp0 = fData3[i1];
-    fData3[i1] = fData3[i2];
-    fData3[i2] = tmp0;
+  void clear() { data3_.clear(); }
+  unsigned int getSize() const { return data3_.size(); }
+  unsigned int getCapacity() const { return data3_.size(); }
+  void copy(const int i1, const int i2) { data3_[i2] = data3_[i1]; }
+  void swap(const int i1, const int i2) {
+    double tmp0 = data3_[i1];
+    data3_[i1] = data3_[i2];
+    data3_[i2] = tmp0;
   }
 
   // custom data access function
-  void SetData3(const int i, const double v) { fData3[i] = v; }
-  double GetData3(const int i) const { return fData3[i]; }
+  void setData3(const int i, const double v) { data3_[i] = v; }
+  double getData3(const int i) const { return data3_[i]; }
 
   // these functions are also needed by the Stack interface
-  void IncrementSize() { fData3.push_back(0.); }
-  void DecrementSize() {
-    if (fData3.size() > 0) { fData3.pop_back(); }
+  void incrementSize() { data3_.push_back(0.); }
+  void decrementSize() {
+    if (data3_.size() > 0) { data3_.pop_back(); }
   }
 
   // custom private data section
 private:
-  std::vector<double> fData3;
+  std::vector<double> data3_;
 };
 
 // ---------------------------------------
@@ -257,29 +257,29 @@ template <typename T>
 class TestParticleInterface3 : public T {
 
 public:
-  using T::GetIndex;
-  using T::GetStackData;
-  using T::SetParticleData;
+  using T::getIndex;
+  using T::getStackData;
+  using T::setParticleData;
 
   // default version for particle-creation from input data
-  void SetParticleData(const std::tuple<double> v = {0.}) { SetData3(std::get<0>(v)); }
-  void SetParticleData(TestParticleInterface3<T>& parent,
-                       const std::tuple<double> v = {0.}) {
-    SetData3(parent.GetData3() + std::get<0>(v));
+  void setParticleData(std::tuple<double> const v = {0.}) { setData3(std::get<0>(v)); }
+  void setParticleData(TestParticleInterface3<T>& parent,
+                       std::tuple<double> const v = {0.}) {
+    setData3(parent.getData3() + std::get<0>(v));
   }
-  void SetData3(const double v) { GetStackData().SetData3(GetIndex(), v); }
-  double GetData3() const { return GetStackData().GetData3(GetIndex()); }
+  void setData3(const double v) { getStackData().setData3(getIndex(), v); }
+  double getData3() const { return getStackData().getData3(getIndex()); }
 };
 
 // double combined stack:
 // combined stack
-template <typename StackIter>
+template <typename TStackIter>
 using CombinedTestInterfaceType2 =
-    corsika::CombinedParticleInterface<StackTest::MPIType, TestParticleInterface3,
-                                              StackIter>;
+    corsika::CombinedParticleInterface<StackTest::pi_type, TestParticleInterface3,
+                                       TStackIter>;
 
-using StackTest2 = CombinedStack<typename StackTest::StackImpl, TestStackData3,
-                                 CombinedTestInterfaceType2>;
+using StackTest2 = CombinedStack<typename StackTest::stack_implementation_type,
+                                 TestStackData3, CombinedTestInterfaceType2>;
 
 TEST_CASE("Combined Stack - multi", "[stack]") {
 
@@ -287,63 +287,63 @@ TEST_CASE("Combined Stack - multi", "[stack]") {
 
     StackTest2 s;
     CHECK(s.getSize() == 0);
-    CHECK(s.IsEmpty()); // size = entries = 0
+    CHECK(s.isEmpty()); // size = entries = 0
 
     // add new particle, only provide tuple data for StackTest
-    auto p1 = s.AddParticle(std::tuple{9.9});
+    auto p1 = s.addParticle(std::tuple{9.9});
     // add new particle, provide tuple data for both StackTest and TestStackData3
-    auto p2 = s.AddParticle(std::tuple{8.8}, std::tuple{0.1});
+    auto p2 = s.addParticle(std::tuple{8.8}, std::tuple{0.1});
 
     CHECK(s.getSize() == 2);
-    CHECK(!s.IsEmpty()); // size = entries = 2
+    CHECK(!s.isEmpty()); // size = entries = 2
 
     // examples to explicitly change data on stack
-    p2.SetData2(0.1); // not clear why this is needed, need to check
+    p2.setData2(0.1); // not clear why this is needed, need to check
                       // SetParticleData workflow for more complicated
                       // settings
-    p1.SetData3(20.2);
-    p2.SetData3(10.3);
+    p1.setData3(20.2);
+    p2.setData3(10.3);
 
-    CHECK(p1.GetData() == 9.9);
-    CHECK(p1.GetData2() == 0.);
-    p1.SetData2(10.2);
-    CHECK(p1.GetData2() == 10.2);
-    CHECK(p1.GetData3() == 20.2);
+    CHECK(p1.getData() == 9.9);
+    CHECK(p1.getData2() == 0.);
+    p1.setData2(10.2);
+    CHECK(p1.getData2() == 10.2);
+    CHECK(p1.getData3() == 20.2);
 
-    CHECK(p2.GetData() == 8.8);
-    CHECK(p2.GetData2() == 0.1);
-    CHECK(p2.GetData3() == 10.3);
+    CHECK(p2.getData() == 8.8);
+    CHECK(p2.getData2() == 0.1);
+    CHECK(p2.getData3() == 10.3);
 
-    auto particle = s.GetNextParticle(); // first particle
-    CHECK(particle.GetData() == 8.8);
-    CHECK(particle.GetData2() == 0.1);
-    CHECK(particle.GetData3() == 10.3);
+    auto particle = s.getNextParticle(); // first particle
+    CHECK(particle.getData() == 8.8);
+    CHECK(particle.getData2() == 0.1);
+    CHECK(particle.getData3() == 10.3);
 
-    auto sec = particle.AddSecondary(std::tuple{4.4});
+    auto sec = particle.addSecondary(std::tuple{4.4});
     CHECK(s.getSize() == 3);
     CHECK(s.getEntries() == 3);
-    CHECK(sec.GetData() == 4.4);
-    CHECK(sec.GetData2() == 0.1);
-    CHECK(sec.GetData3() == 10.3);
+    CHECK(sec.getData() == 4.4);
+    CHECK(sec.getData2() == 0.1);
+    CHECK(sec.getData3() == 10.3);
 
-    sec.Delete(); // mark for deletion: size=3, entries=2
+    sec.erase(); // mark for deletion: size=3, entries=2
     CHECK(s.getSize() == 3);
     CHECK(s.getEntries() == 2);
-    CHECK(!s.IsEmpty());
+    CHECK(!s.isEmpty());
 
-    s.last().Delete(); // mark for deletion: size=3, entries=1
+    s.last().erase(); // mark for deletion: size=3, entries=1
     CHECK(s.getSize() == 3);
     CHECK(s.getEntries() == 1);
-    CHECK(!s.IsEmpty());
+    CHECK(!s.isEmpty());
 
     /*
        GetNextParticle will find two entries marked as "deleted" and
        will purge this from the end of the stack: size = 1
     */
-    s.GetNextParticle().Delete(); // mark for deletion: size=3, entries=0
+    s.getNextParticle().erase(); // mark for deletion: size=3, entries=0
     CHECK(s.getSize() == 1);
     CHECK(s.getEntries() == 0);
-    CHECK(s.IsEmpty());
+    CHECK(s.isEmpty());
   }
 }
 
@@ -359,33 +359,33 @@ TEST_CASE("Combined Stack - multi", "[stack]") {
   remove the clang branch here and also in corsika::Cascade. The gcc
   code is much more generic and universal.
  */
-template <typename StackIter>
+template <typename TStackIter>
 using CombinedTestInterfaceType2 =
-    corsika::CombinedParticleInterface<StackTest::MPIType, TestParticleInterface3,
-                                              StackIter>;
+    corsika::CombinedParticleInterface<StackTest::pi_type, TestParticleInterface3,
+                                       TStackIter>;
 
-using StackTest2 = CombinedStack<typename StackTest::StackImpl, TestStackData3,
-                                 CombinedTestInterfaceType2>;
+using StackTest2 = CombinedStack<typename StackTest::stack_implementation_type,
+                                 TestStackData3, CombinedTestInterfaceType2>;
 
 #if defined(__clang__)
-using StackTestView =
-    SecondaryView<typename StackTest2::StackImpl, CombinedTestInterfaceType2>;
+using StackTestView = SecondaryView<typename StackTest2::stack_implementation_type,
+                                    CombinedTestInterfaceType2>;
 #elif defined(__GNUC__) || defined(__GNUG__)
 using StackTestView = corsika::MakeView<StackTest2>::type;
 #endif
 
-using Particle2 = typename StackTest2::ParticleType;
+using Particle2 = typename StackTest2::particle_type;
 
 TEST_CASE("Combined Stack - secondary view") {
 
   SECTION("create secondaries via secondaryview") {
 
     StackTest2 stack;
-    auto particle = stack.AddParticle(std::tuple{9.9});
+    auto particle = stack.addParticle(std::tuple{9.9});
     StackTestView view(particle);
 
-    auto projectile = view.GetProjectile();
-    projectile.AddSecondary(std::tuple{8.8});
+    auto projectile = view.getProjectile();
+    projectile.addSecondary(std::tuple{8.8});
 
     CHECK(stack.getSize() == 2);
   }
diff --git a/tests/framework/testSecondaryView.cpp b/tests/framework/testSecondaryView.cpp
index 7d881da4e..197d03825 100644
--- a/tests/framework/testSecondaryView.cpp
+++ b/tests/framework/testSecondaryView.cpp
@@ -10,6 +10,7 @@
 
 #include <corsika/framework/stack/SecondaryView.hpp>
 #include <corsika/framework/stack/Stack.hpp>
+#include <corsika/framework/logging/Logging.hpp>
 
 #include <testTestStack.h> // for testing: simple stack. This is a
 // test-build, and inluce file is obtained from CMAKE_CURRENT_SOURCE_DIR
@@ -20,7 +21,6 @@
 #include <catch2/catch.hpp>
 
 using namespace corsika;
-using namespace corsika::stack;
 using namespace std;
 
 typedef Stack<TestStackData, TestParticleInterface> StackTest;
@@ -39,69 +39,69 @@ using StackTestView = SecondaryView<TestStackData, TestParticleInterface>;
 using StackTestView = MakeView<StackTest>::type;
 #endif
 
-using Particle = typename StackTest::ParticleType;
+using Particle = typename StackTest::particle_type;
 
 TEST_CASE("SecondaryStack", "[stack]") {
 
-  logging::SetLevel(logging::level::debug);
+  logging::set_level(logging::level::debug);
 
   // helper function for sum over stack data
   auto sum = [](const StackTest& stack) {
     double v = 0;
-    for (const auto& p : stack) { v += p.GetData(); }
+    for (const auto& p : stack) { v += p.getData(); }
     return v;
   };
 
   auto sumView = [](const StackTestView& stack) {
     double value = 0;
-    for (const auto& p : stack) { value += p.GetData(); }
+    for (const auto& p : stack) { value += p.getData(); }
     return value;
   };
 
   SECTION("secondary view") {
     StackTest stack;
     CHECK(stack.getSize() == 0);
-    CHECK(stack.IsEmpty());
+    CHECK(stack.isEmpty());
 
-    stack.AddParticle(std::tuple{9.9});
-    stack.AddParticle(std::tuple{8.8});
+    stack.addParticle(std::tuple{9.9});
+    stack.addParticle(std::tuple{8.8});
     const double sumS = 9.9 + 8.8; // helper, see below
     CHECK(stack.getSize() == 2);
     CHECK(stack.getEntries() == 2);
-    CHECK(!stack.IsEmpty());
+    CHECK(!stack.isEmpty());
 
-    auto particle = stack.GetNextParticle();
+    auto particle = stack.getNextParticle();
 
     StackTestView view(particle);
     CHECK(view.getSize() == 0);
     CHECK(view.getEntries() == 0);
-    CHECK(view.IsEmpty());
+    CHECK(view.isEmpty());
 
     {
-      auto proj = view.GetProjectile();
-      CHECK(proj.GetData() == particle.GetData());
-      proj.AddSecondary(std::tuple{4.4});
+      auto proj = view.getProjectile();
+      CHECK(proj.getData() == particle.getData());
+      proj.addSecondary(std::tuple{4.4});
     }
     CHECK(view.getSize() == 1);
     CHECK(view.getEntries() == 1);
-    CHECK(!view.IsEmpty());
+    CHECK(!view.isEmpty());
     CHECK(stack.getSize() == 3);
     CHECK(stack.getEntries() == 3);
-    CHECK(!stack.IsEmpty());
+    CHECK(!stack.isEmpty());
 
-    view.AddSecondary(std::tuple{4.5});
-    view.AddSecondary(std::tuple{4.6});
+    view.addSecondary(std::tuple{4.5});
+    view.addSecondary(std::tuple{4.6});
     CHECK(view.getSize() == 3);
     CHECK(view.getEntries() == 3);
-    CHECK(!view.IsEmpty());
+    CHECK(!view.isEmpty());
     CHECK(stack.getSize() == 5);
     CHECK(stack.getEntries() == 5);
-    CHECK(!stack.IsEmpty());
+    CHECK(!stack.isEmpty());
 
     CHECK(sum(stack) == sumS + 4.4 + 4.5 + 4.6);
     CHECK(sumView(view) == 4.4 + 4.5 + 4.6);
 
-    view.last().Delete();
+    view.last().erase();
     CHECK(view.getSize() == 3);
     CHECK(view.getEntries() == 2);
     CHECK(stack.getSize() == 5);
@@ -110,22 +110,22 @@ TEST_CASE("SecondaryStack", "[stack]") {
     CHECK(sum(stack) == sumS + 4.4 + 4.5);
     CHECK(sumView(view) == 4.4 + 4.5);
 
-    auto pDel = view.GetNextParticle();
-    view.Delete(pDel);
+    auto pDel = view.getNextParticle();
+    view.erase(pDel);
     CHECK(view.getSize() == 2);
     CHECK(stack.getSize() == 4);
 
-    CHECK(sum(stack) == sumS + 4.4 + 4.5 - pDel.GetData());
-    CHECK(sumView(view) == 4.4 + 4.5 - pDel.GetData());
+    CHECK(sum(stack) == sumS + 4.4 + 4.5 - pDel.getData());
+    CHECK(sumView(view) == 4.4 + 4.5 - pDel.getData());
 
-    view.Delete(view.GetNextParticle());
+    view.erase(view.getNextParticle());
     CHECK(sum(stack) == sumS);
     CHECK(sumView(view) == 0);
-    CHECK(view.IsEmpty());
+    CHECK(view.isEmpty());
 
     {
-      auto proj = view.GetProjectile();
-      CHECK(proj.GetData() == particle.GetData());
+      auto proj = view.getProjectile();
+      CHECK(proj.getData() == particle.getData());
       CHECK(particle == view.parent());
     }
 
@@ -138,34 +138,34 @@ TEST_CASE("SecondaryStack", "[stack]") {
   SECTION("secondary view, construct from ParticleType") {
     StackTest stack;
     CHECK(stack.getSize() == 0);
-    stack.AddParticle(std::tuple{9.9});
-    stack.AddParticle(std::tuple{8.8});
+    stack.addParticle(std::tuple{9.9});
+    stack.addParticle(std::tuple{8.8});
 
-    auto iterator = stack.GetNextParticle();
-    typename StackTest::ParticleType& particle = iterator; // as in corsika::Cascade
+    auto iterator = stack.getNextParticle();
+    typename StackTest::particle_type& particle = iterator; // as in corsika::Cascade
 
     StackTestView view(particle);
     CHECK(view.getSize() == 0);
 
-    view.AddSecondary(std::tuple{4.4});
+    view.addSecondary(std::tuple{4.4});
 
     CHECK(view.getSize() == 1);
   }
 
   SECTION("deletion") {
     StackTest stack;
-    stack.AddParticle(std::tuple{-99.});
-    stack.AddParticle(std::tuple{0.});
+    stack.addParticle(std::tuple{-99.});
+    stack.addParticle(std::tuple{0.});
 
     {
-      auto particle = stack.GetNextParticle();
+      auto particle = stack.getNextParticle();
       StackTestView view(particle);
 
-      auto proj = view.GetProjectile();
-      proj.AddSecondary(std::tuple{-2.});
-      proj.AddSecondary(std::tuple{-1.});
-      proj.AddSecondary(std::tuple{1.});
-      proj.AddSecondary(std::tuple{2.});
+      auto proj = view.getProjectile();
+      proj.addSecondary(std::tuple{-2.});
+      proj.addSecondary(std::tuple{-1.});
+      proj.addSecondary(std::tuple{1.});
+      proj.addSecondary(std::tuple{2.});
 
       CHECK(stack.getSize() == 6); // -99, 0, -2, -1, 1, 2
       CHECK(view.getSize() == 4);  // -2, -1, 1, 2
@@ -173,8 +173,8 @@ TEST_CASE("SecondaryStack", "[stack]") {
       // now delete all negative entries, i.e. -1 and -2
       auto p = view.begin();
       while (p != view.end()) {
-        auto data = p.GetData();
-        if (data < 0) { p.Delete(); }
+        auto data = p.getData();
+        if (data < 0) { p.erase(); }
         ++p;
       }
       CHECK(stack.getSize() == 6);
@@ -186,21 +186,21 @@ TEST_CASE("SecondaryStack", "[stack]") {
     // repeat
 
     {
-      auto particle = stack.GetNextParticle();
+      auto particle = stack.getNextParticle();
       StackTestView view(particle);
 
       // put -2,...,+2 on stack
-      auto proj = view.GetProjectile();
-      proj.AddSecondary(std::tuple{-2.});
-      proj.AddSecondary(std::tuple{-1.});
-      proj.AddSecondary(std::tuple{1.});
-      proj.AddSecondary(std::tuple{2.});
+      auto proj = view.getProjectile();
+      proj.addSecondary(std::tuple{-2.});
+      proj.addSecondary(std::tuple{-1.});
+      proj.addSecondary(std::tuple{1.});
+      proj.addSecondary(std::tuple{2.});
       // stack should contain -99, 0, 2, 1, [-2, -1, 1, 2]
 
       auto p = view.begin();
       while (p != view.end()) {
-        auto data = p.GetData();
-        if (data < 0) { p.Delete(); }
+        auto data = p.getData();
+        if (data < 0) { p.erase(); }
         ++p;
       }
 
@@ -214,43 +214,43 @@ TEST_CASE("SecondaryStack", "[stack]") {
 
   SECTION("swap particle") {
     StackTest stack;
-    stack.AddParticle(std::tuple{-99.});
+    stack.addParticle(std::tuple{-99.});
 
     StackTestView view(stack.first());
-    view.AddSecondary(std::tuple{-2.});
-    view.AddSecondary(std::tuple{-1.});
-    view.AddSecondary(std::tuple{1.});
+    view.addSecondary(std::tuple{-2.});
+    view.addSecondary(std::tuple{-1.});
+    view.addSecondary(std::tuple{1.});
 
     auto p1 = view.begin();
     auto p2 = p1 + 1;
 
-    CHECK(p1.GetData() == -2.);
-    CHECK(p2.GetData() == -1.);
+    CHECK(p1.getData() == -2.);
+    CHECK(p2.getData() == -1.);
 
-    view.Swap(p1, p2);
+    view.swap(p1, p2);
 
-    CHECK(p1.GetData() == -1);
-    CHECK(p2.GetData() == -2);
+    CHECK(p1.getData() == -1);
+    CHECK(p2.getData() == -2);
   }
 
   SECTION("copy particle") {
     StackTest stack;
-    stack.AddParticle(std::tuple{-99.});
+    stack.addParticle(std::tuple{-99.});
 
     StackTestView view(stack.first());
-    view.AddSecondary(std::tuple{-2.});
-    view.AddSecondary(std::tuple{-1.});
-    view.AddSecondary(std::tuple{1.});
+    view.addSecondary(std::tuple{-2.});
+    view.addSecondary(std::tuple{-1.});
+    view.addSecondary(std::tuple{1.});
 
     auto p1 = view.begin();
     auto p2 = p1 + 1;
 
-    CHECK(p1.GetData() == -2.);
-    CHECK(p2.GetData() == -1.);
+    CHECK(p1.getData() == -2.);
+    CHECK(p2.getData() == -1.);
 
-    view.Copy(p1, p2);
+    view.copy(p1, p2);
 
-    CHECK(p1.GetData() == -2);
-    CHECK(p2.GetData() == -2);
+    CHECK(p1.getData() == -2);
+    CHECK(p2.getData() == -2);
   }
 }
diff --git a/tests/framework/testStackInterface.cpp b/tests/framework/testStackInterface.cpp
index eab48ec97..3b65e2067 100644
--- a/tests/framework/testStackInterface.cpp
+++ b/tests/framework/testStackInterface.cpp
@@ -30,7 +30,7 @@ TEST_CASE("Stack", "[Stack]") {
   // helper function for sum over stack data
   auto sum = [](const StackTest& stack) {
     double v = 0;
-    for (const auto& p : stack) v += p.GetData();
+    for (const auto& p : stack) v += p.getData();
     return v;
   };
 
@@ -38,15 +38,15 @@ TEST_CASE("Stack", "[Stack]") {
 
     // construct a valid Stack object
     StackTest stack;
-    stack.Clear();
+    stack.clear();
     CHECK(stack.getSize() == 0);
-    CHECK(stack.IsEmpty());                          // stack empty here
-    auto pTest0 = stack.AddParticle(std::tuple{0.}); // [0]
+    CHECK(stack.isEmpty());                          // stack empty here
+    auto pTest0 = stack.addParticle(std::tuple{0.}); // [0]
     CHECK(stack.getSize() == 1);
-    CHECK(!stack.IsEmpty());
-    auto pTest1 = stack.AddParticle(std::tuple{1.}); // [0,1]
+    CHECK(!stack.isEmpty());
+    auto pTest1 = stack.addParticle(std::tuple{1.}); // [0,1]
     CHECK(stack.getSize() == 2);
-    CHECK(pTest1.GetData() == 1.);
+    CHECK(pTest1.getData() == 1.);
     auto pTestAt = stack.at(1); // -> 1
     CHECK(pTestAt == pTest1);
     auto pTestFirst = stack.first(); // -> 0
@@ -62,7 +62,7 @@ TEST_CASE("Stack", "[Stack]") {
   SECTION("write and read") {
 
     StackTest stack;
-    stack.AddParticle(std::tuple{9.9});
+    stack.addParticle(std::tuple{9.9});
     const double v = sum(stack);
     CHECK(v == 9.9);
   }
@@ -71,12 +71,12 @@ TEST_CASE("Stack", "[Stack]") {
 
     StackTest stack;
     CHECK(stack.getSize() == 0);
-    StackTest::StackIterator p =
-        stack.AddParticle(std::tuple{0.}); // valid way to access particle data
-    p.SetData(9.9);
+    StackTest::stack_iterator_type p =
+        stack.addParticle(std::tuple{0.}); // valid way to access particle data
+    p.setData(9.9);
     CHECK(stack.getSize() == 1);
     CHECK(stack.getEntries() == 1);
-    stack.Delete(p);
+    stack.erase(p);
     CHECK(stack.getSize() == 1);
     CHECK(stack.getEntries() == 0);
   }
@@ -85,44 +85,44 @@ TEST_CASE("Stack", "[Stack]") {
 
     StackTest stack;
     CHECK(stack.getSize() == 0);
-    stack.AddParticle(std::tuple{8.9});
-    stack.AddParticle(std::tuple{7.9});
-    auto p = stack.AddParticle(
+    stack.addParticle(std::tuple{8.9});
+    stack.addParticle(std::tuple{7.9});
+    auto p = stack.addParticle(
         std::tuple{9.9}); // also valid way to access particle data, identical to above
 
     CHECK(stack.getSize() == 3);
     CHECK(stack.getEntries() == 3);
-    CHECK(!stack.IsEmpty());
+    CHECK(!stack.isEmpty());
 
-    p.Delete(); // mark for deletion: size=3, entries=2
+    p.erase(); // mark for deletion: size=3, entries=2
     CHECK(stack.getSize() == 3);
     CHECK(stack.getEntries() == 2);
-    CHECK(!stack.IsEmpty());
+    CHECK(!stack.isEmpty());
 
-    stack.last().Delete(); // mark for deletion: size=3, entries=1
+    stack.last().erase(); // mark for deletion: size=3, entries=1
     CHECK(stack.getSize() == 3);
     CHECK(stack.getEntries() == 1);
-    CHECK(!stack.IsEmpty());
+    CHECK(!stack.isEmpty());
 
     /*
        GetNextParticle will find two entries marked as "deleted" and
        will purge this from the end of the stack: size = 1
     */
-    stack.GetNextParticle().Delete(); // mark for deletion: size=3, entries=0
+    stack.getNextParticle().erase(); // mark for deletion: size=3, entries=0
     CHECK(stack.getSize() == 1);
     CHECK(stack.getEntries() == 0);
-    CHECK(stack.IsEmpty());
+    CHECK(stack.isEmpty());
   }
 
   SECTION("create secondaries") {
 
     StackTest stack;
     CHECK(stack.getSize() == 0);
-    auto iter = stack.AddParticle(std::tuple{9.9});
-    StackTest::ParticleInterfaceType& p =
+    auto iter = stack.addParticle(std::tuple{9.9});
+    StackTest::particle_interface_type& p =
         *iter; // also this is valid to access particle data
     CHECK(stack.getSize() == 1);
-    p.AddSecondary(std::tuple{4.4});
+    p.addSecondary(std::tuple{4.4});
     CHECK(stack.getSize() == 2);
   }
 
@@ -130,85 +130,85 @@ TEST_CASE("Stack", "[Stack]") {
     StackTest stack;
     CHECK(stack.getSize() == 0);
     CHECK(stack.getEntries() == 0);
-    CHECK(stack.IsEmpty());
+    CHECK(stack.isEmpty());
 
-    stack.AddParticle(std::tuple{9.9});
-    stack.AddParticle(std::tuple{8.8});
+    stack.addParticle(std::tuple{9.9});
+    stack.addParticle(std::tuple{8.8});
     CHECK(stack.getSize() == 2);
     CHECK(stack.getEntries() == 2);
-    CHECK(!stack.IsEmpty());
+    CHECK(!stack.isEmpty());
 
-    auto particle = stack.GetNextParticle(); // first particle
-    CHECK(particle.GetData() == 8.8);
+    auto particle = stack.getNextParticle(); // first particle
+    CHECK(particle.getData() == 8.8);
 
-    particle.Delete(); // only marks (last) particle as deleted
+    particle.erase(); // only marks (last) particle as deleted
     CHECK(stack.getSize() == 2);
     CHECK(stack.getEntries() == 1);
-    CHECK(!stack.IsEmpty());
+    CHECK(!stack.isEmpty());
 
     /*
       This following call to GetNextParticle will realize that the
       current last particle on the stack was marked "deleted" and will
       purge it: stack size is reduced by one.
      */
-    auto particle2 = stack.GetNextParticle(); // first particle
-    CHECK(particle2.GetData() == 9.9);
+    auto particle2 = stack.getNextParticle(); // first particle
+    CHECK(particle2.getData() == 9.9);
     CHECK(stack.getSize() == 1);
     CHECK(stack.getEntries() == 1);
-    CHECK(!stack.IsEmpty());
+    CHECK(!stack.isEmpty());
 
-    particle2.Delete(); // also mark this particle as deleted
+    particle2.erase(); // also mark this particle as deleted
 
     CHECK(stack.getSize() == 1);
     CHECK(stack.getEntries() == 0);
-    CHECK(stack.IsEmpty());
+    CHECK(stack.isEmpty());
   }
 
   SECTION("swap particle") {
     StackTest stack;
     CHECK(stack.getSize() == 0);
     CHECK(stack.getEntries() == 0);
-    CHECK(stack.IsEmpty());
+    CHECK(stack.isEmpty());
 
-    stack.AddParticle(std::tuple{9.888});
-    stack.AddParticle(std::tuple{8.999});
+    stack.addParticle(std::tuple{9.888});
+    stack.addParticle(std::tuple{8.999});
     CHECK(stack.getSize() == 2);
     CHECK(stack.getEntries() == 2);
-    CHECK(!stack.IsEmpty());
+    CHECK(!stack.isEmpty());
 
     auto p1 = stack.begin();
     auto p2 = p1 + 1;
 
-    CHECK(p1.GetData() == 9.888);
-    CHECK(p2.GetData() == 8.999);
+    CHECK(p1.getData() == 9.888);
+    CHECK(p2.getData() == 8.999);
 
-    stack.Swap(p1, p2);
+    stack.swap(p1, p2);
 
-    CHECK(p1.GetData() == 8.999);
-    CHECK(p2.GetData() == 9.888);
+    CHECK(p1.getData() == 8.999);
+    CHECK(p2.getData() == 9.888);
   }
 
   SECTION("copy particle") {
     StackTest stack;
     CHECK(stack.getSize() == 0);
     CHECK(stack.getEntries() == 0);
-    CHECK(stack.IsEmpty());
+    CHECK(stack.isEmpty());
 
-    stack.AddParticle(std::tuple{9.888});
-    stack.AddParticle(std::tuple{8.999});
+    stack.addParticle(std::tuple{9.888});
+    stack.addParticle(std::tuple{8.999});
     CHECK(stack.getSize() == 2);
     CHECK(stack.getEntries() == 2);
-    CHECK(!stack.IsEmpty());
+    CHECK(!stack.isEmpty());
 
     auto p1 = stack.begin();
     auto p2 = p1 + 1;
 
-    CHECK(p1.GetData() == 9.888);
-    CHECK(p2.GetData() == 8.999);
+    CHECK(p1.getData() == 9.888);
+    CHECK(p2.getData() == 8.999);
 
-    stack.Copy(p1, p2);
+    stack.copy(p1, p2);
 
-    CHECK(p1.GetData() == 9.888);
-    CHECK(p2.GetData() == 9.888);
+    CHECK(p1.getData() == 9.888);
+    CHECK(p2.getData() == 9.888);
   }
 }
diff --git a/tests/framework/testTestStack.h b/tests/framework/testTestStack.h
index e9e3e9645..c71d2922b 100644
--- a/tests/framework/testTestStack.h
+++ b/tests/framework/testTestStack.h
@@ -16,35 +16,36 @@ n/*
  * definition of stack-data object for unit tests
  *
  * TestStackData contain only a single variable "Data" stored in fData
- * with Get/SetData functions.
+ * with get/setData functions.
  */
 class TestStackData {
 
 public:
   // these functions are needed for the Stack interface
-  void Clear() { fData.clear(); }
-  unsigned int GetSize() const { return fData.size(); }
-  unsigned int GetCapacity() const { return fData.size(); }
-  void Copy(const unsigned int i1, const unsigned int i2) { fData[i2] = fData[i1]; }
-  void Swap(const unsigned int i1, const unsigned int i2) {
-    double tmp0 = fData[i1];
-    fData[i1] = fData[i2];
-    fData[i2] = tmp0;
+  void clear() { data_.clear(); }
+  unsigned int getSize() const { return data_.size(); }
+  unsigned int getCapacity() const { return data_.size(); }
+  void copy(const unsigned int i1, const unsigned int i2) { data_[i2] = data_[i1]; }
+  void swap(const unsigned int i1, const unsigned int i2) {
+    double tmp0 = data_[i1];
+    data_[i1] = data_[i2];
+    data_[i2] = tmp0;
   }
 
   // custom data access function
-  void SetData(const unsigned int i, const double v) { fData[i] = v; }
-  double GetData(const unsigned int i) const { return fData[i]; }
+  void setData(const unsigned int i, const double v) { data_[i] = v; }
+  double getData(const unsigned int i) const { return data_[i]; }
+
 
   // these functions are also needed by the Stack interface
-  void IncrementSize() { fData.push_back(0.); }
-  void DecrementSize() {
-    if (fData.size() > 0) { fData.pop_back(); }
+   void incrementSize() { data_.push_back(0.); }
+  void decrementSize() {
+    if (data_.size() > 0) { data_.pop_back(); }
   }
 
   // custom private data section
 private:
-  std::vector<double> fData;
+  std::vector<double> data_;
 };
 
 /**
@@ -54,17 +55,17 @@ private:
  *
  * It provides Get/Set methods to read and write data to the "Data"
  * storage of TestStackData obtained via
- * "StackIteratorInterface::GetStackData()", given the index of the
- * iterator "StackIteratorInterface::GetIndex()"
+ * "StackIteratorInterface::getStackData()", given the index of the
+ * iterator "StackIteratorInterface::getIndex()"
  *
  */
 template <typename StackIteratorInterface>
 class TestParticleInterface
-    : public corsika::stack::ParticleBase<StackIteratorInterface> {
-
+  : public corsika::ParticleBase<StackIteratorInterface> {
+  
+  typedef corsika::ParticleBase<StackIteratorInterface> super_type;
+  
 public:
-  using corsika::stack::ParticleBase<StackIteratorInterface>::GetStackData;
-  using corsika::stack::ParticleBase<StackIteratorInterface>::GetIndex;
 
   /*
      The SetParticleData methods are called for creating new entries
@@ -73,13 +74,13 @@ public:
   */
 
   // default version for particle-creation from input data
-  void SetParticleData(const std::tuple<double> v) { SetData(std::get<0>(v)); }
-  void SetParticleData(TestParticleInterface<StackIteratorInterface>& /*parent*/,
+  void setParticleData(const std::tuple<double> v) { setData(std::get<0>(v)); }
+  void setParticleData(TestParticleInterface<StackIteratorInterface>& /*parent*/,
                        std::tuple<double> v) {
-    SetData(std::get<0>(v));
+    setData(std::get<0>(v));
   }
 
   // here are the fundamental methods for access to TestStackData data
-  void SetData(const double v) { GetStackData().SetData(GetIndex(), v); }
-  double GetData() const { return GetStackData().GetData(GetIndex()); }
+  void setData(const double v) { super_type::getStackData().setData(super_type::getIndex(), v); }
+  double getData() const { return super_type::getStackData().getData(super_type::getIndex()); }
 };
diff --git a/tests/stack/testDummyStack.cpp b/tests/stack/testDummyStack.cpp
index 41a573158..c7b055468 100644
--- a/tests/stack/testDummyStack.cpp
+++ b/tests/stack/testDummyStack.cpp
@@ -6,10 +6,9 @@
  * the license.
  */
 
-#include <corsika/stack/dummy/DummyStack.h>
+#include <corsika/stack/DummyStack.hpp>
 
 using namespace corsika;
-using namespace corsika::stack;
 
 #include <catch2/catch.hpp>
 
@@ -17,14 +16,14 @@ using namespace corsika::stack;
 
 TEST_CASE("DummyStack", "[stack]") {
 
-  using TestStack = dummy::DummyStack;
+  using TestStack = dummy_stack::DummyStack;
 
-  dummy::NoData noData;
+  dummy_stack::NoData noData;
 
   SECTION("write node") {
 
     TestStack s;
-    s.AddParticle(std::tuple<dummy::NoData>{noData});
+    s.addParticle(std::tuple<dummy_stack::NoData>{noData});
     CHECK(s.getEntries() == 1);
   }
 
@@ -32,10 +31,10 @@ TEST_CASE("DummyStack", "[stack]") {
 
     TestStack s;
     // add 99 particles, each 10th particle is a nucleus with A=i and Z=A/2!
-    for (int i = 0; i < 99; ++i) { s.AddParticle(std::tuple<dummy::NoData>{noData}); }
+    for (int i = 0; i < 99; ++i) { s.addParticle(std::tuple<dummy_stack::NoData>{noData}); }
 
     CHECK(s.getEntries() == 99);
-    for (int i = 0; i < 99; ++i) s.GetNextParticle().Delete();
+    for (int i = 0; i < 99; ++i) s.getNextParticle().erase();
     CHECK(s.getEntries() == 0);
   }
 }
diff --git a/tests/stack/testGeometryNodeStackExtension.cpp b/tests/stack/testGeometryNodeStackExtension.cpp
index b566c2c8e..35f5c20bd 100644
--- a/tests/stack/testGeometryNodeStackExtension.cpp
+++ b/tests/stack/testGeometryNodeStackExtension.cpp
@@ -6,12 +6,11 @@
  * the license.
  */
 
-#include <corsika/stack/CombinedStack.h>
-#include <corsika/stack/dummy/DummyStack.h>
-#include <corsika/stack/node/GeometryNodeStackExtension.h>
+#include <corsika/framework/stack/CombinedStack.hpp>
+#include <corsika/stack/DummyStack.hpp>
+#include <corsika/stack/GeometryNodeStackExtension.hpp>
 
 using namespace corsika;
-using namespace corsika::stack;
 
 #include <catch2/catch.hpp>
 
@@ -27,29 +26,28 @@ public:
 // the GeometryNode stack needs to know the type of geometry-nodes from the DummyEnv:
 template <typename TStackIter>
 using DummyGeometryDataInterface =
-    typename corsika::stack::node::MakeGeometryDataInterface<TStackIter, DummyEnv>::type;
+    typename node::MakeGeometryDataInterface<TStackIter, DummyEnv>::type;
 
 // combine dummy stack with geometry information for tracking
 template <typename TStackIter>
 using StackWithGeometryInterface =
-    corsika::stack::CombinedParticleInterface<dummy::DummyStack::MPIType,
-                                              DummyGeometryDataInterface, TStackIter>;
+    CombinedParticleInterface<dummy_stack::DummyStack::pi_type,
+                              DummyGeometryDataInterface, TStackIter>;
 
 using TestStack =
-    corsika::stack::CombinedStack<typename stack::dummy::DummyStack::StackImpl,
-                                  stack::node::GeometryData<DummyEnv>,
-                                  StackWithGeometryInterface>;
+    CombinedStack<typename dummy_stack::DummyStack::stack_implementation_type,
+                  node::GeometryData<DummyEnv>, StackWithGeometryInterface>;
 
 TEST_CASE("GeometryNodeStackExtension", "[stack]") {
 
-  dummy::NoData noData;
+  dummy_stack::NoData noData;
 
   SECTION("write node") {
 
     const int data = 5;
 
     TestStack s;
-    s.AddParticle(std::make_tuple(noData), std::tuple<const int*>{&data});
+    s.addParticle(std::make_tuple(noData), std::tuple<const int*>{&data});
 
     CHECK(s.getEntries() == 1);
   }
@@ -58,12 +56,12 @@ TEST_CASE("GeometryNodeStackExtension", "[stack]") {
     const int data = 15;
 
     TestStack s;
-    auto p = s.AddParticle(std::make_tuple(noData));
-    p.SetNode(&data);
+    auto p = s.addParticle(std::make_tuple(noData));
+    p.setNode(&data);
     CHECK(s.getEntries() == 1);
 
-    const auto pout = s.GetNextParticle();
-    CHECK(*(pout.GetNode()) == 15);
+    const auto pout = s.getNextParticle();
+    CHECK(*(pout.getNode()) == 15);
   }
 
   SECTION("stack fill and cleanup") {
@@ -73,16 +71,16 @@ TEST_CASE("GeometryNodeStackExtension", "[stack]") {
     TestStack s;
     // add 99 particles, each 10th particle is a nucleus with A=i and Z=A/2!
     for (int i = 0; i < 99; ++i) {
-      auto p = s.AddParticle(std::tuple<dummy::NoData>{noData});
-      p.SetNode(&data);
+      auto p = s.addParticle(std::tuple<dummy_stack::NoData>{noData});
+      p.setNode(&data);
     }
 
     CHECK(s.getEntries() == 99);
     double v = 0;
     for (int i = 0; i < 99; ++i) {
-      auto p = s.GetNextParticle();
-      v += *(p.GetNode());
-      p.Delete();
+      auto p = s.getNextParticle();
+      v += *(p.getNode());
+      p.erase();
     }
     CHECK(v == 99 * data);
     CHECK(s.getEntries() == 0);
diff --git a/tests/stack/testNuclearStackExtension.cpp b/tests/stack/testNuclearStackExtension.cpp
index 477404cbf..491904d51 100644
--- a/tests/stack/testNuclearStackExtension.cpp
+++ b/tests/stack/testNuclearStackExtension.cpp
@@ -6,14 +6,11 @@
  * the license.
  */
 
-#include <corsika/geometry/RootCoordinateSystem.h>
-#include <corsika/stack/nuclear_extension/NuclearStackExtension.h>
-#include <corsika/units/PhysicalUnits.h>
+#include <corsika/framework/geometry/RootCoordinateSystem.hpp>
+#include <corsika/stack/NuclearStackExtension.hpp>
+#include <corsika/framework/core/PhysicalUnits.hpp>
 
 using namespace corsika;
-using namespace corsika::stack::nuclear_extension;
-using namespace corsika::geometry;
-using namespace corsika::units::si;
 
 #include <catch2/catch.hpp>
 
@@ -22,237 +19,236 @@ using namespace std;
 
 TEST_CASE("NuclearStackExtension", "[stack]") {
 
-  CoordinateSystem& dummyCS =
-      RootCoordinateSystem::getInstance().GetRootCoordinateSystem();
+  CoordinateSystemPtr const& dummyCS = get_root_CoordinateSystem();
 
   SECTION("write non nucleus") {
-    NuclearStackExtension<corsika::stack::super_stupid::SuperStupidStack,
-                          ExtendedParticleInterfaceType>
+    nuclear_stack::NuclearStackExtension<simple_stack::SuperStupidStack,
+                                         nuclear_stack::ExtendedParticleInterfaceType>
         s;
-    s.AddParticle(
-        std::make_tuple(particles::Code::Electron, 1.5_GeV,
-                        corsika::stack::MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}),
+    s.addParticle(
+        std::make_tuple(Code::Electron, 1.5_GeV,
+                        simple_stack::MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}),
                         Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s));
     CHECK(s.getEntries() == 1);
   }
 
   SECTION("write nucleus") {
-    NuclearStackExtension<corsika::stack::super_stupid::SuperStupidStack,
-                          ExtendedParticleInterfaceType>
+    nuclear_stack::NuclearStackExtension<simple_stack::SuperStupidStack,
+                                         nuclear_stack::ExtendedParticleInterfaceType>
         s;
-    s.AddParticle(std::make_tuple(
-        particles::Code::Nucleus, 1.5_GeV,
-        corsika::stack::MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}),
+    s.addParticle(std::make_tuple(
+        Code::Nucleus, 1.5_GeV,
+        simple_stack::MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}),
         Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s, 10, 10));
     CHECK(s.getEntries() == 1);
   }
 
   SECTION("write invalid nucleus") {
-    ParticleDataStack s;
-    CHECK_THROWS(s.AddParticle(
-        std::make_tuple(particles::Code::Nucleus, 1.5_GeV,
-                        corsika::stack::MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}),
+    nuclear_stack::ParticleDataStack s;
+    CHECK_THROWS(s.addParticle(
+        std::make_tuple(Code::Nucleus, 1.5_GeV,
+                        simple_stack::MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}),
                         Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s, 0, 0)));
   }
 
   SECTION("read non nucleus") {
-    ParticleDataStack s;
-    s.AddParticle(
-        std::make_tuple(particles::Code::Electron, 1.5_GeV,
-                        corsika::stack::MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}),
+    nuclear_stack::ParticleDataStack s;
+    s.addParticle(
+        std::make_tuple(Code::Electron, 1.5_GeV,
+                        simple_stack::MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}),
                         Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s));
-    const auto pout = s.GetNextParticle();
-    CHECK(pout.GetPID() == particles::Code::Electron);
-    CHECK(pout.GetEnergy() == 1.5_GeV);
-    CHECK(pout.GetTime() == 100_s);
+    const auto pout = s.getNextParticle();
+    CHECK(pout.getPID() == Code::Electron);
+    CHECK(pout.getEnergy() == 1.5_GeV);
+    CHECK(pout.getTime() == 100_s);
   }
 
   SECTION("read nucleus") {
-    ParticleDataStack s;
-    s.AddParticle(
-        std::make_tuple(particles::Code::Nucleus, 1.5_GeV,
-                        corsika::stack::MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}),
+    nuclear_stack::ParticleDataStack s;
+    s.addParticle(
+        std::make_tuple(Code::Nucleus, 1.5_GeV,
+                        simple_stack::MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}),
                         Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s, 10, 9));
-    const auto pout = s.GetNextParticle();
-    CHECK(pout.GetPID() == particles::Code::Nucleus);
-    CHECK(pout.GetEnergy() == 1.5_GeV);
-    CHECK(pout.GetTime() == 100_s);
-    CHECK(pout.GetNuclearA() == 10);
-    CHECK(pout.GetNuclearZ() == 9);
+    const auto pout = s.getNextParticle();
+    CHECK(pout.getPID() == Code::Nucleus);
+    CHECK(pout.getEnergy() == 1.5_GeV);
+    CHECK(pout.getTime() == 100_s);
+    CHECK(pout.getNuclearA() == 10);
+    CHECK(pout.getNuclearZ() == 9);
   }
 
   SECTION("read invalid nucleus") {
-    ParticleDataStack s;
-    s.AddParticle(
-        std::make_tuple(particles::Code::Electron, 1.5_GeV,
-                        corsika::stack::MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}),
+    nuclear_stack::ParticleDataStack s;
+    s.addParticle(
+        std::make_tuple(Code::Electron, 1.5_GeV,
+                        simple_stack::MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}),
                         Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s));
-    const auto pout = s.GetNextParticle();
-    CHECK_THROWS(pout.GetNuclearA());
-    CHECK_THROWS(pout.GetNuclearZ());
+    const auto pout = s.getNextParticle();
+    CHECK_THROWS(pout.getNuclearA());
+    CHECK_THROWS(pout.getNuclearZ());
   }
 
   SECTION("stack fill and cleanup") {
 
-    ParticleDataStack s;
+    nuclear_stack::ParticleDataStack s;
     // add 99 particles, each 10th particle is a nucleus with A=i and Z=A/2!
     for (int i = 0; i < 99; ++i) {
       if ((i + 1) % 10 == 0) {
-        s.AddParticle(std::make_tuple(
-            particles::Code::Nucleus, 1.5_GeV,
-            corsika::stack::MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}),
+        s.addParticle(std::make_tuple(
+            Code::Nucleus, 1.5_GeV,
+            simple_stack::MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}),
             Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s, i, i / 2));
       } else {
-        s.AddParticle(std::make_tuple(
-            particles::Code::Electron, 1.5_GeV,
-            corsika::stack::MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}),
-            Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s));
+        s.addParticle(
+            std::make_tuple(Code::Electron, 1.5_GeV,
+                            simple_stack::MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}),
+                            Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s));
       }
     }
 
     CHECK(s.getEntries() == 99);
-    for (int i = 0; i < 99; ++i) s.GetNextParticle().Delete();
+    for (int i = 0; i < 99; ++i) s.getNextParticle().erase();
     CHECK(s.getEntries() == 0);
   }
 
   SECTION("stack operations") {
 
-    ParticleDataStack s;
+    nuclear_stack::ParticleDataStack s;
     // add 99 particles, each 10th particle is a nucleus with A=i and Z=A/2!
     // i=9, 19, 29, etc. are nuclei
     for (int i = 0; i < 99; ++i) {
       if ((i + 1) % 10 == 0) {
-        s.AddParticle(std::make_tuple(
-            particles::Code::Nucleus, i * 15_GeV,
-            corsika::stack::MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}),
+        s.addParticle(std::make_tuple(
+            Code::Nucleus, i * 15_GeV,
+            simple_stack::MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}),
             Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s, i, i / 2));
       } else {
-        s.AddParticle(std::make_tuple(
-            particles::Code::Electron, i * 1.5_GeV,
-            corsika::stack::MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}),
-            Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s));
+        s.addParticle(
+            std::make_tuple(Code::Electron, i * 1.5_GeV,
+                            simple_stack::MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}),
+                            Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s));
       }
     }
 
     // copy
     {
-      s.Copy(s.begin() + 9, s.begin() + 10); // nuclei to non-nuclei
+      s.copy(s.begin() + 9, s.begin() + 10); // nuclei to non-nuclei
       const auto& p9 = s.cbegin() + 9;
       const auto& p10 = s.cbegin() + 10;
 
-      CHECK(p9.GetPID() == particles::Code::Nucleus);
-      CHECK(p9.GetEnergy() == 9 * 15_GeV);
-      CHECK(p9.GetTime() == 100_s);
-      CHECK(p9.GetNuclearA() == 9);
-      CHECK(p9.GetNuclearZ() == 9 / 2);
-
-      CHECK(p10.GetPID() == particles::Code::Nucleus);
-      CHECK(p10.GetEnergy() == 9 * 15_GeV);
-      CHECK(p10.GetTime() == 100_s);
-      CHECK(p10.GetNuclearA() == 9);
-      CHECK(p10.GetNuclearZ() == 9 / 2);
+      CHECK(p9.getPID() == Code::Nucleus);
+      CHECK(p9.getEnergy() == 9 * 15_GeV);
+      CHECK(p9.getTime() == 100_s);
+      CHECK(p9.getNuclearA() == 9);
+      CHECK(p9.getNuclearZ() == 9 / 2);
+
+      CHECK(p10.getPID() == Code::Nucleus);
+      CHECK(p10.getEnergy() == 9 * 15_GeV);
+      CHECK(p10.getTime() == 100_s);
+      CHECK(p10.getNuclearA() == 9);
+      CHECK(p10.getNuclearZ() == 9 / 2);
     }
 
     // copy
     {
-      s.Copy(s.begin() + 93, s.begin() + 9); // non-nuclei to nuclei
+      s.copy(s.begin() + 93, s.begin() + 9); // non-nuclei to nuclei
       const auto& p93 = s.cbegin() + 93;
       const auto& p9 = s.cbegin() + 9;
 
-      CHECK(p9.GetPID() == particles::Code::Electron);
-      CHECK(p9.GetEnergy() == 93 * 1.5_GeV);
-      CHECK(p9.GetTime() == 100_s);
+      CHECK(p9.getPID() == Code::Electron);
+      CHECK(p9.getEnergy() == 93 * 1.5_GeV);
+      CHECK(p9.getTime() == 100_s);
 
-      CHECK(p93.GetPID() == particles::Code::Electron);
-      CHECK(p93.GetEnergy() == 93 * 1.5_GeV);
-      CHECK(p93.GetTime() == 100_s);
+      CHECK(p93.getPID() == Code::Electron);
+      CHECK(p93.getEnergy() == 93 * 1.5_GeV);
+      CHECK(p93.getTime() == 100_s);
     }
 
     // copy
     {
-      s.Copy(s.begin() + 89, s.begin() + 79); // nuclei to nuclei
+      s.copy(s.begin() + 89, s.begin() + 79); // nuclei to nuclei
       const auto& p89 = s.cbegin() + 89;
       const auto& p79 = s.cbegin() + 79;
 
-      CHECK(p89.GetPID() == particles::Code::Nucleus);
-      CHECK(p89.GetEnergy() == 89 * 15_GeV);
-      CHECK(p89.GetTime() == 100_s);
+      CHECK(p89.getPID() == Code::Nucleus);
+      CHECK(p89.getEnergy() == 89 * 15_GeV);
+      CHECK(p89.getTime() == 100_s);
 
-      CHECK(p79.GetPID() == particles::Code::Nucleus);
-      CHECK(p79.GetEnergy() == 89 * 15_GeV);
-      CHECK(p79.GetTime() == 100_s);
+      CHECK(p79.getPID() == Code::Nucleus);
+      CHECK(p79.getEnergy() == 89 * 15_GeV);
+      CHECK(p79.getTime() == 100_s);
     }
 
     // swap
     {
-      s.Swap(s.begin() + 11, s.begin() + 10);
+      s.swap(s.begin() + 11, s.begin() + 10);
       const auto& p11 = s.cbegin() + 11; // now: nucleus
       const auto& p10 = s.cbegin() + 10; // now: electron
 
-      CHECK(p11.GetPID() == particles::Code::Nucleus);
-      CHECK(p11.GetEnergy() == 9 * 15_GeV);
-      CHECK(p11.GetTime() == 100_s);
-      CHECK(p11.GetNuclearA() == 9);
-      CHECK(p11.GetNuclearZ() == 9 / 2);
+      CHECK(p11.getPID() == Code::Nucleus);
+      CHECK(p11.getEnergy() == 9 * 15_GeV);
+      CHECK(p11.getTime() == 100_s);
+      CHECK(p11.getNuclearA() == 9);
+      CHECK(p11.getNuclearZ() == 9 / 2);
 
-      CHECK(p10.GetPID() == particles::Code::Electron);
-      CHECK(p10.GetEnergy() == 11 * 1.5_GeV);
-      CHECK(p10.GetTime() == 100_s);
+      CHECK(p10.getPID() == Code::Electron);
+      CHECK(p10.getEnergy() == 11 * 1.5_GeV);
+      CHECK(p10.getTime() == 100_s);
     }
 
     // swap two nuclei
     {
-      s.Swap(s.begin() + 29, s.begin() + 59);
+      s.swap(s.begin() + 29, s.begin() + 59);
       const auto& p29 = s.cbegin() + 29;
       const auto& p59 = s.cbegin() + 59;
 
-      CHECK(p29.GetPID() == particles::Code::Nucleus);
-      CHECK(p29.GetEnergy() == 59 * 15_GeV);
-      CHECK(p29.GetTime() == 100_s);
-      CHECK(p29.GetNuclearA() == 59);
-      CHECK(p29.GetNuclearZ() == 59 / 2);
-
-      CHECK(p59.GetPID() == particles::Code::Nucleus);
-      CHECK(p59.GetEnergy() == 29 * 15_GeV);
-      CHECK(p59.GetTime() == 100_s);
-      CHECK(p59.GetNuclearA() == 29);
-      CHECK(p59.GetNuclearZ() == 29 / 2);
+      CHECK(p29.getPID() == Code::Nucleus);
+      CHECK(p29.getEnergy() == 59 * 15_GeV);
+      CHECK(p29.getTime() == 100_s);
+      CHECK(p29.getNuclearA() == 59);
+      CHECK(p29.getNuclearZ() == 59 / 2);
+
+      CHECK(p59.getPID() == Code::Nucleus);
+      CHECK(p59.getEnergy() == 29 * 15_GeV);
+      CHECK(p59.getTime() == 100_s);
+      CHECK(p59.getNuclearA() == 29);
+      CHECK(p59.getNuclearZ() == 29 / 2);
     }
 
-    for (int i = 0; i < 99; ++i) s.last().Delete();
+    for (int i = 0; i < 99; ++i) s.last().erase();
     CHECK(s.getEntries() == 0);
   }
 
   SECTION("not allowed") {
-    NuclearStackExtension<corsika::stack::super_stupid::SuperStupidStack,
-                          ExtendedParticleInterfaceType>
+    nuclear_stack::NuclearStackExtension<simple_stack::SuperStupidStack,
+                                         nuclear_stack::ExtendedParticleInterfaceType>
         s;
 
     // not valid:
-    CHECK_THROWS(s.AddParticle(std::make_tuple(
-        particles::Code::Oxygen, 1.5_GeV,
-        corsika::stack::MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}),
+    CHECK_THROWS(s.addParticle(std::make_tuple(
+        Code::Oxygen, 1.5_GeV,
+        simple_stack::MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}),
         Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s, 16, 8)));
 
     // valid
-    auto particle = s.AddParticle(
-        std::make_tuple(particles::Code::Nucleus, 1.5_GeV,
-                        corsika::stack::MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}),
+    auto particle = s.addParticle(
+        std::make_tuple(Code::Nucleus, 1.5_GeV,
+                        simple_stack::MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}),
                         Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s, 10, 9));
 
     // not valid
-    CHECK_THROWS(particle.AddSecondary(std::make_tuple(
-        particles::Code::Oxygen, 1.5_GeV,
-        corsika::stack::MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}),
+    CHECK_THROWS(particle.addSecondary(std::make_tuple(
+        Code::Oxygen, 1.5_GeV,
+        simple_stack::MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}),
         Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s, 16, 8)));
 
     // add a another nucleus, so there are two now
-    s.AddParticle(
-        std::make_tuple(particles::Code::Nucleus, 1.5_GeV,
-                        corsika::stack::MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}),
+    s.addParticle(
+        std::make_tuple(Code::Nucleus, 1.5_GeV,
+                        simple_stack::MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}),
                         Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s, 10, 9));
 
     // not valid, since end() is not a valid entry
-    CHECK_THROWS(s.Swap(s.begin(), s.end()));
+    CHECK_THROWS(s.swap(s.begin(), s.end()));
   }
 }
diff --git a/tests/stack/testSuperStupidStack.cpp b/tests/stack/testSuperStupidStack.cpp
index 74412b69b..cae1bbd44 100644
--- a/tests/stack/testSuperStupidStack.cpp
+++ b/tests/stack/testSuperStupidStack.cpp
@@ -8,54 +8,48 @@
 
 #define protected public // to also test the internal state of objects
 
-#include <corsika/geometry/RootCoordinateSystem.h>
-#include <corsika/stack/super_stupid/SuperStupidStack.h>
-#include <corsika/units/PhysicalUnits.h>
-
-using namespace corsika::geometry;
-using namespace corsika::units::si;
+#include <corsika/framework/geometry/RootCoordinateSystem.hpp>
+#include <corsika/stack/SuperStupidStack.hpp>
+#include <corsika/framework/core/PhysicalUnits.hpp>
 
 #include <catch2/catch.hpp>
 
 using namespace corsika;
-using namespace corsika::stack::super_stupid;
-
 using namespace std;
 
 TEST_CASE("SuperStupidStack", "[stack]") {
 
-  CoordinateSystem& dummyCS =
-      RootCoordinateSystem::getInstance().GetRootCoordinateSystem();
+  const CoordinateSystemPtr& dummyCS = get_root_CoordinateSystem();
 
   SECTION("read+write") {
 
-    SuperStupidStack s;
-    s.AddParticle(
-        std::make_tuple(particles::Code::Electron, 1.5_GeV,
-                        corsika::stack::MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}),
+    simple_stack::SuperStupidStack s;
+    s.addParticle(
+        std::make_tuple(Code::Electron, 1.5_GeV,
+                        simple_stack::MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}),
                         Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s));
 
     // read
     CHECK(s.getEntries() == 1);
     CHECK(s.getSize() == 1);
-    auto pout = s.GetNextParticle();
-    CHECK(pout.GetPID() == particles::Code::Electron);
-    CHECK(pout.GetEnergy() == 1.5_GeV);
-    CHECK(pout.GetTime() == 100_s);
+    auto pout = s.getNextParticle();
+    CHECK(pout.getPID() == Code::Electron);
+    CHECK(pout.getEnergy() == 1.5_GeV);
+    CHECK(pout.getTime() == 100_s);
   }
 
   SECTION("write+delete") {
 
-    SuperStupidStack s;
+    simple_stack::SuperStupidStack s;
     for (int i = 0; i < 99; ++i)
-      s.AddParticle(
-          std::make_tuple(particles::Code::Electron, 1.5_GeV,
-                          corsika::stack::MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}),
+      s.addParticle(
+          std::make_tuple(Code::Electron, 1.5_GeV,
+                          simple_stack::MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}),
                           Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s));
 
     CHECK(s.getSize() == 99);
 
-    for (int i = 0; i < 99; ++i) s.GetNextParticle().Delete();
+    for (int i = 0; i < 99; ++i) s.getNextParticle().erase();
 
     CHECK(s.getEntries() == 0);
     CHECK(s.getSize() == 1);
-- 
GitLab