diff --git a/corsika/detail/framework/utility/COMBoost.inl b/corsika/detail/framework/utility/COMBoost.inl index 8a87616bc0eb03772c9eb806157cd1d7427d2d7e..352ee4e6c8eee3d7088a2ec0390aa64b16249380 100644 --- a/corsika/detail/framework/utility/COMBoost.inl +++ b/corsika/detail/framework/utility/COMBoost.inl @@ -10,110 +10,111 @@ #pragma once +#include <cmath> + #include <Eigen/Dense> #include <corsika/framework/core/PhysicalUnits.hpp> #include <corsika/framework/geometry/CoordinateSystem.hpp> #include <corsika/framework/geometry/FourVector.hpp> #include <corsika/framework/geometry/Vector.hpp> +#include <corsika/framework/logging/Logging.h> #include <corsika/framework/utility/sgn.hpp> +// using namespace corsika::units::si; + namespace corsika { - auto const& COMBoost::GetRotationMatrix() const { return fRotation; } + COMBoost::COMBoost(FourVector<HEPEnergyType, Vector<hepmomentum_d>> const& Pprojectile, + const HEPMassType massTarget) + : originalCS_{Pprojectile.GetSpaceLikeComponents().GetCoordinateSystem()} + , rotatedCS_{originalCS_.RotateToZ(Pprojectile.GetSpaceLikeComponents())} { + auto const pProjectile = Pprojectile.GetSpaceLikeComponents(); + auto const pProjNormSquared = pProjectile.squaredNorm(); + auto const pProjNorm = sqrt(pProjNormSquared); + + auto const eProjectile = Pprojectile.GetTimeLikeComponent(); + auto const massProjectileSquared = eProjectile * eProjectile - pProjNormSquared; + auto const s = + massTarget * massTarget + massProjectileSquared + 2 * eProjectile * massTarget; + + auto const sqrtS = sqrt(s); + auto const sinhEta = -pProjNorm / sqrtS; + auto const coshEta = sqrt(1 + pProjNormSquared / s); + + setBoost(coshEta, sinhEta); + + C8LOG_TRACE("COMBoost (1-beta)={}, gamma={}, det={}", 1 - sinhEta / coshEta, coshEta, + boost_.determinant() - 1); + } + + COMBoost::COMBoost(geometry::Vector<units::si::hepmomentum_d> const& momentum, + units::si::HEPEnergyType mass) + : originalCS_{momentum.GetCoordinateSystem()} + , rotatedCS_{originalCS_.RotateToZ(momentum)} { + auto const squaredNorm = momentum.squaredNorm(); + auto const norm = sqrt(squaredNorm); + auto const sinhEta = -norm / mass; + auto const coshEta = sqrt(1 + squaredNorm / (mass * mass)); + setBoost(coshEta, sinhEta); + } - //! transforms a 4-momentum from lab frame to the center-of-mass frame template <typename FourVector> - inline FourVector COMBoost::toCoM(const FourVector& p) const { - auto pComponents = p.GetSpaceLikeComponents().GetComponents(fCS); - Eigen::Vector3d eVecRotated = fRotation * pComponents.eVector; + FourVector COMBoost::toCoM(const FourVector& p) const { + using namespace corsika::units::si; + auto pComponents = p.GetSpaceLikeComponents().GetComponents(rotatedCS_); + Eigen::Vector3d eVecRotated = pComponents.eVector; Eigen::Vector2d lab; lab << (p.GetTimeLikeComponent() * (1 / 1_GeV)), (eVecRotated(2) * (1 / 1_GeV).magnitude()); - auto const boostedZ = fBoost * lab; + auto const boostedZ = boost_ * lab; auto const E_CoM = boostedZ(0) * 1_GeV; eVecRotated(2) = boostedZ(1) * (1_GeV).magnitude(); - return FourVector(E_CoM, corsika::Vector<hepmomentum_d>(fCS, eVecRotated)); + return FourVector(E_CoM, + corsika::geometry::Vector<hepmomentum_d>(rotatedCS_, eVecRotated)); } - //! transforms a 4-momentum from the center-of-mass frame back to lab frame template <typename FourVector> - inline FourVector COMBoost::fromCoM(const FourVector& p) const { + FourVector COMBoost::fromCoM(const FourVector& p) const { + using namespace corsika::units::si; + auto pCM = p.GetSpaceLikeComponents().GetComponents(rotatedCS_); + auto const Ecm = p.GetTimeLikeComponent(); + Eigen::Vector2d com; - com << (p.GetTimeLikeComponent() * (1 / 1_GeV)), - (p.GetSpaceLikeComponents().GetComponents().eVector(2) * (1 / 1_GeV).magnitude()); + com << (Ecm * (1 / 1_GeV)), (pCM.eVector(2) * (1 / 1_GeV).magnitude()); - auto const plab = p.GetSpaceLikeComponents().GetComponents(); - std::cout << "COMBoost::fromCoM Ecm=" << p.GetTimeLikeComponent() / 1_GeV << " GeV, " - << " pcm = " << plab / 1_GeV << " (norm = " << plab.norm() / 1_GeV - << " GeV), invariant mass = " << p.GetNorm() / 1_GeV << " GeV" << std::endl; + C8LOG_TRACE( + "COMBoost::fromCoM Ecm={} GeV" + " pcm={} GeV (norm = {} GeV), invariant mass={} GeV", + Ecm / 1_GeV, pCM / 1_GeV, pCM.norm() / 1_GeV, p.GetNorm() / 1_GeV); - auto const boostedZ = fInverseBoost * com; + auto const boostedZ = inverseBoost_ * com; auto const E_lab = boostedZ(0) * 1_GeV; - auto pLab = p.GetSpaceLikeComponents().GetComponents(); - pLab.eVector(2) = boostedZ(1) * (1_GeV).magnitude(); - pLab.eVector = fRotation.transpose() * pLab.eVector; + pCM.eVector(2) = boostedZ(1) * (1_GeV).magnitude(); + + geometry::Vector<typename decltype(pCM)::dimension> pLab{rotatedCS_, pCM}; + pLab.rebase(originalCS_); - FourVector f(E_lab, corsika::Vector(fCS, pLab)); + FourVector f(E_lab, pLab); - std::cout << "COMBoost::fromCoM --> Elab=" << E_lab / 1_GeV << "GeV, " - << " pcm = " << pLab / 1_GeV << " (norm =" << pLab.norm() / 1_GeV - << " GeV), invariant mass = " << f.GetNorm() / 1_GeV << " GeV" << std::endl; + C8LOG_TRACE("COMBoost::fromCoM --> Elab={} GeV", + " plab={} GeV (norm={} GeV) " + " GeV), invariant mass = {}", + E_lab / 1_GeV, f.GetNorm() / 1_GeV, pLab.GetComponents(), + pLab.norm() / 1_GeV); return f; } - inline COMBoost::COMBoost( - FourVector<HEPEnergyType, Vector<hepmomentum_d>> const& Pprojectile, - const HEPMassType massTarget) - : fCS(Pprojectile.GetSpaceLikeComponents().GetCoordinateSystem()) { - auto const pProjectile = Pprojectile.GetSpaceLikeComponents(); - auto const pProjNorm = pProjectile.norm(); - auto const a = (pProjectile / pProjNorm).GetComponents().eVector; - auto const a1 = a(0), a2 = a(1); - - auto const s = sgn(a(2)); - auto const c = 1 / (1 + s * a(2)); - - Eigen::Matrix3d A, B; - - if (s > 0) { - A << 1, 0, -a1, // comment to prevent clang-format - 0, 1, -a2, // . - a1, a2, 1; // . - B << -a1 * a1 * c, -a1 * a2 * c, 0, // . - -a1 * a2 * c, -a2 * a2 * c, 0, // . - 0, 0, -(a1 * a1 + a2 * a2) * c; // . - - } else { - A << 1, 0, a1, // comment to prevent clang-format - 0, -1, -a2, // . - a1, a2, -1; // . - B << -a1 * a1 * c, -a1 * a2 * c, 0, // . - +a1 * a2 * c, +a2 * a2 * c, 0, // . - 0, 0, (a1 * a1 + a2 * a2) * c; // . - } - - fRotation = A + B; - - // calculate boost - double const beta = pProjNorm / (Pprojectile.GetTimeLikeComponent() + massTarget); - - /* Accurracy matters here, beta = 1 - epsilon for ultra-relativistic boosts */ - double const coshEta = 1 / std::sqrt((1 + beta) * (1 - beta)); - //~ double const coshEta = 1 / std::sqrt((1-beta*beta)); - double const sinhEta = -beta * coshEta; - - std::cout << "COMBoost (1-beta)=" << 1 - beta << " gamma=" << coshEta << std::endl; - std::cout << " det = " << fRotation.determinant() - 1 << std::endl; - - fBoost << coshEta, sinhEta, sinhEta, coshEta; - - fInverseBoost << coshEta, -sinhEta, -sinhEta, coshEta; + void COMBoost::setBoost(double coshEta, double sinhEta) { + boost_ << coshEta, sinhEta, sinhEta, coshEta; + inverseBoost_ << coshEta, -sinhEta, -sinhEta, coshEta; } + CoordinateSystem const& COMBoost::GetRotatedCS() const { return rotatedCS_; } + } // namespace corsika diff --git a/corsika/detail/framework/utility/CorsikaData.inl b/corsika/detail/framework/utility/CorsikaData.inl new file mode 100644 index 0000000000000000000000000000000000000000..e690e3e0add5dd0327681752a0f2365a6b299585 --- /dev/null +++ b/corsika/detail/framework/utility/CorsikaData.inl @@ -0,0 +1,22 @@ +/* + * (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 <cstdlib> +#include <stdexcept> +#include <string> + +std::string corsika::CorsikaData(std::string const& key) { + if (auto const* p = std::getenv("CORSIKA_DATA"); p != nullptr) { + auto const path = std::string(p) + "/" + key; + return path; + } else { + throw std::runtime_error("CORSIKA_DATA not set"); + } +} diff --git a/corsika/framework/utility/COMBoost.hpp b/corsika/framework/utility/COMBoost.hpp index 96823d123fb6fb2f9c5ec0c44415dab9ec277fbd..08932465b1f54792126179d26564dfd04ccff8ef 100644 --- a/corsika/framework/utility/COMBoost.hpp +++ b/corsika/framework/utility/COMBoost.hpp @@ -8,12 +8,13 @@ #pragma once -#include <iostream> -#include <Eigen/Dense> -#include <corsika/framework/core/PhysicalUnits.hpp> #include <corsika/framework/geometry/CoordinateSystem.hpp> #include <corsika/framework/geometry/FourVector.hpp> +#include <corsika/framework/core/PhysicalUnits.hpp> +#include <corsika/framework/logging/Logging.hpp> + +#include <Eigen/Dense> namespace corsika { @@ -23,26 +24,38 @@ namespace corsika { */ class COMBoost { - Eigen::Matrix3d fRotation; - Eigen::Matrix2d fBoost, fInverseBoost; - corsika::CoordinateSystem const& fCS; + Eigen::Matrix2d boost_, inverseBoost_; + corsika::CoordinateSystem const &originalCS_, rotatedCS_; + + void setBoost(double coshEta, double sinhEta); public: - //! construct a COMBoost given four-vector of prjectile and mass of target - COMBoost(const corsika::FourVector<HEPEnergyType, corsika::Vector<hepmomentum_d>>& - Pprojectile, - const HEPEnergyType massTarget); + //! construct a COMBoost given four-vector of projectile and mass of target + COMBoost( + const corsika::geometry::FourVector< + corsika::units::si::HEPEnergyType, + corsika::geometry::Vector<corsika::units::si::hepmomentum_d>>& Pprojectile, + const corsika::units::si::HEPEnergyType massTarget); - inline auto const& GetRotationMatrix() const; + //! construct a COMBoost to boost into the rest frame given a 3-momentum and mass + COMBoost(Vector<units::si::hepmomentum_d> const& momentum, + units::si::HEPEnergyType mass); //! transforms a 4-momentum from lab frame to the center-of-mass frame template <typename FourVector> - inline FourVector toCoM(const FourVector& p) const; + FourVector toCoM(const FourVector& p) const; + //! transforms a 4-momentum from the center-of-mass frame back to lab frame template <typename FourVector> - inline FourVector fromCoM(const FourVector& p) const; + FourVector fromCoM(const FourVector& p) const; + + + CoordinateSystem const& GetRotatedCS() const; }; } // namespace corsika #include <corsika/detail/framework/utility/COMBoost.inl> + + + diff --git a/tests/framework/testCorsikaFenv.cpp b/tests/framework/testCorsikaFenv.cpp index e4ec2eff44264cb30a33780bd1e7c387f6cac60f..a82f440333fdc5b5ccc78f38b93dcdf0b460ecba 100644 --- a/tests/framework/testCorsikaFenv.cpp +++ b/tests/framework/testCorsikaFenv.cpp @@ -21,7 +21,11 @@ static void handle_fpe(int /*signo*/) { gRESULT = 0; } TEST_CASE("CorsikaFenv", "[fenv]") { - feenableexcept(FE_ALL_EXCEPT); + SECTION("Enable all exceptions") + { + feenableexcept(FE_ALL_EXCEPT); + } + signal(SIGFPE, handle_fpe); SECTION("exception") { @@ -29,5 +33,8 @@ TEST_CASE("CorsikaFenv", "[fenv]") { [[maybe_unused]] auto trigger = std::log(0.); std::cout << "trigger: " << trigger << std::endl; CHECK(gRESULT == 0); - } + } + +} + } diff --git a/tests/framework/testSaveBoostHistogram.cpp b/tests/framework/testSaveBoostHistogram.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b825816fe0af8ca112db1999e450d094dd430532 --- /dev/null +++ b/tests/framework/testSaveBoostHistogram.cpp @@ -0,0 +1,39 @@ +/* + * (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 <catch2/catch.hpp> +#include <corsika/utl/SaveBoostHistogram.hpp> + +#include <random> + +namespace bh = boost::histogram; + +TEST_CASE("SaveHistogram") { + std::mt19937 rng; + std::normal_distribution n1{2., 6.}; + std::exponential_distribution e{1.}; + std::uniform_int_distribution u{1, 10}; + std::uniform_real_distribution<double> r{-3, 3}; + + auto h = bh::make_histogram( + bh::axis::regular{5, 0, 10, "normal"}, bh::axis::regular{3, 0, 4, "exponential"}, + bh::axis::category<int>{{2, 3, 5, 7}, "integer category"}, + bh::axis::regular<double, bh::use_default, bh::use_default, + bh::axis::option::growth_t>{10, -1, 1, "integer category"}); + + for (int i{0}; i < 100'000; ++i) { + auto const a = n1(rng); + auto const b = e(rng); + auto const c = u(rng); + auto const d = r(rng); + + h(a, b, c, d); + } + + corsika::save_hist(h, "hist.npz"); +}