From 21a72942500e33121cfa55b31793af48282e9531 Mon Sep 17 00:00:00 2001 From: Maximilian Reininghaus <maximilian.reininghaus@kit.edu> Date: Mon, 5 Dec 2022 18:45:10 +0100 Subject: [PATCH] implemented EMThinning --- .../detail/modules/thinning/EMThinning.inl | 72 ++++++++++++++++--- corsika/modules/thinning/EMThinning.hpp | 41 ++++++----- 2 files changed, 85 insertions(+), 28 deletions(-) diff --git a/corsika/detail/modules/thinning/EMThinning.inl b/corsika/detail/modules/thinning/EMThinning.inl index 9eea31d14..c0198da2c 100644 --- a/corsika/detail/modules/thinning/EMThinning.inl +++ b/corsika/detail/modules/thinning/EMThinning.inl @@ -13,17 +13,69 @@ namespace corsika { -EMThinning::EMThinning(HEPEnergyType threshold, double maxWeight) : threshold_{threshold}, maxWeight_{maxWeight} {} + EMThinning::EMThinning(HEPEnergyType threshold, double maxWeight) + : threshold_{threshold} + , maxWeight_{maxWeight} {} + + template <typename TStackView> + void EMThinning::doSecondaries(TStackView& view) { + if (view.getSize() != 2) return; + + auto projectile = view.getProjectile(); + if (!is_em(projectile.getPID())) return; + + double const parentWeight = projectile.getWeight(); + if (parentWeight >= maxWeight_) { return; } -template <typename TStackView> - void EMThinning::doSecondaries(TStackView& view) { - if (view.size() != 2) return; auto particle1 = view.begin(); - auto particle2 = std::next(particle1); + auto particle2 = ++(view.begin()); + + // skip non-EM interactions + if (!is_em(particle1.getPID()) || !is_em(particle2.getPID())) { return; } + + /* skip high-energy interactions + * We consider only the primary energy. A more sophisticated algorithm might + * sort out above-threshold secondaries and apply thinning only on the subset of + * those below the threshold. + */ + if (projectile.getEnergy() > threshold_) { return; } + + corsika::HEPEnergyType const Esum = particle1.getEnergy() + particle2.getEnergy(); + + double const p1 = particle1.getEnergy() / Esum; + double const p2 = particle2.getEnergy() / Esum; + + double const w1 = parentWeight / p1; + double const w2 = parentWeight / p2; + + if (w1 <= maxWeight_ && w2 <= maxWeight_) { // apply Hillas thinning + if (uniform_(rng_) <= p1) { // keep 1st with probability p1 + particle2.setWeight(0); + particle1.setWeight(w1); + } else { // keep 2nd + particle1.setWeight(0); + particle2.setWeight(w2); + } + } else { // weight limitation kicks in, do statistical thinning + double const w1prime = std::min(w1, maxWeight_); + double const w2prime = std::min(w2, maxWeight_); + + if (uniform_(rng_) * w1prime <= parentWeight) { // keep 1st + particle1.setWeight(w1prime); + } else { + particle1.setWeight(0); + } + if (uniform_(rng_) * w2prime <= parentWeight) { // keep 2nd + particle2.setWeight(w2prime); + } else { + particle2.setWeight(0); + } + } - if (.getCode()) - corsika::HEPEnergyType const E0 = - -} + // TODO: skip this for multithinning + for (auto& p : view) { + if (auto const w = p.getWeight(); w == 0) { p.erase(); } + } + } -} +} // namespace corsika diff --git a/corsika/modules/thinning/EMThinning.hpp b/corsika/modules/thinning/EMThinning.hpp index 017d0b770..b414be492 100644 --- a/corsika/modules/thinning/EMThinning.hpp +++ b/corsika/modules/thinning/EMThinning.hpp @@ -8,36 +8,41 @@ #pragma once +#include <random> + #include <corsika/framework/core/PhysicalUnits.hpp> +#include <corsika/framework/random/RNGManager.hpp> #include <corsika/framework/process/SecondariesProcess.hpp> namespace corsika { -//! This process implements thinning for EM splitting processes (1 -> 2) - -class EMThinning : public SecondariesProcess<EMThinning> { -public: - /** - * Construct a new EMThinning process. - * - * @param threshold: thinning applied below this energy - * @param maxWeight: maximum allowed weight - */ - EMThinning(HEPEnergyType threshold, double maxWeight); + //! This process implements thinning for EM splitting processes (1 -> 2) + class EMThinning : public SecondariesProcess<EMThinning> { + public: + /** + * Construct a new EMThinning process. + * + * @param threshold: thinning applied below this energy + * @param maxWeight: maximum allowed weight + */ + EMThinning(HEPEnergyType threshold, double maxWeight); /** - * Apply thinning to secondaries. Only EM primaries with two EM secondaries are considered. + * Apply thinning to secondaries. Only EM primaries with two EM secondaries are + * considered. * * @tparam TStackView */ template <typename TStackView> void doSecondaries(TStackView&); -private: - HEPEnergyType const threshold_; - double const maxWeight_; -}; -} + private: + default_prng_type& rng_ = RNGManager<>::getInstance().getRandomStream("thinning"); + std::uniform_real_distribution<double> uniform_{}; + HEPEnergyType const threshold_; + double const maxWeight_; + }; +} // namespace corsika -#include <corsika/detail/process/thinning/EMThinning.inl> +#include <corsika/detail/modules/thinning/EMThinning.inl> -- GitLab