diff --git a/corsika/detail/framework/core/Cascade.inl b/corsika/detail/framework/core/Cascade.inl
index eb09a2c763ccf49015ce2d5e22539a1342ee5b8c..22bb73f4daef94f7079e915ee72a292d9ea5a590 100644
--- a/corsika/detail/framework/core/Cascade.inl
+++ b/corsika/detail/framework/core/Cascade.inl
@@ -26,9 +26,8 @@
 
 namespace corsika {
 
-  template <typename TTracking, typename TProcessList, typename TOutput, typename TStack,
-            typename TStackView>
-  inline void Cascade<TTracking, TProcessList, TOutput, TStack, TStackView>::run() {
+  template <typename TTracking, typename TProcessList, typename TOutput, typename TStack>
+  inline void Cascade<TTracking, TProcessList, TOutput, TStack>::run() {
     setNodes(); // put each particle on stack in correct environment volume
 
     while (!stack_.isEmpty()) {
@@ -53,23 +52,20 @@ namespace corsika {
     }
   }
 
-  template <typename TTracking, typename TProcessList, typename TOutput, typename TStack,
-            typename TStackView>
-  inline void
-  Cascade<TTracking, TProcessList, TOutput, TStack, TStackView>::forceInteraction() {
+  template <typename TTracking, typename TProcessList, typename TOutput, typename TStack>
+  inline void Cascade<TTracking, TProcessList, TOutput, TStack>::forceInteraction() {
     CORSIKA_LOG_TRACE("forced interaction!");
     setNodes();
     auto vParticle = stack_.getNextParticle();
-    TStackView secondaries(vParticle);
+    stack_view_type secondaries(vParticle);
     interaction(secondaries, sequence_.getInverseInteractionLength(vParticle));
     sequence_.doSecondaries(secondaries);
     vParticle.erase(); // primary particle is done
   }
 
-  template <typename TTracking, typename TProcessList, typename TOutput, typename TStack,
-            typename TStackView>
-  inline void Cascade<TTracking, TProcessList, TOutput, TStack, TStackView>::step(
-      Particle& vParticle) {
+  template <typename TTracking, typename TProcessList, typename TOutput, typename TStack>
+  inline void Cascade<TTracking, TProcessList, TOutput, TStack>::step(
+      particle_type& vParticle) {
 
     // determine combined total interaction length (inverse)
     InverseGrammageType const total_inv_lambda =
@@ -229,7 +225,7 @@ namespace corsika {
     // secondaries, b) the projectile particle deleted (or
     // changed)
 
-    TStackView secondaries(vParticle);
+    stack_view_type secondaries(vParticle);
 
     /*
       Create SecondaryView object on Stack. The data container
@@ -259,11 +255,9 @@ namespace corsika {
     vParticle.erase();
   }
 
-  template <typename TTracking, typename TProcessList, typename TOutput, typename TStack,
-            typename TStackView>
-  inline ProcessReturn
-  Cascade<TTracking, TProcessList, TOutput, TStack, TStackView>::decay(
-      TStackView& view, InverseTimeType initial_inv_decay_time) {
+  template <typename TTracking, typename TProcessList, typename TOutput, typename TStack>
+  inline ProcessReturn Cascade<TTracking, TProcessList, TOutput, TStack>::decay(
+      stack_view_type& view, InverseTimeType initial_inv_decay_time) {
     CORSIKA_LOG_DEBUG("decay");
 
 #ifdef DEBUG
@@ -291,11 +285,9 @@ namespace corsika {
     return returnCode;
   }
 
-  template <typename TTracking, typename TProcessList, typename TOutput, typename TStack,
-            typename TStackView>
-  inline ProcessReturn
-  Cascade<TTracking, TProcessList, TOutput, TStack, TStackView>::interaction(
-      TStackView& view, InverseGrammageType initial_inv_int_length) {
+  template <typename TTracking, typename TProcessList, typename TOutput, typename TStack>
+  inline ProcessReturn Cascade<TTracking, TProcessList, TOutput, TStack>::interaction(
+      stack_view_type& view, InverseGrammageType initial_inv_int_length) {
     CORSIKA_LOG_DEBUG("collide");
 
 #ifdef DEBUG
@@ -324,9 +316,8 @@ namespace corsika {
     return returnCode;
   }
 
-  template <typename TTracking, typename TProcessList, typename TOutput, typename TStack,
-            typename TStackView>
-  inline void Cascade<TTracking, TProcessList, TOutput, TStack, TStackView>::setNodes() {
+  template <typename TTracking, typename TProcessList, typename TOutput, typename TStack>
+  inline void Cascade<TTracking, TProcessList, TOutput, TStack>::setNodes() {
     std::for_each(stack_.begin(), stack_.end(), [&](auto& p) {
       auto const* numericalNode =
           environment_.getUniverse()->getContainingNode(p.getPosition());
@@ -334,11 +325,10 @@ namespace corsika {
     });
   }
 
-  template <typename TTracking, typename TProcessList, typename TOutput, typename TStack,
-            typename TStackView>
-  inline void Cascade<TTracking, TProcessList, TOutput, TStack, TStackView>::setEventType(
-      TStackView& view, [[maybe_unused]] history::EventType eventType) {
-    if constexpr (TStackView::has_event) {
+  template <typename TTracking, typename TProcessList, typename TOutput, typename TStack>
+  inline void Cascade<TTracking, TProcessList, TOutput, TStack>::setEventType(
+      stack_view_type& view, [[maybe_unused]] history::EventType eventType) {
+    if constexpr (stack_view_type::has_event) {
       for (auto&& sec : view) { sec.getEvent()->setEventType(eventType); }
     }
   }
diff --git a/corsika/detail/framework/stack/Stack.inl b/corsika/detail/framework/stack/Stack.inl
index 2929f93fe794f861e6ac6857fe3fc4c93305bc48..314e89e959b59f69e0cd6b481cf31809c11daed2 100644
--- a/corsika/detail/framework/stack/Stack.inl
+++ b/corsika/detail/framework/stack/Stack.inl
@@ -19,17 +19,21 @@
 
 namespace corsika {
 
-  template <typename StackData, template <typename> typename MParticleInterface>
+  template <typename StackData, template <typename> typename MParticleInterface,
+            template <typename T1, template <class> class T2> class MSecondaryProducer>
   template <typename... TArgs>
-  inline void Stack<StackData, MParticleInterface>::clear(TArgs... args) {
+  inline void Stack<StackData, MParticleInterface, MSecondaryProducer>::clear(
+      TArgs... args) {
     data_.clear(args...);
     deleted_ = std::vector<bool>(data_.getSize(), false);
     nDeleted_ = 0;
   }
 
-  template <typename StackData, template <typename> typename MParticleInterface>
-  typename Stack<StackData, MParticleInterface>::stack_iterator_type inline Stack<
-      StackData, MParticleInterface>::begin() {
+  template <typename StackData, template <typename> typename MParticleInterface,
+            template <typename T1, template <class> class T2> class MSecondaryProducer>
+  typename Stack<StackData, MParticleInterface, MSecondaryProducer>::
+      stack_iterator_type inline Stack<StackData, MParticleInterface,
+                                       MSecondaryProducer>::begin() {
     unsigned int i = 0;
     for (; i < getSize(); ++i) {
       if (!deleted_[i]) break;
@@ -37,15 +41,19 @@ namespace corsika {
     return stack_iterator_type(*this, i);
   }
 
-  template <typename StackData, template <typename> typename MParticleInterface>
-  typename Stack<StackData, MParticleInterface>::stack_iterator_type inline Stack<
-      StackData, MParticleInterface>::end() {
+  template <typename StackData, template <typename> typename MParticleInterface,
+            template <typename T1, template <class> class T2> class MSecondaryProducer>
+  typename Stack<StackData, MParticleInterface, MSecondaryProducer>::
+      stack_iterator_type inline Stack<StackData, MParticleInterface,
+                                       MSecondaryProducer>::end() {
     return stack_iterator_type(*this, getSize());
   }
 
-  template <typename StackData, template <typename> typename MParticleInterface>
-  typename Stack<StackData, MParticleInterface>::stack_iterator_type inline Stack<
-      StackData, MParticleInterface>::last() {
+  template <typename StackData, template <typename> typename MParticleInterface,
+            template <typename T1, template <class> class T2> class MSecondaryProducer>
+  typename Stack<StackData, MParticleInterface, MSecondaryProducer>::
+      stack_iterator_type inline Stack<StackData, MParticleInterface,
+                                       MSecondaryProducer>::last() {
     unsigned int i = 0;
     for (; i < getSize(); ++i) {
       if (!deleted_[getSize() - 1 - i]) break;
@@ -53,9 +61,11 @@ namespace corsika {
     return stack_iterator_type(*this, getSize() - 1 - i);
   }
 
-  template <typename StackData, template <typename> typename MParticleInterface>
-  typename Stack<StackData, MParticleInterface>::const_stack_iterator_type inline Stack<
-      StackData, MParticleInterface>::begin() const {
+  template <typename StackData, template <typename> typename MParticleInterface,
+            template <typename T1, template <class> class T2> class MSecondaryProducer>
+  typename Stack<StackData, MParticleInterface, MSecondaryProducer>::
+      const_stack_iterator_type inline Stack<StackData, MParticleInterface,
+                                             MSecondaryProducer>::begin() const {
     unsigned int i = 0;
     for (; i < getSize(); ++i) {
       if (!deleted_[i]) break;
@@ -63,15 +73,19 @@ namespace corsika {
     return const_stack_iterator_type(*this, i);
   }
 
-  template <typename StackData, template <typename> typename MParticleInterface>
-  typename Stack<StackData, MParticleInterface>::const_stack_iterator_type inline Stack<
-      StackData, MParticleInterface>::end() const {
+  template <typename StackData, template <typename> typename MParticleInterface,
+            template <typename T1, template <class> class T2> class MSecondaryProducer>
+  typename Stack<StackData, MParticleInterface, MSecondaryProducer>::
+      const_stack_iterator_type inline Stack<StackData, MParticleInterface,
+                                             MSecondaryProducer>::end() const {
     return const_stack_iterator_type(*this, getSize());
   }
 
-  template <typename StackData, template <typename> typename MParticleInterface>
-  typename Stack<StackData, MParticleInterface>::const_stack_iterator_type
-  Stack<StackData, MParticleInterface>::last() const {
+  template <typename StackData, template <typename> typename MParticleInterface,
+            template <typename T1, template <class> class T2> class MSecondaryProducer>
+  typename Stack<StackData, MParticleInterface,
+                 MSecondaryProducer>::const_stack_iterator_type
+  Stack<StackData, MParticleInterface, MSecondaryProducer>::last() const {
     unsigned int i = 0;
     for (; i < getSize(); ++i) {
       if (!deleted_[getSize() - 1 - i]) break;
@@ -79,9 +93,11 @@ namespace corsika {
     return const_stack_iterator_type(*this, getSize() - 1 - i);
   }
 
-  template <typename StackData, template <typename> typename MParticleInterface>
-  typename Stack<StackData, MParticleInterface>::const_stack_iterator_type inline Stack<
-      StackData, MParticleInterface>::cbegin() const {
+  template <typename StackData, template <typename> typename MParticleInterface,
+            template <typename T1, template <class> class T2> class MSecondaryProducer>
+  typename Stack<StackData, MParticleInterface, MSecondaryProducer>::
+      const_stack_iterator_type inline Stack<StackData, MParticleInterface,
+                                             MSecondaryProducer>::cbegin() const {
     unsigned int i = 0;
     for (; i < getSize(); ++i) {
       if (!deleted_[i]) break;
@@ -89,15 +105,19 @@ namespace corsika {
     return const_stack_iterator_type(*this, i);
   }
 
-  template <typename StackData, template <typename> typename MParticleInterface>
-  typename Stack<StackData, MParticleInterface>::const_stack_iterator_type inline Stack<
-      StackData, MParticleInterface>::cend() const {
+  template <typename StackData, template <typename> typename MParticleInterface,
+            template <typename T1, template <class> class T2> class MSecondaryProducer>
+  typename Stack<StackData, MParticleInterface, MSecondaryProducer>::
+      const_stack_iterator_type inline Stack<StackData, MParticleInterface,
+                                             MSecondaryProducer>::cend() const {
     return const_stack_iterator_type(*this, getSize());
   }
 
-  template <typename StackData, template <typename> typename MParticleInterface>
-  typename Stack<StackData, MParticleInterface>::const_stack_iterator_type inline Stack<
-      StackData, MParticleInterface>::clast() const {
+  template <typename StackData, template <typename> typename MParticleInterface,
+            template <typename T1, template <class> class T2> class MSecondaryProducer>
+  typename Stack<StackData, MParticleInterface, MSecondaryProducer>::
+      const_stack_iterator_type inline Stack<StackData, MParticleInterface,
+                                             MSecondaryProducer>::clast() const {
     unsigned int i = 0;
     for (; i < getSize(); ++i) {
       if (!deleted_[getSize() - 1 - i]) break;
@@ -106,69 +126,87 @@ namespace corsika {
     return const_stack_iterator_type(*this, getSize() - 1 - i);
   }
 
-  template <typename StackData, template <typename> typename MParticleInterface>
-  typename Stack<StackData, MParticleInterface>::stack_iterator_type inline Stack<
-      StackData, MParticleInterface>::at(unsigned int i) {
+  template <typename StackData, template <typename> typename MParticleInterface,
+            template <typename T1, template <class> class T2> class MSecondaryProducer>
+  typename Stack<StackData, MParticleInterface, MSecondaryProducer>::
+      stack_iterator_type inline Stack<StackData, MParticleInterface,
+                                       MSecondaryProducer>::at(unsigned int i) {
     return stack_iterator_type(*this, i);
   }
 
-  template <typename StackData, template <typename> typename MParticleInterface>
-  typename Stack<StackData, MParticleInterface>::const_stack_iterator_type inline Stack<
-      StackData, MParticleInterface>::at(unsigned int i) const {
+  template <typename StackData, template <typename> typename MParticleInterface,
+            template <typename T1, template <class> class T2> class MSecondaryProducer>
+  typename Stack<StackData, MParticleInterface, MSecondaryProducer>::
+      const_stack_iterator_type inline Stack<
+          StackData, MParticleInterface, MSecondaryProducer>::at(unsigned int i) const {
     return const_stack_iterator_type(*this, i);
   }
 
-  template <typename StackData, template <typename> typename MParticleInterface>
-  typename Stack<StackData, MParticleInterface>::stack_iterator_type inline Stack<
-      StackData, MParticleInterface>::first() {
+  template <typename StackData, template <typename> typename MParticleInterface,
+            template <typename T1, template <class> class T2> class MSecondaryProducer>
+  typename Stack<StackData, MParticleInterface, MSecondaryProducer>::
+      stack_iterator_type inline Stack<StackData, MParticleInterface,
+                                       MSecondaryProducer>::first() {
     return stack_iterator_type{*this, 0};
   }
 
-  template <typename StackData, template <typename> typename MParticleInterface>
-  typename Stack<StackData, MParticleInterface>::const_stack_iterator_type inline Stack<
-      StackData, MParticleInterface>::cfirst() const {
+  template <typename StackData, template <typename> typename MParticleInterface,
+            template <typename T1, template <class> class T2> class MSecondaryProducer>
+  typename Stack<StackData, MParticleInterface, MSecondaryProducer>::
+      const_stack_iterator_type inline Stack<StackData, MParticleInterface,
+                                             MSecondaryProducer>::cfirst() const {
     return const_stack_iterator_type{*this, 0};
   }
 
-  template <typename StackData, template <typename> typename MParticleInterface>
-  typename Stack<StackData, MParticleInterface>::stack_iterator_type inline Stack<
-      StackData, MParticleInterface>::getNextParticle() {
+  template <typename StackData, template <typename> typename MParticleInterface,
+            template <typename T1, template <class> class T2> class MSecondaryProducer>
+  typename Stack<StackData, MParticleInterface, MSecondaryProducer>::
+      stack_iterator_type inline Stack<StackData, MParticleInterface,
+                                       MSecondaryProducer>::getNextParticle() {
     while (purgeLastIfDeleted()) {}
     return last();
   }
 
-  template <typename StackData, template <typename> typename MParticleInterface>
+  template <typename StackData, template <typename> typename MParticleInterface,
+            template <typename T1, template <class> class T2> class MSecondaryProducer>
   template <typename... TArgs>
-  typename Stack<StackData, MParticleInterface>::stack_iterator_type inline Stack<
-      StackData, MParticleInterface>::addParticle(const TArgs... v) {
+  typename Stack<StackData, MParticleInterface, MSecondaryProducer>::
+      stack_iterator_type inline Stack<
+          StackData, MParticleInterface,
+          MSecondaryProducer>::addParticle(const TArgs... v) {
     data_.incrementSize();
     deleted_.push_back(false);
     return stack_iterator_type(*this, getSize() - 1, v...);
   }
 
-  template <typename StackData, template <typename> typename MParticleInterface>
-  inline void Stack<StackData, MParticleInterface>::swap(stack_iterator_type a,
-                                                         stack_iterator_type b) {
+  template <typename StackData, template <typename> typename MParticleInterface,
+            template <typename T1, template <class> class T2> class MSecondaryProducer>
+  inline void Stack<StackData, MParticleInterface, MSecondaryProducer>::swap(
+      stack_iterator_type a, stack_iterator_type b) {
     swap(a.getIndex(), b.getIndex());
   }
 
-  template <typename StackData, template <typename> typename MParticleInterface>
-  inline void Stack<StackData, MParticleInterface>::copy(stack_iterator_type a,
-                                                         stack_iterator_type b) {
+  template <typename StackData, template <typename> typename MParticleInterface,
+            template <typename T1, template <class> class T2> class MSecondaryProducer>
+  inline void Stack<StackData, MParticleInterface, MSecondaryProducer>::copy(
+      stack_iterator_type a, stack_iterator_type b) {
     copy(a.getIndex(), b.getIndex());
   }
 
-  template <typename StackData, template <typename> typename MParticleInterface>
-  inline void Stack<StackData, MParticleInterface>::copy(const_stack_iterator_type a,
-                                                         stack_iterator_type b) {
+  template <typename StackData, template <typename> typename MParticleInterface,
+            template <typename T1, template <class> class T2> class MSecondaryProducer>
+  inline void Stack<StackData, MParticleInterface, MSecondaryProducer>::copy(
+      const_stack_iterator_type a, stack_iterator_type b) {
     data_.copy(a.getIndex(), b.getIndex());
     if (deleted_[b.getIndex()] && !deleted_[a.getIndex()]) nDeleted_--;
     if (!deleted_[b.getIndex()] && deleted_[a.getIndex()]) nDeleted_++;
     deleted_[b.getIndex()] = deleted_[a.getIndex()];
   }
 
-  template <typename StackData, template <typename> typename MParticleInterface>
-  inline void Stack<StackData, MParticleInterface>::erase(stack_iterator_type p) {
+  template <typename StackData, template <typename> typename MParticleInterface,
+            template <typename T1, template <class> class T2> class MSecondaryProducer>
+  inline void Stack<StackData, MParticleInterface, MSecondaryProducer>::erase(
+      stack_iterator_type p) {
     if (this->isEmpty()) {
       throw std::runtime_error("Stack, cannot delete entry since size is zero");
     }
@@ -181,8 +219,10 @@ namespace corsika {
   /*
    * delete this particle
    */
-  template <typename StackData, template <typename> typename MParticleInterface>
-  inline void Stack<StackData, MParticleInterface>::erase(particle_interface_type p) {
+  template <typename StackData, template <typename> typename MParticleInterface,
+            template <typename T1, template <class> class T2> class MSecondaryProducer>
+  inline void Stack<StackData, MParticleInterface, MSecondaryProducer>::erase(
+      particle_interface_type p) {
     this->erase(p.getIterator());
   }
 
@@ -190,28 +230,32 @@ namespace corsika {
    * check if there are no further non-deleted particles on stack
    */
 
-  template <typename StackData, template <typename> typename MParticleInterface>
-  inline bool Stack<StackData, MParticleInterface>::isEmpty() {
+  template <typename StackData, template <typename> typename MParticleInterface,
+            template <typename T1, template <class> class T2> class MSecondaryProducer>
+  inline bool Stack<StackData, MParticleInterface, MSecondaryProducer>::isEmpty() {
     return getEntries() == 0;
   }
 
   /*
    * check if this particle was already deleted
    */
-  template <typename StackData, template <typename> typename MParticleInterface>
-  inline bool Stack<StackData, MParticleInterface>::isErased(
+  template <typename StackData, template <typename> typename MParticleInterface,
+            template <typename T1, template <class> class T2> class MSecondaryProducer>
+  inline bool Stack<StackData, MParticleInterface, MSecondaryProducer>::isErased(
       const stack_iterator_type& p) const {
     return isErased(p.getIndex());
   }
 
-  template <typename StackData, template <typename> typename MParticleInterface>
-  inline bool Stack<StackData, MParticleInterface>::isErased(
+  template <typename StackData, template <typename> typename MParticleInterface,
+            template <typename T1, template <class> class T2> class MSecondaryProducer>
+  inline bool Stack<StackData, MParticleInterface, MSecondaryProducer>::isErased(
       const const_stack_iterator_type& p) const {
     return isErased(p.getIndex());
   }
 
-  template <typename StackData, template <typename> typename MParticleInterface>
-  inline bool Stack<StackData, MParticleInterface>::isErased(
+  template <typename StackData, template <typename> typename MParticleInterface,
+            template <typename T1, template <class> class T2> class MSecondaryProducer>
+  inline bool Stack<StackData, MParticleInterface, MSecondaryProducer>::isErased(
       const particle_interface_type& p) const {
     return isErased(p.getIterator());
   }
@@ -221,8 +265,10 @@ namespace corsika {
    * if it was marked as deleted before. If this is not the case,
    * the function will just return false and do nothing.
    */
-  template <typename StackData, template <typename> typename MParticleInterface>
-  inline bool Stack<StackData, MParticleInterface>::purgeLastIfDeleted() {
+  template <typename StackData, template <typename> typename MParticleInterface,
+            template <typename T1, template <class> class T2> class MSecondaryProducer>
+  inline bool
+  Stack<StackData, MParticleInterface, MSecondaryProducer>::purgeLastIfDeleted() {
     if (!deleted_.back())
       return false; // the last particle is not marked for deletion. Do nothing.
 
@@ -242,8 +288,9 @@ namespace corsika {
    * (copied).
    */
 
-  template <typename StackData, template <typename> typename MParticleInterface>
-  inline void Stack<StackData, MParticleInterface>::purge() {
+  template <typename StackData, template <typename> typename MParticleInterface,
+            template <typename T1, template <class> class T2> class MSecondaryProducer>
+  inline void Stack<StackData, MParticleInterface, MSecondaryProducer>::purge() {
     unsigned int iStackFront = 0;
     unsigned int iStackBack = getSize() - 1;
 
@@ -260,13 +307,17 @@ namespace corsika {
     nDeleted_ = 0;
   }
 
-  template <typename StackData, template <typename> typename MParticleInterface>
-  inline unsigned int Stack<StackData, MParticleInterface>::getSize() const {
+  template <typename StackData, template <typename> typename MParticleInterface,
+            template <typename T1, template <class> class T2> class MSecondaryProducer>
+  inline unsigned int Stack<StackData, MParticleInterface, MSecondaryProducer>::getSize()
+      const {
     return data_.getSize();
   }
 
-  template <typename StackData, template <typename> typename MParticleInterface>
-  inline std::string Stack<StackData, MParticleInterface>::asString() const {
+  template <typename StackData, template <typename> typename MParticleInterface,
+            template <typename T1, template <class> class T2> class MSecondaryProducer>
+  inline std::string Stack<StackData, MParticleInterface, MSecondaryProducer>::asString()
+      const {
     std::string str(fmt::format("size {}, entries {}, deleted {} \n", getSize(),
                                 getEntries(), getErased()));
     // we make our own begin/end since we want ALL entries
@@ -280,40 +331,48 @@ namespace corsika {
     return str;
   }
 
-  template <typename StackData, template <typename> typename MParticleInterface>
+  template <typename StackData, template <typename> typename MParticleInterface,
+            template <typename T1, template <class> class T2> class MSecondaryProducer>
   template <typename... TArgs>
-  inline typename Stack<StackData, MParticleInterface>::stack_iterator_type
-  Stack<StackData, MParticleInterface>::addSecondary(stack_iterator_type& parent,
-                                                     const TArgs... v) {
+  inline typename Stack<StackData, MParticleInterface,
+                        MSecondaryProducer>::stack_iterator_type
+  Stack<StackData, MParticleInterface, MSecondaryProducer>::addSecondary(
+      stack_iterator_type& parent, const TArgs... v) {
     data_.incrementSize();
     deleted_.push_back(false);
     return stack_iterator_type(*this, getSize() - 1, parent, v...);
   }
 
-  template <typename StackData, template <typename> typename MParticleInterface>
-  inline void Stack<StackData, MParticleInterface>::swap(unsigned int const a,
-                                                         unsigned int const b) {
+  template <typename StackData, template <typename> typename MParticleInterface,
+            template <typename T1, template <class> class T2> class MSecondaryProducer>
+  inline void Stack<StackData, MParticleInterface, MSecondaryProducer>::swap(
+      unsigned int const a, unsigned int const b) {
     data_.swap(a, b);
     std::swap(deleted_[a], deleted_[b]);
   }
 
-  template <typename StackData, template <typename> typename MParticleInterface>
-  inline void Stack<StackData, MParticleInterface>::copy(unsigned int const a,
-                                                         unsigned int const b) {
+  template <typename StackData, template <typename> typename MParticleInterface,
+            template <typename T1, template <class> class T2> class MSecondaryProducer>
+  inline void Stack<StackData, MParticleInterface, MSecondaryProducer>::copy(
+      unsigned int const a, unsigned int const b) {
     data_.copy(a, b);
     if (deleted_[b] && !deleted_[a]) nDeleted_--;
     if (!deleted_[b] && deleted_[a]) nDeleted_++;
     deleted_[b] = deleted_[a];
   }
 
-  template <typename StackData, template <typename> typename MParticleInterface>
-  inline bool Stack<StackData, MParticleInterface>::isErased(unsigned int const i) const {
+  template <typename StackData, template <typename> typename MParticleInterface,
+            template <typename T1, template <class> class T2> class MSecondaryProducer>
+  inline bool Stack<StackData, MParticleInterface, MSecondaryProducer>::isErased(
+      unsigned int const i) const {
     if (i >= deleted_.size()) return false;
     return deleted_.at(i);
   }
 
-  template <typename StackData, template <typename> typename MParticleInterface>
-  inline void Stack<StackData, MParticleInterface>::erase(unsigned int const i) {
+  template <typename StackData, template <typename> typename MParticleInterface,
+            template <typename T1, template <class> class T2> class MSecondaryProducer>
+  inline void Stack<StackData, MParticleInterface, MSecondaryProducer>::erase(
+      unsigned int const i) {
     deleted_[i] = true;
     nDeleted_++;
   }
@@ -322,8 +381,10 @@ namespace corsika {
    * will remove from storage the element i. This is a helper
    * function for SecondaryView.
    */
-  template <typename StackData, template <typename> typename MParticleInterface>
-  inline void Stack<StackData, MParticleInterface>::purge(unsigned int i) {
+  template <typename StackData, template <typename> typename MParticleInterface,
+            template <typename T1, template <class> class T2> class MSecondaryProducer>
+  inline void Stack<StackData, MParticleInterface, MSecondaryProducer>::purge(
+      unsigned int i) {
     unsigned int iStackBack = getSize() - 1;
     // search for last non-deleted particle on stack
     while (deleted_[iStackBack]) { iStackBack--; }
@@ -335,21 +396,26 @@ namespace corsika {
     deleted_.pop_back();
   }
 
-  template <typename StackData, template <typename> typename MParticleInterface>
-  inline unsigned int Stack<StackData, MParticleInterface>::getIndexFromIterator(
+  template <typename StackData, template <typename> typename MParticleInterface,
+            template <typename T1, template <class> class T2> class MSecondaryProducer>
+  inline unsigned int
+  Stack<StackData, MParticleInterface, MSecondaryProducer>::getIndexFromIterator(
       const unsigned int vI) const {
     return vI;
   }
 
-  template <typename StackData, template <typename> typename MParticleInterface>
-  inline typename Stack<StackData, MParticleInterface>::value_type&
-  Stack<StackData, MParticleInterface>::getStackData() {
+  template <typename StackData, template <typename> typename MParticleInterface,
+            template <typename T1, template <class> class T2> class MSecondaryProducer>
+  inline typename Stack<StackData, MParticleInterface, MSecondaryProducer>::value_type&
+  Stack<StackData, MParticleInterface, MSecondaryProducer>::getStackData() {
     return data_;
   }
 
-  template <typename StackData, template <typename> typename MParticleInterface>
-  inline const typename Stack<StackData, MParticleInterface>::value_type&
-  Stack<StackData, MParticleInterface>::getStackData() const {
+  template <typename StackData, template <typename> typename MParticleInterface,
+            template <typename T1, template <class> class T2> class MSecondaryProducer>
+  inline const typename Stack<StackData, MParticleInterface,
+                              MSecondaryProducer>::value_type&
+  Stack<StackData, MParticleInterface, MSecondaryProducer>::getStackData() const {
     return data_;
   }
 
diff --git a/corsika/detail/modules/sibyll/NuclearInteraction.inl b/corsika/detail/modules/sibyll/NuclearInteraction.inl
index 6e212db022aae8071e3e83d1a665ec3e8936b70a..ccdd56b2d757eda8978eb108f6c039ae6f0b0662 100644
--- a/corsika/detail/modules/sibyll/NuclearInteraction.inl
+++ b/corsika/detail/modules/sibyll/NuclearInteraction.inl
@@ -18,10 +18,6 @@
 #include <corsika/framework/utility/COMBoost.hpp>
 #include <corsika/framework/core/Logging.hpp>
 
-#include <corsika/setup/SetupEnvironment.hpp>
-#include <corsika/setup/SetupStack.hpp>
-#include <corsika/setup/SetupTrajectory.hpp>
-
 #include <nuclib.hpp>
 
 namespace corsika::sibyll {
@@ -579,17 +575,16 @@ namespace corsika::sibyll {
       auto pCode = Code::Proton;
       // temporarily add to stack, will be removed after interaction in DoInteraction
       CORSIKA_LOG_DEBUG("inelastic interaction no. {}", j);
-      setup::Stack nucleonStack;
+      typename TSecondaryView::inner_stack_value_type nucleonStack;
       auto inelasticNucleon = nucleonStack.addParticle(
           std::make_tuple(pCode, PprojNucLab.getSpaceLikeComponents(), pOrig, tOrig));
       inelasticNucleon.setNode(projectile.getNode());
       // create inelastic interaction for each nucleon
       CORSIKA_LOG_TRACE("calling HadronicInteraction...");
       // create new StackView for each of the nucleons
-      setup::StackView nucleon_secondaries(inelasticNucleon);
+      TSecondaryView nucleon_secondaries(inelasticNucleon);
       // all inner hadronic event generator
       hadronicInteraction_.doInteraction(nucleon_secondaries);
-      // inelasticNucleon.Delete(); // this is just a temporary object
       for (const auto& pSec : nucleon_secondaries) {
         projectile.addSecondary(std::make_tuple(pSec.getPID(), pSec.getMomentum(),
                                                 pSec.getPosition(), pSec.getTime()));
diff --git a/corsika/detail/output/OutputManager.inl b/corsika/detail/output/OutputManager.inl
index 6a4ec62045acddbf9028f27d9991239c63012553..1fa7e0267c66af797cdf851d45c16f2146527776 100644
--- a/corsika/detail/output/OutputManager.inl
+++ b/corsika/detail/output/OutputManager.inl
@@ -194,7 +194,12 @@ namespace corsika {
     if (state_ == OutputState::NoInit) { startOfLibrary(); }
 
     // now start the event for all the outputs
-    for (auto& [name, output] : outputs_) { output.get().startOfShower(); }
+    for (auto& [name, output] : outputs_) {
+      {
+        [[maybe_unused]] auto const& dummy_name = name;
+      }
+      output.get().startOfShower();
+    }
 
     // increment our shower count
     ++count_;
@@ -205,7 +210,12 @@ namespace corsika {
 
   inline void OutputManager::endOfShower() {
 
-    for (auto& [name, output] : outputs_) { output.get().endOfShower(); }
+    for (auto& [name, output] : outputs_) {
+      {
+        [[maybe_unused]] auto const& dummy_name = name;
+      }
+      output.get().endOfShower();
+    }
 
     // switch back to the initialized state
     state_ = OutputState::LibraryReady;
diff --git a/corsika/detail/setup/SetupStack.hpp b/corsika/detail/setup/SetupStack.hpp
index 03016a47ebabcab2d2fd7b087e4f1a8f401b19a0..1f62ab4baaa245cb47420aee20fa53dc3617ae5a 100644
--- a/corsika/detail/setup/SetupStack.hpp
+++ b/corsika/detail/setup/SetupStack.hpp
@@ -38,7 +38,8 @@ namespace corsika {
 
     using StackWithGeometry =
         CombinedStack<typename nuclear_stack::ParticleDataStack::stack_data_type,
-                      node::GeometryData<setup::Environment>, StackWithGeometryInterface>;
+                      node::GeometryData<setup::Environment>, StackWithGeometryInterface,
+                      DefaultSecondaryProducer>;
 
     // ------------------------------------------
     // Add [optional] history data to stack, too:
@@ -51,7 +52,8 @@ namespace corsika {
 
     using StackWithHistory =
         CombinedStack<typename StackWithGeometry::stack_data_type,
-                      history::HistoryEventData, StackWithHistoryInterface>;
+                      history::HistoryEventData, StackWithHistoryInterface,
+                      history::HistorySecondaryProducer>;
 
   } // namespace setup::detail
 
diff --git a/corsika/framework/core/Cascade.hpp b/corsika/framework/core/Cascade.hpp
index 1eadbce1160a405f6cc1738d62997a20923aab3a..1804f406e98e915fd15970cb5dce75f9d721e6cc 100644
--- a/corsika/framework/core/Cascade.hpp
+++ b/corsika/framework/core/Cascade.hpp
@@ -9,22 +9,16 @@
 #pragma once
 
 #include <corsika/framework/process/ProcessReturn.hpp>
-
 #include <corsika/framework/core/PhysicalUnits.hpp>
 #include <corsika/framework/random/ExponentialDistribution.hpp>
 #include <corsika/framework/random/RNGManager.hpp>
 #include <corsika/framework/random/UniformRealDistribution.hpp>
 #include <corsika/framework/stack/SecondaryView.hpp>
-#include <corsika/media/Environment.hpp>
 #include <corsika/framework/core/Logging.hpp>
 
-/*  see Issue 161, we need to include SetupStack only because we need
-    to globally define StackView. This is clearly not nice and should
-    be changed, when possible. It might be that StackView needs to be
-    templated in Cascade, but this would be even worse... so we don't
-    do that until it is really needed.
- */
-#include <corsika/setup/SetupStack.hpp>
+#include <corsika/media/Environment.hpp>
+
+#include <corsika/stack/history/HistoryStackExtension.hpp>
 
 #include <cassert>
 #include <cmath>
@@ -47,29 +41,26 @@ namespace corsika {
    * TrackingInterface providing the functions:
    *
    * <code>
-   * auto getTrack(Particle const& p)</auto>,
+   * auto getTrack(particle_type const& p)</auto>,
    * with the return type <code>geometry::Trajectory<Line>
    * </code>
    *
    * <b>TProcessList</b> must be a ProcessSequence.   *
    * <b>Stack</b> is the storage object for particle data, i.e. with
-   * Particle class type <code>Stack::ParticleType</code>
-   *
+   * particle class type <code>Stack::particle_type</code>
    *
    */
-  template <typename TTracking, typename TProcessList, typename TOutput, typename TStack,
-            /*
-             TStackView is needed as explicit template parameter because
-             of issue 161 and the
-             inability of clang to understand "stack::MakeView" so far.
-            */
-            typename TStackView = corsika::setup::StackView>
+  template <typename TTracking, typename TProcessList, typename TOutput, typename TStack>
   class Cascade {
 
-    typedef typename TStack::particle_type Particle;
-    typedef std::remove_pointer_t<decltype(((Particle*)nullptr)->getNode())>
-        VolumeTreeNode;
-    typedef typename VolumeTreeNode::IModelProperties MediumInterface;
+    typedef typename TStack::stack_view_type stack_view_type;
+
+    typedef typename TStack::particle_type particle_type;
+
+    typedef std::remove_pointer_t<decltype(((particle_type*)nullptr)->getNode())>
+        volume_tree_node_type;
+
+    typedef typename volume_tree_node_type::IModelProperties medium_interface_type;
 
   public:
     /**
@@ -83,8 +74,8 @@ namespace corsika {
     Cascade(Cascade&&) = default;
     ~Cascade() = default;
     Cascade& operator=(Cascade const&) = default;
-    Cascade(Environment<MediumInterface> const& env, TTracking& tr, TProcessList& pl,
-            TOutput& out, TStack& stack)
+    Cascade(Environment<medium_interface_type> const& env, TTracking& tr,
+            TProcessList& pl, TOutput& out, TStack& stack)
         : environment_(env)
         , tracking_(tr)
         , sequence_(pl)
@@ -93,7 +84,7 @@ namespace corsika {
       CORSIKA_LOG_INFO(c8_ascii_);
       CORSIKA_LOG_INFO("Tracking algorithm: {} (version {})", TTracking::getName(),
                        TTracking::getVersion());
-      if constexpr (TStackView::has_event) {
+      if constexpr (stack_view_type::has_event) {
         CORSIKA_LOG_INFO("Stack - with full cascade HISTORY.");
       }
     }
@@ -129,15 +120,15 @@ namespace corsika {
      * New particles produced in one step are subject to further
      * processing, e.g. thinning, etc.
      */
-    void step(Particle& vParticle);
+    void step(particle_type& vParticle);
 
-    ProcessReturn decay(TStackView& view, InverseTimeType initial_inv_decay_time);
-    ProcessReturn interaction(TStackView& view,
+    ProcessReturn decay(stack_view_type& view, InverseTimeType initial_inv_decay_time);
+    ProcessReturn interaction(stack_view_type& view,
                               InverseGrammageType initial_inv_int_length);
-    void setEventType(TStackView& view, history::EventType);
+    void setEventType(stack_view_type& view, history::EventType);
 
     // data members
-    Environment<MediumInterface> const& environment_;
+    Environment<medium_interface_type> const& environment_;
     TTracking& tracking_;
     TProcessList& sequence_;
     TOutput& output_;
diff --git a/corsika/framework/process/DecayProcess.hpp b/corsika/framework/process/DecayProcess.hpp
index dc1e9a3ed3984570787b2a6ce36f3d88a20d90b7..6fa5a754cdf08059062fb6348f4a20ccc2e57d34 100644
--- a/corsika/framework/process/DecayProcess.hpp
+++ b/corsika/framework/process/DecayProcess.hpp
@@ -36,7 +36,7 @@ namespace corsika {
      @endcode
 
      Where, of course, SecondaryView and Particle are the valid
-     classes to access particles on the Stack. Those two methods do
+     classes to access particles on the Stack. In user code those two methods do
      not need to be templated, they could use the types
      e.g. corsika::setup::Stack::particle_type -- but by the cost of
      loosing all flexibility otherwise provided.
diff --git a/corsika/framework/process/InteractionProcess.hpp b/corsika/framework/process/InteractionProcess.hpp
index 6965457a7fe1a6c495e42b62943ebe87b3771702..c446e6f90ba8c8f17b54932e3c3226f8caa8b236 100644
--- a/corsika/framework/process/InteractionProcess.hpp
+++ b/corsika/framework/process/InteractionProcess.hpp
@@ -36,7 +36,7 @@ namespace corsika {
      @endcode
 
      Where, of course, SecondaryView and Particle are the valid
-     classes to access particles on the Stack. Those two methods do
+     classes to access particles on the Stack. In user code, those two methods do
      not need to be templated, they could use the types
      e.g. corsika::setup::Stack::particle_type -- but by the cost of
      loosing all flexibility otherwise provided.
diff --git a/corsika/framework/stack/CombinedStack.hpp b/corsika/framework/stack/CombinedStack.hpp
index e83e33a2f07e7a6f86de83bd516141ee8f77d398..9a945b0a5517c6c8b32b6e974a61f4effc531ca1 100644
--- a/corsika/framework/stack/CombinedStack.hpp
+++ b/corsika/framework/stack/CombinedStack.hpp
@@ -128,8 +128,11 @@ namespace corsika {
    * initialization are forwarded to Stack1Impl (first).
    */
 
-  template <typename Stack1Impl, typename Stack2Impl, template <typename> typename _PI>
-  using CombinedStack = Stack<CombinedStackImpl<Stack1Impl, Stack2Impl>, _PI>;
+  template <typename Stack1Impl, typename Stack2Impl, template <typename> typename _PI,
+            template <typename T1, template <class> class T2> class _MSecondaryProducer =
+                DefaultSecondaryProducer>
+  using CombinedStack =
+      Stack<CombinedStackImpl<Stack1Impl, Stack2Impl>, _PI, _MSecondaryProducer>;
 
 } // namespace corsika
 
diff --git a/corsika/framework/stack/DefaultSecondaryProducer.hpp b/corsika/framework/stack/DefaultSecondaryProducer.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..b91039aca3a6f1471876ab4701e23c66ac90921d
--- /dev/null
+++ b/corsika/framework/stack/DefaultSecondaryProducer.hpp
@@ -0,0 +1,54 @@
+/*
+ * (c) Copyright 2021 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
+
+#include <corsika/framework/stack/SecondaryView.hpp>
+
+namespace corsika {
+
+  /**
+   * Class to handle the generation of new secondaries. Used as default mix-in for
+   * SecondaryView.
+   */
+  template <class T1, template <class> class T2>
+  class DefaultSecondaryProducer {
+
+    using view_type = SecondaryView<T1, T2, DefaultSecondaryProducer>;
+
+  public:
+    static bool constexpr has_event{false};
+
+    /**
+     * Method is called after a new secondary has been created on the
+     * SecondaryView. Extra logic can be introduced here.
+     *
+     * The input Particle is the new secondary that was produced and
+     * is of course a reference into the SecondaryView itself.
+     */
+    template <typename Particle>
+    void new_secondary(Particle&&) const {
+      CORSIKA_LOG_TRACE("DefaultSecondaryProducer::new_secondary(Particle&&)");
+    }
+
+    /**
+     * Method is called when a new SecondaryView is being created
+     * created. Extra logic can be introduced here.
+     *
+     * The input Particle is a reference object into the original
+     * parent stack! It is not a reference into the SecondaryView
+     * itself.
+     */
+    template <typename Particle>
+    DefaultSecondaryProducer(Particle const&) {
+
+      CORSIKA_LOG_TRACE("DefaultSecondaryProducer::DefaultSecondaryProducer(Particle&)");
+    }
+  };
+
+} // namespace corsika
\ No newline at end of file
diff --git a/corsika/framework/stack/SecondaryView.hpp b/corsika/framework/stack/SecondaryView.hpp
index 6ba881b9262be89f403f58aed3338dd15fd9f218..9ffaf150582b081cacff72a4d021403353b29dcb 100644
--- a/corsika/framework/stack/SecondaryView.hpp
+++ b/corsika/framework/stack/SecondaryView.hpp
@@ -26,7 +26,7 @@ namespace corsika {
    * SecondaryView can only be constructed by giving a valid
    * Projectile particle, following calls to addSecondary will
    * populate the original Stack, but will be directly accessible via
-   * the SecondaryView, e.g.
+   * the SecondaryView, e.g.StackViewPr
 
      This allows to write code like
      \verbatim
@@ -61,54 +61,46 @@ namespace corsika {
   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> {
+  class SecondaryView
+      : public Stack<TStackDataType&, TParticleInterface, MSecondaryProducer>,
+        public MSecondaryProducer<TStackDataType, TParticleInterface> {
 
-    // using ViewType = SecondaryView<TStackDataType, TParticleInterface,
-    // MSecondaryProducer>;
+  public:
     typedef SecondaryView<TStackDataType, TParticleInterface, MSecondaryProducer>
         view_type;
     /**
      * Helper type for inside this class
      */
-    // using InnerStackTypeRef = Stack<TStackDataType&, TParticleInterface>;
-    typedef Stack<TStackDataType&, TParticleInterface> inner_stack_reference_type;
+    typedef Stack<TStackDataType&, TParticleInterface, MSecondaryProducer>
+        inner_stack_reference_type;
 
     /**
      * @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;
+    typedef Stack<TStackDataType, TParticleInterface, MSecondaryProducer>
+        inner_stack_value_type;
 
   public:
     typedef StackIteratorInterface<typename std::remove_reference<TStackDataType>::type,
-                                   TParticleInterface, inner_stack_value_type>
+                                   TParticleInterface, MSecondaryProducer,
+                                   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>
+        MSecondaryProducer, inner_stack_value_type>
         const_stack_value_iterator;
     /// @}
 
-    //    using StackIterator =
-    //        StackIteratorInterface<typename std::remove_reference<TStackDataType>::type,
-    //                               TParticleInterface, view_type>;
-
     typedef StackIteratorInterface<typename std::remove_reference<TStackDataType>::type,
-                                   TParticleInterface, view_type>
+                                   TParticleInterface, MSecondaryProducer, view_type>
         stack_view_iterator;
 
     typedef ConstStackIteratorInterface<
         typename std::remove_reference<TStackDataType>::type, TParticleInterface,
-        view_type>
+        MSecondaryProducer, view_type>
         const_stack_view_iterator;
 
     /**
@@ -130,7 +122,8 @@ namespace corsika {
         stack_view_iterator to another Stack object (here: lvalue)
       **/
     SecondaryView(stack_value_iterator& particle)
-        : Stack<TStackDataType&, TParticleInterface>(particle.getStackData())
+        : Stack<TStackDataType&, TParticleInterface, MSecondaryProducer>(
+              particle.getStackData())
         , MSecondaryProducer<TStackDataType, TParticleInterface>{particle}
         , inner_stack_(particle.getStack())
         , projectile_index_(particle.getIndex()) {
@@ -141,7 +134,8 @@ namespace corsika {
        stack_view_iterator to another Stack object (here: rvalue)
      **/
     SecondaryView(stack_value_iterator&& particle)
-        : Stack<TStackDataType&, TParticleInterface>(particle.getStackData())
+        : Stack<TStackDataType&, TParticleInterface, MSecondaryProducer>(
+              particle.getStackData())
         , MSecondaryProducer<TStackDataType, TParticleInterface>{particle}
         , inner_stack_(particle.getStack())
         , projectile_index_(particle.getIndex()) {
@@ -154,7 +148,8 @@ namespace corsika {
      * 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<TStackDataType&, TParticleInterface>{view.getStackData()}
+        : Stack<TStackDataType&, TParticleInterface,
+                MSecondaryProducer>{view.getStackData()}
         , MSecondaryProducer<TStackDataType, TParticleInterface>{stack_value_iterator{
               view.inner_stack_, view.getIndexFromIterator(projectile.getIndex())}}
         , inner_stack_{view.inner_stack_}
@@ -333,11 +328,11 @@ namespace corsika {
   protected:
     friend class StackIteratorInterface<
         typename std::remove_reference<TStackDataType>::type, TParticleInterface,
-        view_type>;
+        MSecondaryProducer, view_type>;
 
     friend class ConstStackIteratorInterface<
         typename std::remove_reference<TStackDataType>::type, TParticleInterface,
-        view_type>;
+        MSecondaryProducer, view_type>;
 
     friend class ParticleBase<stack_view_iterator>;
 
@@ -378,44 +373,6 @@ namespace corsika {
     std::vector<unsigned int> indices_;
   };
 
-  /**
-   * Class to handle the generation of new secondaries. Used as default mix-in for
-   * SecondaryView.
-   */
-  template <class T1, template <class> class T2>
-  class DefaultSecondaryProducer {
-    using View = SecondaryView<T1, T2, DefaultSecondaryProducer>;
-
-  public:
-    static bool constexpr has_event{false};
-
-    /**
-     * Method is called after a new secondary has been created on the
-     * SecondaryView. Extra logic can be introduced here.
-     *
-     * The input Particle is the new secondary that was produced and
-     * is of course a reference into the SecondaryView itself.
-     */
-    template <typename Particle>
-    void new_secondary(Particle&&) const {
-      CORSIKA_LOG_TRACE("DefaultSecondaryProducer::new_secondary(Particle&&)");
-    }
-
-    /**
-     * Method is called when a new SecondaryView is being created
-     * created. Extra logic can be introduced here.
-     *
-     * The input Particle is a reference object into the original
-     * parent stack! It is not a reference into the SecondaryView
-     * itself.
-     */
-    template <typename Particle>
-    DefaultSecondaryProducer(Particle const&) {
-
-      CORSIKA_LOG_TRACE("DefaultSecondaryProducer::DefaultSecondaryProducer(Particle&)");
-    }
-  };
-
   /*
     See Issue 161
 
diff --git a/corsika/framework/stack/Stack.hpp b/corsika/framework/stack/Stack.hpp
index 81da792924c4c9d4e3197a44562e93ef90db5ed4..8bfa92f96c2642ac04c6d38de3772702ab7b46dc 100644
--- a/corsika/framework/stack/Stack.hpp
+++ b/corsika/framework/stack/Stack.hpp
@@ -10,6 +10,8 @@
 
 #include <corsika/framework/core/Logging.hpp>
 #include <corsika/framework/stack/StackIteratorInterface.hpp>
+#include <corsika/framework/stack/DefaultSecondaryProducer.hpp>
+#include <corsika/framework/stack/SecondaryView.hpp>
 
 #include <stdexcept>
 #include <string>
@@ -43,17 +45,6 @@ corsika::stack
 
 namespace corsika {
 
-  /**
-     This is just a forward declatation for the user-defined
-     ParticleInterface, which is one of the essential template
-     parameters for the Stack.
-
-     <b>Important:</b> ParticleInterface must inherit from ParticleBase !
-   */
-
-  template <typename>
-  class ParticleInterface;
-
   /**
      The Stack class provides (and connects) the main particle data storage machinery.
 
@@ -67,12 +58,22 @@ namespace corsika {
      provide all functions to read single particle data from the
      StackDataType, given an 'unsigned int' index.
 
+     <b>Important:</b> ParticleInterface must inherit from ParticleBase.
+
      The Stack implements the
      std-type begin/end function to allow integration in normal for
      loops, ranges, etc.
-   */
 
-  template <typename TStackData, template <typename> typename MParticleInterface>
+
+    The template argument MSecondaryProducer is only needed because of gitlab Issue 161
+
+    Due to a limitation of clang the corsika::MakeView does not work. Thus,
+    MSecondaryProducer is needed here to fully define a SecondaryView class.
+**/
+
+  template <typename TStackData, template <typename> typename MParticleInterface,
+            template <typename T1, template <class> class T2> class MSecondaryProducer =
+                DefaultSecondaryProducer>
   class Stack {
 
     typedef typename std::remove_reference<TStackData>::type value_type;
@@ -81,8 +82,11 @@ namespace corsika {
     typedef TStackData stack_data_type; ///< this is the type of the
                                         ///< user-provided data structure
 
+    typedef SecondaryView<TStackData, MParticleInterface, MSecondaryProducer>
+        stack_view_type;
+
     template <typename TStackIterator>
-    using pi_type = MParticleInterface<TStackIterator>; // @todo pi_type -> pi_template
+    using pi_type = MParticleInterface<TStackIterator>;
 
     /**
      * Via the StackIteratorInterface and ConstStackIteratorInterface
@@ -91,10 +95,12 @@ namespace corsika {
      * object. Using CRTP, this also determines the type of
      * MParticleInterface template class simultaneously.
      */
-    typedef StackIteratorInterface<value_type, MParticleInterface, Stack>
+    typedef StackIteratorInterface<value_type, MParticleInterface, MSecondaryProducer,
+                                   Stack>
         stack_iterator_type;
 
-    typedef ConstStackIteratorInterface<value_type, MParticleInterface, Stack>
+    typedef ConstStackIteratorInterface<value_type, MParticleInterface,
+                                        MSecondaryProducer, Stack>
         const_stack_iterator_type;
 
     /**
@@ -197,10 +203,7 @@ namespace corsika {
     /**
      * increase stack size, create new particle at end of stack
      */
-    template <typename... TArgs> //,
-    //        typename = std::enable_if_t<std::is_same_v<
-    //      void, std::invoke_result_t<decltype((**stack_iterator_type).setParticleData),
-    //                                 TArgs...>>>>
+    template <typename... TArgs>
     stack_iterator_type addParticle(const TArgs... v);
 
     void swap(stack_iterator_type a, stack_iterator_type b);
@@ -293,15 +296,14 @@ namespace corsika {
 
     const value_type& getStackData() const;
 
-    friend class StackIteratorInterface<value_type, MParticleInterface, Stack>;
-    friend class ConstStackIteratorInterface<value_type, MParticleInterface, Stack>;
-    template <typename T1, //=StackData,
-              template <typename>
-              typename M1, //=MParticleInterface,
-                           //             template<typename>typename M2>
-              template <class T2, template <class> class T3> class MSecondaryProducer>
-    friend class SecondaryView; //<StackData,MParticleInterface,M>; // access for
-                                // SecondaryView
+    friend class StackIteratorInterface<value_type, MParticleInterface,
+                                        MSecondaryProducer, Stack>;
+    friend class ConstStackIteratorInterface<value_type, MParticleInterface,
+                                             MSecondaryProducer, Stack>;
+    template <typename T1,                     //=TStackData,
+              template <typename> typename M1, //=MParticleInterface,
+              template <class T2, template <class> class T3> class M2>
+    friend class SecondaryView;
 
     friend class ParticleBase<stack_iterator_type>;
 
@@ -311,7 +313,7 @@ namespace corsika {
   private:
     TStackData data_; ///< this in general holds all the data and can be quite big
     std::vector<bool> deleted_; ///< bit field to flag deleted entries
-  };
+  };                            // namespace corsika
 
 } // namespace corsika
 
diff --git a/corsika/framework/stack/StackIteratorInterface.hpp b/corsika/framework/stack/StackIteratorInterface.hpp
index d6a267014def6b44d46011cf5c46f0791df5e76e..88e6b8f988062ab29262c37496a56ca89e6ec370 100644
--- a/corsika/framework/stack/StackIteratorInterface.hpp
+++ b/corsika/framework/stack/StackIteratorInterface.hpp
@@ -19,7 +19,8 @@ namespace corsika::history {
 
 namespace corsika {
 
-  template <typename TStackData, template <typename> typename TParticleInterface>
+  template <typename TStackData, template <typename> typename TParticleInterface,
+            template <class T1, template <class> class T2> class MSecondaryProducer>
   class Stack; // forward decl
 
   template <typename TStackData, template <typename> typename TParticleInterface,
@@ -27,6 +28,7 @@ namespace corsika {
   class SecondaryView; // forward decl
 
   template <typename TStackData, template <typename> typename TParticleInterface,
+            template <class T1, template <class> class T2> class MSecondaryProducer,
             typename StackType>
   class ConstStackIteratorInterface; // forward decl
 
@@ -69,14 +71,16 @@ namespace corsika {
   */
 
   template <typename TStackData, template <typename> typename TParticleInterface,
-            typename TStackType = Stack<TStackData, TParticleInterface>>
+            template <typename T1, template <class> class T2> class MSecondaryProducer,
+            typename TStackType =
+                Stack<TStackData, TParticleInterface, MSecondaryProducer>>
   class StackIteratorInterface
-      : public TParticleInterface<
-            StackIteratorInterface<TStackData, TParticleInterface, TStackType>> {
+      : public TParticleInterface<StackIteratorInterface<
+            TStackData, TParticleInterface, MSecondaryProducer, TStackType>> {
 
   public:
-    typedef TParticleInterface<
-        corsika::StackIteratorInterface<TStackData, TParticleInterface, TStackType>>
+    typedef TParticleInterface<corsika::StackIteratorInterface<
+        TStackData, TParticleInterface, MSecondaryProducer, TStackType>>
         particle_interface_type;
 
     typedef TStackType stack_type;
@@ -174,12 +178,12 @@ namespace corsika {
     bool operator!=(StackIteratorInterface const& rhs) const {
       return index_ != rhs.index_;
     }
-    bool operator==(
-        const ConstStackIteratorInterface<TStackData, TParticleInterface, stack_type>&
-            rhs) const; // implemented below
-    bool operator!=(
-        const ConstStackIteratorInterface<TStackData, TParticleInterface, stack_type>&
-            rhs) const; // implemented below
+    bool operator==(const ConstStackIteratorInterface<
+                    TStackData, TParticleInterface, MSecondaryProducer,
+                    stack_type>& rhs) const; // implemented below
+    bool operator!=(const ConstStackIteratorInterface<
+                    TStackData, TParticleInterface, MSecondaryProducer,
+                    stack_type>& rhs) const; // implemented below
 
     /**
      * Convert iterator to value type, where value type is the user-provided particle
@@ -220,11 +224,12 @@ namespace corsika {
     ///@}
 
     // 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 getStackDataType
+    friend class Stack<TStackData, TParticleInterface,
+                       MSecondaryProducer>; // for access to getIndex for Stack
+    friend class Stack<TStackData&, TParticleInterface,
+                       MSecondaryProducer>;            // for access to getIndex
+                                                       // SecondaryView : public Stack
+    friend class ParticleBase<StackIteratorInterface>; // for access to getStackDataType
 
     template <typename T1,                     // best fix this to: TStackData,
               template <typename> typename M1, // best fix this to: TParticleInterface,
@@ -234,7 +239,8 @@ namespace corsika {
     template <typename T, template <typename> typename TParticleInterface_>
     friend class corsika::history::HistorySecondaryProducer;
 
-    friend class ConstStackIteratorInterface<TStackData, TParticleInterface, stack_type>;
+    friend class ConstStackIteratorInterface<TStackData, TParticleInterface,
+                                             MSecondaryProducer, stack_type>;
 
   protected:
     unsigned int index_ = 0;
@@ -260,14 +266,16 @@ namespace corsika {
    */
 
   template <typename TStackData, template <typename> typename TParticleInterface,
-            typename TStackType = Stack<TStackData, TParticleInterface>>
+            template <typename T1, template <class> class T2> class MSecondaryProducer,
+            typename TStackType =
+                Stack<TStackData, TParticleInterface, MSecondaryProducer>>
   class ConstStackIteratorInterface
-      : public TParticleInterface<
-            ConstStackIteratorInterface<TStackData, TParticleInterface, TStackType>> {
+      : public TParticleInterface<ConstStackIteratorInterface<
+            TStackData, TParticleInterface, MSecondaryProducer, TStackType>> {
 
   public:
-    typedef TParticleInterface<
-        ConstStackIteratorInterface<TStackData, TParticleInterface, TStackType>>
+    typedef TParticleInterface<ConstStackIteratorInterface<
+        TStackData, TParticleInterface, MSecondaryProducer, TStackType>>
         particle_interface_type;
 
     typedef TStackType stack_type;
@@ -314,12 +322,14 @@ namespace corsika {
     bool operator!=(ConstStackIteratorInterface const& rhs) const {
       return index_ != rhs.index_;
     }
-    bool operator==(StackIteratorInterface<stack_data_type, TParticleInterface,
-                                           stack_type> const& rhs) const {
+    bool operator==(
+        StackIteratorInterface<stack_data_type, TParticleInterface, MSecondaryProducer,
+                               stack_type> const& rhs) const {
       return index_ == rhs.index_;
     }
-    bool operator!=(StackIteratorInterface<stack_data_type, TParticleInterface,
-                                           stack_type> const& rhs) const {
+    bool operator!=(
+        StackIteratorInterface<stack_data_type, TParticleInterface, MSecondaryProducer,
+                               stack_type> const& rhs) const {
       return index_ != rhs.index_;
     }
 
@@ -343,18 +353,20 @@ namespace corsika {
     ///@}
 
     // friends are needed for access to protected methods
-    friend class Stack<stack_data_type,
-                       TParticleInterface>; // for access to GetIndex for Stack
-    friend class Stack<stack_data_type&, TParticleInterface>; // for access to GetIndex
+    friend class Stack<stack_data_type, TParticleInterface,
+                       MSecondaryProducer>; // for access to GetIndex for Stack
+    friend class Stack<stack_data_type&, TParticleInterface,
+                       MSecondaryProducer>; // for access to GetIndex
 
     friend class ParticleBase<ConstStackIteratorInterface>; // for access to GetStackData
 
     template <typename T1,                     // best fix to: stack_data_type,
               template <typename> typename M1, // best fix to: TParticleInterface,
-              template <class T2, template <class> class T3> class MSecondaryProducer>
+              template <class T2, template <class> class T3> class M2>
     friend class SecondaryView; // access for SecondaryView
 
-    friend class StackIteratorInterface<stack_data_type, TParticleInterface, stack_type>;
+    friend class StackIteratorInterface<stack_data_type, TParticleInterface,
+                                        MSecondaryProducer, stack_type>;
 
     template <typename T, template <typename> typename TParticleInterface_>
     friend class corsika::history::HistorySecondaryProducer;
diff --git a/corsika/modules/sibyll/Interaction.hpp b/corsika/modules/sibyll/Interaction.hpp
index 81f0aa68571101dec0a48bb0aae72055882980f2..c00c68ac995cf0dfd4dc9bace54af082952b2dda 100644
--- a/corsika/modules/sibyll/Interaction.hpp
+++ b/corsika/modules/sibyll/Interaction.hpp
@@ -57,7 +57,6 @@ namespace corsika::sibyll {
     HEPEnergyType getMaxEnergyCoM() const { return maxEnergyCoM_; }
 
     default_prng_type& RNG_ = RNGManager::getInstance().getRandomStream("sibyll");
-    const bool internalDecays_ = true;
     const HEPEnergyType minEnergyCoM_ = 10. * 1e9 * electronvolt;
     const HEPEnergyType maxEnergyCoM_ = 1.e6 * 1e9 * electronvolt;
     const int maxTargetMassNumber_ = 18;
diff --git a/corsika/output/NoOutput.hpp b/corsika/output/NoOutput.hpp
index 289c19ad720f9f03d621d3b50ac031c40cc794cf..abee413e0d007e1b2de042de0249afe46b07e40a 100644
--- a/corsika/output/NoOutput.hpp
+++ b/corsika/output/NoOutput.hpp
@@ -45,7 +45,7 @@ namespace corsika {
     /**
      * Get the configuration of this output.
      */
-    YAML::Node getConfig() const { return YAML::Node(); };
+    YAML::Node getConfig() const override { return YAML::Node(); };
 
     /**
      * Get any summary information for the entire library.
diff --git a/corsika/setup/SetupStack.hpp b/corsika/setup/SetupStack.hpp
index a051e4db177cd36e087f42612652ffe0737c585d..305089ec5a7577d8816fda6d8004cf0fcfcd52f5 100644
--- a/corsika/setup/SetupStack.hpp
+++ b/corsika/setup/SetupStack.hpp
@@ -25,8 +25,6 @@ namespace corsika::setup {
    * the version with history
    */
   using Stack = detail::StackWithHistory;
-  template <typename T1, template <typename> typename M2>
-  using StackViewProducer = history::HistorySecondaryProducer<T1, M2>;
 
 #else // WITH_HISTORY
 
@@ -34,47 +32,10 @@ namespace corsika::setup {
    * the version without history
    */
   using Stack = detail::StackWithGeometry;
-  template <typename T1, template <typename> typename M2>
-  using StackViewProducer = DefaultSecondaryProducer<T1, M2>;
 
 #endif
 
-  // ---------------------------------------
-  // this is the stackitertor (particle type) we use in C8 executables:
-
-  /*
-    See Issue 161
-
-    unfortunately clang does not support this in the same way (yet) as
-    gcc, so we have to distinguish here. If clang cataches up, we
-    could remove the clang branch here and also in
-    corsika::Cascade. The gcc code is much more generic and
-    universal. If we could do the gcc version, we won't had to define
-    StackView globally, we could do it with MakeView whereever it is
-    actually needed. Keep an eye on this!
-  */
-
-#ifdef WITH_HISTORY
-
-#if defined(__clang__)
-  using StackView = SecondaryView<typename Stack::stack_data_type,
-                                  // CHECK with CLANG: setup::Stack::MPIType>;
-                                  detail::StackWithHistoryInterface, StackViewProducer>;
-#elif defined(__GNUC__) || defined(__GNUG__)
-  using StackView = MakeView<setup::Stack, StackViewProducer>::type;
-#endif
-
-#else // WITH_HISTORY
-
-#if defined(__clang__)
-  using StackView = SecondaryView<typename setup::Stack::stack_data_type,
-                                  // CHECK with CLANG:
-                                  // setup::Stack::MPIType>;
-                                  setup::detail::StackWithGeometryInterface>;
-#elif defined(__GNUC__) || defined(__GNUG__)
-  using StackView = MakeView<setup::Stack>::type;
-#endif
-
-#endif // WITH_HISTORY
+  // the correct secondary stack view
+  using StackView = typename Stack::stack_view_type;
 
 } // namespace corsika::setup
diff --git a/tests/framework/testCascade.cpp b/tests/framework/testCascade.cpp
index df55ee318d51675bb4cb1f19b0da38d25d7316d3..b069c23b9f8b49c5e70fc873b078198ffc08bd09 100644
--- a/tests/framework/testCascade.cpp
+++ b/tests/framework/testCascade.cpp
@@ -167,9 +167,8 @@ TEST_CASE("Cascade", "[Cascade]") {
 
   DummyTracking tracking;
   DummyOutputManager output;
-  Cascade<DummyTracking, decltype(sequence), DummyOutputManager, TestCascadeStack,
-          TestCascadeStackView>
-      EAS(env, tracking, sequence, output, stack);
+  Cascade<DummyTracking, decltype(sequence), DummyOutputManager, TestCascadeStack> EAS(
+      env, tracking, sequence, output, stack);
 
   SECTION("full cascade") {
     EAS.run();
diff --git a/tests/modules/testSibyll.cpp b/tests/modules/testSibyll.cpp
index f6a517e1a8822b36a30b743cfc15ce1b9883305f..41f511a47742e1eef4ddd70b3673b71597194474 100644
--- a/tests/modules/testSibyll.cpp
+++ b/tests/modules/testSibyll.cpp
@@ -255,6 +255,7 @@ TEST_CASE("SibyllInterface", "[processes]") {
     const HEPEnergyType P0 = 1000_EeV;
     auto [stack, viewPtr] = setup::testing::setup_stack(
         Code::Proton, 0, 0, P0, (setup::Environment::BaseNodeType* const)nodePtr, cs);
+    { [[maybe_unused]] auto const& dummy1 = stack; }
     MomentumVector plab =
         MomentumVector(cs, {P0, 0_eV, 0_eV}); // this is secret knowledge about setupStack
     setup::StackView& view = *viewPtr;
@@ -265,10 +266,12 @@ TEST_CASE("SibyllInterface", "[processes]") {
 
   SECTION("InteractionInterface - target nucleus out of range") {
     auto [env1, csPtr1, nodePtr1] = setup::testing::setup_environment(Code::Argon);
+    { [[maybe_unused]] auto const& dummy1 = env1; }
     auto const& cs1 = *csPtr1;
     const HEPEnergyType P0 = 150_GeV;
     auto [stack, viewPtr] = setup::testing::setup_stack(
         Code::Electron, 0, 0, P0, (setup::Environment::BaseNodeType* const)nodePtr1, cs1);
+    { [[maybe_unused]] auto const& dummy1 = stack; }
     MomentumVector plab = MomentumVector(
         cs1, {P0, 0_eV, 0_eV}); // this is secret knowledge about setupStack
     setup::StackView& view = *viewPtr;
diff --git a/tests/stack/CMakeLists.txt b/tests/stack/CMakeLists.txt
index 17305b6a4dbbf330c8a28a6bb11e6a771a52858a..58aa2b3025ea50c492d7cba79e6d3f9749277e59 100644
--- a/tests/stack/CMakeLists.txt
+++ b/tests/stack/CMakeLists.txt
@@ -1,7 +1,7 @@
 set (test_stack_sources
   TestMain.cpp
   testHistoryStack.cpp
-  testHistoryView.cpp
+#  testHistoryView.cpp
   testGeometryNodeStackExtension.cpp
   testWeightStackExtension.cpp
   testDummyStack.cpp
diff --git a/tests/stack/testNuclearStackExtension.cpp b/tests/stack/testNuclearStackExtension.cpp
index 198fe7da953b8f7567e733501280f89ed7f71d6e..98727de42d47a31426877c35224782b675077107 100644
--- a/tests/stack/testNuclearStackExtension.cpp
+++ b/tests/stack/testNuclearStackExtension.cpp
@@ -77,6 +77,11 @@ TEST_CASE("NuclearStackExtension", "stack") {
     CHECK(pout.getTime() == 100_s);
     CHECK(pout.getNuclearA() == 10);
     CHECK(pout.getNuclearZ() == 9);
+
+    // -> set to rest
+    auto pout_mod = s.begin();
+    pout_mod.setMomentum(MomentumVector{dummyCS, {0_GeV, 0_GeV, 0_GeV}});
+    CHECK(pout_mod.getKineticEnergy() / 1_GeV == Approx(0));
   }
 
   SECTION("read invalid nucleus") {
@@ -181,6 +186,9 @@ TEST_CASE("NuclearStackExtension", "stack") {
       CHECK(p79.getTime() == 100_s);
     }
 
+    // invalid copy
+    { CHECK_THROWS(s.copy(s.begin(), s.end() + 1000)); }
+
     // swap
     {
       s.swap(s.begin() + 11, s.begin() + 10);
@@ -227,8 +235,7 @@ TEST_CASE("NuclearStackExtension", "stack") {
                                          nuclear_stack::ExtendedParticleInterfaceType>
         s;
 
-    // not valid, no A,Z:
-    // not valid, no A,Z:
+    // not valid, no A,Z (implicit A=Z=0):
     CHECK_THROWS(s.addParticle(
         std::make_tuple(Code::Nucleus, 100_GeV, DirectionVector(dummyCS, {1, 0, 0}),
                         Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s)));
@@ -236,20 +243,40 @@ TEST_CASE("NuclearStackExtension", "stack") {
         std::make_tuple(Code::Nucleus, MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}),
                         Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s)));
 
-    // not valid:
+    // not valid, non-Code::Nuclei with A and Z
     CHECK_THROWS(s.addParticle(std::make_tuple(
         Code::Oxygen, MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}),
-        Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s, 16, 8)));
+        Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s, 20, 10)));
+
+    // not valid, non-Code::Nuclei with A and Z
+    CHECK_THROWS(s.addParticle(std::make_tuple(
+        Code::Oxygen, 100_GeV, DirectionVector(dummyCS, {0, 0, 1}),
+        Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s, 20, 10)));
+
+    // valid, non-Nucleus with implicit A=Z=0
+    s.addParticle(
+        std::make_tuple(Code::Proton, MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}),
+                        Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s));
 
-    // valid
+    // valid, for further use
     auto particle = s.addParticle(
         std::make_tuple(Code::Nucleus, MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}),
-                        Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s, 10, 9));
+                        Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s, 10, 5));
 
-    // not valid
+    // not valid, Oxygen, but A and Z
     CHECK_THROWS(particle.addSecondary(std::make_tuple(
         Code::Oxygen, MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}),
-        Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s, 16, 8)));
+        Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s, 20, 10)));
+
+    // not valid, Nucleus, no A, Z
+    CHECK_THROWS(particle.addSecondary(
+        std::make_tuple(Code::Nucleus, MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}),
+                        Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s)));
+
+    // not valid, Nucleus, no A, Z, and Energy
+    CHECK_THROWS(particle.addSecondary(
+        std::make_tuple(Code::Nucleus, 100_GeV, DirectionVector(dummyCS, {1, 0, 0}),
+                        Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s)));
 
     // add a another nucleus, so there are two now
     s.addParticle(