From 3da6496400d755d7ff0a67e80912f13cadc7e18b Mon Sep 17 00:00:00 2001
From: ralfulrich <ralf.ulrich@kit.edu>
Date: Tue, 15 Sep 2020 16:36:30 +0200
Subject: [PATCH] reorganized Stacks and StackExtensions

---
 Framework/Cascade/testCascade.h               |  16 +-
 .../TrackingLine/testTrackingLineStack.h      |  20 +-
 Setup/CMakeLists.txt                          |   4 +-
 Setup/SetupStack.h                            | 122 ++-------
 Stack/CMakeLists.txt                          |   2 +
 Stack/DummyStack/CMakeLists.txt               |   9 +
 Stack/DummyStack/DummyStack.h                 |  48 ++--
 Stack/DummyStack/testDummyStack.cc            |  44 ++++
 .../GeometryNodeStackExtension/CMakeLists.txt |  38 +++
 .../GeometryNodeStackExtension.h              |   8 +-
 .../testGeometryNodeStackExtension.cc         |  97 +++++++
 Stack/History/CMakeLists.txt                  |  43 ++++
 Stack/History/HistoryStackExtension.h         | 125 +++++++++
 Stack/History/testHistory.cc                  | 241 ++++++++++++++++++
 Stack/NuclearStackExtension/CMakeLists.txt    |   2 +-
 .../NuclearStackExtension.h                   |  55 ++--
 .../testNuclearStackExtension.cc              |  23 +-
 Stack/SuperStupidStack/SuperStupidStack.h     |  23 +-
 18 files changed, 703 insertions(+), 217 deletions(-)
 create mode 100644 Stack/DummyStack/testDummyStack.cc
 create mode 100644 Stack/GeometryNodeStackExtension/CMakeLists.txt
 create mode 100644 Stack/GeometryNodeStackExtension/testGeometryNodeStackExtension.cc
 create mode 100644 Stack/History/CMakeLists.txt
 create mode 100644 Stack/History/HistoryStackExtension.h
 create mode 100644 Stack/History/testHistory.cc

diff --git a/Framework/Cascade/testCascade.h b/Framework/Cascade/testCascade.h
index 41a96ee3e..286318452 100644
--- a/Framework/Cascade/testCascade.h
+++ b/Framework/Cascade/testCascade.h
@@ -9,23 +9,27 @@
 #pragma once
 
 #include <corsika/environment/Environment.h>
-#include <corsika/setup/SetupStack.h>
+
+#include <corsika/stack/node/GeometryNodeStackExtension.h>
+#include <corsika/stack/nuclear_extension/NuclearStackExtension.h>
+#include <corsika/stack/CombinedStack.h>
 
 using TestEnvironmentType =
     corsika::environment::Environment<corsika::environment::IMediumModel>;
 
 template <typename T>
-using SetupGeometryDataInterface = GeometryDataInterface<T, TestEnvironmentType>;
+using SetupGeometryDataInterface =
+    corsika::stack::node::GeometryDataInterface<T, TestEnvironmentType>;
 
 // combine particle data stack with geometry information for tracking
 template <typename StackIter>
 using StackWithGeometryInterface = corsika::stack::CombinedParticleInterface<
-    corsika::setup::detail::ParticleDataStack::PIType, SetupGeometryDataInterface,
-    StackIter>;
+    corsika::stack::nuclear_extension::ParticleDataStack::PIType,
+    SetupGeometryDataInterface, StackIter>;
 
 using TestCascadeStack = corsika::stack::CombinedStack<
