From 2d1bbeb6d0e676c797eefb62b51ea12c36b32438 Mon Sep 17 00:00:00 2001 From: ralfulrich <ralf.ulrich@kit.edu> Date: Sun, 20 Sep 2020 12:48:18 +0200 Subject: [PATCH] history works now, in principle and mostly, see testHistoryView --- Framework/StackInterface/SecondaryView.h | 4 +- Stack/History/CMakeLists.txt | 12 +-- Stack/History/Event.hpp | 33 ++++-- Stack/History/HSecondaryView.hpp | 51 --------- Stack/History/HistorySecondaryView.hpp | 72 +++++++++++++ Stack/History/testHistoryView.cc | 129 ++++++++++++++++++++--- 6 files changed, 221 insertions(+), 80 deletions(-) delete mode 100644 Stack/History/HSecondaryView.hpp create mode 100644 Stack/History/HistorySecondaryView.hpp diff --git a/Framework/StackInterface/SecondaryView.h b/Framework/StackInterface/SecondaryView.h index dc7d33ae7..4a33b404c 100644 --- a/Framework/StackInterface/SecondaryView.h +++ b/Framework/StackInterface/SecondaryView.h @@ -126,13 +126,13 @@ namespace corsika::stack { } template <typename... Args> - auto AddSecondary(const Args... v) { + StackIterator AddSecondary(const Args... v) { StackIterator proj = GetProjectile(); return AddSecondary(proj, v...); } template <typename... Args> - auto AddSecondary(StackIterator& proj, const Args... v) { + StackIterator AddSecondary(StackIterator& proj, const Args... v) { // make space on stack InnerStackType::GetStackData().IncrementSize(); innerstack_.deleted_.push_back(false); diff --git a/Stack/History/CMakeLists.txt b/Stack/History/CMakeLists.txt index d2ca77365..9d0365b2d 100644 --- a/Stack/History/CMakeLists.txt +++ b/Stack/History/CMakeLists.txt @@ -1,18 +1,18 @@ set ( - SETUP_HEADERS + HISTORY_HEADERS Event.hpp - HSecondaryView.hpp + HistorySecondaryView.hpp HistoryStackExtension.h SecondaryParticle.hpp ) set ( - SETUP_NAMESPACE + HISTORY_NAMESPACE corsika/history ) add_library (CORSIKAhistory INTERFACE) -CORSIKA_COPY_HEADERS_TO_NAMESPACE (CORSIKAhistory ${SETUP_NAMESPACE} ${SETUP_HEADERS}) +CORSIKA_COPY_HEADERS_TO_NAMESPACE (CORSIKAhistory ${HISTORY_NAMESPACE} ${HISTORY_HEADERS}) target_link_libraries ( CORSIKAhistory @@ -31,8 +31,8 @@ target_include_directories ( ) install ( - FILES ${SETUP_HEADERS} - DESTINATION include/${SETUP_NAMESPACE} + FILES ${HISTORY_HEADERS} + DESTINATION include/${HISTORY_NAMESPACE} ) # ---------------- diff --git a/Stack/History/Event.hpp b/Stack/History/Event.hpp index be8d72d4e..6adc08ddc 100644 --- a/Stack/History/Event.hpp +++ b/Stack/History/Event.hpp @@ -18,31 +18,46 @@ namespace corsika::history { - struct Event { - size_t const projectileIndex_; //!< reference to projectile + class Event; + using EvtPtr = std::shared_ptr<history::Event>; + + class Event { + + size_t projectileIndex_ = 0; //!< reference to projectile (for secondaries_) std::vector<SecondaryParticle> secondaries_; - //std::shared_ptr<Event> parent_event_; + EvtPtr parent_event_; + size_t sec_index_ = 0; - // 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(const size_t projectileIndex) - : projectileIndex_{projectileIndex} { - std::cout << "Event created (index = " << projectileIndex_ << ")" << std::endl; + Event() = default; + + void setParentEventAndSecondaryIndex(EvtPtr& evt, size_t sec_index) { + parent_event_ = evt; + sec_index_ = sec_index; // this is the index of the projectile + // of this Event in the parent_event_; } + + EvtPtr parentEvent() { return parent_event_; } + + void setProjectileIndex(size_t i) { projectileIndex_=i; } + size_t projectileIndex() const { return projectileIndex_; } + + template<typename TStackIterator> + TStackIterator projectile(TStackIterator begin) { return begin+projectileIndex_; } void addSecondary(units::si::HEPEnergyType energy, geometry::Vector<units::si::hepmomentum_d> momentum, particles::Code pid) { secondaries_.emplace_back(energy, momentum, pid); } + std::vector<SecondaryParticle>& secondaries() { return secondaries_; } void setTargetCode(const particles::Code t) { targetCode_=t; } + }; - - using EvtPtr = std::shared_ptr<history::Event>; } // namespace corsika::history diff --git a/Stack/History/HSecondaryView.hpp b/Stack/History/HSecondaryView.hpp deleted file mode 100644 index 4552cc2df..000000000 --- a/Stack/History/HSecondaryView.hpp +++ /dev/null @@ -1,51 +0,0 @@ -/* - * (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/SecondaryView.h> -#include <corsika/history/Event.hpp> - -#include <memory> -#include <type_traits> -#include <utility> - -namespace corsika::history { - - template <typename TView> - class HSecondaryView : public TView { - - std::shared_ptr<Event> event_; - - using StackIterator = typename TView::StackIteratorValue; - - public: - HSecondaryView(StackIterator& p) - : TView(p), - event_{std::make_shared<Event>(p.GetIndex())} { - p.SetEvent(event_); // here an entry on the main particle stack obtains its Event - // RU: what seems to missing to me right now, at 2am..., is the - // actual back reference to the parent event. This needs to be added. - } - - template <typename... Args> - void AddSecondary(Args&&... args) { - auto s = TView::AddSecondary( - std::forward<Args...>(args...)); - // store particles at production time here - // RU: consider if we can call - // TView::AddSecondary twice instead: 1. for particle at production time - // , 2. dynamic particle ... not sure, but would be extremely flexible. - event_->addSecondary(s.GetEnergy(), s.GetMomentum(), s.GetPID()); - } - - // it is probably better to have one method "GetEvent()" and then one can always call GetEvent().set/getWhatever(...) - void SetTarget(const particles::Code targetCode) { event_->setTargetCode(targetCode); } - }; - -} // namespace corsika::history diff --git a/Stack/History/HistorySecondaryView.hpp b/Stack/History/HistorySecondaryView.hpp new file mode 100644 index 000000000..16603e948 --- /dev/null +++ b/Stack/History/HistorySecondaryView.hpp @@ -0,0 +1,72 @@ +/* + * (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/SecondaryView.h> +#include <corsika/history/Event.hpp> + +#include <memory> +#include <type_traits> +#include <utility> + +namespace corsika::history { + + template <typename TView> + class HistorySecondaryView : public TView { + + EvtPtr event_; + + using StackIteratorValue = typename TView::StackIteratorValue; + using StackIterator = typename TView::StackIterator; + + public: + HistorySecondaryView(StackIteratorValue& p) + : TView(p) + , event_{p.GetEvent()} { + if (event_ == nullptr) { + // aha, this particle has no [registered] anchestor + // thus, create Event here: + p.SetEvent(std::make_shared<Event>()); + std::cout << "Event created for index=" << p.GetIndex() << std::endl; + event_ = p.GetEvent(); + } + event_->setProjectileIndex(p.GetIndex()); + // event_{std::make_shared<Event>(p.GetIndex())} { + // p.SetEvent(event_); // here an entry on the main particle stack obtains its Event + // RU: what seems to missing to me right now, at 2am..., is the + // actual back reference to the parent event. This needs to be added. + } + + template <typename... Args> + StackIterator AddSecondary(Args&&... args) { + auto sec = TView::AddSecondary(std::forward<Args...>(args...)); + // generate new Event for all secondaries to link them to + // anchestor (aka projectile, here). + auto sec_event = std::make_shared<Event>(); + sec_event->setParentEventAndSecondaryIndex(event_, event_->secondaries().size()); + sec.SetEvent(sec_event); + + // store particles at production time in parent/projectile Event here + event_->addSecondary(sec.GetEnergy(), sec.GetMomentum(), sec.GetPID()); + + // RU: consider if we can call + // TView::AddSecondary twice instead: 1. for particle at production time + // , 2. dynamic particle ... not sure, but would be extremely flexible. + + return sec; + } + + // it is probably better to have one method "GetEvent()" and then one can always call + // GetEvent().set/getWhatever(...) + void SetTarget(const particles::Code targetCode) { + event_->setTargetCode(targetCode); + } + }; + +} // namespace corsika::history diff --git a/Stack/History/testHistoryView.cc b/Stack/History/testHistoryView.cc index 673921696..1eb9efe14 100644 --- a/Stack/History/testHistoryView.cc +++ b/Stack/History/testHistoryView.cc @@ -8,7 +8,7 @@ #include <corsika/history/HistoryStackExtension.h> #include <corsika/history/Event.hpp> -#include <corsika/history/HSecondaryView.hpp> +#include <corsika/history/HistorySecondaryView.hpp> #include <corsika/stack/CombinedStack.h> #include <corsika/stack/dummy/DummyStack.h> @@ -66,41 +66,146 @@ TEST_CASE("HistoryStackExtension", "[stack]") { geometry::CoordinateSystem& dummyCS = geometry::RootCoordinateSystem::GetInstance().GetRootCoordinateSystem(); + // in this test we only use one singel stack ! TestStack s; - SECTION("add lone particle") { + // add primary particle + auto p0 = 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}); - auto p = s.AddParticle( + CHECK(s.getEntries() == 1); + corsika::history::EvtPtr evt = p0.GetEvent(); + CHECK(evt == nullptr); + + // add secondaries, 1st generation + history::HistorySecondaryView<TestStackView> hview0(p0); + + auto ev0 = p0.GetEvent(); + CHECK(ev0 != nullptr); + // CHECK(ev0->projectile(s.begin()) == p0); + + // add 5 secondaries + for (int i = 0; i < 5; ++i) { + auto sec = hview0.AddSecondary( + 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}); + + CHECK(sec.GetEvent()->parentEvent() == ev0); + CHECK(sec.GetEvent()->parentEvent()->parentEvent() == nullptr); + } + + // read 1st genertion particle particle + auto p1 = s.GetNextParticle(); + + history::HistorySecondaryView<TestStackView> hview1(p1); + + auto ev1 = p1.GetEvent(); + + // add second generation of secondaries + // add 10 secondaries + for (int i = 0; i < 10; ++i) { + auto sec = hview1.AddSecondary( 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}); - CHECK(s.GetSize() == 1); - corsika::history::EvtPtr evt = p.GetEvent(); - CHECK(evt == nullptr); + CHECK(sec.GetEvent()->parentEvent() == ev1); + CHECK(sec.GetEvent()->parentEvent()->parentEvent() == ev0); + CHECK(sec.GetEvent()->parentEvent()->parentEvent()->parentEvent() == nullptr); } - SECTION("generate event") { - auto p = s.AddParticle( + // read 2nd genertion particle particle + auto p2 = s.GetNextParticle(); + + history::HistorySecondaryView<TestStackView> hview2(p2); + + auto ev2 = p2.GetEvent(); + + // add third generation of secondaries + // add 15 secondaries + for (int i = 0; i < 15; ++i) { + auto sec = hview2.AddSecondary( 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}); - history::HSecondaryView<TestStackView> hview(p); + CHECK(sec.GetEvent()->parentEvent() == ev2); + CHECK(sec.GetEvent()->parentEvent()->parentEvent() == ev1); + CHECK(sec.GetEvent()->parentEvent()->parentEvent()->parentEvent() == ev0); + CHECK(sec.GetEvent()->parentEvent()->parentEvent()->parentEvent()->parentEvent() == + nullptr); + } + + // read 3rd genertion particle particle + auto p3 = s.GetNextParticle(); + + history::HistorySecondaryView<TestStackView> hview3(p3); + + auto ev3 = p3.GetEvent(); - hview.AddSecondary( + // add fourth generation of secondaries + // add 20 secondaries + for (int i = 0; i < 20; ++i) { + auto sec = hview3.AddSecondary( 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}); - // ... continue actual real test here an below ... + CHECK(sec.GetEvent()->parentEvent() == ev3); + CHECK(sec.GetEvent()->parentEvent()->parentEvent() == ev2); + CHECK(sec.GetEvent()->parentEvent()->parentEvent()->parentEvent() == ev1); + CHECK(sec.GetEvent()->parentEvent()->parentEvent()->parentEvent()->parentEvent() == + ev0); + CHECK(sec.GetEvent() + ->parentEvent() + ->parentEvent() + ->parentEvent() + ->parentEvent() + ->parentEvent() == nullptr); } - // REQUIRE(pout.GetPID() == particles::Code::Electron); + /* + Now, let's perform some history reading and checking based on p3 + + p3 should have 20 secondaries, and a projectile (with 15 + secondaries), with another projectil (with 10 secondaries), with + antother projectil (5 secondaries), with NO parent + + **/ + { + auto test_ev3 = p3.GetEvent(); + auto test_sec3 = test_ev3->secondaries(); + CHECK(test_sec3.size() == 20); + + auto test_proj3 = test_ev3->projectile(s.begin()); + CHECK(test_proj3.GetEvent() == ev3); + auto test_ev2 = test_ev3->parentEvent(); + auto test_sec2 = test_ev2->secondaries(); + CHECK(test_sec2.size() == 15); + + auto test_proj2 = test_ev2->projectile(s.begin()); + CHECK(test_proj2.GetEvent() == ev2); + auto test_ev1 = test_ev2->parentEvent(); + auto test_sec1 = test_ev1->secondaries(); + CHECK(test_sec1.size() == 10); + + auto test_proj1 = test_ev1->projectile(s.begin()); + CHECK(test_proj1.GetEvent() == ev1); + + CHECK(test_proj1.GetEvent()->parentEvent() == ev0); + CHECK(test_proj1.GetEvent()->parentEvent()->parentEvent() == nullptr); + } } -- GitLab