diff --git a/Framework/Cascade/History.h b/Framework/Cascade/History.h index 235767cb9a6338ed638f82d1a39e374cd4a8e589..530e5917a4fa0878d3757b20222f53d596399b6b 100644 --- a/Framework/Cascade/History.h +++ b/Framework/Cascade/History.h @@ -1,3 +1,11 @@ +/* + * (c) Copyright 2020 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 <memory> #include <utility> #include <variant> diff --git a/Framework/Cascade/testCascade.h b/Framework/Cascade/testCascade.h index 286318452b3764fb477ee37f9c254b9fa473a096..b876107dea8849a342630c300437d81506636b12 100644 --- a/Framework/Cascade/testCascade.h +++ b/Framework/Cascade/testCascade.h @@ -10,9 +10,9 @@ #include <corsika/environment/Environment.h> +#include <corsika/stack/CombinedStack.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>; diff --git a/Framework/StackInterface/SecondaryView.h b/Framework/StackInterface/SecondaryView.h index 077e56ea2dff557ac0c7f43dc7f9446a2fa0caaf..546ae571a317c4ec151f8cc23fd34a27fbf44f24 100644 --- a/Framework/StackInterface/SecondaryView.h +++ b/Framework/StackInterface/SecondaryView.h @@ -70,12 +70,13 @@ namespace corsika::stack { * @{ */ using InnerStackTypeValue = Stack<StackDataType, ParticleInterface>; + + public: using StackIteratorValue = StackIteratorInterface<typename std::remove_reference<StackDataType>::type, ParticleInterface, InnerStackTypeValue>; /// @} - public: using StackIterator = StackIteratorInterface<typename std::remove_reference<StackDataType>::type, ParticleInterface, ViewType>; diff --git a/Processes/TrackingLine/testTrackingLineStack.h b/Processes/TrackingLine/testTrackingLineStack.h index 52955a8163bde6a8ef3c372767b34fb1acc0daa1..d727064eb10655ac9f91bfe1902d6e9147bfde58 100644 --- a/Processes/TrackingLine/testTrackingLineStack.h +++ b/Processes/TrackingLine/testTrackingLineStack.h @@ -15,9 +15,9 @@ #include <corsika/particles/ParticleProperties.h> +#include <corsika/stack/CombinedStack.h> #include <corsika/stack/node/GeometryNodeStackExtension.h> #include <corsika/stack/nuclear_extension/NuclearStackExtension.h> -#include <corsika/stack/CombinedStack.h> #include <corsika/units/PhysicalUnits.h> diff --git a/Setup/SetupStack.h b/Setup/SetupStack.h index b4c99c3393fefbcbae7c402ef396b698dc905ac1..aeef45dce69311652f97d12d07a299c227a5d8cf 100644 --- a/Setup/SetupStack.h +++ b/Setup/SetupStack.h @@ -8,11 +8,10 @@ #pragma once +#include <corsika/stack/CombinedStack.h> #include <corsika/stack/node/GeometryNodeStackExtension.h> #include <corsika/stack/nuclear_extension/NuclearStackExtension.h> -//#include <corsika/history/HistoryStackExtension.h> - -#include <corsika/stack/CombinedStack.h> +#include <corsika/history/HistoryStackExtension.h> #include <corsika/setup/SetupEnvironment.h> @@ -20,15 +19,26 @@ namespace corsika::setup { namespace detail { - // the GeometryNode stack needs to know the type of geometry-nodes from the environment: + // 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; + using SetupGeometryDataInterface = + typename stack::node::MakeGeometryDataInterface<TStackIter, + setup::SetupEnvironment>::type; + + /* + template <typename TStackIter> + using SetupGeometryHistoryDataInterface = + typename stack::node::MakeHistoryDataInterface<TStackIter, + ...event... >::type; + */ + // combine particle data stack with geometry information for tracking template <typename TStackIter> using StackWithGeometryInterface = corsika::stack::CombinedParticleInterface< - stack::nuclear_extension::ParticleDataStack::PIType, - SetupGeometryDataInterface, TStackIter>; + stack::nuclear_extension::ParticleDataStack::PIType, SetupGeometryDataInterface, + TStackIter>; using StackWithGeometry = corsika::stack::CombinedStack< typename corsika::stack::nuclear_extension::ParticleDataStack::StackImpl, @@ -54,8 +64,8 @@ namespace corsika::setup { #if defined(__clang__) using StackView = corsika::stack::SecondaryView<typename corsika::setup::Stack::StackImpl, - // CHECK with CLANG: corsika::setup::Stack::PIType>; - 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/DummyStack/DummyStack.h b/Stack/DummyStack/DummyStack.h index 5f584b016bb819346d7e98062f178292f3d3cf52..8427475abd443584c74362716c956bdb9eb98261 100644 --- a/Stack/DummyStack/DummyStack.h +++ b/Stack/DummyStack/DummyStack.h @@ -23,14 +23,18 @@ namespace corsika::stack { */ /** - however, conceptually we need to provide fake data. A stack without data does not work... + however, conceptually we need to provide fake data. A stack without data does not + work... */ - struct NoData {/* nothing */ int nothing=0; }; - + struct NoData { /* nothing */ + int nothing = 0; + }; + template <typename StackIteratorInterface> - class ParticleInterface : public corsika::stack::ParticleBase<StackIteratorInterface> { - + class ParticleInterface + : public corsika::stack::ParticleBase<StackIteratorInterface> { + protected: using corsika::stack::ParticleBase<StackIteratorInterface>::GetStack; using corsika::stack::ParticleBase<StackIteratorInterface>::GetStackData; @@ -40,7 +44,8 @@ namespace corsika::stack { public: void SetParticleData(const std::tuple<NoData>& /*v*/) {} - void SetParticleData(ParticleInterface<StackIteratorInterface>& /*parent*/, const std::tuple<NoData>& /*v*/) {} + void SetParticleData(ParticleInterface<StackIteratorInterface>& /*parent*/, + const std::tuple<NoData>& /*v*/) {} }; /** @@ -51,9 +56,9 @@ namespace corsika::stack { class DummyStackImpl { public: - void Init() {entries_=0;} + void Init() { entries_ = 0; } - void Clear() {entries_=0;} + void Clear() { entries_ = 0; } int GetSize() const { return entries_; } int GetCapacity() const { return entries_; } @@ -63,12 +68,12 @@ namespace corsika::stack { */ void Copy(const int /*i1*/, const int /*i2*/) {} - void IncrementSize() {entries_++;} - void DecrementSize() {entries_--;} + void IncrementSize() { entries_++; } + void DecrementSize() { entries_--; } private: int entries_ = 0; - + }; // end class DummyStackImpl typedef Stack<DummyStackImpl, ParticleInterface> DummyStack; diff --git a/Stack/DummyStack/testDummyStack.cc b/Stack/DummyStack/testDummyStack.cc index 64195ef65b48d72fde7ff0119396a1b43cbca8f2..17952705507b87ccc1a4ece0e9fecb39a0656a4d 100644 --- a/Stack/DummyStack/testDummyStack.cc +++ b/Stack/DummyStack/testDummyStack.cc @@ -20,7 +20,7 @@ TEST_CASE("DummyStack", "[stack]") { using TestStack = dummy::DummyStack; dummy::NoData noData; - + SECTION("write node") { TestStack s; @@ -28,17 +28,14 @@ TEST_CASE("DummyStack", "[stack]") { 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}); - } - + 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/GeometryNodeStackExtension.h b/Stack/GeometryNodeStackExtension/GeometryNodeStackExtension.h index 16b9e02d69bb3b6cc6a424f7d87afcaead9734de..d33997b8eecddca3d53be9fd4f1f7b1b95ad4835 100644 --- a/Stack/GeometryNodeStackExtension/GeometryNodeStackExtension.h +++ b/Stack/GeometryNodeStackExtension/GeometryNodeStackExtension.h @@ -36,7 +36,7 @@ namespace corsika::stack::node { using T::GetIndex; using BaseNodeType = typename TEnvType::BaseNodeType; - public: + public: // default version for particle-creation from input data void SetParticleData(const std::tuple<BaseNodeType const*> v) { SetNode(std::get<0>(v)); @@ -56,8 +56,6 @@ namespace corsika::stack::node { BaseNodeType const* GetNode() const { return GetStackData().GetNode(GetIndex()); } }; - - // definition of stack-data object to store geometry information template <typename TEnvType> @@ -93,10 +91,9 @@ 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 index f637540b6c7d6a6fc3e9c4c587a239cf7d3b620b..bad4864254345c980cd02e19c840cbd5eb29fe77 100644 --- a/Stack/GeometryNodeStackExtension/testGeometryNodeStackExtension.cc +++ b/Stack/GeometryNodeStackExtension/testGeometryNodeStackExtension.cc @@ -6,9 +6,9 @@ * the license. */ -#include <corsika/stack/node/GeometryNodeStackExtension.h> -#include <corsika/stack/dummy/DummyStack.h> #include <corsika/stack/CombinedStack.h> +#include <corsika/stack/dummy/DummyStack.h> +#include <corsika/stack/node/GeometryNodeStackExtension.h> using namespace corsika; using namespace corsika::stack; @@ -26,19 +26,19 @@ public: // the GeometryNode stack needs to know the type of geometry-nodes from the DummyEnv: template <typename TStackIter> -using DummyGeometryDataInterface = typename corsika::stack::node::MakeGeometryDataInterface<TStackIter, DummyEnv>::type; +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>; +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]") { @@ -47,25 +47,21 @@ TEST_CASE("GeometryNodeStackExtension", "[stack]") { SECTION("write node") { const int data = 5; - + TestStack s; - s.AddParticle( - std::tuple<dummy::NoData>{ - noData}, std::tuple<const int*>{&data}); - + 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}); + 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); } @@ -77,12 +73,10 @@ TEST_CASE("GeometryNodeStackExtension", "[stack]") { TestStack s; // add 99 particles, each 10th particle is a nucleus with A=i and Z=A/2! for (int i = 0; i < 99; ++i) { - auto p = s.AddParticle( - std::tuple<dummy::NoData>{ - noData}); + 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) { @@ -90,7 +84,7 @@ TEST_CASE("GeometryNodeStackExtension", "[stack]") { v += *(p.GetNode()); p.Delete(); } - CHECK(v == 99*data); - CHECK(s.GetSize() == 0); - } + CHECK(v == 99 * data); + CHECK(s.GetSize() == 0); + } } diff --git a/Stack/History/CMakeLists.txt b/Stack/History/CMakeLists.txt index 5bf3be2b074b3886151ffe3c4127b7ec7bef1423..8b327411f1a2885333e251cf56ef35c059b255e2 100644 --- a/Stack/History/CMakeLists.txt +++ b/Stack/History/CMakeLists.txt @@ -1,6 +1,9 @@ set ( SETUP_HEADERS + Event.hpp + HStackView.hpp HistoryStackExtension.h + SecondaryParticle.hpp ) set ( @@ -14,6 +17,8 @@ CORSIKA_COPY_HEADERS_TO_NAMESPACE (CORSIKAhistory ${SETUP_NAMESPACE} ${SETUP_HEA target_link_libraries ( CORSIKAhistory INTERFACE + CORSIKAparticles + CORSIKAgeometry SuperStupidStack NuclearStackExtension ) diff --git a/Stack/History/Event.hpp b/Stack/History/Event.hpp new file mode 100644 index 0000000000000000000000000000000000000000..82d949a7be94c72edee3fd0f5927990b50bdd6c0 --- /dev/null +++ b/Stack/History/Event.hpp @@ -0,0 +1,34 @@ +/* + * (c) Copyright 2020 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/particles/ParticleProperties.h> +#include <corsika/stack/Stack.h> +#include <corsika/history/SecondaryParticle.hpp> + +#include <optional> +#include <vector> + +namespace corsika::history { + + template <typename TStackIterator> + class Event { + TStackIterator const projectile_; //!< reference to projectile + std::vector<SecondaryParticle> secondaries; + + // meta information, could also be in a separate class + std::optional<corsika::particles::Code> + targetCode; // cannot be const, value set only after construction + + public: + Event(TStackIterator projectile) + : projectile_{projectile} {} + }; + +} // namespace corsika::history diff --git a/Stack/History/HStackView.hpp b/Stack/History/HStackView.hpp new file mode 100644 index 0000000000000000000000000000000000000000..c5a7e104829f082ac8459476a75dc74f6bd3040c --- /dev/null +++ b/Stack/History/HStackView.hpp @@ -0,0 +1,39 @@ +/* + * (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 + +#include <corsika/stack/history/Event.hpp> + +#include <memory> + +namespace corsika::history { + + template <typename TStackView> + class HStackView : public TStackView { + std::shared_ptr<Event<typename TStackView::StackIteratorValue>> event_; + + public: + template <typename... Args> + EventBuilder(Args&&... args) + : TStackView{std::forward<Args>(args)} + , event_{std::make_shared<Event>()} {} + + template <typename... Args> + void AddSecondary(Args&&... args) { + auto const s = TStackView::AddSecondary( + std::forward<Args>(args), event_); // what if event is not last argument? + event_->secondaries.emplace_back(s.GetEnergy(), s.GetMomentum(), s.GetParticleID()); + } + + void SetTarget(corsika::particles::ParticleCode targetCode) { + event_->targetCode = targetCode; + } + }; + +} // namespace corsika::history diff --git a/Stack/History/HistoryStackExtension.h b/Stack/History/HistoryStackExtension.h index cfd5515d6b58e9e909ffe559f086d43bd95d2161..d12632d9e28a4c556794c48cc3859342ae89defb 100644 --- a/Stack/History/HistoryStackExtension.h +++ b/Stack/History/HistoryStackExtension.h @@ -1,5 +1,5 @@ /* - * (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu + * (c) Copyright 2020 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 @@ -9,10 +9,11 @@ #pragma once #include <corsika/stack/Stack.h> +#include <corsika/history/Event.hpp> +#include <memory> #include <tuple> #include <vector> -#include <memory> namespace corsika::history { @@ -28,26 +29,27 @@ namespace corsika::history { 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]); } + void Clear() { event_.clear(); } + unsigned int GetSize() const { return event_.size(); } + unsigned int GetCapacity() const { return event_.size(); } + void Copy(const int i1, const int i2) { event_[i2] = event_[i1]; } + void Swap(const int i1, const int i2) { std::swap(event_[i1], event_[i2]); } // custom data access function - void SetEvent(const int i, std::shared_ptr<TEvent> v) { fEvent[i] = v; } - std::shared_ptr<TEvent> GetEvent(const int i) const { return fEvent[i]; } + void SetEvent(const int i, std::shared_ptr<TEvent> v) { event_[i] = std::move(v); } + std::shared_ptr<TEvent> GetEvent(const int i) const { return event_[i]; } // these functions are also needed by the Stack interface - void IncrementSize() { fEvent.push_back(nullptr); } + void IncrementSize() { event_.push_back(nullptr); } void DecrementSize() { - if (fEvent.size() > 0) { fEvent.pop_back(); } + if (event_.size() > 0) { event_.pop_back(); } } // custom private data section private: - std::vector<std::shared_ptr<TEvent>> fEvent; + std::vector<std::shared_ptr<TEvent>> event_; }; + /** * @class HistoryDataInterface @@ -59,34 +61,33 @@ namespace corsika::history { */ template <typename T, typename TEvent> class HistoryDataInterface : public T { - protected: - using T::GetStack; - using T::GetStackData; + protected: + using T::GetStack; + using T::GetStackData; - public: - using T::GetIndex; + public: + using T::GetIndex; public: - // default version for particle-creation from input data - void SetParticleData(const std::tuple<TEvent const*> v) { SetEvent(std::get<0>(v)); } - void SetParticleData(HistoryDataInterface& parent, - const std::tuple<std::shared_ptr<TEvent>>) { - SetEvent(parent.GetEvent()); // copy Event from parent particle! - } - void SetParticleData() { SetEvent(nullptr); } + + // create a new particle from scratch + void SetParticleData() { } // nullptr, already by design + + // create a new particle as secondary of a parent void SetParticleData(HistoryDataInterface& parent) { - SetEvent(parent.GetEvent()); // copy Event from parent particle! + SetEvent(std::make_shared<TEvent>(parent.GetEvent())); + GetEvent().getParent().addSecondary(GetEvent()); } - void SetEvent(std::shared_ptr<TEvent> v) { GetStackData().SetEvent(GetIndex(), v); } + + void SetEvent(const std::shared_ptr<TEvent>& v) { GetStackData().SetEvent(GetIndex(), v); } std::shared_ptr<TEvent> GetEvent() const { return GetStackData().GetEvent(GetIndex()); } }; - + template <typename T, typename TEvent> - struct MakeHistoryDataInterface { - typedef HistoryDataInterface<T, TEvent> type; - }; - - + struct MakeHistoryDataInterface { + typedef HistoryDataInterface<T, TEvent> type; + }; + } // namespace corsika::history diff --git a/Stack/History/SecondaryParticle.hpp b/Stack/History/SecondaryParticle.hpp new file mode 100644 index 0000000000000000000000000000000000000000..319eeaa2484b63f00a0a461cdee5fbf662535579 --- /dev/null +++ b/Stack/History/SecondaryParticle.hpp @@ -0,0 +1,38 @@ +/* + * (c) Copyright 2020 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/geometry/Vector.h> +#include <corsika/particles/ParticleProperties.h> +#include <corsika/units/PhysicalUnits.h> + +#include <vector> + +namespace corsika::history { + + /** + * This class stores the non-common properties of secondaries in an event. All + * other (common) properties are available via the event itself. + */ + class SecondaryParticle { + units::si::HEPEnergyType const energy_; + geometry::Vector<units::si::hepmomentum_d> const momentum_; + particles::Code const pid_; + + // what else...? + // - polarization? + + public: + SecondaryParticle(units::si::HEPEnergyType energy, geometry::Vector<units::si::hepmomentum_d> momentum, particles::Code pid) + : energy_{energy} + , momentum_{momentum} + , pid_{pid} {} + }; + +} // namespace corsika::history diff --git a/Stack/History/testHistory.cc b/Stack/History/testHistory.cc index 5dd6faf2bcd2179a2348b37c6f758ce72782d7ee..468ca6415a63e5e684bed13d658e986b4226c7ab 100644 --- a/Stack/History/testHistory.cc +++ b/Stack/History/testHistory.cc @@ -21,7 +21,20 @@ using namespace std; // this is our dummy environment, it only knows its trivial BaseNodeType class DummyEvent { public: - int id; + DummyEvent() {} + DummyEvent(const std::shared_ptr<DummyEvent>& parent) { + parent_ = parent; + //parent.addSecondary(); + } + + std::shared_ptr<DummyEvent> getParent() { return parent_; } + void addSecondary(const std::shared_ptr<DummyEvent>& particle) { secondaries_.push_back(particle); } + + int multiplicity() const { return secondaries_.size(); } + +private: + std::shared_ptr<DummyEvent> parent_; + std::vector<std::shared_ptr<DummyEvent>> secondaries_; }; // the GeometryNode stack needs to know the type of geometry-nodes from the DummyEnv: diff --git a/Stack/SuperStupidStack/SuperStupidStack.h b/Stack/SuperStupidStack/SuperStupidStack.h index c3b755bbbfb47f2a5717a84078cb18639d26a2f5..7c88628b6c95bd18f7654b2e5215e3f184d4f5c8 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 <vector> #include <tuple> +#include <vector> namespace corsika::stack { @@ -224,7 +224,7 @@ namespace corsika::stack { }; // end class SuperStupidStackImpl typedef Stack<SuperStupidStackImpl, ParticleInterface> SuperStupidStack; - + } // namespace super_stupid } // namespace corsika::stack