From 04211f1252d843df4d8d525ff76014d28a4e7752 Mon Sep 17 00:00:00 2001 From: ralfulrich <ralf.ulrich@kit.edu> Date: Tue, 5 Jan 2021 18:05:44 +0100 Subject: [PATCH] various improvements --- corsika/corsika.hpp | 32 ++- corsika/detail/framework/geometry/Sphere.inl | 2 +- .../detail/framework/geometry/Trajectory.inl | 156 ----------- corsika/detail/media/Universe.inl | 4 +- corsika/detail/media/VolumeTreeNode.inl | 15 +- .../detail/modules/tracking/TrackingLine.inl | 59 ---- .../modules/tracking/TrackingStraight.inl | 100 +++++++ .../detail/stack/NuclearStackExtension.inl | 2 +- corsika/detail/stack/SuperStupidStack.inl | 93 ------- corsika/framework/core/ParticleProperties.hpp | 5 + corsika/framework/geometry/IVolume.hpp | 2 +- corsika/framework/geometry/Sphere.hpp | 2 +- corsika/framework/geometry/Trajectory.hpp | 216 --------------- corsika/framework/stack/Stack.hpp | 24 ++ corsika/media/Universe.hpp | 2 +- corsika/media/VolumeTreeNode.hpp | 4 +- corsika/modules/tracking/Intersect.hpp | 104 +------ .../tracking/TrackingLeapFrogCurved.hpp | 225 +-------------- .../tracking/TrackingLeapFrogStraight.hpp | 167 +----------- corsika/modules/tracking/TrackingStraight.hpp | 76 +----- corsika/setup/SetupTrajectory.hpp | 5 +- corsika/stack/NuclearStackExtension.hpp | 8 +- corsika/stack/SuperStupidStack.hpp | 176 ------------ examples/geometry_example.cpp | 8 +- examples/stack_example.cpp | 8 +- tests/common/SetupTestTrajectory.hpp | 9 +- tests/common/testTestStack.hpp | 19 +- tests/framework/testCascade.cpp | 2 +- tests/framework/testGeometry.cpp | 11 +- tests/framework/testRandom.cpp | 12 +- tests/modules/CMakeLists.txt | 4 +- tests/modules/testInteractionCounter.cpp | 32 +-- tests/modules/testQGSJetII.cpp | 44 +-- tests/modules/testStackInspector.cpp | 2 +- tests/modules/testSwitchProcess.cpp | 258 ------------------ tests/stack/CMakeLists.txt | 2 +- tests/stack/testNuclearStackExtension.cpp | 6 +- ...perStupidStack.cpp => testSimpleStack.cpp} | 8 +- 38 files changed, 303 insertions(+), 1601 deletions(-) delete mode 100644 corsika/detail/framework/geometry/Trajectory.inl delete mode 100644 corsika/detail/modules/tracking/TrackingLine.inl create mode 100644 corsika/detail/modules/tracking/TrackingStraight.inl delete mode 100644 corsika/detail/stack/SuperStupidStack.inl delete mode 100644 corsika/framework/geometry/Trajectory.hpp delete mode 100644 corsika/stack/SuperStupidStack.hpp delete mode 100644 tests/modules/testSwitchProcess.cpp rename tests/stack/{testSuperStupidStack.cpp => testSimpleStack.cpp} (91%) diff --git a/corsika/corsika.hpp b/corsika/corsika.hpp index 137cccc6b..36fa90b63 100644 --- a/corsika/corsika.hpp +++ b/corsika/corsika.hpp @@ -8,10 +8,32 @@ #pragma once -// Usage: -// to get the version X.YY.Z, -// set CORSIKA_VERSION X0YY0Z -// +/** + @file corsika.hpp + + The CORSIKA 8 air shower simulation framework. + + @mainpage Technical documentation of the CORSIKA 8 software framework + + Software documentatin and reference guide for the CORSIKA 8 + software framework for air shower simulations. CORSIKA 8 is developed + at <a href="https://gitlab.ikp.kit.edu/AirShowerPhysics">https://gitlab.ikp.kit.edu</a>. + If you got the code from somewhere else, consider to switch to the official development + repository. If you want to report bugs, or want to suggest features or future + development, please submit an "issue" on this gitlab server. We only accept Issues and + discussion via our central development server https://gitlab.ikp.kit.edu. + + Write to corsika-devel@lists.kit.edu, or even register yourself at + https://www.lists.kit.edu/sympa/info/corsika-devel to get in contact + with other developers. + + For more information about the project, see @ref md_README. + **/ + +/*! Usage: + * to get the version X.YY.Z, + * set CORSIKA_VERSION X0YY0Z + */ #define CORSIKA_VERSION 800000 /*! \def CORSIKA_MAJOR_VERSION @@ -30,4 +52,4 @@ * \brief The preprocessor macro \p CORSIKA_PATCH_NUMBER encodes the * patch number of the CORSIKA library. */ -#define CORSIKA_PATCH_NUMBER 0 \ No newline at end of file +#define CORSIKA_PATCH_NUMBER 0 diff --git a/corsika/detail/framework/geometry/Sphere.inl b/corsika/detail/framework/geometry/Sphere.inl index a793984dd..be1ba2774 100644 --- a/corsika/detail/framework/geometry/Sphere.inl +++ b/corsika/detail/framework/geometry/Sphere.inl @@ -13,7 +13,7 @@ namespace corsika { - inline bool Sphere::isInside(Point const& p) const { + inline bool Sphere::contains(Point const& p) const { return radius_ * radius_ > (center_ - p).getSquaredNorm(); } diff --git a/corsika/detail/framework/geometry/Trajectory.inl b/corsika/detail/framework/geometry/Trajectory.inl deleted file mode 100644 index ab7779c83..000000000 --- a/corsika/detail/framework/geometry/Trajectory.inl +++ /dev/null @@ -1,156 +0,0 @@ -/* - * (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/framework/core/PhysicalUnits.hpp> -#include <corsika/framework/geometry/Line.hpp> -#include <corsika/framework/geometry/Point.hpp> -#include <corsika/framework/geometry/PhysicalGeometry.hpp> - -namespace corsika { - - inline VelocityVector LineTrajectory::getVelocity(double const u) const { - return initialVelocity_ * (1 - u) + finalVelocity_ * u; - } - - inline TimeType LineTrajectory::getDuration(double const u) const { - return u * timeStep_; - } - - inline LengthType LineTrajectory::getLength(double const u) const { - if (timeLength_ == 0_s) return 0_m; - if (timeStep_ == std::numeric_limits<TimeType::value_type>::infinity() * 1_s) - return std::numeric_limits<LengthType::value_type>::infinity() * 1_m; - return getDistance(u) * timeStep_ / timeLength_; - } - - ///! set new duration along potentially bend trajectory. - inline void LineTrajectory::setLength(LengthType const limit) { - setDuration(line_.getTimeFromArclength(limit)); - } - - ///! set new duration along potentially bend trajectory. - // Scale other properties by "limit/timeLength_" - inline void LineTrajectory::setDuration(TimeType const limit) { - if (timeStep_ == 0_s) { - timeLength_ = 0_s; - setFinalVelocity(getVelocity(0)); - timeStep_ = limit; - } else { - // for infinite steps there can't be a difference between - // curved and straight trajectory, this is fundamentally - // undefined: assume they are the same (which, i.e. is always correct for a - // straight line trajectory). - // - // Final note: only straight-line trajectories should have - // infinite steps! Everything else is ill-defined. - if (timeStep_ == std::numeric_limits<TimeType::value_type>::infinity() * 1_s || - timeLength_ == std::numeric_limits<TimeType::value_type>::infinity() * 1_s) { - timeLength_ = limit; - timeStep_ = limit; - // ...and don't touch velocity - } else { - const double scale = limit / timeStep_; - timeLength_ *= scale; - setFinalVelocity(getVelocity(scale)); - timeStep_ = limit; - } - } - } - - inline LengthType LineTrajectory::getDistance(double const u) const { - assert(u <= 1); - assert(u >= 0); - return line_.getArcLength(0 * second, u * timeLength_); - } - - inline Line const LeapFrogTrajectory::getLine() const { - auto D = getPosition(1) - getPosition(0); - auto d = D.getNorm(); - auto v = initialVelocity_; - if (d > 1_um) { // if trajectory is ultra-short, we do not - // re-calculate velocity, just use initial - // value. Otherwise, this is numerically unstable - v = D / d * getVelocity(0).getNorm(); - } - return Line(getPosition(0), v); - } - - inline Point LeapFrogTrajectory::getPosition(double const u) const { - Point position = initialPosition_ + initialVelocity_ * timeStep_ * u / 2; - VelocityVector velocity = - initialVelocity_ + initialVelocity_.cross(magneticfield_) * timeStep_ * u * k_; - return position + velocity * timeStep_ * u / 2; - } - - inline VelocityVector LeapFrogTrajectory::getVelocity(double const u) const { - return initialVelocity_ + initialVelocity_.cross(magneticfield_) * timeStep_ * u * k_; - } - - inline DirectionVector LeapFrogTrajectory::getDirection(double const u) const { - return getVelocity(u).normalized(); - } - - ///! duration along potentially bend trajectory - inline TimeType LeapFrogTrajectory::getDuration(double const u) const { - return u * timeStep_ * - (double(getVelocity(u).getNorm() / initialVelocity_.getNorm()) + 1.0) / 2; - } - - ///! total length along potentially bend trajectory - inline LengthType LeapFrogTrajectory::getLength(double const u) const { - return timeStep_ * initialVelocity_.getNorm() * u; - } - - ///! set new duration along potentially bend trajectory. - inline void LeapFrogTrajectory::setLength(LengthType const limit) { - if (initialVelocity_.getNorm() == 0_m / 1_s) setDuration(0_s); - setDuration(limit / initialVelocity_.getNorm()); - } - - ///! set new duration along potentially bend trajectory. - // Scale other properties by "limit/timeLength_" - inline void LeapFrogTrajectory::setDuration(TimeType const limit) { timeStep_ = limit; } - - /* - template <typename TType> - Point Trajectory<TType>::getPosition(double const u) const { - return TType::getPosition(timeLength_ * u); - } - - template <typename TType> - TimeType Trajectory<TType>::getDuration() const { - return timeLength_; - } - - template <typename TType> - LengthType Trajectory<TType>::getLength() const { - return getDistance(timeLength_); - } - - template <typename TType> - LengthType Trajectory<TType>::getDistance(TimeType const t) const { - assert(t <= timeLength_); - assert(t >= 0 * second); - return TType::getArcLength(0 * second, t); - } - - template <typename TType> - void Trajectory<TType>::getLimitEndTo(LengthType const limit) { - timeLength_ = TType::getTimeFromArclength(limit); - } - - template <typename TType> - auto Trajectory<TType>::getNormalizedDirection() const { - static_assert(std::is_same_v<TType, corsika::Line>); - return TType::getVelocity().normalized(); - } - */ - -} // namespace corsika diff --git a/corsika/detail/media/Universe.inl b/corsika/detail/media/Universe.inl index 6a2bdd6e9..b3f4d2541 100644 --- a/corsika/detail/media/Universe.inl +++ b/corsika/detail/media/Universe.inl @@ -16,6 +16,6 @@ namespace corsika { : corsika::Sphere(Point{pCS, 0 * meter, 0 * meter, 0 * meter}, meter * std::numeric_limits<double>::infinity()) {} - bool Universe::isInside(corsika::Point const&) const { return true; } + bool Universe::contains(corsika::Point const&) const { return true; } -} // namespace corsika \ No newline at end of file +} // namespace corsika diff --git a/corsika/detail/media/VolumeTreeNode.inl b/corsika/detail/media/VolumeTreeNode.inl index 6f978f86b..bdae7cc12 100644 --- a/corsika/detail/media/VolumeTreeNode.inl +++ b/corsika/detail/media/VolumeTreeNode.inl @@ -13,18 +13,17 @@ namespace corsika { - //! convenience function equivalent to Volume::isInside template <typename IModelProperties> - bool VolumeTreeNode<IModelProperties>::isInside(Point const& p) const { - return geoVolume_->isInside(p); + bool VolumeTreeNode<IModelProperties>::contains(Point const& p) const { + return geoVolume_->contains(p); } template <typename IModelProperties> inline VolumeTreeNode<IModelProperties> const* - VolumeTreeNode<IModelProperties>::isExcluded(Point const& p) const { + VolumeTreeNode<IModelProperties>::excludes(Point const& p) const { auto exclContainsIter = std::find_if(excludedNodes_.cbegin(), excludedNodes_.cend(), - [&](auto const& s) { return bool(s->isInside(p)); }); + [&](auto const& s) { return bool(s->contains(p)); }); return exclContainsIter != excludedNodes_.cend() ? *exclContainsIter : nullptr; } @@ -35,14 +34,14 @@ namespace corsika { template <typename IModelProperties> VolumeTreeNode<IModelProperties> const* VolumeTreeNode<IModelProperties>::getContainingNode(Point const& p) const { - if (!isInside(p)) { return nullptr; } + if (!contains(p)) { return nullptr; } if (auto const childContainsIter = std::find_if(childNodes_.cbegin(), childNodes_.cend(), - [&](auto const& s) { return bool(s->isInside(p)); }); + [&](auto const& s) { return bool(s->contains(p)); }); childContainsIter == childNodes_.cend()) // not contained in any of the children { - if (auto const exclContainsIter = isExcluded(p)) // contained in any excluded nodes + if (auto const exclContainsIter = excludes(p)) // contained in any excluded nodes { return exclContainsIter->getContainingNode(p); } else { diff --git a/corsika/detail/modules/tracking/TrackingLine.inl b/corsika/detail/modules/tracking/TrackingLine.inl deleted file mode 100644 index 52200c42d..000000000 --- a/corsika/detail/modules/tracking/TrackingLine.inl +++ /dev/null @@ -1,59 +0,0 @@ -/* - * (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/framework/geometry/Point.hpp> -#include <corsika/framework/geometry/QuantityVector.hpp> -#include <corsika/framework/geometry/Sphere.hpp> -#include <corsika/framework/geometry/Vector.hpp> -#include <corsika/media/Environment.hpp> - -#include <limits> -#include <stdexcept> -#include <utility> - -namespace corsika::tracking_line { - - std::optional<std::pair<TimeType, TimeType>> TimeOfIntersection( - corsika::Line const& line, corsika::Sphere const& sphere) { - auto const delta = line.getStartPoint() - sphere.getCenter(); - auto const v = line.getVelocity(); - auto const vSqNorm = - v.getSquaredNorm(); // todo: get rid of this by having V0 normalized always - auto const R = sphere.getRadius(); - - auto const vDotDelta = v.dot(delta); - auto const discriminant = - vDotDelta * vDotDelta - vSqNorm * (delta.getSquaredNorm() - R * R); - - if (discriminant.magnitude() > 0) { - auto const sqDisc = sqrt(discriminant); - auto const invDenom = 1 / vSqNorm; - return std::make_pair((-vDotDelta - sqDisc) * invDenom, - (-vDotDelta + sqDisc) * invDenom); - } else { - return {}; - } - } - - TimeType getTimeOfIntersection(Line const& vLine, Plane const& vPlane) { - - auto const delta = vPlane.getCenter() - vLine.getStartPoint(); - auto const v = vLine.getVelocity(); - auto const n = vPlane.getNormal(); - auto const c = n.dot(v); - - if (c.magnitude() == 0) { - return std::numeric_limits<TimeType::value_type>::infinity() * 1_s; - } else { - return n.dot(delta) / c; - } - } - -} // namespace corsika::tracking_line diff --git a/corsika/detail/modules/tracking/TrackingStraight.inl b/corsika/detail/modules/tracking/TrackingStraight.inl new file mode 100644 index 000000000..33ad57ede --- /dev/null +++ b/corsika/detail/modules/tracking/TrackingStraight.inl @@ -0,0 +1,100 @@ +/* + * (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/framework/core/PhysicalUnits.hpp> +#include <corsika/framework/geometry/Line.hpp> +#include <corsika/framework/geometry/Plane.hpp> +#include <corsika/framework/geometry/Sphere.hpp> +#include <corsika/framework/geometry/Vector.hpp> +#include <corsika/framework/geometry/StraightTrajectory.hpp> +#include <corsika/framework/geometry/Intersections.hpp> +#include <corsika/framework/logging/Logging.hpp> +#include <corsika/modules/tracking/Intersect.hpp> + +#include <type_traits> +#include <utility> + +namespace corsika::tracking_line { + + template <typename TParticle> + inline auto Tracking::getTrack(TParticle const& particle) { + VelocityVector const initialVelocity = + particle.getMomentum() / particle.getEnergy() * constants::c; + + auto const initialPosition = particle.getPosition(); + CORSIKA_LOG_DEBUG( + "Tracking pid: {}" + " , E = {} GeV", + particle.getPID(), particle.getEnergy() / 1_GeV); + CORSIKA_LOG_DEBUG("Tracking pos: {}", initialPosition.getCoordinates()); + CORSIKA_LOG_DEBUG("Tracking E: {} GeV", particle.getEnergy() / 1_GeV); + CORSIKA_LOG_DEBUG("Tracking p: {} GeV", + particle.getMomentum().getComponents() / 1_GeV); + CORSIKA_LOG_DEBUG("Tracking v: {} ", initialVelocity.getComponents()); + + // traverse the environment volume tree and find next + // intersection + auto [minTime, minNode] = nextIntersect(particle); + + return std::make_tuple(StraightTrajectory(Line(initialPosition, initialVelocity), + minTime), // trajectory + minNode); // next volume node + } + + template <typename TParticle, typename TMedium> + Intersections Tracking::intersect(TParticle const& particle, Sphere const& sphere, + TMedium const&) { + auto const delta = particle.getPosition() - sphere.getCenter(); + auto const velocity = particle.getMomentum() / particle.getEnergy() * constants::c; + auto const vSqNorm = velocity.getSquaredNorm(); + auto const R = sphere.getRadius(); + + auto const vDotDelta = velocity.dot(delta); + auto const discriminant = + vDotDelta * vDotDelta - vSqNorm * (delta.getSquaredNorm() - R * R); + + if (discriminant.magnitude() > 0) { + auto const sqDisc = sqrt(discriminant); + auto const invDenom = 1 / vSqNorm; + return Intersections((-vDotDelta - sqDisc) * invDenom, + (-vDotDelta + sqDisc) * invDenom); + } + return Intersections(); + } + + template <typename TParticle, typename TBaseNodeType> + Intersections Tracking::intersect(TParticle const& particle, + TBaseNodeType const& volumeNode) { + Sphere const* sphere = dynamic_cast<Sphere const*>(&volumeNode.getVolume()); + if (sphere) { + typedef typename std::remove_const_t< + std::remove_reference_t<decltype(volumeNode.getModelProperties())>> + medium_type; + return Tracking::intersect<TParticle, medium_type>(particle, *sphere, + volumeNode.getModelProperties()); + } + throw std::runtime_error( + "The Volume type provided is not supported in Intersect(particle, node)"); + } + + template <typename TParticle, typename TMedium> + Intersections Tracking::intersect(TParticle const& particle, Plane const& plane, + TMedium const&) { + auto const delta = plane.getCenter() - particle.getPosition(); + auto const velocity = particle.getMomentum() / particle.getEnergy() * constants::c; + auto const n = plane.getNormal(); + auto const c = n.dot(velocity); + + return Intersections(c.magnitude() == 0 + ? std::numeric_limits<TimeType::value_type>::infinity() * 1_s + : n.dot(delta) / c); + } + +} // namespace corsika::tracking_line diff --git a/corsika/detail/stack/NuclearStackExtension.inl b/corsika/detail/stack/NuclearStackExtension.inl index 2d10e28ee..b1fe9ba1c 100644 --- a/corsika/detail/stack/NuclearStackExtension.inl +++ b/corsika/detail/stack/NuclearStackExtension.inl @@ -13,7 +13,7 @@ #include <corsika/framework/stack/Stack.hpp> #include <corsika/framework/geometry/Point.hpp> #include <corsika/framework/geometry/Vector.hpp> -#include <corsika/stack/SuperStupidStack.hpp> +#include <corsika/stack/SimpleStack.hpp> #include <algorithm> #include <tuple> diff --git a/corsika/detail/stack/SuperStupidStack.inl b/corsika/detail/stack/SuperStupidStack.inl deleted file mode 100644 index 35d00a6d1..000000000 --- a/corsika/detail/stack/SuperStupidStack.inl +++ /dev/null @@ -1,93 +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/framework/core/ParticleProperties.hpp> -#include <corsika/framework/core/PhysicalUnits.hpp> -#include <corsika/framework/stack/Stack.hpp> - -#include <corsika/framework/geometry/Point.hpp> -#include <corsika/framework/geometry/RootCoordinateSystem.hpp> -#include <corsika/framework/geometry/Vector.hpp> - -#include <string> -#include <tuple> -#include <vector> - -namespace corsika { - - template <typename StackIteratorInterface> - void ParticleInterface<StackIteratorInterface>::setParticleData( - std::tuple<Code, HEPEnergyType, MomentumVector, Point, TimeType> const& v) { - this->setPID(std::get<0>(v)); - this->setEnergy(std::get<1>(v)); - this->setMomentum(std::get<2>(v)); - this->setPosition(std::get<3>(v)); - this->setTime(std::get<4>(v)); - } - - template <typename StackIteratorInterface> - void ParticleInterface<StackIteratorInterface>::setParticleData( - ParticleInterface<StackIteratorInterface> const&, - std::tuple<Code, HEPEnergyType, MomentumVector, Point, TimeType> const& v) { - this->setPID(std::get<0>(v)); - this->setEnergy(std::get<1>(v)); - this->setMomentum(std::get<2>(v)); - this->setPosition(std::get<3>(v)); - this->setTime(std::get<4>(v)); - } - - inline void SuperStupidStackImpl::clear() { - dataPID_.clear(); - dataE_.clear(); - momentum_.clear(); - position_.clear(); - time_.clear(); - } - - inline void SuperStupidStackImpl::copy(size_t i1, size_t i2) { - dataPID_[i2] = dataPID_[i1]; - dataE_[i2] = dataE_[i1]; - momentum_[i2] = momentum_[i1]; - position_[i2] = position_[i1]; - time_[i2] = time_[i1]; - } - - inline void SuperStupidStackImpl::swap(size_t i1, size_t i2) { - std::swap(dataPID_[i2], dataPID_[i1]); - std::swap(dataE_[i2], dataE_[i1]); - std::swap(momentum_[i2], momentum_[i1]); - std::swap(position_[i2], position_[i1]); - std::swap(time_[i2], time_[i1]); - } - - inline void SuperStupidStackImpl::incrementSize() { - dataPID_.push_back(Code::Unknown); - dataE_.push_back(0 * electronvolt); - - CoordinateSystemPtr const& dummyCS = get_root_CoordinateSystem(); - - momentum_.push_back( - MomentumVector(dummyCS, {0 * electronvolt, 0 * electronvolt, 0 * electronvolt})); - - position_.push_back(Point(dummyCS, {0 * meter, 0 * meter, 0 * meter})); - time_.push_back(0 * second); - } - - inline void SuperStupidStackImpl::decrementSize() { - if (dataE_.size() > 0) { - dataPID_.pop_back(); - dataE_.pop_back(); - momentum_.pop_back(); - position_.pop_back(); - time_.pop_back(); - } - } - -} // namespace corsika diff --git a/corsika/framework/core/ParticleProperties.hpp b/corsika/framework/core/ParticleProperties.hpp index bec9a2700..2deb03a86 100644 --- a/corsika/framework/core/ParticleProperties.hpp +++ b/corsika/framework/core/ParticleProperties.hpp @@ -10,6 +10,11 @@ @file ParticleProperties.hpp Interface to particle properties + + The properties of all particles are saved in static and flat + arrays. There is a enum corsika::Code to identify each + particles, and each individual particles has its own static class, + which can be used to retrieve its physical properties. */ #pragma once diff --git a/corsika/framework/geometry/IVolume.hpp b/corsika/framework/geometry/IVolume.hpp index 59b9acb55..1960dfdf2 100644 --- a/corsika/framework/geometry/IVolume.hpp +++ b/corsika/framework/geometry/IVolume.hpp @@ -16,7 +16,7 @@ namespace corsika { public: //! returns true if the Point p is within the volume - virtual bool isInside(Point const& p) const = 0; + virtual bool contains(Point const& p) const = 0; virtual ~IVolume() = default; }; diff --git a/corsika/framework/geometry/Sphere.hpp b/corsika/framework/geometry/Sphere.hpp index cea283b3d..81e5e0b15 100644 --- a/corsika/framework/geometry/Sphere.hpp +++ b/corsika/framework/geometry/Sphere.hpp @@ -28,7 +28,7 @@ namespace corsika { , radius_(pRadius) {} //! returns true if the Point p is within the sphere - bool isInside(Point const& p) const override; + bool contains(Point const& p) const override; Point const& getCenter() const; diff --git a/corsika/framework/geometry/Trajectory.hpp b/corsika/framework/geometry/Trajectory.hpp deleted file mode 100644 index 6a3700eea..000000000 --- a/corsika/framework/geometry/Trajectory.hpp +++ /dev/null @@ -1,216 +0,0 @@ -/* - * (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/framework/core/PhysicalUnits.hpp> -#include <corsika/framework/geometry/Line.hpp> -#include <corsika/framework/geometry/Point.hpp> -#include <corsika/framework/geometry/PhysicalGeometry.hpp> - -namespace corsika { - - /** - * - * A Trajectory is a description of a momvement of an object in - * three-dimensional space that describes the trajectory (connection - * between two Points in space), as well as the direction of motion - * at any given point. - * - * A Trajectory has a start `0` and an end `1`, where - * e.g. getPosition(0) returns the start point and getDirection(1) - * the direction of motion at the end. Values outside 0...1 are not - * defined. - * - * A Trajectory has a length in [m], getLength, a duration in [s], getDuration. - * - * Note: so far it is assumed that the speed (d|vec{r}|/dt) between - * start and end does not change and is constant for the entire - * Trajectory. - * - **/ - - class LineTrajectory { - - public: - LineTrajectory() = delete; - LineTrajectory(LineTrajectory const&) = default; - LineTrajectory(LineTrajectory&&) = default; - LineTrajectory& operator=(LineTrajectory const&) = delete; - - /** - * \param theLine The geometric \sa Line object that represents a straight-line - * connection - * - * \param timeLength The time duration to traverse the straight trajectory - * in units of \sa TimeType - */ - LineTrajectory(Line const& theLine, TimeType timeLength) - : line_(theLine) - , timeLength_(timeLength) - , timeStep_(timeLength) - , initialVelocity_(theLine.getVelocity(TimeType::zero())) - , finalVelocity_(theLine.getVelocity(timeLength)) {} - - /** - * \param theLine The geometric \sa Line object that represents a straight-line - * connection - * - * \param timeLength The time duration to traverse the straight trajectory - * in units of \sa TimeType - * - * \param timeStep Time duration to folow eventually curved - * trajectory in units of \sa TimesType - * - * \param initialV Initial velocity vector at - * start of trajectory \param finalV Final velocity vector at start of trajectory - */ - LineTrajectory(Line const& theLine, - TimeType const timeLength, // length of theLine (straight) - TimeType const timeStep, // length of bend step (curved) - VelocityVector const& initialV, VelocityVector const& finalV) - : line_(theLine) - , timeLength_(timeLength) - , timeStep_(timeStep) - , initialVelocity_(initialV) - , finalVelocity_(finalV) {} - - Line const& getLine() const { return line_; } - - Point getPosition(double const u) const { return line_.getPosition(timeLength_ * u); } - - VelocityVector getVelocity(double const u) const; - - DirectionVector getDirection(double const u) const { - return getVelocity(u).normalized(); - } - - ///! duration along potentially bend trajectory - TimeType getDuration(double const u = 1) const; - - ///! total length along potentially bend trajectory - LengthType getLength(double const u = 1) const; - - ///! set new duration along potentially bend trajectory. - void setLength(LengthType const limit); - - ///! set new duration along potentially bend trajectory. - // Scale other properties by "limit/timeLength_" - void setDuration(TimeType const limit); - - protected: - ///! total length along straight trajectory - LengthType getDistance(double const u) const; - - void setFinalVelocity(VelocityVector const& v) { finalVelocity_ = v; } - - private: - Line line_; - TimeType timeLength_; ///! length of straight step (shortest connecting line) - TimeType timeStep_; ///! length of bend step (curved) - VelocityVector initialVelocity_; - VelocityVector finalVelocity_; - }; - - /** - * The LeapFrogTrajectory stores information on one leap-frog step. - * - * The leap-frog algorithm uses a half-step and is used in magnetic - * field tracking. The LeapFrogTrajectory will solve the leap-frog - * algorithm equation for a given constant $k$ that has to be - * specified during construction (essentially fixing the magnetic - * field). Thus, different steps (length) can be dynamically - * generated here. The velocity vector will correctly point into the - * direction as calculated by the algorithm for any steplength, or - * intermediate position. - * - **/ - - class LeapFrogTrajectory { - - public: - LeapFrogTrajectory() = delete; - LeapFrogTrajectory(LeapFrogTrajectory const&) = default; - LeapFrogTrajectory(LeapFrogTrajectory&&) = default; - LeapFrogTrajectory& operator=(LeapFrogTrajectory const&) = delete; - - LeapFrogTrajectory(Point const& pos, VelocityVector const& initialVelocity, - MagneticFieldVector const& Bfield, - decltype(square(meter) / (square(second) * volt)) const k, - TimeType const timeStep) // leap-from total length - : initialPosition_(pos) - , initialVelocity_(initialVelocity) - , initialDirection_(initialVelocity.normalized()) - , magneticfield_(Bfield) - , k_(k) - , timeStep_(timeStep) {} - - Line const getLine() const; - - Point getPosition(double const u) const; - - VelocityVector getVelocity(double const u) const; - - DirectionVector getDirection(double const u) const; - - ///! duration along potentially bend trajectory - TimeType getDuration(double const u = 1) const; - - ///! total length along potentially bend trajectory - LengthType getLength(double const u = 1) const; - - ///! set new duration along potentially bend trajectory. - void setLength(LengthType const limit); - - ///! set new duration along potentially bend trajectory. - // Scale other properties by "limit/timeLength_" - void setDuration(TimeType const limit); - - private: - Point initialPosition_; - VelocityVector initialVelocity_; - DirectionVector initialDirection_; - MagneticFieldVector magneticfield_; - decltype(square(meter) / (square(second) * volt)) k_; - TimeType timeStep_; - }; - - /* - - template <typename TType> - class Trajectory : public TType { - - public: - - using TType::getArcLength; - using TType::getPosition; - - Trajectory(TType const& theT, TimeType timeLength) - : TType(theT) - , timeLength_(timeLength) {} - - Point getPosition(double const u) const; - - TimeType getDuration() const; - - LengthType getLength() const; - - LengthType getDistance(TimeType const t) const; - - void getLimitEndTo(LengthType const limit); - - auto getNormalizedDirection() const; - - private: - TimeType timeLength_; - }; - */ - -} // namespace corsika - -#include <corsika/detail/framework/geometry/Trajectory.inl> diff --git a/corsika/framework/stack/Stack.hpp b/corsika/framework/stack/Stack.hpp index dab5bb2d9..4a6f09056 100644 --- a/corsika/framework/stack/Stack.hpp +++ b/corsika/framework/stack/Stack.hpp @@ -17,6 +17,30 @@ #include <utility> #include <type_traits> +/** + @file Stack.hpp + + Description of particle stacks + + In the CORSIKA 8 framework particle data is always stored in + particle stacks. A particle is, thus, always a reference (iterator) + to an entry on a stack, e.g. + + \verbatim + ModelStack stack; + stack.begin(); // returns an iterator: StackIterator, ConstStackIterator + + *stack.begin(); // return a reference to ParticleInterfaceType, which is the class +provided by the user to read/write particle properties + + \endverbatim + + All functionality and algorithms for stack data access is located in the namespace +corsika::stack + + The minimal example of how to use this is shown in stack_example.cc +**/ + namespace corsika { /** diff --git a/corsika/media/Universe.hpp b/corsika/media/Universe.hpp index af1ead8cb..cdd5c2bd2 100644 --- a/corsika/media/Universe.hpp +++ b/corsika/media/Universe.hpp @@ -15,7 +15,7 @@ namespace corsika { struct Universe : public corsika::Sphere { inline Universe(corsika::CoordinateSystemPtr const& pCS); - inline bool isInside(corsika::Point const&) const override; + inline bool contains(corsika::Point const&) const override; }; } // namespace corsika diff --git a/corsika/media/VolumeTreeNode.hpp b/corsika/media/VolumeTreeNode.hpp index 2647b4def..fba07bc58 100644 --- a/corsika/media/VolumeTreeNode.hpp +++ b/corsika/media/VolumeTreeNode.hpp @@ -29,9 +29,9 @@ namespace corsika { : geoVolume_(std::move(pVolume)) {} //! convenience function equivalent to Volume::isInside - inline bool isInside(Point const& p) const; + inline bool contains(Point const& p) const; - inline VolumeTreeNode<IModelProperties> const* isExcluded(Point const& p) const; + inline VolumeTreeNode<IModelProperties> const* excludes(Point const& p) const; /** returns a pointer to the sub-VolumeTreeNode which is "responsible" for the given * \class Point \p p, or nullptr iff \p p is not contained in this volume. diff --git a/corsika/modules/tracking/Intersect.hpp b/corsika/modules/tracking/Intersect.hpp index 14ba805b7..459cef850 100644 --- a/corsika/modules/tracking/Intersect.hpp +++ b/corsika/modules/tracking/Intersect.hpp @@ -37,100 +37,18 @@ namespace corsika { class Intersect { protected: + /** + * Determines next intersection with any of the geometry volumes. + * + * + */ template <typename TParticle> - auto nextIntersect( - const TParticle& particle, - TimeType step_limit = std::numeric_limits<TimeType::value_type>::infinity() * - second) const { - - typedef - typename std::remove_reference<decltype(*particle.getNode())>::type node_type; - - node_type& volumeNode = - *particle.getNode(); // current "logical" node, from previous tracking step - CORSIKA_LOG_DEBUG("volumeNode={}, numericallyInside={} ", fmt::ptr(&volumeNode), - volumeNode.getVolume().isInside(particle.getPosition())); - - // start values: - TimeType minTime = step_limit; - node_type* minNode = &volumeNode; - - // determine the first geometric collision with any other Volume boundary - - // first check, where we leave the current volume - // this assumes our convention, that all Volume primitives must be convex - // thus, the last entry is always the exit point - const Intersections time_intersections_curr = - TDerived::intersect(particle, volumeNode); - CORSIKA_LOG_TRACE("curr node {}, parent node {}, hasIntersections={} ", - fmt::ptr(&volumeNode), fmt::ptr(volumeNode.getParent()), - time_intersections_curr.hasIntersections()); - if (time_intersections_curr.hasIntersections()) { - CORSIKA_LOG_DEBUG( - "intersection times with currentLogicalVolumeNode: {} s and {} s", - time_intersections_curr.getEntry() / 1_s, - time_intersections_curr.getExit() / 1_s); - if (time_intersections_curr.getExit() <= minTime) { - minTime = - time_intersections_curr.getExit(); // we exit currentLogicalVolumeNode here - minNode = volumeNode.getParent(); - } - } - - // where do we collide with any of the next-tree-level volumes - // entirely contained by currentLogicalVolumeNode - for (const auto& node : volumeNode.getChildNodes()) { - - const Intersections time_intersections = TDerived::intersect(particle, *node); - if (!time_intersections.hasIntersections()) { continue; } - CORSIKA_LOG_DEBUG( - "intersection times with child volume {} : enter {} s, exit {} s", - fmt::ptr(node), time_intersections.getEntry() / 1_s, - time_intersections.getExit() / 1_s); - - const auto t_entry = time_intersections.getEntry(); - const auto t_exit = time_intersections.getExit(); - CORSIKA_LOG_TRACE("children t-entry: {}, t-exit: {}, smaller? {} ", t_entry, - t_exit, t_entry <= minTime); - // note, theoretically t can even be smaller than 0 since we - // KNOW we can't yet be in this volume yet, so we HAVE TO - // enter it IF exit point is not also in the "past", AND if - // extry point is [[much much]] closer than exit point - // (because we might have already numerically "exited" it)! - if (t_exit > 0_s && t_entry <= minTime && - -t_entry < t_exit) { // protection agains numerical problem, when we already - // _exited_ before - // enter chile volume here - minTime = t_entry; - minNode = node.get(); - } - } - - // these are volumes from the previous tree-level that are cut-out partly from the - // current volume - for (node_type* node : volumeNode.getExcludedNodes()) { - - const Intersections time_intersections = TDerived::intersect(particle, *node); - if (!time_intersections.hasIntersections()) { continue; } - CORSIKA_LOG_DEBUG( - "intersection times with exclusion volume {} : enter {} s, exit {} s", - fmt::ptr(node), time_intersections.getEntry() / 1_s, - time_intersections.getExit() / 1_s); - const auto t_entry = time_intersections.getEntry(); - const auto t_exit = time_intersections.getExit(); - CORSIKA_LOG_TRACE("children t-entry: {}, t-exit: {}, smaller? {} ", t_entry, - t_exit, t_entry <= minTime); - // note, theoretically t can even be smaller than 0 since we - // KNOW we can't yet be in this volume yet, so we HAVE TO - // enter it IF exit point is not also in the "past"! - if (t_exit > 0_s && t_entry <= minTime) { // enter volumen child here - minTime = t_entry; - minNode = node; - } - } - CORSIKA_LOG_TRACE("t-intersect: {}, node {} ", minTime, fmt::ptr(minNode)); - return std::make_tuple(minTime, minNode); - } + auto nextIntersect(TParticle const& particle, + TimeType const step_limit = + std::numeric_limits<TimeType::value_type>::infinity() * + second) const; }; } // namespace corsika + +#include <corsika/detail/modules/tracking/Intersect.inl> diff --git a/corsika/modules/tracking/TrackingLeapFrogCurved.hpp b/corsika/modules/tracking/TrackingLeapFrogCurved.hpp index bb75daf62..883f96dbc 100644 --- a/corsika/modules/tracking/TrackingLeapFrogCurved.hpp +++ b/corsika/modules/tracking/TrackingLeapFrogCurved.hpp @@ -12,7 +12,7 @@ #include <corsika/framework/geometry/Line.hpp> #include <corsika/framework/geometry/Plane.hpp> #include <corsika/framework/geometry/Sphere.hpp> -#include <corsika/framework/geometry/Trajectory.hpp> +#include <corsika/framework/geometry/LeapFrogTrajectory.hpp> #include <corsika/framework/geometry/Vector.hpp> #include <corsika/framework/geometry/Intersections.hpp> #include <corsika/framework/core/ParticleProperties.hpp> @@ -29,6 +29,7 @@ namespace corsika { namespace tracking_leapfrog_curved { /** + * \file TrackingLeapFrogCurved.hpp * \function LeapFrogStep * * Performs one leap-frog step consistent of two halve-steps with steplength/2 @@ -36,32 +37,7 @@ namespace corsika { *boundary. **/ template <typename TParticle> - auto LeapFrogStep(TParticle const& particle, LengthType steplength) { - if (particle.getMomentum().norm() == 0_GeV) { - return std::make_tuple(particle.getPosition(), particle.getMomentum() / 1_GeV, - double(0)); - } // charge of the particle - int const chargeNumber = particle.getChargeNumber(); - auto const* currentLogicalVolumeNode = particle.getNode(); - MagneticFieldVector const& magneticfield = - currentLogicalVolumeNode->getModelProperties().getMagneticField( - particle.getPosition()); - VelocityVector velocity = - particle.getMomentum() / particle.getEnergy() * constants::c; - decltype(meter / (second * volt)) k = - chargeNumber * constants::cSquared * 1_eV / - (velocity.getNorm() * particle.getEnergy() * 1_V); - DirectionVector direction = velocity.normalized(); - auto position = particle.getPosition(); // First Movement - // assuming magnetic field does not change during movement - position = - position + direction * steplength / 2; // Change of direction by magnetic field - direction = - direction + direction.cross(magneticfield) * steplength * k; // Second Movement - position = position + direction * steplength / 2; - auto steplength_true = steplength * (1.0 + (double)direction.getNorm()) / 2; - return std::make_tuple(position, direction.normalized(), steplength_true); - } + auto make_LeapFrogStep(TParticle const& particle, LengthType steplength); /** * @@ -82,185 +58,15 @@ namespace corsika { : straightTracking_{tracking_line::Tracking()} {} template <typename TParticle> - auto getTrack(TParticle const& particle) { - VelocityVector const initialVelocity = - particle.getMomentum() / particle.getEnergy() * constants::c; - - auto const position = particle.getPosition(); - CORSIKA_LOG_DEBUG( - "Tracking pid: {}" - " , E = {} GeV", - particle.getPID(), particle.getEnergy() / 1_GeV); - CORSIKA_LOG_DEBUG("Tracking pos: {}", position.getCoordinates()); - CORSIKA_LOG_DEBUG("Tracking E: {} GeV", particle.getEnergy() / 1_GeV); - CORSIKA_LOG_DEBUG("Tracking p: {} GeV", - particle.getMomentum().getComponents() / 1_GeV); - CORSIKA_LOG_DEBUG("Tracking v: {} ", initialVelocity.getComponents()); - - typedef - typename std::remove_reference<decltype(*particle.getNode())>::type node_type; - node_type& volumeNode = *particle.getNode(); - - // for the event of magnetic fields and curved trajectories, we need to limit - // maximum step-length since we need to follow curved - // trajectories segment-wise -- at least if we don't employ concepts as "Helix - // Trajectories" or similar - MagneticFieldVector const& magneticfield = - volumeNode.getModelProperties().getMagneticField(position); - MagneticFluxType const magnitudeB = magneticfield.getNorm(); - int const chargeNumber = particle.getChargeNumber(); - bool const no_deflection = chargeNumber == 0 || magnitudeB == 0_T; - - if (no_deflection) { return getLinearTrajectory(particle); } - - HEPMomentumType const pAlongB_delta = - (particle.getMomentum() - - particle.getMomentum().getParallelProjectionOnto(magneticfield)) - .getNorm(); - - if (pAlongB_delta == 0_GeV) { - // particle travel along, parallel to magnetic field. Rg is - // "0", but for purpose of step limit we return infinity here. - CORSIKA_LOG_TRACE("pAlongB_delta is 0_GeV --> parallel"); - return getLinearTrajectory(particle); - } - - LengthType const gyroradius = - (pAlongB_delta * 1_V / - (constants::c * abs(chargeNumber) * magnitudeB * 1_eV)); - - const double maxRadians = 0.01; - const LengthType steplimit = 2 * cos(maxRadians) * sin(maxRadians) * gyroradius; - const TimeType steplimit_time = steplimit / initialVelocity.getNorm(); - CORSIKA_LOG_DEBUG("gyroradius {}, steplimit: {} = {}", gyroradius, steplimit, - steplimit_time); - - // traverse the environment volume tree and find next - // intersection - auto [minTime, minNode] = nextIntersect(particle, steplimit_time); - - const auto k = - chargeNumber * constants::cSquared * 1_eV / (particle.getEnergy() * 1_V); - return std::make_tuple( - LeapFrogTrajectory(position, initialVelocity, magneticfield, k, - minTime), // trajectory - minNode); // next volume node - } + auto getTrack(TParticle const& particle); template <typename TParticle, typename TMedium> static Intersections intersect(const TParticle& particle, const Sphere& sphere, - const TMedium& medium) { - - if (sphere.getRadius() == 1_km * std::numeric_limits<double>::infinity()) { - return Intersections(); - } - - int const chargeNumber = particle.getChargeNumber(); - auto const& position = particle.getPosition(); - MagneticFieldVector const& magneticfield = medium.getMagneticField(position); - - VelocityVector const velocity = - particle.getMomentum() / particle.getEnergy() * constants::c; - DirectionVector const directionBefore = - velocity.normalized(); // determine steplength to next volume - - auto const projectedDirection = directionBefore.cross(magneticfield); - auto const projectedDirectionSqrNorm = projectedDirection.getSquaredNorm(); - bool const isParallel = (projectedDirectionSqrNorm == 0 * square(1_T)); - - if (chargeNumber == 0 || magneticfield.getNorm() == 0_T || isParallel) { - return tracking_line::Tracking::intersect(particle, sphere, medium); - } - - bool const numericallyInside = sphere.isInside(particle.getPosition()); - - const auto absVelocity = velocity.getNorm(); - auto energy = particle.getEnergy(); - auto k = chargeNumber * constants::cSquared * 1_eV / (absVelocity * energy * 1_V); - - auto const denom = - (directionBefore.cross(magneticfield)).getSquaredNorm() * k * k; - const double a = - ((directionBefore.cross(magneticfield)).dot(position - sphere.getCenter()) * - k + - 1) * - 4 / (1_m * 1_m * denom); - const double b = directionBefore.dot(position - sphere.getCenter()) * 8 / - (denom * 1_m * 1_m * 1_m); - const double c = ((position - sphere.getCenter()).getSquaredNorm() - - (sphere.getRadius() * sphere.getRadius())) * - 4 / (denom * 1_m * 1_m * 1_m * 1_m); - CORSIKA_LOG_TRACE("denom={}, a={}, b={}, c={}", denom, a, b, c); - std::complex<double>* solutions = quartic_solver::solve_quartic(0, a, b, c); - LengthType d_enter, d_exit; - int first = 0, first_entry = 0, first_exit = 0; - for (int i = 0; i < 4; i++) { - if (solutions[i].imag() == 0) { - LengthType const dist = solutions[i].real() * 1_m; - CORSIKA_LOG_TRACE("Solution (real) for current Volume: {} ", dist); - if (numericallyInside) { - // there must be an entry (negative) and exit (positive) solution - if (dist < -0.0001_m) { // security margin to assure transfer to next - // logical volume - if (first_entry == 0) { - d_enter = dist; - } else { - d_enter = std::max(d_enter, dist); // closest negative to zero (-1e-4) m - } - first_entry++; - - } else { // thus, dist >= -0.0001_m - - if (first_exit == 0) { - d_exit = dist; - } else { - d_exit = std::min(d_exit, dist); // closest positive to zero (-1e-4) m - } - first_exit++; - } - first = int(first_exit > 0) + int(first_entry > 0); - - } else { // thus, numericallyInside == false - - // both physical solutions (entry, exit) must be positive, and as small as - // possible - if (dist < -0.0001_m) { // need small numerical margin, to assure transport - // into next logical volume - continue; - } - if (first == 0) { - d_enter = dist; - } else { - if (dist < d_enter) { - d_exit = d_enter; - d_enter = dist; - } else { - d_exit = dist; - } - } - first++; - } - } // loop over solutions - } - delete[] solutions; - - if (first != 2) { // entry and exit points found - CORSIKA_LOG_DEBUG("no intersection! count={}", first); - return Intersections(); - } - return Intersections(d_enter / absVelocity, d_exit / absVelocity); - } + const TMedium& medium); template <typename TParticle, typename TBaseNodeType> static Intersections intersect(const TParticle& particle, - const TBaseNodeType& volumeNode) { - const Sphere* sphere = dynamic_cast<const Sphere*>(&volumeNode.getVolume()); - if (sphere) { - return intersect(particle, *sphere, volumeNode.getModelProperties()); - } - throw std::runtime_error( - "The Volume type provided is not supported in intersect(particle, node)"); - } + const TBaseNodeType& volumeNode); protected: /** @@ -270,22 +76,7 @@ namespace corsika { * */ template <typename TParticle> - auto getLinearTrajectory(TParticle& particle) { - - // perform simple linear tracking - auto [straightTrajectory, minNode] = straightTracking_.getTrack(particle); - - // return as leap-frog trajectory - return std::make_tuple( - LeapFrogTrajectory( - straightTrajectory.getLine().getStartPoint(), - straightTrajectory.getLine().getVelocity(), - MagneticFieldVector(particle.getPosition().getCoordinateSystem(), 0_T, - 0_T, 0_T), - square(0_m) / (square(1_s) * 1_V), - straightTrajectory.getDuration()), // trajectory - minNode); // next volume node - } + auto getLinearTrajectory(TParticle& particle); protected: tracking_line::Tracking @@ -296,3 +87,5 @@ namespace corsika { } // namespace tracking_leapfrog_curved } // namespace corsika + +#include <corsika/detail/modules/tracking/TrackingLeapFrogCurved.inl> diff --git a/corsika/modules/tracking/TrackingLeapFrogStraight.hpp b/corsika/modules/tracking/TrackingLeapFrogStraight.hpp index 0bc38b93d..f54e355ba 100644 --- a/corsika/modules/tracking/TrackingLeapFrogStraight.hpp +++ b/corsika/modules/tracking/TrackingLeapFrogStraight.hpp @@ -11,7 +11,7 @@ #include <corsika/framework/geometry/Line.hpp> #include <corsika/framework/geometry/Plane.hpp> #include <corsika/framework/geometry/Sphere.hpp> -#include <corsika/framework/geometry/Trajectory.hpp> +#include <corsika/framework/geometry/StraightTrajectory.hpp> #include <corsika/framework/geometry/Vector.hpp> #include <corsika/framework/core/ParticleProperties.hpp> #include <corsika/framework/core/PhysicalUnits.hpp> @@ -50,171 +50,16 @@ namespace corsika { * relative to full linear step to next volume boundary. This * should not be less than 0.5, otherwise you risk that * particles will never travel from one volume to the next - * one. A cross should be possible (even likely). If - * firstFraction is too big (~1) the resulting calculated error - * will be largest. + * one. A crossing must be possible (even likely). However, if + * firstFraction is too big (~1) the resulting calculated + * numerical error will be largest. * */ Tracking(double const firstFraction = 0.55) : firstFraction_(firstFraction) {} template <typename Particle> - auto getTrack(Particle& particle) { - VelocityVector initialVelocity = - particle.getMomentum() / particle.getEnergy() * constants::c; - - const Point initialPosition = particle.getPosition(); - CORSIKA_LOG_DEBUG( - "TrackingB pid: {}" - " , E = {} GeV", - particle.getPID(), particle.getEnergy() / 1_GeV); - CORSIKA_LOG_DEBUG("TrackingB pos: {}", initialPosition.getCoordinates()); - CORSIKA_LOG_DEBUG("TrackingB E: {} GeV", particle.getEnergy() / 1_GeV); - CORSIKA_LOG_DEBUG("TrackingB p: {} GeV", - particle.getMomentum().getComponents() / 1_GeV); - CORSIKA_LOG_DEBUG("TrackingB v: {} ", initialVelocity.getComponents()); - - typedef decltype(particle.getNode()) node_type; - node_type const volumeNode = particle.getNode(); - - // check if particle is moving at all - auto const absVelocity = initialVelocity.getNorm(); - if (absVelocity * 1_s == 0_m) { - return std::make_tuple( - LineTrajectory(Line(initialPosition, initialVelocity), 0_s), volumeNode); - } - - // charge of the particle, and magnetic field - const int chargeNumber = particle.getChargeNumber(); - auto magneticfield = - volumeNode->getModelProperties().getMagneticField(initialPosition); - const auto magnitudeB = magneticfield.getNorm(); - CORSIKA_LOG_DEBUG("field={} uT, chargeNumber={}, magnitudeB={} uT", - magneticfield.getComponents() / 1_uT, chargeNumber, - magnitudeB / 1_T); - bool const no_deflection = chargeNumber == 0 || magnitudeB == 0_T; - - // check, where the first halve-step direction has geometric intersections - const auto [initialTrack, initialTrackNextVolume] = - tracking_line::Tracking::getTrack(particle); - { [[maybe_unused]] auto& initialTrackNextVolume_dum = initialTrackNextVolume; } - const auto initialTrackLength = initialTrack.getLength(1); - - CORSIKA_LOG_DEBUG("initialTrack(0)={}, initialTrack(1)={}, initialTrackLength={}", - initialTrack.getPosition(0).getCoordinates(), - initialTrack.getPosition(1).getCoordinates(), - initialTrackLength); - - // if particle is non-deflectable, we are done: - if (no_deflection) { - CORSIKA_LOG_DEBUG("no deflection. tracking finished"); - return std::make_tuple(initialTrack, initialTrackNextVolume); - } - - HEPMomentumType const pAlongB_delta = - (particle.getMomentum() - - particle.getMomentum().getParallelProjectionOnto(magneticfield)) - .getNorm(); - - if (pAlongB_delta == 0_GeV) { - // particle travel along, parallel to magnetic field. Rg is - // "0", but for purpose of step limit we return infinity here. - CORSIKA_LOG_TRACE("pAlongB_delta is 0_GeV --> parallel"); - return std::make_tuple(initialTrack, initialTrackNextVolume); - } - - LengthType const gyroradius = - (pAlongB_delta * 1_V / - (constants::c * abs(chargeNumber) * magnitudeB * 1_eV)); - - // we need to limit maximum step-length since we absolutely - // need to follow strongly curved trajectories segment-wise, - // at least if we don't employ concepts as "Helix - // Trajectories" or similar - const double maxRadians = 0.01; - const LengthType steplimit = 2 * cos(maxRadians) * sin(maxRadians) * gyroradius; - CORSIKA_LOG_DEBUG("gyroradius {}, Steplimit: {}", gyroradius, steplimit); - - // calculate first halve step for "steplimit" - auto const initialMomentum = particle.getMomentum(); - auto const absMomentum = initialMomentum.getNorm(); - DirectionVector const direction = initialVelocity.normalized(); - - // avoid any intersections within first halve steplength - LengthType const firstHalveSteplength = - std::min(steplimit, initialTrackLength * firstFraction_); - - CORSIKA_LOG_DEBUG( - "first halve step length {}, steplimit={}, initialTrackLength={}", - firstHalveSteplength, steplimit, initialTrackLength); - // perform the first halve-step - const Point position_mid = initialPosition + direction * firstHalveSteplength; - const auto k = - chargeNumber * constants::c * 1_eV / (particle.getMomentum().getNorm() * 1_V); - const auto new_direction = - direction + direction.cross(magneticfield) * firstHalveSteplength * 2 * k; - const auto new_direction_norm = new_direction.getNorm(); // by design this is >1 - CORSIKA_LOG_DEBUG( - "position_mid={}, new_direction={}, (new_direction_norm)={}, deflection={}", - position_mid.getCoordinates(), new_direction.getComponents(), - new_direction_norm, - acos(std::min(1.0, direction.dot(new_direction) / new_direction_norm)) * 180 / - M_PI); - - // check, where the second halve-step direction has geometric intersections - particle.setPosition(position_mid); - particle.setMomentum(new_direction * absMomentum); - const auto [finalTrack, finalTrackNextVolume] = - tracking_line::Tracking::getTrack(particle); - particle.setPosition(initialPosition); // this is not nice... - particle.setMomentum(initialMomentum); // this is not nice... - - LengthType const finalTrackLength = finalTrack.getLength(1); - LengthType const secondLeapFrogLength = firstHalveSteplength * new_direction_norm; - - // check if volume transition is obvious, OR - // for numerical reasons, particles slighly bend "away" from a - // volume boundary have a very hard time to cross the border, - // thus, if secondLeapFrogLength is just slighly shorter (1e-4m) than - // finalTrackLength we better just [extend the - // secondLeapFrogLength slightly and] force the volume - // crossing: - bool const switch_volume = finalTrackLength - 0.0001_m <= secondLeapFrogLength; - LengthType const secondHalveStepLength = - std::min(secondLeapFrogLength, finalTrackLength); - - CORSIKA_LOG_DEBUG( - "finalTrack(0)={}, finalTrack(1)={}, finalTrackLength={}, " - "secondLeapFrogLength={}, secondHalveStepLength={}, " - "secondLeapFrogLength-finalTrackLength={}, " - "secondHalveStepLength-finalTrackLength={}, " - "nextVol={}, transition={}", - finalTrack.getPosition(0).getCoordinates(), - finalTrack.getPosition(1).getCoordinates(), finalTrackLength, - secondLeapFrogLength, secondHalveStepLength, - secondLeapFrogLength - finalTrackLength, - secondHalveStepLength - finalTrackLength, fmt::ptr(finalTrackNextVolume), - switch_volume); - - // perform the second halve-step - auto const new_direction_normalized = new_direction.normalized(); - const Point finalPosition = - position_mid + new_direction_normalized * secondHalveStepLength; - - const LengthType totalStep = firstHalveSteplength + secondHalveStepLength; - const auto delta_pos = finalPosition - initialPosition; - const auto distance = delta_pos.getNorm(); - - return std::make_tuple( - LineTrajectory(Line(initialPosition, - (distance == 0_m ? initialVelocity - : delta_pos.normalized() * absVelocity)), - distance / absVelocity, // straight distance - totalStep / absVelocity, // bend distance - initialVelocity, - new_direction_normalized * absVelocity), // trajectory - (switch_volume ? finalTrackNextVolume : volumeNode)); - } + auto getTrack(Particle& particle); protected: double firstFraction_; @@ -223,3 +68,5 @@ namespace corsika { } // namespace tracking_leapfrog_straight } // namespace corsika + +#include <corsika/detail/modules/tracking/TrackingLeapFrogStraight.inl> diff --git a/corsika/modules/tracking/TrackingStraight.hpp b/corsika/modules/tracking/TrackingStraight.hpp index f563766d5..c595a75a5 100644 --- a/corsika/modules/tracking/TrackingStraight.hpp +++ b/corsika/modules/tracking/TrackingStraight.hpp @@ -13,7 +13,7 @@ #include <corsika/framework/geometry/Plane.hpp> #include <corsika/framework/geometry/Sphere.hpp> #include <corsika/framework/geometry/Vector.hpp> -#include <corsika/framework/geometry/Trajectory.hpp> +#include <corsika/framework/geometry/StraightTrajectory.hpp> #include <corsika/framework/geometry/Intersections.hpp> #include <corsika/framework/logging/Logging.hpp> #include <corsika/modules/tracking/Intersect.hpp> @@ -24,9 +24,10 @@ namespace corsika::tracking_line { /** - * \class Tracking - * + * Tracking of particles without charge or in no magnetic fields. * + * This will simply follow traight lines, but intersect them with + * the geometry volume model of the environment. * **/ @@ -35,77 +36,26 @@ namespace corsika::tracking_line { using Intersect<Tracking>::nextIntersect; public: + //! Determine track of particle template <typename TParticle> - auto getTrack(TParticle const& particle) { - VelocityVector const initialVelocity = - particle.getMomentum() / particle.getEnergy() * constants::c; - - auto const initialPosition = particle.getPosition(); - CORSIKA_LOG_DEBUG( - "Tracking pid: {}" - " , E = {} GeV", - particle.getPID(), particle.getEnergy() / 1_GeV); - CORSIKA_LOG_DEBUG("Tracking pos: {}", initialPosition.getCoordinates()); - CORSIKA_LOG_DEBUG("Tracking E: {} GeV", particle.getEnergy() / 1_GeV); - CORSIKA_LOG_DEBUG("Tracking p: {} GeV", - particle.getMomentum().getComponents() / 1_GeV); - CORSIKA_LOG_DEBUG("Tracking v: {} ", initialVelocity.getComponents()); - - // traverse the environment volume tree and find next - // intersection - auto [minTime, minNode] = nextIntersect(particle); - - return std::make_tuple(LineTrajectory(Line(initialPosition, initialVelocity), - minTime), // trajectory - minNode); // next volume node - } + auto getTrack(TParticle const& particle); + //! find intersection of Sphere with Track template <typename TParticle, typename TMedium> static Intersections intersect(TParticle const& particle, Sphere const& sphere, - TMedium const&) { - auto const delta = particle.getPosition() - sphere.getCenter(); - auto const velocity = particle.getMomentum() / particle.getEnergy() * constants::c; - auto const vSqNorm = velocity.getSquaredNorm(); - auto const R = sphere.getRadius(); - - auto const vDotDelta = velocity.dot(delta); - auto const discriminant = - vDotDelta * vDotDelta - vSqNorm * (delta.getSquaredNorm() - R * R); - - if (discriminant.magnitude() > 0) { - auto const sqDisc = sqrt(discriminant); - auto const invDenom = 1 / vSqNorm; - return Intersections((-vDotDelta - sqDisc) * invDenom, - (-vDotDelta + sqDisc) * invDenom); - } - return Intersections(); - } + TMedium const&); + //! find intersection of Volume with Track template <typename TParticle, typename TBaseNodeType> static Intersections intersect(TParticle const& particle, - TBaseNodeType const& volumeNode) { - Sphere const* sphere = dynamic_cast<Sphere const*>(&volumeNode.getVolume()); - if (sphere) { - return intersect(particle, *sphere, volumeNode.getModelProperties()); - } - throw std::runtime_error( - "The Volume type provided is not supported in Intersect(particle, node)"); - } + TBaseNodeType const& volumeNode); + //! find intersection of Plane with Track template <typename TParticle, typename TMedium> static Intersections intersect(TParticle const& particle, Plane const& plane, - TMedium const&) { - auto const delta = plane.getCenter() - particle.getPosition(); - auto const velocity = particle.getMomentum() / particle.getEnergy() * constants::c; - auto const n = plane.getNormal(); - auto const c = n.dot(velocity); - - return Intersections( - c.magnitude() == 0 ? std::numeric_limits<TimeType::value_type>::infinity() * 1_s - : n.dot(delta) / c); - } + TMedium const&); }; } // namespace corsika::tracking_line -// #include <corsika/detail/modules/tracking/TrackingLine.inl> +#include <corsika/detail/modules/tracking/TrackingStraight.inl> diff --git a/corsika/setup/SetupTrajectory.hpp b/corsika/setup/SetupTrajectory.hpp index a20d1db3d..fdbfcbeaa 100644 --- a/corsika/setup/SetupTrajectory.hpp +++ b/corsika/setup/SetupTrajectory.hpp @@ -8,7 +8,8 @@ #pragma once -#include <corsika/framework/geometry/Trajectory.hpp> +#include <corsika/framework/geometry/StraightTrajectory.hpp> +#include <corsika/framework/geometry/LeapFrogTrajectory.hpp> #include <corsika/modules/Tracking.hpp> namespace corsika::setup { @@ -45,7 +46,7 @@ namespace corsika::setup { The default trajectory. */ /// definition of Trajectory base class, to be used in tracking and cascades - typedef LineTrajectory Trajectory; + typedef StraightTrajectory Trajectory; // typedef corsika::geometry::LeapFrogTrajectory Trajectory; } // namespace corsika::setup diff --git a/corsika/stack/NuclearStackExtension.hpp b/corsika/stack/NuclearStackExtension.hpp index c9559a753..bcd187c05 100644 --- a/corsika/stack/NuclearStackExtension.hpp +++ b/corsika/stack/NuclearStackExtension.hpp @@ -14,7 +14,7 @@ #include <corsika/framework/geometry/Point.hpp> #include <corsika/framework/geometry/Vector.hpp> #include <corsika/framework/geometry/PhysicalGeometry.hpp> -#include <corsika/stack/SuperStupidStack.hpp> +#include <corsika/stack/SimpleStack.hpp> #include <algorithm> #include <tuple> @@ -27,7 +27,7 @@ namespace corsika::nuclear_stack { * Define ParticleInterface for NuclearStackExtension Stack derived from * ParticleInterface of Inner stack class * - * Add A and Z data to existing stack (currently SuperStupidStack) of particle + * Add A and Z data to existing stack (currently SimpleStack) 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. @@ -210,11 +210,11 @@ namespace corsika::nuclear_stack { // template <typename TStackIter> using ExtendedParticleInterfaceType = - NuclearParticleInterface<SuperStupidStack::pi_type, TStackIter>; + NuclearParticleInterface<SimpleStack::pi_type, TStackIter>; // the particle data stack with extra nuclear information: using ParticleDataStack = - NuclearStackExtension<SuperStupidStack, ExtendedParticleInterfaceType>; + NuclearStackExtension<SimpleStack, ExtendedParticleInterfaceType>; } // namespace corsika::nuclear_stack diff --git a/corsika/stack/SuperStupidStack.hpp b/corsika/stack/SuperStupidStack.hpp deleted file mode 100644 index 81e44a49c..000000000 --- a/corsika/stack/SuperStupidStack.hpp +++ /dev/null @@ -1,176 +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/framework/core/ParticleProperties.hpp> -#include <corsika/framework/core/PhysicalUnits.hpp> -#include <corsika/framework/stack/Stack.hpp> - -#include <corsika/framework/geometry/Point.hpp> -#include <corsika/framework/geometry/Vector.hpp> -#include <corsika/framework/geometry/PhysicalGeometry.hpp> - -#include <string> -#include <tuple> -#include <vector> - -namespace corsika { - - /** - * Example of a particle object on the stack. - */ - - template <typename StackIteratorInterface> - struct ParticleInterface : public ParticleBase<StackIteratorInterface> { - - private: - typedef ParticleBase<StackIteratorInterface> super_type; - - public: - std::string asString() const { - return fmt::format("particle: i={}, PID={}, E={}GeV", super_type::getIndex(), - get_name(this->getPID()), this->getEnergy() / 1_GeV); - } - - void setParticleData( - std::tuple<Code, HEPEnergyType, MomentumVector, Point, TimeType> const& v); - - void setParticleData( - ParticleInterface<StackIteratorInterface> const&, - std::tuple<Code, HEPEnergyType, MomentumVector, Point, TimeType> const& v); - - /// individual setters - void setPID(Code const id) { - super_type::getStackData().setPID(super_type::getIndex(), id); - } - void setEnergy(HEPEnergyType const& e) { - super_type::getStackData().setEnergy(super_type::getIndex(), e); - } - void setMomentum(MomentumVector const& v) { - super_type::getStackData().setMomentum(super_type::getIndex(), v); - } - void setPosition(Point const& v) { - super_type::getStackData().setPosition(super_type::getIndex(), v); - } - void setTime(TimeType const& v) { - super_type::getStackData().setTime(super_type::getIndex(), v); - } - - /// individual getters - Code getPID() const { - return super_type::getStackData().getPID(super_type::getIndex()); - } - HEPEnergyType getEnergy() const { - return super_type::getStackData().getEnergy(super_type::getIndex()); - } - MomentumVector getMomentum() const { - return super_type::getStackData().getMomentum(super_type::getIndex()); - } - Point getPosition() const { - return super_type::getStackData().getPosition(super_type::getIndex()); - } - TimeType getTime() const { - return super_type::getStackData().getTime(super_type::getIndex()); - } - /** - * @name derived quantities - * - * @{ - */ - DirectionVector getDirection() const { - return this->getMomentum() / this->getEnergy(); - } - - HEPMassType getMass() const { return get_mass(this->getPID()); } - - int16_t getChargeNumber() const { return get_charge_number(this->getPID()); } - ///@} - }; - - /** - * Memory implementation of the most simple (stupid) particle stack object. - * - */ - - class SuperStupidStackImpl { - - public: - typedef std::vector<Code> code_vector_type; - typedef std::vector<HEPEnergyType> energy_vector_type; - typedef std::vector<Point> point_vector_type; - typedef std::vector<TimeType> time_vector_type; - typedef std::vector<MomentumVector> momentum_vector_type; - - SuperStupidStackImpl() = default; - - SuperStupidStackImpl(SuperStupidStackImpl const& other) = default; - - SuperStupidStackImpl(SuperStupidStackImpl&& other) = default; - - SuperStupidStackImpl& operator=(SuperStupidStackImpl const& other) = default; - - SuperStupidStackImpl& operator=(SuperStupidStackImpl&& other) = default; - - void dump() const {} - - inline void clear(); - - unsigned int getSize() const { return dataPID_.size(); } - unsigned int getCapacity() const { return dataPID_.size(); } - - void setPID(size_t i, Code const id) { dataPID_[i] = id; } - void setEnergy(size_t i, HEPEnergyType const& e) { dataE_[i] = e; } - void setMomentum(size_t i, MomentumVector const& v) { momentum_[i] = v; } - void setPosition(size_t i, Point const& v) { position_[i] = v; } - void setTime(size_t i, TimeType const& v) { time_[i] = v; } - - Code getPID(size_t i) const { return dataPID_[i]; } - - HEPEnergyType getEnergy(size_t i) const { return dataE_[i]; } - - MomentumVector getMomentum(size_t i) const { return momentum_[i]; } - - Point getPosition(size_t i) const { return position_[i]; } - TimeType getTime(size_t i) const { return time_[i]; } - - HEPEnergyType getDataE(size_t i) const { return dataE_[i]; } - - void setDataE(size_t i, HEPEnergyType const& dataE) { dataE_[i] = dataE; } - - Code getDataPid(size_t i) const { return dataPID_[i]; } - - void setDataPid(size_t i, Code const& dataPid) { dataPID_[i] = dataPid; } - /** - * Function to copy particle at location i2 in stack to i1 - */ - inline void copy(size_t i1, size_t i2); - - /** - * Function to copy particle at location i2 in stack to i1 - */ - inline void swap(size_t i1, size_t i2); - - inline void incrementSize(); - inline void decrementSize(); - - private: - /// the actual memory to store particle data - code_vector_type dataPID_; - energy_vector_type dataE_; - momentum_vector_type momentum_; - point_vector_type position_; - time_vector_type time_; - - }; // end class SuperStupidStackImpl - - typedef Stack<SuperStupidStackImpl, ParticleInterface> SuperStupidStack; - -} // namespace corsika - -#include <corsika/detail/stack/SuperStupidStack.inl> diff --git a/examples/geometry_example.cpp b/examples/geometry_example.cpp index cca5656e3..8c471cb60 100644 --- a/examples/geometry_example.cpp +++ b/examples/geometry_example.cpp @@ -51,12 +51,12 @@ int main() { assert(norm == 1 * meter * meter); Sphere s(p1, 10_m); // define a sphere around a point with a radius - CORSIKA_LOG_INFO("p1 inside s:{} ", s.isInside(p2)); - assert(s.isInside(p2) == 1); + CORSIKA_LOG_INFO("p1 inside s:{} ", s.contains(p2)); + assert(s.contains(p2) == 1); Sphere s2(p1, 3_um); // another sphere - CORSIKA_LOG_INFO("p1 inside s2: {}", s2.isInside(p2)); - assert(s2.isInside(p2) == 0); + CORSIKA_LOG_INFO("p1 inside s2: {}", s2.contains(p2)); + assert(s2.contains(p2) == 0); // let's try parallel projections: auto const v1 = Vector<length_d>(root, {1_m, 1_m, 0_m}); diff --git a/examples/stack_example.cpp b/examples/stack_example.cpp index 5e5f3ba70..196efa5c9 100644 --- a/examples/stack_example.cpp +++ b/examples/stack_example.cpp @@ -7,7 +7,7 @@ */ #include <corsika/framework/core/ParticleProperties.hpp> -#include <corsika/stack/SuperStupidStack.hpp> +#include <corsika/stack/SimpleStack.hpp> #include <corsika/framework/geometry/Point.hpp> #include <corsika/framework/geometry/RootCoordinateSystem.hpp> @@ -19,7 +19,7 @@ using namespace corsika; using namespace std; -void fill(SuperStupidStack& s) { +void fill(SimpleStack& s) { CoordinateSystemPtr const& rootCS = get_root_CoordinateSystem(); for (int i = 0; i < 11; ++i) { s.addParticle(std::make_tuple(Code::Electron, 1.5_GeV * i, @@ -28,7 +28,7 @@ void fill(SuperStupidStack& s) { } } -void read(SuperStupidStack& s) { +void read(SimpleStack& s) { assert(s.getEntries() == 11); // stack has 11 particles HEPEnergyType total_energy; @@ -44,7 +44,7 @@ void read(SuperStupidStack& s) { int main() { std::cout << "stack_example" << std::endl; - SuperStupidStack s; + SimpleStack s; fill(s); read(s); return 0; diff --git a/tests/common/SetupTestTrajectory.hpp b/tests/common/SetupTestTrajectory.hpp index dd028b0c7..0c06d7f39 100644 --- a/tests/common/SetupTestTrajectory.hpp +++ b/tests/common/SetupTestTrajectory.hpp @@ -11,8 +11,9 @@ #include <corsika/framework/core/PhysicalUnits.hpp> #include <corsika/framework/geometry/Line.hpp> #include <corsika/framework/geometry/Helix.hpp> -#include <corsika/framework/geometry/Trajectory.hpp> +#include <corsika/framework/geometry/StraightTrajectory.hpp> +// #include <corsika/framework/geometry/LeapFrogTrajectory.hpp> // #include <corsika/modules/TrackingLine.hpp> // #include <corsika/modules/TrackingCurved.hpp> // simple leap-frog implementation // #include <corsika/modules/TrackingLeapFrog.hpp> // more complete leap-frog @@ -24,9 +25,9 @@ namespace corsika::setup::testing { TTrack make_track(Line const& line, TimeType const tEnd); template <> - inline LineTrajectory make_track<LineTrajectory>(Line const& line, - TimeType const tEnd) { - return LineTrajectory(line, tEnd); + inline StraightTrajectory make_track<StraightTrajectory>(Line const& line, + TimeType const tEnd) { + return StraightTrajectory(line, tEnd); } /* diff --git a/tests/common/testTestStack.hpp b/tests/common/testTestStack.hpp index a905231fb..70f4d5f14 100644 --- a/tests/common/testTestStack.hpp +++ b/tests/common/testTestStack.hpp @@ -36,9 +36,8 @@ public: void setData(const unsigned int i, const double v) { data_[i] = v; } double getData(const unsigned int i) const { return data_[i]; } - // these functions are also needed by the Stack interface - void incrementSize() { data_.push_back(0.); } + void incrementSize() { data_.push_back(0.); } void decrementSize() { if (data_.size() > 0) { data_.pop_back(); } } @@ -60,13 +59,11 @@ private: * */ template <typename StackIteratorInterface> -class TestParticleInterface - : public corsika::ParticleBase<StackIteratorInterface> { - +class TestParticleInterface : public corsika::ParticleBase<StackIteratorInterface> { + typedef corsika::ParticleBase<StackIteratorInterface> super_type; - -public: +public: /* The SetParticleData methods are called for creating new entries on the stack. You can specifiy various parametric versions to @@ -81,6 +78,10 @@ public: } // here are the fundamental methods for access to TestStackData data - void setData(const double v) { super_type::getStackData().setData(super_type::getIndex(), v); } - double getData() const { return super_type::getStackData().getData(super_type::getIndex()); } + void setData(const double v) { + super_type::getStackData().setData(super_type::getIndex(), v); + } + double getData() const { + return super_type::getStackData().getData(super_type::getIndex()); + } }; diff --git a/tests/framework/testCascade.cpp b/tests/framework/testCascade.cpp index 6664f0acb..27880dfb8 100644 --- a/tests/framework/testCascade.cpp +++ b/tests/framework/testCascade.cpp @@ -68,7 +68,7 @@ public: VelocityVector const initialVelocity = particle.getMomentum() / particle.getEnergy() * constants::c; return std::make_tuple( - LineTrajectory( + StraightTrajectory( Line(particle.getPosition(), initialVelocity), std::numeric_limits<TimeType::value_type>::infinity() * 1_s), // trajectory, // just diff --git a/tests/framework/testGeometry.cpp b/tests/framework/testGeometry.cpp index 8f9ef0b85..3472cf2dd 100644 --- a/tests/framework/testGeometry.cpp +++ b/tests/framework/testGeometry.cpp @@ -16,7 +16,8 @@ #include <corsika/framework/geometry/Point.hpp> #include <corsika/framework/geometry/RootCoordinateSystem.hpp> #include <corsika/framework/geometry/Sphere.hpp> -#include <corsika/framework/geometry/Trajectory.hpp> +#include <corsika/framework/geometry/StraightTrajectory.hpp> +#include <corsika/framework/geometry/LeapFrogTrajectory.hpp> #include <PhysicalUnitsCatch2.hpp> // namespace corsike::testing @@ -228,7 +229,7 @@ TEST_CASE("CoordinateSystem hirarchy") { } TEST_CASE("Sphere") { - CoordinateSystemPtr rootCS = get_root_CoordinateSystem(); + CoordinateSystemPtr const& rootCS = get_root_CoordinateSystem(); Point center(rootCS, {0_m, 3_m, 4_m}); Sphere sphere(center, 5_m); @@ -241,8 +242,8 @@ TEST_CASE("Sphere") { } SECTION("isInside") { - CHECK_FALSE(sphere.isInside(Point(rootCS, {100_m, 0_m, 0_m}))); - CHECK(sphere.isInside(Point(rootCS, {2_m, 3_m, 4_m}))); + CHECK_FALSE(sphere.contains(Point(rootCS, {100_m, 0_m, 0_m}))); + CHECK(sphere.contains(Point(rootCS, {2_m, 3_m, 4_m}))); } } @@ -270,7 +271,7 @@ TEST_CASE("Trajectories") { .magnitude() == Approx(0).margin(absMargin)); auto const t = 1_s; - LineTrajectory base(line, t); + StraightTrajectory base(line, t); CHECK(line.getPosition(t).getCoordinates() == base.getPosition(1.).getCoordinates()); CHECK((base.getDirection(0).getComponents(rootCS) - diff --git a/tests/framework/testRandom.cpp b/tests/framework/testRandom.cpp index f31a2d9dc..17c9c7c7a 100644 --- a/tests/framework/testRandom.cpp +++ b/tests/framework/testRandom.cpp @@ -23,25 +23,25 @@ SCENARIO("random-number streams can be registered and retrieved") { RNGManager& rngManager = RNGManager::getInstance(); WHEN("the sequence name is not registered") { - REQUIRE(rngManager.isRegistered("stream_A") == false); + CHECK(rngManager.isRegistered("stream_A") == false); THEN("a sequence is registered by name") { rngManager.registerRandomStream("stream_A"); THEN("the sequence can be retrieved") { - REQUIRE_NOTHROW(rngManager.getRandomStream("stream_A")); + CHECK_NOTHROW(rngManager.getRandomStream("stream_A")); THEN("we can check that the sequence exists") { - REQUIRE_NOTHROW(rngManager.getRandomStream("stream_A")); + CHECK_NOTHROW(rngManager.getRandomStream("stream_A")); THEN("an unknown sequence cannot be retrieved") { - REQUIRE(rngManager.isRegistered("stream_A") == true); + CHECK(rngManager.isRegistered("stream_A") == true); THEN("an unknown sequence cannot be retrieved") { - REQUIRE_THROWS(rngManager.getRandomStream("stream_UNKNOWN")); + CHECK_THROWS(rngManager.getRandomStream("stream_UNKNOWN")); THEN("an unknown sequence is not registered") { - REQUIRE(rngManager.isRegistered("stream_UNKNOWN") == false); + CHECK(rngManager.isRegistered("stream_UNKNOWN") == false); } } } diff --git a/tests/modules/CMakeLists.txt b/tests/modules/CMakeLists.txt index 01f18af02..d72de5b53 100644 --- a/tests/modules/CMakeLists.txt +++ b/tests/modules/CMakeLists.txt @@ -2,17 +2,15 @@ set (test_modules_sources TestMain.cpp testStackInspector.cpp testTracking.cpp - # testExecTime.cpp + # testExecTime.cpp --> needs to be fixed, see #326 testObservationPlane.cpp testQGSJetII.cpp - # testSwitchProcess.cpp -> gone testPythia8.cpp testUrQMD.cpp testCONEX.cpp testOnShellCheck.cpp testParticleCut.cpp testSibyll.cpp - # testNullModel.cpp -> gone, framework now ) CORSIKA_ADD_TEST (testModules SOURCES ${test_modules_sources}) diff --git a/tests/modules/testInteractionCounter.cpp b/tests/modules/testInteractionCounter.cpp index 62a8c17df..6a147372f 100644 --- a/tests/modules/testInteractionCounter.cpp +++ b/tests/modules/testInteractionCounter.cpp @@ -1,5 +1,5 @@ /* - * (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu + * (c) Copyright 2021 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 @@ -46,7 +46,7 @@ TEST_CASE("InteractionCounter", "[process]") { InteractionCounter countedProcess(d); SECTION("GetInteractionLength") { - REQUIRE(countedProcess.GetInteractionLength(nullptr) == 100_g / 1_cm / 1_cm); + CHECK(countedProcess.GetInteractionLength(nullptr) == 100_g / 1_cm / 1_cm); } auto [env, csPtr, nodePtr] = setup::testing::setupEnvironment(particles::Code::Oxygen); @@ -56,19 +56,19 @@ TEST_CASE("InteractionCounter", "[process]") { unsigned short constexpr A = 14, Z = 7; auto [stackPtr, secViewPtr] = setup::testing::setupStack(particles::Code::Nucleus, A, Z, 105_TeV, nodePtr, *csPtr); - REQUIRE(stackPtr->getEntries() == 1); - REQUIRE(secViewPtr->getEntries() == 0); + CHECK(stackPtr->getEntries() == 1); + CHECK(secViewPtr->getEntries() == 0); auto const ret = countedProcess.DoInteraction(*secViewPtr); - REQUIRE(ret == nullptr); + CHECK(ret == nullptr); auto const& h = countedProcess.GetHistogram().labHist(); - REQUIRE(h.at(h.axis(0).index(1'000'070'140), h.axis(1).index(1.05e14)) == 1); - REQUIRE(std::accumulate(h.cbegin(), h.cend(), 0) == 1); + CHECK(h.at(h.axis(0).index(1'000'070'140), h.axis(1).index(1.05e14)) == 1); + CHECK(std::accumulate(h.cbegin(), h.cend(), 0) == 1); auto const& h2 = countedProcess.GetHistogram().CMSHist(); - REQUIRE(h2.at(h2.axis(0).index(1'000'070'140), h2.axis(1).index(1.6e12)) == 1); - REQUIRE(std::accumulate(h2.cbegin(), h2.cend(), 0) == 1); + CHECK(h2.at(h2.axis(0).index(1'000'070'140), h2.axis(1).index(1.6e12)) == 1); + CHECK(std::accumulate(h2.cbegin(), h2.cend(), 0) == 1); countedProcess.GetHistogram().saveLab("testInteractionCounter_file1.npz", utl::SaveMode::overwrite); @@ -80,19 +80,19 @@ TEST_CASE("InteractionCounter", "[process]") { auto constexpr code = particles::Code::Lambda0; auto [stackPtr, secViewPtr] = setup::testing::setupStack(code, 0, 0, 105_TeV, nodePtr, *csPtr); - REQUIRE(stackPtr->getEntries() == 1); - REQUIRE(secViewPtr->getEntries() == 0); + CHECK(stackPtr->getEntries() == 1); + CHECK(secViewPtr->getEntries() == 0); auto const ret = countedProcess.DoInteraction(*secViewPtr); - REQUIRE(ret == nullptr); + CHECK(ret == nullptr); auto const& h = countedProcess.GetHistogram().labHist(); - REQUIRE(h.at(h.axis(0).index(3122), h.axis(1).index(1.05e14)) == 1); - REQUIRE(std::accumulate(h.cbegin(), h.cend(), 0) == 1); + CHECK(h.at(h.axis(0).index(3122), h.axis(1).index(1.05e14)) == 1); + CHECK(std::accumulate(h.cbegin(), h.cend(), 0) == 1); auto const& h2 = countedProcess.GetHistogram().CMSHist(); - REQUIRE(h2.at(h2.axis(0).index(3122), h2.axis(1).index(1.6e12)) == 1); - REQUIRE(std::accumulate(h2.cbegin(), h2.cend(), 0) == 1); + CHECK(h2.at(h2.axis(0).index(3122), h2.axis(1).index(1.6e12)) == 1); + CHECK(std::accumulate(h2.cbegin(), h2.cend(), 0) == 1); } } diff --git a/tests/modules/testQGSJetII.cpp b/tests/modules/testQGSJetII.cpp index 00f0d8013..eeb6d95a7 100644 --- a/tests/modules/testQGSJetII.cpp +++ b/tests/modules/testQGSJetII.cpp @@ -42,9 +42,9 @@ TEST_CASE("CORSIKA_DATA", "[processes]") { SECTION("check CORSIKA_DATA") { const char* data = std::getenv("CORSIKA_DATA"); - // these REQUIRES are needed: - REQUIRE(data != 0); - REQUIRE(std::experimental::filesystem::is_directory( + // these CHECKS are needed: + CHECK(data != 0); + CHECK(std::experimental::filesystem::is_directory( std::experimental::filesystem::path(std::string(data) + "/QGSJetII"))); std::cout << "data: " << data << " isDir: " << std::experimental::filesystem::is_directory(std::string(data) + @@ -62,37 +62,37 @@ TEST_CASE("QgsjetII", "[processes]") { } SECTION("QgsjetII -> Corsika") { - REQUIRE(Code::PiPlus == corsika::qgsjetII::convertFromQgsjetII( - corsika::qgsjetII::QgsjetIICode::PiPlus)); + CHECK(Code::PiPlus == corsika::qgsjetII::convertFromQgsjetII( + corsika::qgsjetII::QgsjetIICode::PiPlus)); } SECTION("Corsika -> QgsjetII") { - REQUIRE(corsika::qgsjetII::convertToQgsjetII(Code::PiMinus) == - corsika::qgsjetII::QgsjetIICode::PiMinus); - REQUIRE(corsika::qgsjetII::convertToQgsjetIIRaw(Code::Proton) == 2); + CHECK(corsika::qgsjetII::convertToQgsjetII(Code::PiMinus) == + corsika::qgsjetII::QgsjetIICode::PiMinus); + CHECK(corsika::qgsjetII::convertToQgsjetIIRaw(Code::Proton) == 2); } SECTION("canInteractInQgsjetII") { - REQUIRE(corsika::qgsjetII::canInteract(Code::Proton)); - REQUIRE(corsika::qgsjetII::canInteract(Code::KPlus)); - REQUIRE(corsika::qgsjetII::canInteract(Code::Nucleus)); - // REQUIRE(corsika::qgsjetII::canInteract(Helium::getCode())); + CHECK(corsika::qgsjetII::canInteract(Code::Proton)); + CHECK(corsika::qgsjetII::canInteract(Code::KPlus)); + CHECK(corsika::qgsjetII::canInteract(Code::Nucleus)); + // CHECK(corsika::qgsjetII::canInteract(Helium::getCode())); - REQUIRE_FALSE(corsika::qgsjetII::canInteract(Code::EtaC)); - REQUIRE_FALSE(corsika::qgsjetII::canInteract(Code::SigmaC0)); + CHECK_FALSE(corsika::qgsjetII::canInteract(Code::EtaC)); + CHECK_FALSE(corsika::qgsjetII::canInteract(Code::SigmaC0)); } SECTION("cross-section type") { - REQUIRE(corsika::qgsjetII::getQgsjetIIXSCode(Code::Neutron) == - corsika::qgsjetII::QgsjetIIXSClass::Baryons); - REQUIRE(corsika::qgsjetII::getQgsjetIIXSCode(Code::K0Long) == - corsika::qgsjetII::QgsjetIIXSClass::Kaons); - REQUIRE(corsika::qgsjetII::getQgsjetIIXSCode(Code::Proton) == - corsika::qgsjetII::QgsjetIIXSClass::Baryons); - REQUIRE(corsika::qgsjetII::getQgsjetIIXSCode(Code::PiMinus) == - corsika::qgsjetII::QgsjetIIXSClass::LightMesons); + CHECK(corsika::qgsjetII::getQgsjetIIXSCode(Code::Neutron) == + corsika::qgsjetII::QgsjetIIXSClass::Baryons); + CHECK(corsika::qgsjetII::getQgsjetIIXSCode(Code::K0Long) == + corsika::qgsjetII::QgsjetIIXSClass::Kaons); + CHECK(corsika::qgsjetII::getQgsjetIIXSCode(Code::Proton) == + corsika::qgsjetII::QgsjetIIXSClass::Baryons); + CHECK(corsika::qgsjetII::getQgsjetIIXSCode(Code::PiMinus) == + corsika::qgsjetII::QgsjetIIXSClass::LightMesons); } } diff --git a/tests/modules/testStackInspector.cpp b/tests/modules/testStackInspector.cpp index a28d274f3..31f3765ae 100644 --- a/tests/modules/testStackInspector.cpp +++ b/tests/modules/testStackInspector.cpp @@ -27,7 +27,7 @@ TEST_CASE("StackInspector", "[processes]") { Point const origin(rootCS, {0_m, 0_m, 0_m}); VelocityVector v(rootCS, 0_m / second, 0_m / second, 1_m / second); Line line(origin, v); - LineTrajectory track(line, 10_s); + StraightTrajectory track(line, 10_s); TestCascadeStack stack; stack.clear(); diff --git a/tests/modules/testSwitchProcess.cpp b/tests/modules/testSwitchProcess.cpp deleted file mode 100644 index 296315768..000000000 --- a/tests/modules/testSwitchProcess.cpp +++ /dev/null @@ -1,258 +0,0 @@ -/* - * (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 <corsika/modules/SwitchProcess.hpp> - -#include <corsika/framework/core/PhysicalUnits.hpp> -#include <corsika/framework/stack/SecondaryView.hpp> -#include <corsika/framework/stack/Stack.hpp> - -#include <catch2/catch.hpp> - -#include <algorithm> -#include <random> - -using namespace corsika; -using namespace corsika::units::si; - -class TestStackData { - -public: - // these functions are needed for the Stack interface - void Init() {} - void Clear() { fData.clear(); } - unsigned int GetSize() const { return fData.size(); } - unsigned int GetCapacity() const { return fData.size(); } - void Copy(int i1, int i2) { fData[i2] = fData[i1]; } - void Swap(int i1, int i2) { std::swap(fData[i1], fData[i2]); } - - // custom data access function - void SetData(unsigned int i, HEPEnergyType v) { fData[i] = v; } - HEPEnergyType GetData(const unsigned int i) const { return fData[i]; } - - // these functions are also needed by the Stack interface - void IncrementSize() { fData.resize(fData.size() + 1); } - void DecrementSize() { - if (fData.size() > 0) { fData.pop_back(); } - } - - // custom private data section -private: - std::vector<HEPEnergyType> fData; -}; - -/** - * From static_cast of a StackIterator over entries in the - * TestStackData class you get and object of type - * TestParticleInterface defined here - * - * It provides Get/Set methods to read and write data to the "Data" - * storage of TestStackData obtained via - * "StackIteratorInterface::GetStackData()", given the index of the - * iterator "StackIteratorInterface::GetIndex()" - * - */ -template <typename StackIteratorInterface> -class TestParticleInterface : public corsika::ParticleBase<StackIteratorInterface> { - -public: - using corsika::ParticleBase<StackIteratorInterface>::GetStackData; - using corsika::ParticleBase<StackIteratorInterface>::GetIndex; - - /* - The SetParticleData methods are called for creating new entries - on the stack. You can specifiy various parametric versions to - perform this task: - */ - - // default version for particle-creation from input data - void SetParticleData(const std::tuple<HEPEnergyType> v) { SetEnergy(std::get<0>(v)); } - void SetParticleData(TestParticleInterface<StackIteratorInterface>& /*parent*/, - std::tuple<HEPEnergyType> v) { - SetEnergy(std::get<0>(v)); - } - - // here are the fundamental methods for access to TestStackData data - void SetEnergy(HEPEnergyType v) { GetStackData().SetData(GetIndex(), v); } - HEPEnergyType GetEnergy() const { return GetStackData().GetData(GetIndex()); } -}; - -using SimpleStack = corsika::Stack<TestStackData, TestParticleInterface>; - -// see issue 161 -#if defined(__clang__) -using StackTestView = corsika::SecondaryView<TestStackData, TestParticleInterface>; -#elif defined(__GNUC__) || defined(__GNUG__) -using StackTestView = corsika::MakeView<SimpleStack>::type; -#endif - -auto constexpr kgMSq = 1_kg / (1_m * 1_m); - -template <int N> -struct DummyProcess : InteractionProcess<DummyProcess<N>> { - void Init() {} - - template <typename TParticle> - corsika::units::si::GrammageType GetInteractionLength(TParticle const&) const { - return N * kgMSq; - } - - template <typename TSecondaries> - void doInteraction(TSecondaries&) { - // to figure out which process was selected in the end, we produce N - // secondaries for DummyProcess<N> - - for (int i = 0; i < N; ++i) { - // vSec.AddSecondary(std::make_tuple(vSec.GetEnergy() / N)); // <-- FIXME, when - // SwitchProcess is removedalter - } - } -}; - -using DummyLowEnergyProcess = DummyProcess<1>; -using DummyHighEnergyProcess = DummyProcess<2>; -using DummyAdditionalProcess = DummyProcess<3>; - -TEST_CASE("SwitchProcess from InteractionProcess") { - DummyLowEnergyProcess low; - DummyHighEnergyProcess high; - DummyAdditionalProcess proc; - - switch_process::SwitchProcess switchProcess(low, high, 1_TeV); - auto seq = corsika::make_sequence(switchProcess, proc); - - SimpleStack stack; - - SECTION("low energy") { - stack.AddParticle(std::tuple<HEPEnergyType>{0.5_TeV}); - auto p = stack.GetNextParticle(); - - // low energy process returns 1 kg/m² - SECTION("interaction length") { - REQUIRE(switchProcess.GetInteractionLength(p) / kgMSq == Approx(1)); - REQUIRE(seq.getInteractionLength(p) / kgMSq == Approx(3. / 4)); - } - - // low energy process creates 1 secondary - //~ SECTION("SelectInteraction") { - //~ typename SimpleStack::ParticleType theParticle = - //~ stack.GetNextParticle(); // as in corsika::Cascade - //~ StackTestView view(theParticle); - //~ auto projectile = view.GetProjectile(); - - //~ InverseGrammageType invLambda = 0 / kgMSq; - //~ switchProcess.SelectInteraction(p, projectile, 0.01 / kgMSq, invLambda); - - //~ REQUIRE(view.GetSize() == 1); - //~ } - } - - SECTION("high energy") { - stack.AddParticle(std::tuple<HEPEnergyType>{4_TeV}); - auto p = stack.GetNextParticle(); - - // high energy process returns 2 kg/m² - SECTION("interaction length") { - REQUIRE(switchProcess.GetInteractionLength(p) / kgMSq == Approx(2)); - REQUIRE(seq.getInteractionLength(p) / kgMSq == Approx(6. / 5)); - } - - // high energy process creates 2 secondaries - SECTION("SelectInteraction") { - typename SimpleStack::ParticleType theParticle = - stack.GetNextParticle(); // as in corsika::Cascade - StackTestView view(theParticle); - auto projectile = view.GetProjectile(); - - InverseGrammageType invLambda = 0 / kgMSq; - switchProcess.SelectInteraction(p, projectile, 0.01 / kgMSq, invLambda); - - REQUIRE(view.GetSize() == 2); - } - } -} - -TEST_CASE("SwitchProcess from ProcessSequence") { - DummyProcess<1> innerA; - DummyProcess<2> innerB; - DummyProcess<3> outer; - DummyProcess<4> additional; - - auto seq = corsika::make_sequence(innerA, innerB); - - switch_process::SwitchProcess switchProcess(seq, outer, 1_TeV); - auto completeSeq = corsika::make_sequence(switchProcess, additional); - - SimpleStack stack; - - SECTION("low energy") { - stack.AddParticle(std::tuple<HEPEnergyType>{0.5_TeV}); - auto p = stack.GetNextParticle(); - - SECTION("interaction length") { - REQUIRE(switchProcess.GetInteractionLength(p) / kgMSq == Approx(2. / 3)); - REQUIRE(completeSeq.getInteractionLength(p) / kgMSq == Approx(4. / 7)); - } - - SECTION("SelectInteraction") { - std::vector<int> numberOfSecondaries; - - for (int i = 0; i < 1000; ++i) { - typename SimpleStack::ParticleType theParticle = - stack.GetNextParticle(); // as in corsika::Cascade - StackTestView view(theParticle); - - double r = i / 1000.; - InverseGrammageType invLambda = r * 7. / 4 / kgMSq; - - InverseGrammageType accumulator = 0 / kgMSq; - completeSeq.selectInteraction(view, invLambda, accumulator); - - numberOfSecondaries.push_back(view.GetSize()); - } - - auto const mean = - std::accumulate(numberOfSecondaries.cbegin(), numberOfSecondaries.cend(), 0.) / - numberOfSecondaries.size(); - REQUIRE(mean == Approx(12. / 7.).margin(0.01)); - } - } - - SECTION("high energy") { - stack.AddParticle(std::tuple<HEPEnergyType>{3.0_TeV}); - auto p = stack.GetNextParticle(); - - SECTION("interaction length") { - REQUIRE(switchProcess.GetInteractionLength(p) / kgMSq == Approx(3)); - REQUIRE(completeSeq.getInteractionLength(p) / kgMSq == Approx(12. / 7.)); - } - - SECTION("SelectInteraction") { - std::vector<int> numberOfSecondaries; - - for (int i = 0; i < 1000; ++i) { - typename SimpleStack::ParticleType theParticle = - stack.GetNextParticle(); // as in corsika::Cascade - StackTestView view(theParticle); - - double r = i / 1000.; - InverseGrammageType invLambda = r * 7. / 12. / kgMSq; - - InverseGrammageType accumulator = 0 / kgMSq; - completeSeq.selectInteraction(view, invLambda, accumulator); - - numberOfSecondaries.push_back(view.GetSize()); - } - - auto const mean = - std::accumulate(numberOfSecondaries.cbegin(), numberOfSecondaries.cend(), 0.) / - numberOfSecondaries.size(); - REQUIRE(mean == Approx(24. / 7.).margin(0.01)); - } - } -} diff --git a/tests/stack/CMakeLists.txt b/tests/stack/CMakeLists.txt index d559a5e13..ffb635624 100644 --- a/tests/stack/CMakeLists.txt +++ b/tests/stack/CMakeLists.txt @@ -4,7 +4,7 @@ set (test_stack_sources testHistoryView.cpp testGeometryNodeStackExtension.cpp testDummyStack.cpp - testSuperStupidStack.cpp + testSimpleStack.cpp testNuclearStackExtension.cpp ) diff --git a/tests/stack/testNuclearStackExtension.cpp b/tests/stack/testNuclearStackExtension.cpp index d64ae6da9..13a3ec18c 100644 --- a/tests/stack/testNuclearStackExtension.cpp +++ b/tests/stack/testNuclearStackExtension.cpp @@ -22,7 +22,7 @@ TEST_CASE("NuclearStackExtension", "[stack]") { CoordinateSystemPtr const& dummyCS = get_root_CoordinateSystem(); SECTION("write non nucleus") { - nuclear_stack::NuclearStackExtension<SuperStupidStack, + nuclear_stack::NuclearStackExtension<SimpleStack, nuclear_stack::ExtendedParticleInterfaceType> s; s.addParticle(std::make_tuple( @@ -33,7 +33,7 @@ TEST_CASE("NuclearStackExtension", "[stack]") { SECTION("write nucleus") { - nuclear_stack::NuclearStackExtension<SuperStupidStack, + nuclear_stack::NuclearStackExtension<SimpleStack, nuclear_stack::ExtendedParticleInterfaceType> s; s.addParticle(std::make_tuple( @@ -212,7 +212,7 @@ TEST_CASE("NuclearStackExtension", "[stack]") { SECTION("not allowed") { - nuclear_stack::NuclearStackExtension<SuperStupidStack, + nuclear_stack::NuclearStackExtension<SimpleStack, nuclear_stack::ExtendedParticleInterfaceType> s; diff --git a/tests/stack/testSuperStupidStack.cpp b/tests/stack/testSimpleStack.cpp similarity index 91% rename from tests/stack/testSuperStupidStack.cpp rename to tests/stack/testSimpleStack.cpp index a038d22c2..7aa764359 100644 --- a/tests/stack/testSuperStupidStack.cpp +++ b/tests/stack/testSimpleStack.cpp @@ -9,7 +9,7 @@ #define protected public // to also test the internal state of objects #include <corsika/framework/geometry/RootCoordinateSystem.hpp> -#include <corsika/stack/SuperStupidStack.hpp> +#include <corsika/stack/SimpleStack.hpp> #include <corsika/framework/core/PhysicalUnits.hpp> #include <catch2/catch.hpp> @@ -17,13 +17,13 @@ using namespace corsika; using namespace std; -TEST_CASE("SuperStupidStack", "[stack]") { +TEST_CASE("SimpleStack", "[stack]") { const CoordinateSystemPtr& dummyCS = get_root_CoordinateSystem(); SECTION("read+write") { - SuperStupidStack s; + SimpleStack s; s.addParticle(std::make_tuple( Code::Electron, 1.5_GeV, MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}), Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s)); @@ -39,7 +39,7 @@ TEST_CASE("SuperStupidStack", "[stack]") { SECTION("write+delete") { - SuperStupidStack s; + SimpleStack s; for (int i = 0; i < 99; ++i) s.addParticle(std::make_tuple( -- GitLab