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