diff --git a/CMakeLists.txt b/CMakeLists.txt index d29d6566625b54239eda5b76578b97498cc97c5d..7ba7c0f9242ac697378101681271151ac56a4306 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -93,6 +93,7 @@ endif(Pythia_FOUND) # get UrQMD # #find_package( UrQMD REQUIRED ) +add_subdirectory(dependencies/urqmd) if(UrQMD_FOUND) include_directories(${UrQMD_INCLUDE_DIR}) endif(UrQMD_FOUND) diff --git a/corsika/detail/framework/geometry/Plane.inl b/corsika/detail/framework/geometry/Plane.inl index d1a41c3eafebcdf6a8f62c15a6734030a39b1163..c63749215efbd087b2ec70670fd95676714209c0 100644 --- a/corsika/detail/framework/geometry/Plane.inl +++ b/corsika/detail/framework/geometry/Plane.inl @@ -17,22 +17,22 @@ namespace corsika { - bool Plane::IsAbove(Point const& vP) const + inline bool Plane::IsAbove(Point const& vP) const { return fNormal.dot(vP - fCenter) > corsika::units::si::LengthType::zero(); } - units::si::LengthType Plane::DistanceTo(corsika::Point const& vP) const + inline units::si::LengthType Plane::DistanceTo(corsika::Point const& vP) const { return (fNormal * (vP - fCenter).dot(fNormal)).norm(); } - Point const& Plane::GetCenter() const + inline Point const& Plane::GetCenter() const { return fCenter; } - Plane::DimLessVec const& Plane::GetNormal() const + inline Plane::DimLessVec const& Plane::GetNormal() const { return fNormal; } diff --git a/corsika/detail/modules/tracking_line/TrackingLine.inl b/corsika/detail/modules/tracking_line/TrackingLine.inl new file mode 100644 index 0000000000000000000000000000000000000000..fa9d86db8fb574491cc99433a6bb5215258355c6 --- /dev/null +++ b/corsika/detail/modules/tracking_line/TrackingLine.inl @@ -0,0 +1,65 @@ +/* + * (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu + * + * See file AUTHORS for a list of contributors. + * + * 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/modules/tracking_line/TrackingLine.hpp> + +#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<units::si::TimeType, units::si::TimeType>> TimeOfIntersection( + corsika::Line const& line, corsika::Sphere const& sphere) { + auto const delta = line.GetR0() - sphere.GetCenter(); + auto const v = line.GetV0(); + auto const vSqNorm = + v.squaredNorm(); // 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.squaredNorm() - 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 {}; + } + } + + units::si::TimeType TimeOfIntersection(Line const& vLine, Plane const& vPlane) { + + using namespace units::si; + + auto const delta = vPlane.GetCenter() - vLine.GetR0(); + auto const v = vLine.GetV0(); + auto const n = vPlane.GetNormal(); + auto const c = n.dot(v); + + if (c.magnitude() == 0) { + return std::numeric_limits<units::si::TimeType::value_type>::infinity() * 1_s; + } else { + return n.dot(delta) / c; + } + } + +} // namespace corsika::tracking_line diff --git a/corsika/detail/modules/urqmd/UrQMD.inl b/corsika/detail/modules/urqmd/UrQMD.inl new file mode 100644 index 0000000000000000000000000000000000000000..eaacb3fb8e9b53fbd017100bdc013a4e643cf457 --- /dev/null +++ b/corsika/detail/modules/urqmd/UrQMD.inl @@ -0,0 +1,327 @@ +/* + * (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu + * + * See file AUTHORS for a list of contributors. + * + * 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/modules/urqmd/UrQMD.hpp> + +#include <corsika/framework/core/ParticleProperties.hpp> +#include <corsika/framework/core/PhysicalUnits.hpp> +#include <corsika/framework/geometry/QuantityVector.hpp> +#include <corsika/framework/geometry/Vector.hpp> + +#include <algorithm> +#include <functional> +#include <iostream> +#include <random> + +namespace corsika::urqmd { + + UrQMD::UrQMD() { iniurqmdc8_(); } + + using SetupStack = corsika::setup::Stack; + using SetupParticle = corsika::setup::Stack::StackIterator; + using SetupProjectile = corsika::setup::StackView::StackIterator; + + corsika::units::si::CrossSectionType UrQMD::GetCrossSection( + corsika::Code vProjectileCode, corsika::Code vTargetCode, + corsika::units::si::HEPEnergyType vLabEnergy, int vAProjectile = 1) { + + using namespace units::si; + + // the following is a translation of ptsigtot() into C++ + if (vProjectileCode != corsika::Code::Nucleus && + !IsNucleus(vTargetCode)) { // both particles are "special" + auto const mProj = corsika::GetMass(vProjectileCode); + auto const mTar = corsika::GetMass(vTargetCode); + double sqrtS = + sqrt(units::si::detail::static_pow<2>(mProj) + + units::si::detail::static_pow<2>(mTar) + 2 * vLabEnergy * mTar) * + (1 / 1_GeV); + + // we must set some UrQMD globals first... + auto const [ityp, iso3] = ConvertToUrQMD(vProjectileCode); + inputs_.spityp[0] = ityp; + inputs_.spiso3[0] = iso3; + + auto const [itypTar, iso3Tar] = ConvertToUrQMD(vTargetCode); + inputs_.spityp[1] = itypTar; + inputs_.spiso3[1] = iso3Tar; + + int one = 1; + int two = 2; + return sigtot_(one, two, sqrtS) * 1_mb; + } else { + int const Ap = vAProjectile; + int const At = IsNucleus(vTargetCode) ? corsika::GetNucleusA(vTargetCode) : 1; + + double const maxImpact = nucrad_(Ap) + nucrad_(At) + 2 * options_.CTParam[30 - 1]; + return 10_mb * M_PI * units::si::detail::static_pow<2>(maxImpact); + // is a constant cross-section really reasonable? + } + } + + template <typename TParticle> // need template here, as this is called both with + // SetupParticle as well as SetupProjectile + corsika::units::si::CrossSectionType UrQMD::GetCrossSection( + TParticle const& vProjectile, corsika::Code vTargetCode) const { + // TODO: return 0 for non-hadrons? + + auto const projectileCode = vProjectile.GetPID(); + auto const projectileEnergyLab = vProjectile.GetEnergy(); + + if (projectileCode == corsika::Code::K0Long) { + return 0.5 * + (GetCrossSection(corsika::Code::K0, vTargetCode, projectileEnergyLab) + + GetCrossSection(corsika::Code::K0Bar, vTargetCode, projectileEnergyLab)); + } + + int const Ap = + (projectileCode == corsika::Code::Nucleus) ? vProjectile.GetNuclearA() : 1; + return GetCrossSection(projectileCode, vTargetCode, projectileEnergyLab, Ap); + } + + bool UrQMD::CanInteract(corsika::Code vCode) const { + // According to the manual, UrQMD can use all mesons, baryons and nucleons + // which are modeled also as input particles. I think it is safer to accept + // only the usual long-lived species as input. + // TODO: Charmed mesons should be added to the list, too + + static corsika::Code const validProjectileCodes[] = { + corsika::Code::Nucleus, corsika::Code::Proton, corsika::Code::AntiProton, + corsika::Code::Neutron, corsika::Code::AntiNeutron, corsika::Code::PiPlus, + corsika::Code::PiMinus, corsika::Code::KPlus, corsika::Code::KMinus, + corsika::Code::K0, corsika::Code::K0Bar, corsika::Code::K0Long}; + + return std::find(std::cbegin(validProjectileCodes), std::cend(validProjectileCodes), + vCode) != std::cend(validProjectileCodes); + } + + corsika::units::si::GrammageType UrQMD::GetInteractionLength( + SetupParticle& vParticle) const { + + using namespace units::si; + + if (!CanInteract(vParticle.GetPID())) { + // we could do the canInteract check in GetCrossSection, too but if + // we do it here we have the advantage of avoiding the loop + return std::numeric_limits<double>::infinity() * 1_g / (1_cm * 1_cm); + } + + auto const& mediumComposition = + vParticle.GetNode()->GetModelProperties().GetNuclearComposition(); + using namespace std::placeholders; + + corsika::units::si::CrossSectionType const weightedProdCrossSection = + mediumComposition.WeightedSum( + std::bind(&UrQMD::GetCrossSection<decltype(vParticle)>, this, vParticle, _1)); + + return mediumComposition.GetAverageMassNumber() * units::constants::u / + weightedProdCrossSection; + } + + corsika::EProcessReturn UrQMD::DoInteraction(SetupProjectile& vProjectile) { + + using namespace units::si; + + auto projectileCode = vProjectile.GetPID(); + auto const projectileEnergyLab = vProjectile.GetEnergy(); + auto const& projectileMomentumLab = vProjectile.GetMomentum(); + auto const& projectilePosition = vProjectile.GetPosition(); + auto const projectileTime = vProjectile.GetTime(); + + // sample target particle + auto const& mediumComposition = + vProjectile.GetNode()->GetModelProperties().GetNuclearComposition(); + auto const componentCrossSections = std::invoke([&]() { + auto const& components = mediumComposition.GetComponents(); + std::vector<corsika::units::si::CrossSectionType> crossSections; + crossSections.reserve(components.size()); + + for (auto const c : components) { + crossSections.push_back(GetCrossSection(vProjectile, c)); + } + + return crossSections; + }); + + auto const targetCode = mediumComposition.SampleTarget(componentCrossSections, fRNG); + auto const targetA = corsika::GetNucleusA(targetCode); + auto const targetZ = corsika::GetNucleusZ(targetCode); + + inputs_.nevents = 1; + sys_.eos = 0; // could be configurable in principle + inputs_.outsteps = 1; + sys_.nsteps = 1; + + // initialization regarding projectile + if (corsika::Code::Nucleus == projectileCode) { + // is this everything? + inputs_.prspflg = 0; + + sys_.Ap = vProjectile.GetNuclearA(); + sys_.Zp = vProjectile.GetNuclearZ(); + rsys_.ebeam = (projectileEnergyLab - vProjectile.GetMass()) * (1 / 1_GeV) / + vProjectile.GetNuclearA(); + + rsys_.bdist = nucrad_(targetA) + nucrad_(sys_.Ap) + 2 * options_.CTParam[30 - 1]; + + int const id = 1; + cascinit_(sys_.Zp, sys_.Ap, id); + } else { + inputs_.prspflg = 1; + sys_.Ap = 1; // even for non-baryons this has to be set, see vanilla UrQMD.f + rsys_.bdist = nucrad_(targetA) + nucrad_(1) + 2 * options_.CTParam[30 - 1]; + rsys_.ebeam = (projectileEnergyLab - vProjectile.GetMass()) * (1 / 1_GeV); + + if (projectileCode == corsika::Code::K0Long) { + projectileCode = fBooleanDist(fRNG) ? corsika::Code::K0 : corsika::Code::K0Bar; + } else if (projectileCode == corsika::Code::K0Short) { + throw std::runtime_error("K0Short should not interact"); + } + + auto const [ityp, iso3] = ConvertToUrQMD(projectileCode); + // todo: conversion of K_long/short into strong eigenstates; + inputs_.spityp[0] = ityp; + inputs_.spiso3[0] = iso3; + } + + // initilazation regarding target + if (corsika::IsNucleus(targetCode)) { + sys_.Zt = targetZ; + sys_.At = targetA; + inputs_.trspflg = 0; // nucleus as target + int const id = 2; + cascinit_(sys_.Zt, sys_.At, id); + } else { + inputs_.trspflg = 1; // special particle as target + auto const [ityp, iso3] = ConvertToUrQMD(targetCode); + inputs_.spityp[1] = ityp; + inputs_.spiso3[1] = iso3; + } + + int iflb = 0; // flag for retrying interaction in case of empty event, 0 means retry + urqmd_(iflb); + + // now retrieve secondaries from UrQMD + auto const& originalCS = projectileMomentumLab.GetCoordinateSystem(); + corsika::CoordinateSystem const zAxisFrame = + originalCS.RotateToZ(projectileMomentumLab); + + for (int i = 0; i < sys_.npart; ++i) { + auto code = ConvertFromUrQMD(isys_.ityp[i], isys_.iso3[i]); + if (code == corsika::Code::K0 || code == corsika::Code::K0Bar) { + code = fBooleanDist(fRNG) ? corsika::Code::K0Short : corsika::Code::K0Long; + } + + // "coor_.p0[i] * 1_GeV" is likely off-shell as UrQMD doesn't preserve masses well + auto momentum = corsika::Vector( + zAxisFrame, corsika::QuantityVector<dimensionless_d>{coor_.px[i], coor_.py[i], + coor_.pz[i]} * + 1_GeV); + + auto const energy = sqrt(momentum.squaredNorm() + square(corsika::GetMass(code))); + + momentum.rebase(originalCS); // transform back into standard lab frame + std::cout << i << " " << code << " " << momentum.GetComponents() << std::endl; + + vProjectile.AddSecondary( + std::tuple<corsika::Code, corsika::units::si::HEPEnergyType, + corsika::MomentumVector, corsika::Point, corsika::units::si::TimeType>{ + code, energy, momentum, projectilePosition, projectileTime}); + } + + std::cout << "UrQMD generated " << sys_.npart << " secondaries!" << std::endl; + + return corsika::EProcessReturn::eOk; + } + + /** + * the random number generator function of UrQMD + */ + double ranf_(int&) { + static corsika::RNG& rng = + corsika::RNGManager::GetInstance().GetRandomStream("UrQMD"); + static std::uniform_real_distribution<double> dist; + + return dist(rng); + } + + corsika::Code ConvertFromUrQMD(int vItyp, int vIso3) { + int const pdgInt = + pdgid_(vItyp, vIso3); // use the conversion function provided by UrQMD + if (pdgInt == 0) { // pdgid_ returns 0 on error + throw std::runtime_error("UrQMD pdgid() returned 0"); + } + auto const pdg = static_cast<corsika::PDGCode>(pdgInt); + return corsika::ConvertFromPDG(pdg); + } + + std::pair<int, int> ConvertToUrQMD(corsika::Code code) { + static const std::map<int, std::pair<int, int>> mapPDGToUrQMD{ + // data mostly from github.com/afedynitch/ParticleDataTool + {22, {100, 0}}, // gamma + {111, {101, 0}}, // pi0 + {211, {101, 2}}, // pi+ + {-211, {101, -2}}, // pi- + {321, {106, 1}}, // K+ + {-321, {-106, -1}}, // K- + {311, {106, -1}}, // K0 + {-311, {-106, 1}}, // K0bar + {2212, {1, 1}}, // p + {2112, {1, -1}}, // n + {-2212, {-1, -1}}, // pbar + {-2112, {-1, 1}}, // nbar + {221, {102, 0}}, // eta + {213, {104, 2}}, // rho+ + {-213, {104, -2}}, // rho- + {113, {104, 0}}, // rho0 + {323, {108, 2}}, // K*+ + {-323, {108, -2}}, // K*- + {313, {108, 0}}, // K*0 + {-313, {-108, 0}}, // K*0-bar + {223, {103, 0}}, // omega + {333, {109, 0}}, // phi + {3222, {40, 2}}, // Sigma+ + {3212, {40, 0}}, // Sigma0 + {3112, {40, -2}}, // Sigma- + {3322, {49, 0}}, // Xi0 + {3312, {49, -1}}, // Xi- + {3122, {27, 0}}, // Lambda0 + {2224, {17, 4}}, // Delta++ + {2214, {17, 2}}, // Delta+ + {2114, {17, 0}}, // Delta0 + {1114, {17, -2}}, // Delta- + {3224, {41, 2}}, // Sigma*+ + {3214, {41, 0}}, // Sigma*0 + {3114, {41, -2}}, // Sigma*- + {3324, {50, 0}}, // Xi*0 + {3314, {50, -1}}, // Xi*- + {3334, {55, 0}}, // Omega- + {411, {133, 2}}, // D+ + {-411, {133, -2}}, // D- + {421, {133, 0}}, // D0 + {-421, {-133, 0}}, // D0-bar + {441, {107, 0}}, // etaC + {431, {138, 1}}, // Ds+ + {-431, {138, -1}}, // Ds- + {433, {139, 1}}, // Ds*+ + {-433, {139, -1}}, // Ds*- + {413, {134, 1}}, // D*+ + {-413, {134, -1}}, // D*- + {10421, {134, 0}}, // D*0 + {-10421, {-134, 0}}, // D*0-bar + {443, {135, 0}}, // jpsi + }; + + return mapPDGToUrQMD.at(static_cast<int>(GetPDG(code))); + } + +} // namespace corsika::urqmd \ No newline at end of file diff --git a/corsika/modules/switch_process/SwitchProcess.hpp b/corsika/modules/switch_process/SwitchProcess.hpp new file mode 100644 index 0000000000000000000000000000000000000000..3d083535342f86cf13ac1701e4f55a994d9b7767 --- /dev/null +++ b/corsika/modules/switch_process/SwitchProcess.hpp @@ -0,0 +1,106 @@ +/* + * (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu + * + * See file AUTHORS for a list of contributors. + * + * 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/sequence/InteractionProcess.hpp> +#include <corsika/framework/sequence/ProcessSequence.hpp> +#include <corsika/setup/SetupStack.hpp> +#include <corsika/framework/core/PhysicalUnits.hpp> + +namespace corsika::switch_process { + + /** + * This process provides an energy-based switch between two interaction processes P1 and + * P1. For energies below the threshold, P1 is invoked, otherwise P2. Both can be either + * single interaction processes or multiple ones combined in a ProcessSequence. A + * SwitchProcess itself will always be regarded as a distinct case when assembled into a + * (greater) ProcessSequence. + */ + + template <class TLowEProcess, class THighEProcess> + class SwitchProcess : public BaseProcess<SwitchProcess<TLowEProcess, THighEProcess>> { + TLowEProcess& fLowEProcess; + THighEProcess& fHighEProcess; + units::si::HEPEnergyType const fThresholdEnergy; + + public: + SwitchProcess(TLowEProcess& vLowEProcess, THighEProcess& vHighEProcess, + units::si::HEPEnergyType vThresholdEnergy) + : fLowEProcess(vLowEProcess) + , fHighEProcess(vHighEProcess) + , fThresholdEnergy(vThresholdEnergy) {} + + void Init() { + fLowEProcess.Init(); + fHighEProcess.Init(); + } + + template <typename TParticle> + corsika::units::si::InverseGrammageType GetInverseInteractionLength(TParticle& p) { + return 1 / GetInteractionLength(p); + } + + template <typename TParticle> + units::si::GrammageType GetInteractionLength(TParticle& vParticle) { + if (vParticle.GetEnergy() < fThresholdEnergy) { + if constexpr (is_process_sequence_v<TLowEProcess>) { + return fLowEProcess.GetTotalInteractionLength(vParticle); + } else { + return fLowEProcess.GetInteractionLength(vParticle); + } + } else { + if constexpr (is_process_sequence_v<THighEProcess>) { + return fHighEProcess.GetTotalInteractionLength(vParticle); + } else { + return fHighEProcess.GetInteractionLength(vParticle); + } + } + } + + // required to conform to ProcessSequence interface. We cannot just + // implement DoInteraction() because we want to call SelectInteraction + // in case a member process is a ProcessSequence. + template <typename TParticle, typename TSecondaries> + EProcessReturn SelectInteraction( + TParticle& vP, TSecondaries& vS, + [[maybe_unused]] corsika::units::si::InverseGrammageType lambda_select, + corsika::units::si::InverseGrammageType& lambda_inv_count) { + if (vP.GetEnergy() < fThresholdEnergy) { + if constexpr (is_process_sequence_v<TLowEProcess>) { + return fLowEProcess.SelectInteraction(vP, vS, lambda_select, lambda_inv_count); + } else { + lambda_inv_count += fLowEProcess.GetInverseInteractionLength(vP); + // check if we should execute THIS process and then EXIT + if (lambda_select < lambda_inv_count) { + fLowEProcess.DoInteraction(vS); + return EProcessReturn::eInteracted; + } else { + return EProcessReturn::eOk; + } + } + } else { + if constexpr (is_process_sequence_v<THighEProcess>) { + return fHighEProcess.SelectInteraction(vP, vS, lambda_select, lambda_inv_count); + } else { + lambda_inv_count += fHighEProcess.GetInverseInteractionLength(vP); + // check if we should execute THIS process and then EXIT + if (lambda_select < lambda_inv_count) { + fHighEProcess.DoInteraction(vS); + return EProcessReturn::eInteracted; + } else { + return EProcessReturn::eOk; + } + } + } + } + }; +} // namespace corsika::switch_process + diff --git a/corsika/modules/tracking_line/TrackingLine.hpp b/corsika/modules/tracking_line/TrackingLine.hpp new file mode 100644 index 0000000000000000000000000000000000000000..f93f931f198eb97e3acf0d01f98ebd2d70dfd2ea --- /dev/null +++ b/corsika/modules/tracking_line/TrackingLine.hpp @@ -0,0 +1,138 @@ +/* + * (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu + * + * See file AUTHORS for a list of contributors. + * + * 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/Trajectory.hpp> +#include <corsika/framework/geometry/Vector.hpp> + +#include <optional> +#include <type_traits> +#include <utility> + +namespace corsika { + template <typename IEnvironmentModel> + class Environment; + template <typename IEnvironmentModel> + class VolumeTreeNode; +} // namespace corsika + +namespace corsika::tracking_line { + + std::optional<std::pair<corsika::units::si::TimeType, corsika::units::si::TimeType>> + TimeOfIntersection(corsika::Line const&, corsika::Sphere const&); + + corsika::units::si::TimeType TimeOfIntersection(corsika::Line const&, + corsika::Plane const&); + + class TrackingLine { + + public: + TrackingLine(){}; + + template <typename Particle> // was Stack previously, and argument was + // Stack::StackIterator + auto GetTrack(Particle const& p) { + using namespace corsika::units::si; + corsika::Vector<SpeedType::dimension_type> const velocity = + p.GetMomentum() / p.GetEnergy() * corsika::units::constants::c; + + auto const currentPosition = p.GetPosition(); + std::cout << "TrackingLine pid: " << p.GetPID() + << " , E = " << p.GetEnergy() / 1_GeV << " GeV" << std::endl; + std::cout << "TrackingLine pos: " + << currentPosition.GetCoordinates() + // << " [" << p.GetNode()->GetModelProperties().GetName() << "]" + << std::endl; + std::cout << "TrackingLine E: " << p.GetEnergy() / 1_GeV << " GeV" << std::endl; + std::cout << "TrackingLine p: " << p.GetMomentum().GetComponents() / 1_GeV + << " GeV " << std::endl; + std::cout << "TrackingLine v: " << velocity.GetComponents() << std::endl; + + // to do: include effect of magnetic field + corsika::Line line(currentPosition, velocity); + + auto const* currentLogicalVolumeNode = p.GetNode(); + //~ auto const* currentNumericalVolumeNode = + //~ fEnvironment.GetUniverse()->GetContainingNode(currentPosition); + auto const numericallyInside = + currentLogicalVolumeNode->GetVolume().Contains(currentPosition); + + std::cout << "numericallyInside = " << (numericallyInside ? "true" : "false"); + + auto const& children = currentLogicalVolumeNode->GetChildNodes(); + auto const& excluded = currentLogicalVolumeNode->GetExcludedNodes(); + + std::vector<std::pair<TimeType, decltype(p.GetNode())>> intersections; + + // for entering from outside + auto addIfIntersects = [&](auto const& vtn) { + auto const& volume = vtn.GetVolume(); + auto const& sphere = dynamic_cast<corsika::Sphere const&>( + volume); // for the moment we are a bit bold here and assume + // everything is a sphere, crashes with exception if not + + if (auto opt = TimeOfIntersection(line, sphere); opt.has_value()) { + auto const [t1, t2] = *opt; + std::cout << "intersection times: " << t1 / 1_s << "; " + << t2 / 1_s + // << " " << vtn.GetModelProperties().GetName() + << std::endl; + if (t1.magnitude() > 0) + intersections.emplace_back(t1, &vtn); + else if (t2.magnitude() > 0) + std::cout << "inside other volume" << std::endl; + } + }; + + for (auto const& child : children) { addIfIntersects(*child); } + for (auto const* ex : excluded) { addIfIntersects(*ex); } + + { + auto const& sphere = + dynamic_cast<corsika::Sphere const&>(currentLogicalVolumeNode->GetVolume()); + // for the moment we are a bit bold here and assume + // everything is a sphere, crashes with exception if not + [[maybe_unused]] auto const [t1, t2] = *TimeOfIntersection(line, sphere); + [[maybe_unused]] auto dummy_t1 = t1; + intersections.emplace_back(t2, currentLogicalVolumeNode->GetParent()); + } + + auto const minIter = std::min_element( + intersections.cbegin(), intersections.cend(), + [](auto const& a, auto const& b) { return a.first < b.first; }); + + TimeType min; + + if (minIter == intersections.cend()) { + min = 1_s; // todo: do sth. more reasonable as soon as tracking is able + // to handle the numerics properly + throw std::runtime_error("no intersection with anything!"); + } else { + min = minIter->first; + } + + std::cout << " t-intersect: " + << min + // << " " << minIter->second->GetModelProperties().GetName() + << std::endl; + + return std::make_tuple(corsika::Trajectory<corsika::Line>(line, min), + velocity.norm() * min, minIter->second); + } + }; + +} // namespace corsika::tracking_line + +#include <corsika/detail/modules/tracking_line/TrackingLine.inl> diff --git a/corsika/modules/urqmd/UrQMD.hpp b/corsika/modules/urqmd/UrQMD.hpp new file mode 100644 index 0000000000000000000000000000000000000000..71abe44adfd72eafd26b28fbf60d683c9fe312fd --- /dev/null +++ b/corsika/modules/urqmd/UrQMD.hpp @@ -0,0 +1,141 @@ +/* + * (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu + * + * See file AUTHORS for a list of contributors. + * + * 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/sequence/InteractionProcess.hpp> +#include <corsika/framework/random/RNGManager.hpp> +#include <corsika/setup/SetupStack.hpp> +#include <corsika/framework/core/PhysicalUnits.hpp> + +#include <array> +#include <utility> + +namespace corsika::urqmd { + + class UrQMD : public corsika::InteractionProcess<UrQMD> { + public: + UrQMD(); + void Init() {} + corsika::units::si::GrammageType GetInteractionLength( + corsika::setup::Stack::StackIterator&) const; + + template <typename TParticle> + corsika::units::si::CrossSectionType GetCrossSection(TParticle const&, + corsika::Code) const; + + corsika::EProcessReturn DoInteraction( + corsika::setup::StackView::StackIterator&); + + bool CanInteract(corsika::Code) const; + + private: + static corsika::units::si::CrossSectionType GetCrossSection( + corsika::Code, corsika::Code, corsika::units::si::HEPEnergyType, int); + corsika::RNG& fRNG = + corsika::RNGManager::GetInstance().GetRandomStream("UrQMD"); + + std::uniform_int_distribution<int> fBooleanDist{0, 1}; + }; + + namespace constants { + // from coms.f + int constexpr nmax = 500; + + // from options.f + int constexpr numcto = 400; + int constexpr numctp = 400; + + // from inputs.f + int constexpr aamax = 300; + + } // namespace constants + + template <typename T> + using nmaxArray = std::array<T, constants::nmax>; + using nmaxIntArray = nmaxArray<int>; + using nmaxDoubleArray = nmaxArray<double>; + + extern "C" { + void iniurqmdc8_(); + double ranf_(int&); + void cascinit_(int const&, int const&, int const&); + double nucrad_(int const&); + void urqmd_(int&); + int pdgid_(int&, int&); + double sigtot_(int&, int&, double&); + + // defined in coms.f + extern struct { + int npart, nbar, nmes, ctag, nsteps, uid_cnt, ranseed, event; + int Ap; // projectile mass number (in case of nucleus) + int At; // target mass number (in case of nucleus) + int Zp; // projectile charge number (in case of nucleus) + int Zt; // target charge number (in case of nucleus) + int eos, dectag, NHardRes, NSoftRes, NDecRes, NElColl, NBlColl; + } sys_; + + extern struct { + double time, acttime, bdist, bimp, bmin; + double ebeam; // lab-frame energy of projectile + double ecm; + } rsys_; + + // defined in coms.f + extern struct { + nmaxIntArray spin, ncoll, charge, ityp, lstcoll, iso3, origin, strid, uid; + } isys_; + + // defined in coor.f + extern struct { + nmaxDoubleArray r0, rx, ry, rz, p0, px, py, pz, fmass, rww, dectime; + } coor_; + + // defined in inputs.f + extern struct { + int nevents; + std::array<int, 2> spityp; // particle codes of: [0]: projectile, [1]: target + int prspflg; // projectile special flag + int trspflg; // target special flag, set to 1 unless target is nucleus > H + std::array<int, 2> spiso3; // particle codes of: [0]: projectile, [1]: target + int outsteps, bflag, srtflag, efuncflag, nsrt, npb, firstev; + } inputs_; + + // defined in inputs.f + extern struct { + double srtmin, srtmax, pbeam, betann, betatar, betapro, pbmin, pbmax; + } input2_; + + // defined in options.f + extern struct { + std::array<double, constants::numcto> CTOption; + std::array<double, constants::numctp> CTParam; + } options_; + + extern struct { + int fixedseed, bf13, bf14, bf15, bf16, bf17, bf18, bf19, bf20; + } loptions_; + + // defined in urqmdInterface.F + extern struct { std::array<double, 3> xs, bim; } cxs_u2_; + } + + /** + * convert CORSIKA code to UrQMD code tuple + * + * In the current implementation a detour via the PDG code is made. + */ + std::pair<int, int> ConvertToUrQMD(corsika::Code); + corsika::Code ConvertFromUrQMD(int vItyp, int vIso3); + +} // namespace corsika::urqmd + +#include <corsika/detail/modules/urqmd/UrQMD.inl> diff --git a/dependencies/UrQMD/CMakeLists.txt b/dependencies/urqmd/CMakeLists.txt similarity index 78% rename from dependencies/UrQMD/CMakeLists.txt rename to dependencies/urqmd/CMakeLists.txt index 6c538f7ff17f4e4d0fcb1a37f2b71c6ab6cf04c7..45b7c244a4ede4722c9a1df0dc9feac755eec9bf 100644 --- a/dependencies/UrQMD/CMakeLists.txt +++ b/dependencies/urqmd/CMakeLists.txt @@ -1,6 +1,5 @@ -cmake_minimum_required(VERSION 3.1) - -project(libUrQMD) +#cmake_minimum_required(VERSION 3.1) +#project(libUrQMD) set ( MODEL_SOURCES @@ -49,3 +48,6 @@ add_library (UrQMD_static STATIC ${MODEL_SOURCES}) set_property(TARGET UrQMD_static PROPERTY POSITION_INDEPENDENT_CODE 1) +# add UrQMD to CORSIKA8 build +add_dependencies (CORSIKA8 UrQMD_static) +target_link_libraries (CORSIKA8 INTERFACE UrQMD_static) diff --git a/dependencies/UrQMD/Copyright b/dependencies/urqmd/Copyright similarity index 100% rename from dependencies/UrQMD/Copyright rename to dependencies/urqmd/Copyright diff --git a/dependencies/UrQMD/README b/dependencies/urqmd/README similarity index 100% rename from dependencies/UrQMD/README rename to dependencies/urqmd/README diff --git a/dependencies/UrQMD/UrQMD.cc b/dependencies/urqmd/UrQMD.cc similarity index 100% rename from dependencies/UrQMD/UrQMD.cc rename to dependencies/urqmd/UrQMD.cc diff --git a/dependencies/UrQMD/UrQMD.h b/dependencies/urqmd/UrQMD.h similarity index 100% rename from dependencies/UrQMD/UrQMD.h rename to dependencies/urqmd/UrQMD.h diff --git a/dependencies/UrQMD/addpart.f b/dependencies/urqmd/addpart.f similarity index 100% rename from dependencies/UrQMD/addpart.f rename to dependencies/urqmd/addpart.f diff --git a/dependencies/UrQMD/angdis.f b/dependencies/urqmd/angdis.f similarity index 100% rename from dependencies/UrQMD/angdis.f rename to dependencies/urqmd/angdis.f diff --git a/dependencies/UrQMD/anndec.f b/dependencies/urqmd/anndec.f similarity index 100% rename from dependencies/UrQMD/anndec.f rename to dependencies/urqmd/anndec.f diff --git a/dependencies/UrQMD/blockres.f b/dependencies/urqmd/blockres.f similarity index 100% rename from dependencies/UrQMD/blockres.f rename to dependencies/urqmd/blockres.f diff --git a/dependencies/UrQMD/boxinc.f b/dependencies/urqmd/boxinc.f similarity index 100% rename from dependencies/UrQMD/boxinc.f rename to dependencies/urqmd/boxinc.f diff --git a/dependencies/UrQMD/boxprg.f b/dependencies/urqmd/boxprg.f similarity index 100% rename from dependencies/UrQMD/boxprg.f rename to dependencies/urqmd/boxprg.f diff --git a/dependencies/UrQMD/cascinit.f b/dependencies/urqmd/cascinit.f similarity index 100% rename from dependencies/UrQMD/cascinit.f rename to dependencies/urqmd/cascinit.f diff --git a/dependencies/UrQMD/colltab.f b/dependencies/urqmd/colltab.f similarity index 100% rename from dependencies/UrQMD/colltab.f rename to dependencies/urqmd/colltab.f diff --git a/dependencies/UrQMD/coload.f b/dependencies/urqmd/coload.f similarity index 100% rename from dependencies/UrQMD/coload.f rename to dependencies/urqmd/coload.f diff --git a/dependencies/UrQMD/comnorm.f b/dependencies/urqmd/comnorm.f similarity index 100% rename from dependencies/UrQMD/comnorm.f rename to dependencies/urqmd/comnorm.f diff --git a/dependencies/UrQMD/comres.f b/dependencies/urqmd/comres.f similarity index 100% rename from dependencies/UrQMD/comres.f rename to dependencies/urqmd/comres.f diff --git a/dependencies/UrQMD/coms.f b/dependencies/urqmd/coms.f similarity index 100% rename from dependencies/UrQMD/coms.f rename to dependencies/urqmd/coms.f diff --git a/dependencies/UrQMD/comstr.f b/dependencies/urqmd/comstr.f similarity index 100% rename from dependencies/UrQMD/comstr.f rename to dependencies/urqmd/comstr.f diff --git a/dependencies/UrQMD/comwid.f b/dependencies/urqmd/comwid.f similarity index 100% rename from dependencies/UrQMD/comwid.f rename to dependencies/urqmd/comwid.f diff --git a/dependencies/UrQMD/dectim.f b/dependencies/urqmd/dectim.f similarity index 100% rename from dependencies/UrQMD/dectim.f rename to dependencies/urqmd/dectim.f diff --git a/dependencies/UrQMD/delpart.f b/dependencies/urqmd/delpart.f similarity index 100% rename from dependencies/UrQMD/delpart.f rename to dependencies/urqmd/delpart.f diff --git a/dependencies/UrQMD/detbal.f b/dependencies/urqmd/detbal.f similarity index 100% rename from dependencies/UrQMD/detbal.f rename to dependencies/urqmd/detbal.f diff --git a/dependencies/UrQMD/dwidth.f b/dependencies/urqmd/dwidth.f similarity index 100% rename from dependencies/UrQMD/dwidth.f rename to dependencies/urqmd/dwidth.f diff --git a/dependencies/UrQMD/error.f b/dependencies/urqmd/error.f similarity index 100% rename from dependencies/UrQMD/error.f rename to dependencies/urqmd/error.f diff --git a/dependencies/UrQMD/freezeout.f b/dependencies/urqmd/freezeout.f similarity index 100% rename from dependencies/UrQMD/freezeout.f rename to dependencies/urqmd/freezeout.f diff --git a/dependencies/UrQMD/getmass.f b/dependencies/urqmd/getmass.f similarity index 100% rename from dependencies/UrQMD/getmass.f rename to dependencies/urqmd/getmass.f diff --git a/dependencies/UrQMD/getspin.f b/dependencies/urqmd/getspin.f similarity index 100% rename from dependencies/UrQMD/getspin.f rename to dependencies/urqmd/getspin.f diff --git a/dependencies/UrQMD/init.f b/dependencies/urqmd/init.f similarity index 100% rename from dependencies/UrQMD/init.f rename to dependencies/urqmd/init.f diff --git a/dependencies/UrQMD/inputs.f b/dependencies/urqmd/inputs.f similarity index 100% rename from dependencies/UrQMD/inputs.f rename to dependencies/urqmd/inputs.f diff --git a/dependencies/UrQMD/iso.f b/dependencies/urqmd/iso.f similarity index 100% rename from dependencies/UrQMD/iso.f rename to dependencies/urqmd/iso.f diff --git a/dependencies/UrQMD/ityp2pdg.f b/dependencies/urqmd/ityp2pdg.f similarity index 100% rename from dependencies/UrQMD/ityp2pdg.f rename to dependencies/urqmd/ityp2pdg.f diff --git a/dependencies/UrQMD/jdecay2.f b/dependencies/urqmd/jdecay2.f similarity index 100% rename from dependencies/UrQMD/jdecay2.f rename to dependencies/urqmd/jdecay2.f diff --git a/dependencies/UrQMD/make22.f b/dependencies/urqmd/make22.f similarity index 100% rename from dependencies/UrQMD/make22.f rename to dependencies/urqmd/make22.f diff --git a/dependencies/UrQMD/newpart.f b/dependencies/urqmd/newpart.f similarity index 100% rename from dependencies/UrQMD/newpart.f rename to dependencies/urqmd/newpart.f diff --git a/dependencies/UrQMD/numrec.f b/dependencies/urqmd/numrec.f similarity index 100% rename from dependencies/UrQMD/numrec.f rename to dependencies/urqmd/numrec.f diff --git a/dependencies/UrQMD/options.f b/dependencies/urqmd/options.f similarity index 100% rename from dependencies/UrQMD/options.f rename to dependencies/urqmd/options.f diff --git a/dependencies/UrQMD/outcom.f b/dependencies/urqmd/outcom.f similarity index 100% rename from dependencies/UrQMD/outcom.f rename to dependencies/urqmd/outcom.f diff --git a/dependencies/UrQMD/output.f b/dependencies/urqmd/output.f similarity index 100% rename from dependencies/UrQMD/output.f rename to dependencies/urqmd/output.f diff --git a/dependencies/UrQMD/paulibl.f b/dependencies/urqmd/paulibl.f similarity index 100% rename from dependencies/UrQMD/paulibl.f rename to dependencies/urqmd/paulibl.f diff --git a/dependencies/UrQMD/proppot.f b/dependencies/urqmd/proppot.f similarity index 100% rename from dependencies/UrQMD/proppot.f rename to dependencies/urqmd/proppot.f diff --git a/dependencies/UrQMD/saveinfo.f b/dependencies/urqmd/saveinfo.f similarity index 100% rename from dependencies/UrQMD/saveinfo.f rename to dependencies/urqmd/saveinfo.f diff --git a/dependencies/UrQMD/scatter.f b/dependencies/urqmd/scatter.f similarity index 100% rename from dependencies/UrQMD/scatter.f rename to dependencies/urqmd/scatter.f diff --git a/dependencies/UrQMD/siglookup.f b/dependencies/urqmd/siglookup.f similarity index 100% rename from dependencies/UrQMD/siglookup.f rename to dependencies/urqmd/siglookup.f diff --git a/dependencies/UrQMD/string.f b/dependencies/urqmd/string.f similarity index 100% rename from dependencies/UrQMD/string.f rename to dependencies/urqmd/string.f diff --git a/dependencies/UrQMD/tabinit.f b/dependencies/urqmd/tabinit.f similarity index 100% rename from dependencies/UrQMD/tabinit.f rename to dependencies/urqmd/tabinit.f diff --git a/dependencies/UrQMD/testUrQMD.cc b/dependencies/urqmd/testUrQMD.cc similarity index 100% rename from dependencies/UrQMD/testUrQMD.cc rename to dependencies/urqmd/testUrQMD.cc diff --git a/dependencies/UrQMD/urqmd.f b/dependencies/urqmd/urqmd.f similarity index 100% rename from dependencies/UrQMD/urqmd.f rename to dependencies/urqmd/urqmd.f diff --git a/dependencies/UrQMD/urqmdInterface.F b/dependencies/urqmd/urqmdInterface.F similarity index 100% rename from dependencies/UrQMD/urqmdInterface.F rename to dependencies/urqmd/urqmdInterface.F diff --git a/dependencies/UrQMD/urqmd_xs.cc b/dependencies/urqmd/urqmd_xs.cc similarity index 100% rename from dependencies/UrQMD/urqmd_xs.cc rename to dependencies/urqmd/urqmd_xs.cc diff --git a/dependencies/UrQMD/whichres.f b/dependencies/urqmd/whichres.f similarity index 100% rename from dependencies/UrQMD/whichres.f rename to dependencies/urqmd/whichres.f diff --git a/tests/modules/CMakeLists.txt b/tests/modules/CMakeLists.txt index 41a0b6ca65c3c6fb11def46aa76b7448b263aa30..0dcfeec74692af74b4418e34489b5b2a2aed769f 100644 --- a/tests/modules/CMakeLists.txt +++ b/tests/modules/CMakeLists.txt @@ -9,8 +9,8 @@ set (test_modules_sources #testQGSJetII.cpp testStackInspector.cpp testSwitchProcess.cpp - #testTrackingLine.cpp - #testUrQMD.cpp + testTrackingLine.cpp + testUrQMD.cpp ) add_executable (testModules ${test_modules_sources}) diff --git a/tests/modules/testSwitchProcess.cpp b/tests/modules/testSwitchProcess.cpp index 510c731ff633331b8996326d3c940c68025b4796..0502bd3b9831993f6b2f3887665ff256837d1a3e 100644 --- a/tests/modules/testSwitchProcess.cpp +++ b/tests/modules/testSwitchProcess.cpp @@ -8,10 +8,10 @@ * the license. */ -#include <corsika/process/switch_process/SwitchProcess.h> -#include <corsika/stack/SecondaryView.h> -#include <corsika/stack/Stack.h> -#include <corsika/units/PhysicalUnits.h> +#include <corsika/modules/switch_process/SwitchProcess.hpp> +#include <corsika/framework/stack/SecondaryView.hpp> +#include <corsika/framework/stack/Stack.hpp> +#include <corsika/framework/core/PhysicalUnits.hpp> #include <catch2/catch.hpp> @@ -19,7 +19,6 @@ #include <random> using namespace corsika; -using namespace corsika::process; using namespace corsika::units::si; class TestStackData { @@ -61,11 +60,11 @@ private: */ template <typename StackIteratorInterface> class TestParticleInterface - : public corsika::stack::ParticleBase<StackIteratorInterface> { + : public corsika::ParticleBase<StackIteratorInterface> { public: - using corsika::stack::ParticleBase<StackIteratorInterface>::GetStackData; - using corsika::stack::ParticleBase<StackIteratorInterface>::GetIndex; + using corsika::ParticleBase<StackIteratorInterface>::GetStackData; + using corsika::ParticleBase<StackIteratorInterface>::GetIndex; /* The SetParticleData methods are called for creating new entries @@ -85,13 +84,13 @@ public: HEPEnergyType GetEnergy() const { return GetStackData().GetData(GetIndex()); } }; -using SimpleStack = corsika::stack::Stack<TestStackData, TestParticleInterface>; +using SimpleStack = corsika::Stack<TestStackData, TestParticleInterface>; // see issue 161 #if defined(__clang__) -using StackTestView = corsika::stack::SecondaryView<TestStackData, TestParticleInterface>; +using StackTestView = corsika::SecondaryView<TestStackData, TestParticleInterface>; #elif defined(__GNUC__) || defined(__GNUG__) -using StackTestView = corsika::stack::MakeView<SimpleStack>::type; +using StackTestView = corsika::MakeView<SimpleStack>::type; #endif auto constexpr kgMSq = 1_kg / (1_m * 1_m); @@ -106,7 +105,7 @@ struct DummyProcess : InteractionProcess<DummyProcess<N>> { } template <typename TSecondaries> - corsika::process::EProcessReturn DoInteraction(TSecondaries& vSec) { + corsika::EProcessReturn DoInteraction(TSecondaries& vSec) { // to figure out which process was selected in the end, we produce N // secondaries for DummyProcess<N> diff --git a/tests/modules/testTrackingLine.cpp b/tests/modules/testTrackingLine.cpp index 638e43bc7f83f8f45d1446b75dbfdb1d5092dee2..1d6c8b8a20d89dc4969f77a288e8515e4141b1c8 100644 --- a/tests/modules/testTrackingLine.cpp +++ b/tests/modules/testTrackingLine.cpp @@ -8,32 +8,31 @@ * the license. */ -#include <corsika/process/tracking_line/TrackingLine.h> -#include <testTrackingLineStack.h> // test-build, and include file is obtained from CMAKE_CURRENT_SOURCE_DIR +#include <corsika/modules/tracking_line/TrackingLine.hpp> -#include <corsika/environment/Environment.h> -#include <corsika/particles/ParticleProperties.h> +#include <testTrackingLineStack.hpp> // test-build, and include file is obtained from CMAKE_CURRENT_SOURCE_DIR -#include <corsika/geometry/Point.h> -#include <corsika/geometry/Sphere.h> -#include <corsika/geometry/Vector.h> +#include <corsika/media/Environment.hpp> +#include <corsika/framework/core/ParticleProperties.hpp> -#include <corsika/setup/SetupTrajectory.h> +#include <corsika/framework/geometry/Point.hpp> +#include <corsika/framework/geometry/Sphere.hpp> +#include <corsika/framework/geometry/Vector.hpp> + +#include <corsika/setup/SetupTrajectory.hpp> using corsika::setup::Trajectory; #include <catch2/catch.hpp> using namespace corsika; -using namespace corsika::process; using namespace corsika::units; -using namespace corsika::geometry; #include <iostream> using namespace std; using namespace corsika::units::si; TEST_CASE("TrackingLine") { - environment::Environment<environment::Empty> env; // dummy environment + corsika::Environment<corsika::Empty> env; // dummy environment auto const& cs = env.GetCoordinateSystem(); tracking_line::TrackingLine tracking; @@ -66,16 +65,16 @@ TEST_CASE("TrackingLine") { auto const radius = 20_m; - auto theMedium = environment::Environment<environment::Empty>::CreateNode<Sphere>( + auto theMedium = corsika::Environment<corsika::Empty>::CreateNode<Sphere>( Point{env.GetCoordinateSystem(), 0_m, 0_m, 0_m}, radius); auto const* theMediumPtr = theMedium.get(); universe.AddChild(std::move(theMedium)); TestTrackingLineStack stack; stack.AddParticle( - std::tuple<particles::Code, units::si::HEPEnergyType, - corsika::stack::MomentumVector, geometry::Point, units::si::TimeType>{ - particles::Code::MuPlus, + std::tuple<corsika::Code, units::si::HEPEnergyType, + corsika::MomentumVector, corsika::Point, units::si::TimeType>{ + corsika::Code::MuPlus, 1_GeV, {cs, {0_GeV, 0_GeV, 1_GeV}}, {cs, {0_m, 0_m, 0_km}}, diff --git a/tests/modules/testTrackingLineStack.hpp b/tests/modules/testTrackingLineStack.hpp new file mode 100644 index 0000000000000000000000000000000000000000..411178f5f670f08b3ad5020dbc60509a921dd01b --- /dev/null +++ b/tests/modules/testTrackingLineStack.hpp @@ -0,0 +1,33 @@ +/* + * (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu + * + * See file AUTHORS for a list of contributors. + * + * 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/geometry/Point.hpp> +#include <corsika/framework/geometry/Vector.hpp> +#include <corsika/media/Environment.hpp> +#include <corsika/setup/SetupStack.hpp> + +using TestEnvironmentType = corsika::Environment<corsika::Empty>; + +template <typename T> +using SetupGeometryDataInterface = GeometryDataInterface<T, TestEnvironmentType>; + +// combine particle data stack with geometry information for tracking +template <typename StackIter> +using StackWithGeometryInterface = + corsika::CombinedParticleInterface<corsika::setup::detail::ParticleDataStack::PIType, + SetupGeometryDataInterface, StackIter>; +using TestTrackingLineStack = + corsika::CombinedStack<typename corsika::setup::detail::ParticleDataStack::StackImpl, + GeometryData<TestEnvironmentType>, StackWithGeometryInterface>; + diff --git a/tests/modules/testUrQMD.cpp b/tests/modules/testUrQMD.cpp index 3339fb9d32cc84939a3d9c4b0bbb6dbc031c4012..a76025124840dca8f18186b906e292e9b13c67ef 100644 --- a/tests/modules/testUrQMD.cpp +++ b/tests/modules/testUrQMD.cpp @@ -8,25 +8,25 @@ * the license. */ -#include <corsika/process/urqmd/UrQMD.h> -#include <corsika/random/RNGManager.h> +#include <corsika/framework/random/RNGManager.hpp> +#include <corsika/modules/urqmd/UrQMD.hpp> -#include <corsika/geometry/Point.h> -#include <corsika/geometry/RootCoordinateSystem.h> -#include <corsika/geometry/Vector.h> +#include <corsika/framework/geometry/Point.hpp> +#include <corsika/framework/geometry/RootCoordinateSystem.hpp> +#include <corsika/framework/geometry/Vector.hpp> -#include <corsika/units/PhysicalConstants.h> -#include <corsika/units/PhysicalUnits.h> +#include <corsika/framework/core/PhysicalConstants.hpp> +#include <corsika/framework/core/PhysicalUnits.hpp> -#include <corsika/utl/CorsikaFenv.h> +#include <corsika/framework/utility/CorsikaFenv.hpp> -#include <corsika/particles/ParticleProperties.h> -#include <corsika/setup/SetupStack.h> -#include <corsika/setup/SetupTrajectory.h> +#include <corsika/framework/core/ParticleProperties.hpp> +#include <corsika/setup/SetupStack.hpp> +#include <corsika/setup/SetupTrajectory.hpp> -#include <corsika/environment/Environment.h> -#include <corsika/environment/HomogeneousMedium.h> -#include <corsika/environment/NuclearComposition.h> +#include <corsika/media/Environment.hpp> +#include <corsika/media/HomogeneousMedium.hpp> +#include <corsika/media/NuclearComposition.hpp> #include <tuple> #include <utility> @@ -34,43 +34,43 @@ #include <catch2/catch.hpp> using namespace corsika; -using namespace corsika::process::UrQMD; +using namespace corsika::urqmd; using namespace corsika::units::si; template <typename TStackView> auto sumCharge(TStackView const& view) { int totalCharge = 0; - for (auto const& p : view) { totalCharge += particles::GetChargeNumber(p.GetPID()); } + for (auto const& p : view) { totalCharge += corsika::GetChargeNumber(p.GetPID()); } return totalCharge; } template <typename TStackView> -auto sumMomentum(TStackView const& view, geometry::CoordinateSystem const& vCS) { - geometry::Vector<hepenergy_d> sum{vCS, 0_eV, 0_eV, 0_eV}; +auto sumMomentum(TStackView const& view, corsika::CoordinateSystem const& vCS) { + corsika::Vector<hepenergy_d> sum{vCS, 0_eV, 0_eV, 0_eV}; for (auto const& p : view) { sum += p.GetMomentum(); } return sum; } -auto setupEnvironment(particles::Code vTargetCode) { +auto setupEnvironment(corsika::Code vTargetCode) { // setup environment, geometry - auto env = std::make_unique<environment::Environment<environment::IMediumModel>>(); + auto env = std::make_unique<corsika::Environment<corsika::IMediumModel>>(); auto& universe = *(env->GetUniverse()); - const geometry::CoordinateSystem& cs = env->GetCoordinateSystem(); + const corsika::CoordinateSystem& cs = env->GetCoordinateSystem(); auto theMedium = - environment::Environment<environment::IMediumModel>::CreateNode<geometry::Sphere>( - geometry::Point{cs, 0_m, 0_m, 0_m}, + corsika::Environment<corsika::IMediumModel>::CreateNode<corsika::Sphere>( + corsika::Point{cs, 0_m, 0_m, 0_m}, 1_km * std::numeric_limits<double>::infinity()); - using MyHomogeneousModel = environment::HomogeneousMedium<environment::IMediumModel>; + using MyHomogeneousModel = corsika::HomogeneousMedium<corsika::IMediumModel>; theMedium->SetModelProperties<MyHomogeneousModel>( 1_kg / (1_m * 1_m * 1_m), - environment::NuclearComposition(std::vector<particles::Code>{vTargetCode}, - std::vector<float>{1.})); + corsika::NuclearComposition(std::vector<corsika::Code>{vTargetCode}, + std::vector<float>{1.})); auto const* nodePtr = theMedium.get(); universe.AddChild(std::move(theMedium)); @@ -80,102 +80,98 @@ auto setupEnvironment(particles::Code vTargetCode) { template <typename TNodeType> auto setupStack(int vA, int vZ, HEPEnergyType vMomentum, TNodeType* vNodePtr, - geometry::CoordinateSystem const& cs) { + corsika::CoordinateSystem const& cs) { auto stack = std::make_unique<setup::Stack>(); auto constexpr mN = corsika::units::constants::nucleonMass; - geometry::Point const origin(cs, {0_m, 0_m, 0_m}); - corsika::stack::MomentumVector const pLab(cs, {vMomentum, 0_GeV, 0_GeV}); + corsika::Point const origin(cs, {0_m, 0_m, 0_m}); + corsika::MomentumVector const pLab(cs, {vMomentum, 0_GeV, 0_GeV}); HEPEnergyType const E0 = sqrt(units::si::detail::static_pow<2>(mN * vA) + pLab.squaredNorm()); - auto particle = - stack->AddParticle(std::tuple<particles::Code, units::si::HEPEnergyType, - corsika::stack::MomentumVector, geometry::Point, - units::si::TimeType, unsigned short, unsigned short>{ - particles::Code::Nucleus, E0, pLab, origin, 0_ns, vA, vZ}); + auto particle = stack->AddParticle( + std::tuple<corsika::Code, units::si::HEPEnergyType, corsika::MomentumVector, + corsika::Point, units::si::TimeType, unsigned short, unsigned short>{ + corsika::Code::Nucleus, E0, pLab, origin, 0_ns, vA, vZ}); particle.SetNode(vNodePtr); return std::make_tuple( std::move(stack), - std::make_unique<decltype(corsika::stack::SecondaryView(particle))>(particle)); + std::make_unique<decltype(corsika::SecondaryView(particle))>(particle)); } template <typename TNodeType> -auto setupStack(particles::Code vProjectileType, HEPEnergyType vMomentum, - TNodeType* vNodePtr, geometry::CoordinateSystem const& cs) { +auto setupStack(corsika::Code vProjectileType, HEPEnergyType vMomentum, + TNodeType* vNodePtr, corsika::CoordinateSystem const& cs) { auto stack = std::make_unique<setup::Stack>(); - geometry::Point const origin(cs, {0_m, 0_m, 0_m}); - corsika::stack::MomentumVector const pLab(cs, {vMomentum, 0_GeV, 0_GeV}); + corsika::Point const origin(cs, {0_m, 0_m, 0_m}); + corsika::MomentumVector const pLab(cs, {vMomentum, 0_GeV, 0_GeV}); HEPEnergyType const E0 = - sqrt(units::si::detail::static_pow<2>(particles::GetMass(vProjectileType)) + + sqrt(units::si::detail::static_pow<2>(corsika::GetMass(vProjectileType)) + pLab.squaredNorm()); auto particle = stack->AddParticle( - std::tuple<particles::Code, units::si::HEPEnergyType, - corsika::stack::MomentumVector, geometry::Point, units::si::TimeType>{ - vProjectileType, E0, pLab, origin, 0_ns}); + std::tuple<corsika::Code, units::si::HEPEnergyType, corsika::MomentumVector, + corsika::Point, units::si::TimeType>{vProjectileType, E0, pLab, origin, + 0_ns}); particle.SetNode(vNodePtr); return std::make_tuple( std::move(stack), - std::make_unique<decltype(corsika::stack::SecondaryView(particle))>(particle)); + std::make_unique<decltype(corsika::SecondaryView(particle))>(particle)); } TEST_CASE("UrQMD") { SECTION("conversion") { - REQUIRE_THROWS(process::UrQMD::ConvertFromUrQMD(106, 0)); - REQUIRE(process::UrQMD::ConvertFromUrQMD(101, 0) == particles::Code::Pi0); - REQUIRE(process::UrQMD::ConvertToUrQMD(particles::Code::PiPlus) == + REQUIRE_THROWS(corsika::urqmd::ConvertFromUrQMD(106, 0)); + REQUIRE(corsika::urqmd::ConvertFromUrQMD(101, 0) == corsika::Code::Pi0); + REQUIRE(corsika::urqmd::ConvertToUrQMD(corsika::Code::PiPlus) == std::make_pair<int, int>(101, 2)); } feenableexcept(FE_INVALID); - corsika::random::RNGManager::GetInstance().RegisterRandomStream("UrQMD"); + corsika::RNGManager::GetInstance().RegisterRandomStream("UrQMD"); UrQMD urqmd; SECTION("cross sections") { - auto [env, csPtr, nodePtr] = setupEnvironment(particles::Code::Unknown); + auto [env, csPtr, nodePtr] = setupEnvironment(corsika::Code::Unknown); auto const& cs = *csPtr; - particles::Code validProjectileCodes[] = { - particles::Code::PiPlus, particles::Code::PiMinus, particles::Code::Proton, - particles::Code::Neutron, particles::Code::KPlus, particles::Code::KMinus, - particles::Code::K0, particles::Code::K0Bar, particles::Code::K0Long}; + corsika::Code validProjectileCodes[] = { + corsika::Code::PiPlus, corsika::Code::PiMinus, corsika::Code::Proton, + corsika::Code::Neutron, corsika::Code::KPlus, corsika::Code::KMinus, + corsika::Code::K0, corsika::Code::K0Bar, corsika::Code::K0Long}; for (auto code : validProjectileCodes) { auto [stack, view] = setupStack(code, 100_GeV, nodePtr, cs); REQUIRE(stack->GetSize() == 1); // simple check whether the cross-section is non-vanishing - REQUIRE(urqmd.GetCrossSection(view->GetProjectile(), particles::Code::Proton) / - 1_mb > + REQUIRE(urqmd.GetCrossSection(view->GetProjectile(), corsika::Code::Proton) / 1_mb > 0); - REQUIRE(urqmd.GetCrossSection(view->GetProjectile(), particles::Code::Nitrogen) / + REQUIRE(urqmd.GetCrossSection(view->GetProjectile(), corsika::Code::Nitrogen) / 1_mb > 0); - REQUIRE(urqmd.GetCrossSection(view->GetProjectile(), particles::Code::Oxygen) / - 1_mb > + REQUIRE(urqmd.GetCrossSection(view->GetProjectile(), corsika::Code::Oxygen) / 1_mb > 0); - REQUIRE(urqmd.GetCrossSection(view->GetProjectile(), particles::Code::Argon) / - 1_mb > + REQUIRE(urqmd.GetCrossSection(view->GetProjectile(), corsika::Code::Argon) / 1_mb > 0); } } SECTION("nucleon projectile") { - auto [env, csPtr, nodePtr] = setupEnvironment(particles::Code::Oxygen); + auto [env, csPtr, nodePtr] = setupEnvironment(corsika::Code::Oxygen); unsigned short constexpr A = 14, Z = 7; auto [stackPtr, secViewPtr] = setupStack(A, Z, 400_GeV, nodePtr, *csPtr); // must be assigned to variable, cannot be used as rvalue?! auto projectile = secViewPtr->GetProjectile(); auto const projectileMomentum = projectile.GetMomentum(); - [[maybe_unused]] process::EProcessReturn const ret = urqmd.DoInteraction(projectile); + [[maybe_unused]] corsika::EProcessReturn const ret = urqmd.DoInteraction(projectile); REQUIRE(sumCharge(*secViewPtr) == - Z + particles::GetChargeNumber(particles::Code::Oxygen)); + Z + corsika::GetChargeNumber(corsika::Code::Oxygen)); auto const secMomSum = sumMomentum(*secViewPtr, projectileMomentum.GetCoordinateSystem()); @@ -184,19 +180,19 @@ TEST_CASE("UrQMD") { } SECTION("\"special\" projectile") { - auto [env, csPtr, nodePtr] = setupEnvironment(particles::Code::Oxygen); + auto [env, csPtr, nodePtr] = setupEnvironment(corsika::Code::Oxygen); auto [stackPtr, secViewPtr] = - setupStack(particles::Code::PiPlus, 400_GeV, nodePtr, *csPtr); + setupStack(corsika::Code::PiPlus, 400_GeV, nodePtr, *csPtr); // must be assigned to variable, cannot be used as rvalue?! auto projectile = secViewPtr->GetProjectile(); auto const projectileMomentum = projectile.GetMomentum(); - [[maybe_unused]] process::EProcessReturn const ret = urqmd.DoInteraction(projectile); + [[maybe_unused]] corsika::EProcessReturn const ret = urqmd.DoInteraction(projectile); REQUIRE(sumCharge(*secViewPtr) == - particles::GetChargeNumber(particles::Code::PiPlus) + - particles::GetChargeNumber(particles::Code::Oxygen)); + corsika::GetChargeNumber(corsika::Code::PiPlus) + + corsika::GetChargeNumber(corsika::Code::Oxygen)); auto const secMomSum = sumMomentum(*secViewPtr, projectileMomentum.GetCoordinateSystem()); @@ -205,19 +201,19 @@ TEST_CASE("UrQMD") { } SECTION("K0Long projectile") { - auto [env, csPtr, nodePtr] = setupEnvironment(particles::Code::Oxygen); + auto [env, csPtr, nodePtr] = setupEnvironment(corsika::Code::Oxygen); auto [stackPtr, secViewPtr] = - setupStack(particles::Code::K0Long, 400_GeV, nodePtr, *csPtr); + setupStack(corsika::Code::K0Long, 400_GeV, nodePtr, *csPtr); // must be assigned to variable, cannot be used as rvalue?! auto projectile = secViewPtr->GetProjectile(); auto const projectileMomentum = projectile.GetMomentum(); - [[maybe_unused]] process::EProcessReturn const ret = urqmd.DoInteraction(projectile); + [[maybe_unused]] corsika::EProcessReturn const ret = urqmd.DoInteraction(projectile); REQUIRE(sumCharge(*secViewPtr) == - particles::GetChargeNumber(particles::Code::K0Long) + - particles::GetChargeNumber(particles::Code::Oxygen)); + corsika::GetChargeNumber(corsika::Code::K0Long) + + corsika::GetChargeNumber(corsika::Code::Oxygen)); auto const secMomSum = sumMomentum(*secViewPtr, projectileMomentum.GetCoordinateSystem());