-    typename corsika::setup::detail::ParticleDataStack::StackImpl,
-    GeometryData<TestEnvironmentType>, StackWithGeometryInterface>;
+    typename corsika::stack::nuclear_extension::ParticleDataStack::StackImpl,
+    corsika::stack::node::GeometryData<TestEnvironmentType>, StackWithGeometryInterface>;
 
 /*
   See also Issue 161
diff --git a/Processes/TrackingLine/testTrackingLineStack.h b/Processes/TrackingLine/testTrackingLineStack.h
index 1aeeecc10..52955a816 100644
--- a/Processes/TrackingLine/testTrackingLineStack.h
+++ b/Processes/TrackingLine/testTrackingLineStack.h
@@ -9,23 +9,31 @@
 #pragma once
 
 #include <corsika/environment/Environment.h>
+
 #include <corsika/geometry/Point.h>
 #include <corsika/geometry/Vector.h>
+
 #include <corsika/particles/ParticleProperties.h>
-#include <corsika/setup/SetupStack.h>
+
+#include <corsika/stack/node/GeometryNodeStackExtension.h>
+#include <corsika/stack/nuclear_extension/NuclearStackExtension.h>
+#include <corsika/stack/CombinedStack.h>
+
 #include <corsika/units/PhysicalUnits.h>
 
 using TestEnvironmentType =
     corsika::environment::Environment<corsika::environment::Empty>;
 
 template <typename T>
-using SetupGeometryDataInterface = GeometryDataInterface<T, TestEnvironmentType>;
+using SetupGeometryDataInterface =
+    corsika::stack::node::GeometryDataInterface<T, TestEnvironmentType>;
 
 // combine particle data stack with geometry information for tracking
 template <typename StackIter>
 using StackWithGeometryInterface = corsika::stack::CombinedParticleInterface<
-    corsika::setup::detail::ParticleDataStack::PIType, SetupGeometryDataInterface,
-    StackIter>;
+    corsika::stack::nuclear_extension::ParticleDataStack::PIType,
+    SetupGeometryDataInterface, StackIter>;
+
 using TestTrackingLineStack = corsika::stack::CombinedStack<
-    typename corsika::setup::detail::ParticleDataStack::StackImpl,
-    GeometryData<TestEnvironmentType>, StackWithGeometryInterface>;
+    typename corsika::stack::nuclear_extension::ParticleDataStack::StackImpl,
+    corsika::stack::node::GeometryData<TestEnvironmentType>, StackWithGeometryInterface>;
diff --git a/Setup/CMakeLists.txt b/Setup/CMakeLists.txt
index 62fed4142..e198d90cd 100644
--- a/Setup/CMakeLists.txt
+++ b/Setup/CMakeLists.txt
@@ -3,6 +3,7 @@ set (
   SetupStack.h
   SetupEnvironment.h
   SetupTrajectory.h
+  GeometryNodeStackExtension.h
   )
 
 set (
@@ -17,8 +18,9 @@ target_link_libraries (
   CORSIKAsetup
   INTERFACE
   CORSIKAgeometry
-  SuperStupidStack
   NuclearStackExtension
+  GeometryNodeStackExtension
+  #  CORSIKAhistory
   )
 
 target_include_directories (
diff --git a/Setup/SetupStack.h b/Setup/SetupStack.h
index 5bf8a2b49..b4c99c339 100644
--- a/Setup/SetupStack.h
+++ b/Setup/SetupStack.h
@@ -8,123 +8,36 @@
 
 #pragma once
 
-// the basic particle data stack:
-#include <corsika/stack/super_stupid/SuperStupidStack.h>
-
-// extension with nuclear data for Code::Nucleus
+#include <corsika/stack/node/GeometryNodeStackExtension.h>
 #include <corsika/stack/nuclear_extension/NuclearStackExtension.h>
+//#include <corsika/history/HistoryStackExtension.h>
 
-// extension with geometry information for tracking
-#include <corsika/environment/Environment.h>
-#include <corsika/setup/SetupEnvironment.h>
 #include <corsika/stack/CombinedStack.h>
 
-#include <tuple>
-#include <utility>
-#include <vector>
-
-// definition of stack-data object to store geometry information
-template <typename TEnvType>
-
-/**
- * @class GeometryData
- *
- * definition of stack-data object to store geometry information
- */
-class GeometryData {
-
-public:
-  using BaseNodeType = typename TEnvType::BaseNodeType;
-
-  // these functions are needed for the Stack interface
-  void Clear() { fNode.clear(); }
-  unsigned int GetSize() const { return fNode.size(); }
-  unsigned int GetCapacity() const { return fNode.size(); }
-  void Copy(const int i1, const int i2) { fNode[i2] = fNode[i1]; }
-  void Swap(const int i1, const int i2) { std::swap(fNode[i1], fNode[i2]); }
-
-  // custom data access function
-  void SetNode(const int i, BaseNodeType const* v) { fNode[i] = v; }
-  auto const* GetNode(const int i) const { return fNode[i]; }
-
-  // these functions are also needed by the Stack interface
-  void IncrementSize() { fNode.push_back(nullptr); }
-  void DecrementSize() {
-    if (fNode.size() > 0) { fNode.pop_back(); }
-  }
-
-  // custom private data section
-private:
-  std::vector<const BaseNodeType*> fNode;
-};
-
-/**
- * @class GeometryDataInterface
- *
- * 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
- */
-template <typename T, typename TEnvType>
-class GeometryDataInterface : public T {
-
-public:
-  using T::GetIndex;
-  using T::GetStackData;
-  using T::SetParticleData;
-  using BaseNodeType = typename TEnvType::BaseNodeType;
-
-  // default version for particle-creation from input data
-  void SetParticleData(const std::tuple<BaseNodeType const*> v) {
-    SetNode(std::get<0>(v));
-  }
-  void SetParticleData(GeometryDataInterface& parent,
-                       const std::tuple<BaseNodeType const*>) {
-    SetNode(parent.GetNode()); // copy Node from parent particle!
-  }
-  void SetParticleData() { SetNode(nullptr); }
-  void SetParticleData(GeometryDataInterface& parent) {
-    SetNode(parent.GetNode()); // copy Node from parent particle!
-  }
-  void SetNode(BaseNodeType const* v) { GetStackData().SetNode(GetIndex(), v); }
-  auto const* GetNode() const { return GetStackData().GetNode(GetIndex()); }
-};
+#include <corsika/setup/SetupEnvironment.h>
 
 namespace corsika::setup {
 
   namespace detail {
 
-    //
-    // this is an auxiliary help typedef, which I don't know how to put
-    // into NuclearStackExtension.h where it belongs...
-    template <typename StackIter>
-    using ExtendedParticleInterfaceType =
-        corsika::stack::nuclear_extension::NuclearParticleInterface<
-            corsika::stack::super_stupid::SuperStupidStack::PIType, StackIter>;
-    //
-
-    // the particle data stack with extra nuclear information:
-    using ParticleDataStack = corsika::stack::nuclear_extension::NuclearStackExtension<
-        corsika::stack::super_stupid::SuperStupidStack, ExtendedParticleInterfaceType>;
-
-    template <typename T>
-    using SetupGeometryDataInterface = GeometryDataInterface<T, setup::SetupEnvironment>;
-
+    // the GeometryNode stack needs to know the type of geometry-nodes from the environment:
+    template <typename TStackIter>
+    using SetupGeometryDataInterface = typename stack::node::MakeGeometryDataInterface<TStackIter, setup::SetupEnvironment>::type;
+    
     // combine particle data stack with geometry information for tracking
-    template <typename StackIter>
-    using StackWithGeometryInterface =
-        corsika::stack::CombinedParticleInterface<ParticleDataStack::PIType,
-                                                  SetupGeometryDataInterface, StackIter>;
+    template <typename TStackIter>
+    using StackWithGeometryInterface = corsika::stack::CombinedParticleInterface<
+        stack::nuclear_extension::ParticleDataStack::PIType,
+    SetupGeometryDataInterface, TStackIter>;
 
-    using StackWithGeometry =
-        corsika::stack::CombinedStack<typename ParticleDataStack::StackImpl,
-                                      GeometryData<setup::SetupEnvironment>,
-                                      StackWithGeometryInterface>;
+    using StackWithGeometry = corsika::stack::CombinedStack<
+        typename corsika::stack::nuclear_extension::ParticleDataStack::StackImpl,
+        corsika::stack::node::GeometryData<setup::SetupEnvironment>,
+        StackWithGeometryInterface>;
 
   } // namespace detail
 
-  // this is the REAL stack we use:
+  // this is the FINAL stack we use in C8:
   using Stack = detail::StackWithGeometry;
 
   /*
@@ -141,7 +54,8 @@ namespace corsika::setup {
 #if defined(__clang__)
   using StackView =
       corsika::stack::SecondaryView<typename corsika::setup::Stack::StackImpl,
-                                    corsika::setup::detail::StackWithGeometryInterface>;
+    // CHECK with CLANG: corsika::setup::Stack::PIType>;
+    corsika::setup::detail::StackWithGeometryInterface>;
 #elif defined(__GNUC__) || defined(__GNUG__)
   using StackView = corsika::stack::MakeView<corsika::setup::Stack>::type;
 #endif
diff --git a/Stack/CMakeLists.txt b/Stack/CMakeLists.txt
index 01130bb11..6171bb71b 100644
--- a/Stack/CMakeLists.txt
+++ b/Stack/CMakeLists.txt
@@ -1,3 +1,5 @@
 add_subdirectory (DummyStack)
 add_subdirectory (SuperStupidStack)
 add_subdirectory (NuclearStackExtension)
+add_subdirectory (GeometryNodeStackExtension)
+#add_subdirectory (History)
diff --git a/Stack/DummyStack/CMakeLists.txt b/Stack/DummyStack/CMakeLists.txt
index 1ac3bf52e..b7e09a9e4 100644
--- a/Stack/DummyStack/CMakeLists.txt
+++ b/Stack/DummyStack/CMakeLists.txt
@@ -26,3 +26,12 @@ install (
   DESTINATION
   include/${DummyStack_NAMESPACE}
   )
+
+# ----------------
+# code unit testing
+ CORSIKA_ADD_TEST(testDummyStack)
+ target_link_libraries (
+   testDummyStack
+   DummyStack
+   CORSIKAtesting
+   )
diff --git a/Stack/DummyStack/DummyStack.h b/Stack/DummyStack/DummyStack.h
index b075916ef..5f584b016 100644
--- a/Stack/DummyStack/DummyStack.h
+++ b/Stack/DummyStack/DummyStack.h
@@ -12,54 +12,66 @@
 #include <corsika/stack/Stack.h>
 #include <corsika/units/PhysicalUnits.h>
 
-#include <string>
-#include <vector>
+#include <tuple>
 
 namespace corsika::stack {
 
   namespace dummy {
 
     /**
-     * Example of a particle object on the stack.
+     * Example of a particle object on the stack, with NO DATA.
      */
 
-    template <typename _Stack>
-    class ParticleRead : public StackIteratorInfo<_Stack, ParticleRead<_Stack> > {
+    /**
+       however, conceptually we need to provide fake data. A stack without data does not work...
+     */
+
+    struct NoData {/* nothing */ int nothing=0; };
+    
+    template <typename StackIteratorInterface>
+      class ParticleInterface : public corsika::stack::ParticleBase<StackIteratorInterface> {
+      
+    protected:
+      using corsika::stack::ParticleBase<StackIteratorInterface>::GetStack;
+      using corsika::stack::ParticleBase<StackIteratorInterface>::GetStackData;
 
-      using StackIteratorInfo<_Stack, ParticleRead>::GetIndex;
-      using StackIteratorInfo<_Stack, ParticleRead>::GetStack;
+    public:
+      using corsika::stack::ParticleBase<StackIteratorInterface>::GetIndex;
 
     public:
+      void SetParticleData(const std::tuple<NoData>& /*v*/) {}
+      void SetParticleData(ParticleInterface<StackIteratorInterface>& /*parent*/, const std::tuple<NoData>& /*v*/) {}
     };
 
     /**
      *
-     * Memory implementation of the most simple (stupid) particle stack object.
+     * Memory implementation of the most simple (no-data) particle stack object.
      */
 
     class DummyStackImpl {
 
     public:
-      void Init() {}
+      void Init() {entries_=0;}
 
-      void Clear() {}
+      void Clear() {entries_=0;}
 
-      int GetSize() const { return 0; }
-      int GetCapacity() const { return 0; }
+      int GetSize() const { return entries_; }
+      int GetCapacity() const { return entries_; }
 
       /**
        *   Function to copy particle at location i2 in stack to i1
        */
-      void Copy(const int i1, const int i2) {}
+      void Copy(const int /*i1*/, const int /*i2*/) {}
 
-    protected:
-      void IncrementSize() {}
-      void DecrementSize() {}
+      void IncrementSize() {entries_++;}
+      void DecrementSize() {entries_--;}
 
+    private:
+      int entries_ = 0;
+      
     }; // end class DummyStackImpl
 
-    typedef StackIterator<DummyStackImpl, ParticleRead<DummyStackImpl> > Particle;
-    typedef Stack<DummyStackImpl, Particle> DummyStack;
+    typedef Stack<DummyStackImpl, ParticleInterface> DummyStack;
 
   } // namespace dummy
 
diff --git a/Stack/DummyStack/testDummyStack.cc b/Stack/DummyStack/testDummyStack.cc
new file mode 100644
index 000000000..64195ef65
--- /dev/null
+++ b/Stack/DummyStack/testDummyStack.cc
@@ -0,0 +1,44 @@
+/*
+ * (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu
+ *
+ * This software is distributed under the terms of the GNU General Public
+ * Licence version 3 (GPL Version 3). See file LICENSE for a full version of
+ * the license.
+ */
+
+#include <corsika/stack/dummy/DummyStack.h>
+
+using namespace corsika;
+using namespace corsika::stack;
+
+#include <catch2/catch.hpp>
+
+#include <tuple>
+
+TEST_CASE("DummyStack", "[stack]") {
+
+  using TestStack = dummy::DummyStack;
+
+  dummy::NoData noData;
+    
+  SECTION("write node") {
+
+    TestStack s;
+    s.AddParticle(std::tuple<dummy::NoData>{noData});
+    REQUIRE(s.GetSize() == 1);
+  }
+
+
+  SECTION("stack fill and cleanup") {
+
+    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});
+    }
+      
+    REQUIRE(s.GetSize() == 99);
+    for (int i = 0; i < 99; ++i) s.GetNextParticle().Delete();
+    REQUIRE(s.GetSize() == 0);
+  }  
+}
diff --git a/Stack/GeometryNodeStackExtension/CMakeLists.txt b/Stack/GeometryNodeStackExtension/CMakeLists.txt
new file mode 100644
index 000000000..8d7a3c7d0
--- /dev/null
+++ b/Stack/GeometryNodeStackExtension/CMakeLists.txt
@@ -0,0 +1,38 @@
+set (GeometryNodeStackExtension_HEADERS GeometryNodeStackExtension.h)
+set (GeometryNodeStackExtension_NAMESPACE corsika/stack/node)
+
+add_library (GeometryNodeStackExtension INTERFACE)
+
+CORSIKA_COPY_HEADERS_TO_NAMESPACE (GeometryNodeStackExtension ${GeometryNodeStackExtension_NAMESPACE} ${GeometryNodeStackExtension_HEADERS})
+
+target_link_libraries (
+  GeometryNodeStackExtension
+  INTERFACE
+  CORSIKAstackinterface
+  CORSIKAunits
+  CORSIKAparticles
+  CORSIKAgeometry
+  )
+
+target_include_directories (
+  GeometryNodeStackExtension
+  INTERFACE
+  $<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include>
+  $<INSTALL_INTERFACE:include>
+  )
+
+install (
+  FILES
+  ${GeometryNodeStackExtension_HEADERS}
+  DESTINATION
+  include/${GeometryNodeStackExtension_NAMESPACE}
+  )
+
+# ----------------
+# code unit testing
+ CORSIKA_ADD_TEST(testGeometryNodeStackExtension)
+ target_link_libraries (
+   testGeometryNodeStackExtension
+   GeometryNodeStackExtension
+   CORSIKAtesting
+   )
diff --git a/Stack/GeometryNodeStackExtension/GeometryNodeStackExtension.h b/Stack/GeometryNodeStackExtension/GeometryNodeStackExtension.h
index d33997b8e..492bd3a74 100644
--- a/Stack/GeometryNodeStackExtension/GeometryNodeStackExtension.h
+++ b/Stack/GeometryNodeStackExtension/GeometryNodeStackExtension.h
@@ -36,7 +36,6 @@ namespace corsika::stack::node {
     using T::GetIndex;
     using BaseNodeType = typename TEnvType::BaseNodeType;
 
-  public:
     // default version for particle-creation from input data
     void SetParticleData(const std::tuple<BaseNodeType const*> v) {
       SetNode(std::get<0>(v));
@@ -91,9 +90,10 @@ namespace corsika::stack::node {
     std::vector<const BaseNodeType*> fNode;
   };
 
+
   template <typename T, typename TEnv>
-  struct MakeGeometryDataInterface {
-    typedef GeometryDataInterface<T, TEnv> type;
-  };
+    struct MakeGeometryDataInterface {
+      typedef GeometryDataInterface<T, TEnv> type;
+    };
 
 } // namespace corsika::stack::node
diff --git a/Stack/GeometryNodeStackExtension/testGeometryNodeStackExtension.cc b/Stack/GeometryNodeStackExtension/testGeometryNodeStackExtension.cc
new file mode 100644
index 000000000..9b7a3b60b
--- /dev/null
+++ b/Stack/GeometryNodeStackExtension/testGeometryNodeStackExtension.cc
@@ -0,0 +1,97 @@
+/*
+ * (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu
+ *
+ * This software is distributed under the terms of the GNU General Public
+ * Licence version 3 (GPL Version 3). See file LICENSE for a full version of
+ * the license.
+ */
+
+#include <corsika/stack/node/GeometryNodeStackExtension.h>
+#include <corsika/stack/dummy/DummyStack.h>
+#include <corsika/stack/CombinedStack.h>
+
+using namespace corsika;
+using namespace corsika::stack;
+
+#include <catch2/catch.hpp>
+
+#include <iostream>
+using namespace std;
+
+// this is our dummy environment, it only knows its trivial BaseNodeType
+class DummyEnv {
+public:
+  typedef int BaseNodeType;
+};
+
+// 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;
+
+
+// combine dummy stack with geometry information for tracking
+template <typename TStackIter>
+using StackWithGeometryInterface = corsika::stack::CombinedParticleInterface<
+  dummy::DummyStack::PIType,
+    DummyGeometryDataInterface, TStackIter>;
+
+using TestStack = corsika::stack::CombinedStack<
+  typename stack::dummy::DummyStack::StackImpl,
+  stack::node::GeometryData<DummyEnv>,
+  StackWithGeometryInterface>;
+
+
+TEST_CASE("GeometryNodeStackExtension", "[stack]") {
+
+  dummy::NoData noData;
+
+  SECTION("write node") {
+
+    const int data = 5;
+    
+    TestStack s;
+    s.AddParticle(
+		  std::tuple<dummy::NoData>{
+		    noData}, std::tuple<const int*>{&data});
+    
+    CHECK(s.GetSize() == 1);
+  }
+
+  SECTION("write/read node") {
+    const int data = 15;
+    
+    TestStack s;
+    auto p = s.AddParticle(
+			   std::tuple<dummy::NoData>{
+			     noData});
+    p.SetNode(&data);
+    CHECK(s.GetSize() == 1);
+    
+    const auto pout = s.GetNextParticle();
+    CHECK(*(pout.GetNode()) == 15);
+  }
+
+  SECTION("stack fill and cleanup") {
+
+    const int data = 16;
+
+    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);
+    }
+      
+    CHECK(s.GetSize() == 99);
+    double v = 0;
+    for (int i = 0; i < 99; ++i) {
+      auto p = s.GetNextParticle();
+      v += *(p.GetNode());
+      p.Delete();
+    }
+    CHECK(v == 99*data);    
+    CHECK(s.GetSize() == 0);    
+  }  
+}
diff --git a/Stack/History/CMakeLists.txt b/Stack/History/CMakeLists.txt
new file mode 100644
index 000000000..2312bf222
--- /dev/null
+++ b/Stack/History/CMakeLists.txt
@@ -0,0 +1,43 @@
+set (
+  SETUP_HEADERS
+  HistoryStackExtension.h
+  )
+
+set (
+  SETUP_NAMESPACE
+  corsika/history
+  )
+
+add_library (CORSIKAhistory INTERFACE)
+CORSIKA_COPY_HEADERS_TO_NAMESPACE (CORSIKAhistory ${SETUP_NAMESPACE} ${SETUP_HEADERS})
+
+target_link_libraries (
+  CORSIKAhistory
+  INTERFACE
+  SuperStupidStack
+  NuclearStackExtension
+  )
+
+target_include_directories (
+  CORSIKAhistory
+  INTERFACE 
+  $<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include>
+  $<INSTALL_INTERFACE:include/include>
+  )
+
+install (
+  FILES ${SETUP_HEADERS} 
+  DESTINATION include/${SETUP_NAMESPACE}
+  )
+
+# ----------------
+# code unit testing
+CORSIKA_ADD_TEST(testHistory)
+target_link_libraries (
+  testHistory
+  SuperStupidStack
+  CORSIKAhistory
+  CORSIKAparticles
+  CORSIKAunits
+  CORSIKAtesting
+  )
diff --git a/Stack/History/HistoryStackExtension.h b/Stack/History/HistoryStackExtension.h
new file mode 100644
index 000000000..00151f901
--- /dev/null
+++ b/Stack/History/HistoryStackExtension.h
@@ -0,0 +1,125 @@
+/*
+ * (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu
+ *
+ * This software is distributed under the terms of the GNU General Public
+ * Licence version 3 (GPL Version 3). See file LICENSE for a full version of
+ * the license.
+ */
+
+#pragma once
+
+// the basic particle data stack:
+#include <corsika/stack/super_stupid/SuperStupidStack.h>
+
+// extension with nuclear data for Code::Nucleus
+#include <corsika/stack/nuclear_extension/NuclearStackExtension.h>
+
+// extension with nuclear data AND volume node ref
+#include <corsika/setup/GeometryNodeStackExtension.h>
+
+#include <memory>
+#include <tuple>
+#include <utility>
+
+class Event {};
+
+namespace corsika::history {
+
+  /**
+   * @class HistoryData
+   *
+   * definition of stack-data object to store history information
+   * this is vector with shared_ptr<Event>
+   */
+  class HistoryData {
+
+  public:
+    // these functions are needed for the Stack interface
+    void Clear() { fEvent.clear(); }
+    unsigned int GetSize() const { return fEvent.size(); }
+    unsigned int GetCapacity() const { return fEvent.size(); }
+    void Copy(const int i1, const int i2) { fEvent[i2] = fEvent[i1]; }
+    void Swap(const int i1, const int i2) { std::swap(fEvent[i1], fEvent[i2]); }
+
+    // custom data access function
+    void SetEvent(const int i, std::shared_ptr<Event> v) { fEvent[i] = v; }
+    std::shared_ptr<Event> GetEvent(const int i) const { return fEvent[i]; }
+
+    // these functions are also needed by the Stack interface
+    void IncrementSize() { fEvent.push_back(nullptr); }
+    void DecrementSize() {
+      if (fEvent.size() > 0) { fEvent.pop_back(); }
+    }
+
+    // custom private data section
+  private:
+    std::vector<std::shared_ptr<Event>> fEvent;
+  };
+
+  /**
+   * @class HistoryDataInterface
+   *
+   * 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
+   */
+  template <typename T>
+  class HistoryDataInterface : public T {
+
+  public:
+    using T::GetIndex;
+    using T::GetStackData;
+    using T::SetParticleData;
+
+    // default version for particle-creation from input data
+    void SetParticleData(const std::tuple<Event const*> v) { SetEvent(std::get<0>(v)); }
+    void SetParticleData(HistoryDataInterface& parent,
+                         const std::tuple<std::shared_ptr<Event>>) {
+      SetEvent(parent.GetEvent()); // copy Event from parent particle!
+    }
+    void SetParticleData() { SetEvent(nullptr); }
+    void SetParticleData(HistoryDataInterface& parent) {
+      SetEvent(parent.GetEvent()); // copy Event from parent particle!
+    }
+    void SetEvent(std::shared_ptr<Event> v) { GetStackData().SetEvent(GetIndex(), v); }
+    std::shared_ptr<Event> GetEvent() const {
+      return GetStackData().GetEvent(GetIndex());
+    }
+  };
+
+  namespace detail {
+
+    //
+    // this is an auxiliary help typedef, which I don't know how to put
+    // into NuclearStackExtension.h where it belongs...
+    template <typename StackIter>
+    using ExtendedParticleInterfaceType =
+        corsika::stack::nuclear_extension::NuclearParticleInterface<
+            corsika::stack::super_stupid::SuperStupidStack::PIType, StackIter>;
+    //
+
+    // the particle data stack with extra nuclear information:
+    using ParticleDataStack = corsika::stack::nuclear_extension::NuclearStackExtension<
+        corsika::stack::super_stupid::SuperStupidStack, ExtendedParticleInterfaceType>;
+
+    template <typename T>
+    using SetupHistoryDataInterface = HistoryDataInterface<T>;
+
+    // combine particle data stack with history information for tracking
+    template <typename StackIter>
+    using StackWithHistoryInterface =
+        corsika::stack::CombinedParticleInterface<ParticleDataStack::PIType,
+                                                  SetupHistoryDataInterface, StackIter>;
+
+    using StackWithHistory =
+        corsika::stack::CombinedStack<typename ParticleDataStack::StackImpl, HistoryData,
+                                      StackWithHistoryInterface>;
+
+  } // namespace detail
+
+  template <typename InnerStack, template <typename> typename _PI>
+  using NuclearStackExtension =
+      Stack<NuclearStackExtensionImpl<typename InnerStack::StackImpl>, _PI>;
+
+} // namespace corsika::history
diff --git a/Stack/History/testHistory.cc b/Stack/History/testHistory.cc
new file mode 100644
index 000000000..6aed02e04
--- /dev/null
+++ b/Stack/History/testHistory.cc
@@ -0,0 +1,241 @@
+/*
+ * (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu
+ *
+ * This software is distributed under the terms of the GNU General Public
+ * Licence version 3 (GPL Version 3). See file LICENSE for a full version of
+ * the license.
+ */
+
+#include <corsika/geometry/RootCoordinateSystem.h>
+#include <corsika/history/HistoryStackExtension.h>
+#include <corsika/stack/super_stupid/SuperStupidStack.h>
+
+using namespace corsika;
+using namespace corsika::history;
+using namespace corsika::stack::nuclear_extension;
+using namespace corsika::geometry;
+using namespace corsika::units::si;
+
+#include <catch2/catch.hpp>
+
+// this is an auxiliary help typedef, which I don't know how to put
+// into NuclearStackExtension.h where it belongs...
+template <typename StackIter>
+using ExtendedParticleInterfaceType =
+    corsika::stack::nuclear_extension::NuclearParticleInterface<
+        corsika::stack::super_stupid::SuperStupidStack::template PIType, StackIter>;
+
+using ExtStack = NuclearStackExtension<corsika::stack::super_stupid::SuperStupidStack,
+                                       ExtendedParticleInterfaceType>;
+
+#include <iostream>
+using namespace std;
+
+TEST_CASE("HistoryStackExtension", "[stack]") {
+
+  geometry::CoordinateSystem& dummyCS =
+      geometry::RootCoordinateSystem::GetInstance().GetRootCoordinateSystem();
+
+  SECTION("write non nucleus") {
+    HistoryStackExtension<corsika::stack::super_stupid::SuperStupidStack,
+                          ExtendedParticleInterfaceType>
+        s;
+    s.AddParticle(
+        std::tuple<particles::Code, units::si::HEPEnergyType,
+                   corsika::stack::MomentumVector, geometry::Point, units::si::TimeType>{
+            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});
+    REQUIRE(s.GetSize() == 1);
+  }
+
+  SECTION("write nucleus") {
+    HistoryStackExtension<corsika::stack::super_stupid::SuperStupidStack,
+                          ExtendedParticleInterfaceType>
+        s;
+    s.AddParticle(std::tuple<particles::Code, units::si::HEPEnergyType,
+                             corsika::stack::MomentumVector, geometry::Point,
+                             units::si::TimeType, unsigned short, unsigned short>{
+        particles::Code::Nucleus, 1.5_GeV,
+        corsika::stack::MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}),
+        Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s, 10, 10});
+    REQUIRE(s.GetSize() == 1);
+  }
+
+  SECTION("write invalid nucleus") {
+    ExtStack s;
+    REQUIRE_THROWS(
+        s.AddParticle(std::tuple<particles::Code, units::si::HEPEnergyType,
+                                 corsika::stack::MomentumVector, geometry::Point,
+                                 units::si::TimeType, unsigned short, unsigned short>{
+            particles::Code::Nucleus, 1.5_GeV,
+            corsika::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") {
+    ExtStack s;
+    s.AddParticle(
+        std::tuple<particles::Code, units::si::HEPEnergyType,
+                   corsika::stack::MomentumVector, geometry::Point, units::si::TimeType>{
+            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});
+    const auto pout = s.GetNextParticle();
+    REQUIRE(pout.GetPID() == particles::Code::Electron);
+    REQUIRE(pout.GetEnergy() == 1.5_GeV);
+    REQUIRE(pout.GetTime() == 100_s);
+  }
+
+  SECTION("read nucleus") {
+    ExtStack s;
+    s.AddParticle(std::tuple<particles::Code, units::si::HEPEnergyType,
+                             corsika::stack::MomentumVector, geometry::Point,
+                             units::si::TimeType, unsigned short, unsigned short>{
+        particles::Code::Nucleus, 1.5_GeV,
+        corsika::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();
+    REQUIRE(pout.GetPID() == particles::Code::Nucleus);
+    REQUIRE(pout.GetEnergy() == 1.5_GeV);
+    REQUIRE(pout.GetTime() == 100_s);
+    REQUIRE(pout.GetHistoryA() == 10);
+    REQUIRE(pout.GetNuclearZ() == 9);
+  }
+
+  SECTION("read invalid nucleus") {
+    ExtStack s;
+    s.AddParticle(
+        std::tuple<particles::Code, units::si::HEPEnergyType,
+                   corsika::stack::MomentumVector, geometry::Point, units::si::TimeType>{
+            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});
+    const auto pout = s.GetNextParticle();
+    REQUIRE_THROWS(pout.GetNuclearA());
+    REQUIRE_THROWS(pout.GetNuclearZ());
+  }
+
+  SECTION("stack fill and cleanup") {
+
+    ExtStack 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::tuple<particles::Code, units::si::HEPEnergyType,
+                                 corsika::stack::MomentumVector, geometry::Point,
+                                 units::si::TimeType, unsigned short, unsigned short>{
+            particles::Code::Nucleus, 1.5_GeV,
+            corsika::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::tuple<particles::Code, units::si::HEPEnergyType,
+                                 corsika::stack::MomentumVector, geometry::Point,
+                                 units::si::TimeType>{
+            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});
+      }
+    }
+
+    REQUIRE(s.GetSize() == 99);
+    for (int i = 0; i < 99; ++i) s.GetNextParticle().Delete();
+    REQUIRE(s.GetSize() == 0);
+  }
+
+  SECTION("stack operations") {
+
+    ExtStack 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::tuple<particles::Code, units::si::HEPEnergyType,
+                                 corsika::stack::MomentumVector, geometry::Point,
+                                 units::si::TimeType, unsigned short, unsigned short>{
+            particles::Code::Nucleus, i * 15_GeV,
+            corsika::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::tuple<particles::Code, units::si::HEPEnergyType,
+                                 corsika::stack::MomentumVector, geometry::Point,
+                                 units::si::TimeType>{
+            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});
+      }
+    }
+
+    // copy
+    {
+      s.Copy(s.begin() + 9, s.begin() + 10); // nuclei to non-nuclei
+      const auto& p9 = s.cbegin() + 9;
+      const auto& p10 = s.cbegin() + 10;
+
+      REQUIRE(p9.GetPID() == particles::Code::Nucleus);
+      REQUIRE(p9.GetEnergy() == 9 * 15_GeV);
+      REQUIRE(p9.GetTime() == 100_s);
+      REQUIRE(p9.GetNuclearA() == 9);
+      REQUIRE(p9.GetNuclearZ() == 9 / 2);
+
+      REQUIRE(p10.GetPID() == particles::Code::Nucleus);
+      REQUIRE(p10.GetEnergy() == 9 * 15_GeV);
+      REQUIRE(p10.GetTime() == 100_s);
+      REQUIRE(p10.GetNuclearA() == 9);
+      REQUIRE(p10.GetNuclearZ() == 9 / 2);
+    }
+
+    // copy
+    {
+      s.Copy(s.begin() + 93, s.begin() + 9); // non-nuclei to nuclei
+      const auto& p93 = s.cbegin() + 93;
+      const auto& p9 = s.cbegin() + 9;
+
+      REQUIRE(p9.GetPID() == particles::Code::Electron);
+      REQUIRE(p9.GetEnergy() == 93 * 1.5_GeV);
+      REQUIRE(p9.GetTime() == 100_s);
+
+      REQUIRE(p93.GetPID() == particles::Code::Electron);
+      REQUIRE(p93.GetEnergy() == 93 * 1.5_GeV);
+      REQUIRE(p93.GetTime() == 100_s);
+    }
+
+    // swap
+    {
+      s.Swap(s.begin() + 11, s.begin() + 10);
+      const auto& p11 = s.cbegin() + 11; // now: nucleus
+      const auto& p10 = s.cbegin() + 10; // now: electron
+
+      REQUIRE(p11.GetPID() == particles::Code::Nucleus);
+      REQUIRE(p11.GetEnergy() == 9 * 15_GeV);
+      REQUIRE(p11.GetTime() == 100_s);
+      REQUIRE(p11.GetNuclearA() == 9);
+      REQUIRE(p11.GetNuclearZ() == 9 / 2);
+
+      REQUIRE(p10.GetPID() == particles::Code::Electron);
+      REQUIRE(p10.GetEnergy() == 11 * 1.5_GeV);
+      REQUIRE(p10.GetTime() == 100_s);
+    }
+
+    // swap two nuclei
+    {
+      s.Swap(s.begin() + 29, s.begin() + 59);
+      const auto& p29 = s.cbegin() + 29;
+      const auto& p59 = s.cbegin() + 59;
+
+      REQUIRE(p29.GetPID() == particles::Code::Nucleus);
+      REQUIRE(p29.GetEnergy() == 59 * 15_GeV);
+      REQUIRE(p29.GetTime() == 100_s);
+      REQUIRE(p29.GetNuclearA() == 59);
+      REQUIRE(p29.GetNuclearZ() == 59 / 2);
+
+      REQUIRE(p59.GetPID() == particles::Code::Nucleus);
+      REQUIRE(p59.GetEnergy() == 29 * 15_GeV);
+      REQUIRE(p59.GetTime() == 100_s);
+      REQUIRE(p59.GetNuclearA() == 29);
+      REQUIRE(p59.GetNuclearZ() == 29 / 2);
+    }
+
+    for (int i = 0; i < 99; ++i) s.DeleteLast();
+    REQUIRE(s.GetSize() == 0);
+  }
+}
diff --git a/Stack/NuclearStackExtension/CMakeLists.txt b/Stack/NuclearStackExtension/CMakeLists.txt
index c33487b15..3e3c5e735 100644
--- a/Stack/NuclearStackExtension/CMakeLists.txt
+++ b/Stack/NuclearStackExtension/CMakeLists.txt
@@ -12,6 +12,7 @@ target_link_libraries (
   CORSIKAunits
   CORSIKAparticles
   CORSIKAgeometry
+  SuperStupidStack
   )
 
 target_include_directories (
@@ -33,7 +34,6 @@ install (
 CORSIKA_ADD_TEST(testNuclearStackExtension)
 target_link_libraries (
   testNuclearStackExtension
-  SuperStupidStack
   NuclearStackExtension
   CORSIKAparticles
   CORSIKAgeometry
diff --git a/Stack/NuclearStackExtension/NuclearStackExtension.h b/Stack/NuclearStackExtension/NuclearStackExtension.h
index e1827f725..0c0dbeff8 100644
--- a/Stack/NuclearStackExtension/NuclearStackExtension.h
+++ b/Stack/NuclearStackExtension/NuclearStackExtension.h
@@ -9,7 +9,10 @@
 #pragma once
 
 #include <corsika/particles/ParticleProperties.h>
+
 #include <corsika/stack/Stack.h>
+#include <corsika/stack/super_stupid/SuperStupidStack.h>
+
 #include <corsika/units/PhysicalUnits.h>
 
 #include <corsika/geometry/Point.h>
@@ -24,7 +27,10 @@ namespace corsika::stack {
   /**
    * @namespace nuclear_extension
    *
-   * Add A and Z data to existing stack of particle properties.
+   * 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.
@@ -324,48 +330,19 @@ namespace corsika::stack {
 
     }; // end class NuclearStackExtensionImpl
 
-    //    template<typename StackIteratorInterface>
-    // using NuclearParticleInterfaceType<StackIteratorInterface> =
-    // NuclearParticleInterface< ,StackIteratorInterface>
-
-    // works, but requires stupd _PI class
-    // template<typename SS> using TEST =
-    // NuclearParticleInterface<corsika::stack::super_stupid::SuperStupidStack::PIType,
-    // SS>;
     template <typename InnerStack, template <typename> typename _PI>
     using NuclearStackExtension =
         Stack<NuclearStackExtensionImpl<typename InnerStack::StackImpl>, _PI>;
 
-    // ----
-
-    // I'm dont't manage to do this properly.......
-    /*
-    template<typename TT, typename SS> using TESTi = typename
-    NuclearParticleInterface<TT::template PIType, SS>::ExtendedParticleInterface;
-    template<typename TT, typename SS> using TEST1 = TESTi<TT, SS>;
-    template<typename SS> using TEST2 = TEST1<typename
-    corsika::stack::super_stupid::SuperStupidStack, SS>;
-
-    using NuclearStackExtension = Stack<NuclearStackExtensionImpl<typename
-    InnerStack::StackImpl>, TEST2>;
-    */
-    /*
-      // .... this should be fixed ....
-
-    template <typename InnerStack, typename SS=StackIteratorInterface>
-      //using NuclearStackExtension = Stack<NuclearStackExtensionImpl<typename
-    InnerStack::StackImpl>, NuclearParticleInterface<typename InnerStack::template PIType,
-    StackIteratorInterface>::ExtendedParticleInterface>; using NuclearStackExtension =
-    Stack<NuclearStackExtensionImpl<typename InnerStack::StackImpl>, TEST1<typename
-    corsika::stack::super_stupid::SuperStupidStack, SS> >;
-
-    //template <typename InnerStack>
-      //  using NuclearStackExtension = Stack<NuclearStackExtensionImpl<typename
-    InnerStack::StackImpl>, TEST<typename
-    corsika::stack::super_stupid::SuperStupidStack::PIType>>;
-    //using NuclearStackExtension = Stack<NuclearStackExtensionImpl<typename
-    InnerStack::StackImpl>, TEST>;
-    */
+    //
+    template <typename StackIter>
+    using ExtendedParticleInterfaceType =
+        corsika::stack::nuclear_extension::NuclearParticleInterface<
+            corsika::stack::super_stupid::SuperStupidStack::PIType, StackIter>;
+
+    // the particle data stack with extra nuclear information:
+    using ParticleDataStack = corsika::stack::nuclear_extension::NuclearStackExtension<
+        corsika::stack::super_stupid::SuperStupidStack, ExtendedParticleInterfaceType>;
 
   } // namespace nuclear_extension
 } // namespace corsika::stack
diff --git a/Stack/NuclearStackExtension/testNuclearStackExtension.cc b/Stack/NuclearStackExtension/testNuclearStackExtension.cc
index a6ae932e7..fe30f2ce4 100644
--- a/Stack/NuclearStackExtension/testNuclearStackExtension.cc
+++ b/Stack/NuclearStackExtension/testNuclearStackExtension.cc
@@ -8,7 +8,6 @@
 
 #include <corsika/geometry/RootCoordinateSystem.h>
 #include <corsika/stack/nuclear_extension/NuclearStackExtension.h>
-#include <corsika/stack/super_stupid/SuperStupidStack.h>
 #include <corsika/units/PhysicalUnits.h>
 
 using namespace corsika;
@@ -18,16 +17,6 @@ using namespace corsika::units::si;
 
 #include <catch2/catch.hpp>
 
-// this is an auxiliary help typedef, which I don't know how to put
-// into NuclearStackExtension.h where it belongs...
-template <typename StackIter>
-using ExtendedParticleInterfaceType =
-    corsika::stack::nuclear_extension::NuclearParticleInterface<
-        corsika::stack::super_stupid::SuperStupidStack::template PIType, StackIter>;
-
-using ExtStack = NuclearStackExtension<corsika::stack::super_stupid::SuperStupidStack,
-                                       ExtendedParticleInterfaceType>;
-
 #include <iostream>
 using namespace std;
 
@@ -63,7 +52,7 @@ TEST_CASE("NuclearStackExtension", "[stack]") {
   }
 
   SECTION("write invalid nucleus") {
-    ExtStack s;
+    ParticleDataStack s;
     REQUIRE_THROWS(
         s.AddParticle(std::tuple<particles::Code, units::si::HEPEnergyType,
                                  corsika::stack::MomentumVector, geometry::Point,
@@ -74,7 +63,7 @@ TEST_CASE("NuclearStackExtension", "[stack]") {
   }
 
   SECTION("read non nucleus") {
-    ExtStack s;
+    ParticleDataStack s;
     s.AddParticle(
         std::tuple<particles::Code, units::si::HEPEnergyType,
                    corsika::stack::MomentumVector, geometry::Point, units::si::TimeType>{
@@ -88,7 +77,7 @@ TEST_CASE("NuclearStackExtension", "[stack]") {
   }
 
   SECTION("read nucleus") {
-    ExtStack s;
+    ParticleDataStack s;
     s.AddParticle(std::tuple<particles::Code, units::si::HEPEnergyType,
                              corsika::stack::MomentumVector, geometry::Point,
                              units::si::TimeType, unsigned short, unsigned short>{
@@ -104,7 +93,7 @@ TEST_CASE("NuclearStackExtension", "[stack]") {
   }
 
   SECTION("read invalid nucleus") {
-    ExtStack s;
+    ParticleDataStack s;
     s.AddParticle(
         std::tuple<particles::Code, units::si::HEPEnergyType,
                    corsika::stack::MomentumVector, geometry::Point, units::si::TimeType>{
@@ -118,7 +107,7 @@ TEST_CASE("NuclearStackExtension", "[stack]") {
 
   SECTION("stack fill and cleanup") {
 
-    ExtStack s;
+    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) {
@@ -145,7 +134,7 @@ TEST_CASE("NuclearStackExtension", "[stack]") {
 
   SECTION("stack operations") {
 
-    ExtStack s;
+    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) {
diff --git a/Stack/SuperStupidStack/SuperStupidStack.h b/Stack/SuperStupidStack/SuperStupidStack.h
index 22cb88a6c..c3b755bbb 100644
--- a/Stack/SuperStupidStack/SuperStupidStack.h
+++ b/Stack/SuperStupidStack/SuperStupidStack.h
@@ -16,8 +16,8 @@
 #include <corsika/geometry/RootCoordinateSystem.h> // remove
 #include <corsika/geometry/Vector.h>
 
-#include <algorithm>
 #include <vector>
+#include <tuple>
 
 namespace corsika::stack {
 
@@ -50,13 +50,6 @@ namespace corsika::stack {
         SetPosition(std::get<3>(v));
         SetTime(std::get<4>(v));
       }
-      /*
-    void SetParticleData(const corsika::particles::Code vDataPID,
-                         const corsika::units::si::HEPEnergyType vDataE,
-                         const MomentumVector& vMomentum,
-                         const corsika::geometry::Point& vPosition,
-                         const corsika::units::si::TimeType vTime) {
-      }*/
 
       void SetParticleData(
           ParticleInterface<StackIteratorInterface>&,
@@ -69,18 +62,6 @@ namespace corsika::stack {
         SetPosition(std::get<3>(v));
         SetTime(std::get<4>(v));
       }
-      /*      void SetParticleData(ParticleInterface<StackIteratorInterface>&,
-                           const corsika::particles::Code vDataPID,
-                           const corsika::units::si::HEPEnergyType vDataE,
-                           const MomentumVector& vMomentum,
-                           const corsika::geometry::Point& vPosition,
-                           const corsika::units::si::TimeType vTime) {
-        SetPID(vDataPID);
-        SetEnergy(vDataE);
-        SetMomentum(vMomentum);
-        SetPosition(vPosition);
-        SetTime(vTime);
-      }*/
 
       /// individual setters
       void SetPID(const corsika::particles::Code id) {
@@ -243,7 +224,7 @@ namespace corsika::stack {
     }; // end class SuperStupidStackImpl
 
     typedef Stack<SuperStupidStackImpl, ParticleInterface> SuperStupidStack;
-
+     
   } // namespace super_stupid
 
 } // namespace corsika::stack
-- 
GitLab