From 8c6ecc16ab8287a50dbb7ef10eac2521017daf13 Mon Sep 17 00:00:00 2001 From: ralfulrich <ralf.ulrich@kit.edu> Date: Wed, 16 Sep 2020 15:11:08 +0200 Subject: [PATCH] various changes towards history stack --- Framework/Cascade/History.h | 8 +++ Framework/Cascade/testCascade.h | 2 +- Framework/StackInterface/SecondaryView.h | 3 +- .../TrackingLine/testTrackingLineStack.h | 2 +- Setup/SetupStack.h | 28 +++++--- Stack/DummyStack/DummyStack.h | 27 ++++---- Stack/DummyStack/testDummyStack.cc | 11 ++-- .../GeometryNodeStackExtension.h | 11 ++-- .../testGeometryNodeStackExtension.cc | 50 +++++++------- Stack/History/CMakeLists.txt | 5 ++ Stack/History/Event.hpp | 34 ++++++++++ Stack/History/HStackView.hpp | 39 +++++++++++ Stack/History/HistoryStackExtension.h | 65 ++++++++++--------- Stack/History/SecondaryParticle.hpp | 38 +++++++++++ Stack/History/testHistory.cc | 15 ++++- Stack/SuperStupidStack/SuperStupidStack.h | 4 +- 16 files changed, 242 insertions(+), 100 deletions(-) create mode 100644 Stack/History/Event.hpp create mode 100644 Stack/History/HStackView.hpp create mode 100644 Stack/History/SecondaryParticle.hpp diff --git a/Framework/Cascade/History.h b/Framework/Cascade/History.h index 235767cb9..530e5917a 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 286318452..b876107de 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 077e56ea2..546ae571a 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 52955a816..d727064eb 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 b4c99c339..aeef45dce 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 5f584b016..8427475ab 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 64195ef65..179527055 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 16b9e02d6..d33997b8e 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 f637540b6..bad486425 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 5bf3be2b0..8b327411f 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 000000000..82d949a7b --- /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 000000000..c5a7e1048 --- /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 cfd5515d6..d12632d9e 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 000000000..319eeaa24 --- /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 5dd6faf2b..468ca6415 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 c3b755bbb..7c88628b6 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 -- GitLab