From df704e193fcf6cbab0d512ecded411ae19d05efa Mon Sep 17 00:00:00 2001 From: ralfulrich <ralf.ulrich@kit.edu> Date: Wed, 17 Feb 2021 10:23:27 +0100 Subject: [PATCH] added weights to stack --- corsika/detail/setup/SetupStack.hpp | 3 +- corsika/stack/GeometryNodeStackExtension.hpp | 2 +- corsika/stack/WeightStackExtension.hpp | 119 ++++++++++++++++++ tests/stack/CMakeLists.txt | 1 + .../stack/testGeometryNodeStackExtension.cpp | 2 +- tests/stack/testWeightStackExtension.cpp | 85 +++++++++++++ 6 files changed, 209 insertions(+), 3 deletions(-) create mode 100644 corsika/stack/WeightStackExtension.hpp create mode 100644 tests/stack/testWeightStackExtension.cpp diff --git a/corsika/detail/setup/SetupStack.hpp b/corsika/detail/setup/SetupStack.hpp index d31e940f6..6577b023f 100644 --- a/corsika/detail/setup/SetupStack.hpp +++ b/corsika/detail/setup/SetupStack.hpp @@ -11,6 +11,7 @@ #include <corsika/framework/stack/CombinedStack.hpp> #include <corsika/stack/GeometryNodeStackExtension.hpp> #include <corsika/stack/NuclearStackExtension.hpp> +#include <corsika/stack/WeightStackExtension.hpp> #include <corsika/stack/history/HistorySecondaryProducer.hpp> #include <corsika/stack/history/HistoryStackExtension.hpp> @@ -27,7 +28,7 @@ namespace corsika { // environment: template <typename TStackIter> using SetupGeometryDataInterface = - typename node::MakeGeometryDataInterface<TStackIter, setup::Environment>::type; + typename node::make_GeometryDataInterface<TStackIter, setup::Environment>::type; // combine particle data stack with geometry information for tracking template <typename TStackIter> diff --git a/corsika/stack/GeometryNodeStackExtension.hpp b/corsika/stack/GeometryNodeStackExtension.hpp index e7298bea4..9cd81cc77 100644 --- a/corsika/stack/GeometryNodeStackExtension.hpp +++ b/corsika/stack/GeometryNodeStackExtension.hpp @@ -117,7 +117,7 @@ namespace corsika::node { }; template <typename T, typename TEnv> - struct MakeGeometryDataInterface { + struct make_GeometryDataInterface { typedef GeometryDataInterface<T, TEnv> type; }; diff --git a/corsika/stack/WeightStackExtension.hpp b/corsika/stack/WeightStackExtension.hpp new file mode 100644 index 000000000..2cbcce482 --- /dev/null +++ b/corsika/stack/WeightStackExtension.hpp @@ -0,0 +1,119 @@ +/* + * (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/framework/core/Logging.hpp> +#include <corsika/framework/stack/Stack.hpp> + +#include <tuple> +#include <utility> +#include <vector> + +namespace corsika::weights { + + /** + * Describe "particle weights" on a Stack. + * + * 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 + */ + + /** + * \tparam TParentStack The stack to be exteneded here with weight data + */ + template <typename TParentStack> + struct WeightDataInterface : public TParentStack { + + typedef TParentStack super_type; + + public: + // default version for particle-creation from input data + void setParticleData(std::tuple<double> const v) { setWeight(std::get<0>(v)); } + void setParticleData(WeightDataInterface& parent, std::tuple<double> const) { + setWeight(parent.getWeight()); // copy Weight from parent particle! + } + void setParticleData() { setWeight(1); } // default weight + void setParticleData(WeightDataInterface& parent) { + setWeight(parent.getWeight()); // copy Weight from parent particle! + } + + std::string asString() const { + return fmt::format("weight={}", fmt::ptr(getWeight())); + } + + void setWeight(double const v) { + + super_type::getStackData().setWeight(super_type::getIndex(), v); + } + + double getWeight() const { + return super_type::getStackData().getWeight(super_type::getIndex()); + } + }; + + // definition of stack-data object to store geometry information + + /** + * @class WeightData + * + * definition of stack-data object to store geometry information + */ + class WeightData { + + public: + typedef std::vector<double> weight_vector_type; + + WeightData() = default; + + WeightData(WeightData const&) = default; + + WeightData(WeightData&&) = default; + + WeightData& operator=(WeightData const&) = default; + + WeightData& operator=(WeightData&&) = default; + + // these functions are needed for the Stack interface + void clear() { weight_vector_.clear(); } + + unsigned int getSize() const { return weight_vector_.size(); } + + unsigned int getCapacity() const { return weight_vector_.size(); } + + void copy(int const i1, int const i2) { weight_vector_[i2] = weight_vector_[i1]; } + + void swap(int const i1, int const i2) { + std::swap(weight_vector_[i1], weight_vector_[i2]); + } + + // custom data access function + void setWeight(int const i, double const v) { weight_vector_[i] = v; } + + double getWeight(int const i) const { return weight_vector_[i]; } + + // these functions are also needed by the Stack interface + void incrementSize() { weight_vector_.push_back(1); } // default weight + + void decrementSize() { + if (weight_vector_.size() > 0) { weight_vector_.pop_back(); } + } + + // custom private data section + private: + weight_vector_type weight_vector_; + }; + + template <typename TParentStack> + struct make_WeightDataInterface { + typedef WeightDataInterface<TParentStack> type; + }; + +} // namespace corsika::weights diff --git a/tests/stack/CMakeLists.txt b/tests/stack/CMakeLists.txt index 8fe1070f1..17305b6a4 100644 --- a/tests/stack/CMakeLists.txt +++ b/tests/stack/CMakeLists.txt @@ -3,6 +3,7 @@ set (test_stack_sources testHistoryStack.cpp testHistoryView.cpp testGeometryNodeStackExtension.cpp + testWeightStackExtension.cpp testDummyStack.cpp testVectorStack.cpp testNuclearStackExtension.cpp diff --git a/tests/stack/testGeometryNodeStackExtension.cpp b/tests/stack/testGeometryNodeStackExtension.cpp index 8256927d9..c623709e6 100644 --- a/tests/stack/testGeometryNodeStackExtension.cpp +++ b/tests/stack/testGeometryNodeStackExtension.cpp @@ -26,7 +26,7 @@ public: // the GeometryNode stack needs to know the type of geometry-nodes from the DummyEnv: template <typename TStackIter> using DummyGeometryDataInterface = - typename node::MakeGeometryDataInterface<TStackIter, DummyEnv>::type; + typename node::make_GeometryDataInterface<TStackIter, DummyEnv>::type; // combine dummy stack with geometry information for tracking template <typename TStackIter> diff --git a/tests/stack/testWeightStackExtension.cpp b/tests/stack/testWeightStackExtension.cpp new file mode 100644 index 000000000..715051b05 --- /dev/null +++ b/tests/stack/testWeightStackExtension.cpp @@ -0,0 +1,85 @@ +/* + * (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/framework/stack/CombinedStack.hpp> +#include <corsika/stack/DummyStack.hpp> +#include <corsika/stack/WeightStackExtension.hpp> + +using namespace corsika; + +#include <catch2/catch.hpp> + +#include <iostream> +using namespace std; + +// the Weight stack: +template <typename TStackIter> +using DummyWeightDataInterface = + typename weights::make_WeightDataInterface<TStackIter>::type; + +// combine dummy stack with geometry information for tracking +template <typename TStackIter> +using StackWithGeometryInterface = + CombinedParticleInterface<dummy_stack::DummyStack::pi_type, DummyWeightDataInterface, + TStackIter>; + +using TestStack = + CombinedStack<typename dummy_stack::DummyStack::stack_implementation_type, + weights::WeightData, StackWithGeometryInterface>; + +TEST_CASE("WeightStackExtension", "[stack]") { + + logging::set_level(logging::level::info); + corsika_logger->set_pattern("[%n:%^%-8l%$] custom pattern: %v"); + + dummy_stack::NoData noData; + + SECTION("write weights") { + + double const weight = 5.1; + + TestStack s; + s.addParticle(std::make_tuple(noData), std::tuple<double>{weight}); + + CHECK(s.getEntries() == 1); + } + + SECTION("write/read weights") { + double const weight = 15; + + TestStack s; + auto p = s.addParticle(std::make_tuple(noData)); + p.setWeight(weight); + CHECK(s.getEntries() == 1); + + const auto pout = s.getNextParticle(); + CHECK(pout.getWeight() == 15); + } + + SECTION("stack fill and cleanup") { + + double const weight = 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_stack::NoData>{noData}); + p.setWeight(weight); + } + + CHECK(s.getEntries() == 99); + double v = 0; + for (int i = 0; i < 99; ++i) { + auto p = s.getNextParticle(); + v += p.getWeight(); + p.erase(); + } + CHECK(v == 99 * weight); + CHECK(s.getEntries() == 0); + } +} -- GitLab