diff --git a/Documentation/Examples/cascade_example.cc b/Documentation/Examples/cascade_example.cc index 9c56a9a23cbdf58be5e1bd5ddd2d3736e368637c..f2326e06e981ac307784b54366d6ba001b290bb3 100644 --- a/Documentation/Examples/cascade_example.cc +++ b/Documentation/Examples/cascade_example.cc @@ -27,6 +27,8 @@ #include <corsika/units/PhysicalUnits.h> +#include <corsika/random/RNGManager.h> + #include <iostream> #include <limits> #include <typeinfo> @@ -116,13 +118,13 @@ public: } template <typename Particle> - double MaxStepLength(Particle& p, setup::Trajectory&) const { + LengthType MaxStepLength(Particle& p, setup::Trajectory&) const { const Code pid = p.GetPID(); if (isEmParticle(pid) || isInvisible(pid)) { cout << "ProcessCut: MinStep: next cut: " << 0. << endl; - return 0.; + return 0_m; } else { - double next_step = std::numeric_limits<double>::infinity(); + LengthType next_step = 1_m * std::numeric_limits<double>::infinity(); cout << "ProcessCut: MinStep: next cut: " << next_step << endl; return next_step; } @@ -196,8 +198,10 @@ public: private: }; - int main() { + + corsika::random::RNGManager::GetInstance().RegisterRandomStream("cascade"); + corsika::environment::Environment env; // dummy environment auto& universe = *(env.GetUniverse()); @@ -215,7 +219,8 @@ int main() { universe.AddChild(std::move(theMedium)); - CoordinateSystem& rootCS = RootCoordinateSystem::GetInstance().GetRootCoordinateSystem(); + CoordinateSystem& rootCS = + RootCoordinateSystem::GetInstance().GetRootCoordinateSystem(); tracking_line::TrackingLine<setup::Stack> tracking(env); stack_inspector::StackInspector<setup::Stack> p0(true); @@ -224,9 +229,10 @@ int main() { corsika::process::sibyll::Decay decay; ProcessEMCut cut; const auto sequence = /*p0 +*/ sibyll + decay + cut; + setup::Stack stack; - corsika::cascade::Cascade EAS(tracking, sequence, stack); + corsika::cascade::Cascade EAS(env, tracking, sequence, stack); stack.Clear(); auto particle = stack.NewParticle(); @@ -242,8 +248,9 @@ int main() { particle.SetPosition(p); EAS.Init(); EAS.Run(); - cout << "Result: E0=" << E0 / 1_GeV - //<< "GeV, particles below energy threshold =" << p1.GetCount() + cout << "Result: E0=" + << E0 / 1_GeV + //<< "GeV, particles below energy threshold =" << p1.GetCount() << endl; cout << "total energy below threshold (GeV): " //<< p1.GetEnergy() / 1_GeV << std::endl; diff --git a/Environment/Environment.h b/Environment/Environment.h index cb75b64855f7d8e49341d3e8b5a17a7dc9e80b98..aa567e8764dfe981324ea53e20b0bb02b5c44a1c 100644 --- a/Environment/Environment.h +++ b/Environment/Environment.h @@ -14,8 +14,8 @@ #include <corsika/environment/IMediumModel.h> #include <corsika/environment/VolumeTreeNode.h> #include <corsika/geometry/Point.h> -#include <corsika/geometry/Sphere.h> #include <corsika/geometry/RootCoordinateSystem.h> +#include <corsika/geometry/Sphere.h> #include <corsika/setup/SetupEnvironment.h> #include <limits> @@ -23,9 +23,9 @@ namespace corsika::environment { struct Universe : public corsika::geometry::Sphere { Universe(corsika::geometry::CoordinateSystem const& pCS) : corsika::geometry::Sphere( - corsika::geometry::Point{ - pCS, 0 * corsika::units::si::meter, - 0 * corsika::units::si::meter, 0 * corsika::units::si::meter}, + corsika::geometry::Point{pCS, 0 * corsika::units::si::meter, + 0 * corsika::units::si::meter, + 0 * corsika::units::si::meter}, corsika::units::si::meter * std::numeric_limits<double>::infinity()) {} bool Contains(corsika::geometry::Point const&) const override { return true; } @@ -35,8 +35,9 @@ namespace corsika::environment { class Environment { public: Environment() - : fCoordinateSystem{corsika::geometry::RootCoordinateSystem::GetInstance().GetRootCoordinateSystem()}, - fUniverse(std::make_unique<VolumeTreeNode<IEnvironmentModel>>( + : fCoordinateSystem{corsika::geometry::RootCoordinateSystem::GetInstance() + .GetRootCoordinateSystem()} + , fUniverse(std::make_unique<VolumeTreeNode<IEnvironmentModel>>( std::make_unique<Universe>(fCoordinateSystem))) {} using IEnvironmentModel = corsika::setup::IEnvironmentModel; diff --git a/Environment/HomogeneousMedium.h b/Environment/HomogeneousMedium.h index a8fa5f7283cfe0e776383f24915b98748d54349f..566b565e7ed4b7d03f37cf9a4a7c0baf7b232409 100644 --- a/Environment/HomogeneousMedium.h +++ b/Environment/HomogeneousMedium.h @@ -43,15 +43,15 @@ namespace corsika::environment { corsika::units::si::GrammageType IntegratedGrammage( corsika::geometry::Trajectory<corsika::geometry::Line> const& pTraj, - corsika::units::si::TimeType pTo) const override { + corsika::units::si::LengthType pTo) const override { using namespace corsika::units::si; - return pTraj.ArcLength(0_s, pTo) * fDensity; + return pTo * fDensity; } - corsika::units::si::TimeType FromGrammage( + corsika::units::si::LengthType ArclengthFromGrammage( corsika::geometry::Trajectory<corsika::geometry::Line> const& pTraj, corsika::units::si::GrammageType pGrammage) const override { - return pTraj.TimeFromArclength(pGrammage / fDensity); + return pGrammage / fDensity; } }; diff --git a/Environment/IMediumModel.h b/Environment/IMediumModel.h index 4a1eedd86562187c310d180a4516ee3425a05674..d527c80435cb9ade5acfaf1c2bc9623fd44a1161 100644 --- a/Environment/IMediumModel.h +++ b/Environment/IMediumModel.h @@ -20,9 +20,9 @@ namespace corsika::environment { // approach for now, only lines are supported virtual corsika::units::si::GrammageType IntegratedGrammage( corsika::geometry::Trajectory<corsika::geometry::Line> const&, - corsika::units::si::TimeType) const = 0; + corsika::units::si::LengthType) const = 0; - virtual corsika::units::si::TimeType FromGrammage( + virtual corsika::units::si::LengthType ArclengthFromGrammage( corsika::geometry::Trajectory<corsika::geometry::Line> const&, corsika::units::si::GrammageType) const = 0; diff --git a/Framework/Cascade/Cascade.h b/Framework/Cascade/Cascade.h index 7cd9d077de0bc6f84174789771714978d8ac3f94..0edd50502ef35bdea96a608e0ab64b157394ff6d 100644 --- a/Framework/Cascade/Cascade.h +++ b/Framework/Cascade/Cascade.h @@ -12,34 +12,34 @@ #ifndef _include_corsika_cascade_Cascade_h_ #define _include_corsika_cascade_Cascade_h_ +#include <corsika/environment/Environment.h> #include <corsika/process/ProcessReturn.h> #include <corsika/random/RNGManager.h> +#include <corsika/random/UniformRealDistribution.h> #include <corsika/setup/SetupTrajectory.h> #include <corsika/units/PhysicalUnits.h> #include <type_traits> -using namespace corsika; -using namespace corsika::units::si; - namespace corsika::cascade { template <typename Tracking, typename ProcessList, typename Stack> class Cascade { - - typedef typename Stack::ParticleType Particle; + using Particle = typename Stack::ParticleType; Cascade() = delete; public: - Cascade(Tracking& tr, ProcessList& pl, Stack& stack) - : fTracking(tr) - , fProcesseList(pl) + Cascade(corsika::environment::Environment const& env, Tracking& tr, ProcessList& pl, + Stack& stack) + : fEnvironment(env) + , fTracking(tr) + , fProcessSequence(pl) , fStack(stack) {} void Init() { fTracking.Init(); - fProcesseList.Init(); + fProcessSequence.Init(); fStack.Init(); } @@ -56,85 +56,96 @@ namespace corsika::cascade { } void Step(Particle& particle) { - - // get access to random number generator - static corsika::random::RNG& rmng = - corsika::random::RNGManager::GetInstance().GetRandomStream("s_rndm"); + using namespace corsika::units::si; // determine geometric tracking corsika::setup::Trajectory step = fTracking.GetTrack(particle); // determine combined total interaction length (inverse) - const double total_inv_lambda = - fProcesseList.GetTotalInverseInteractionLength(particle, step); + InverseGrammageType const total_inv_lambda = + fProcessSequence.GetTotalInverseInteractionLength(particle, step); + + // sample random exponential step length in grammage + std::exponential_distribution expDist((1_m * 1_m / 1_g) / total_inv_lambda); + GrammageType const next_interact = (1_g / (1_m * 1_m)) * expDist(fRNG); - // sample random exponential step length - const double sample_step = rmng() / (double)rmng.max(); - const double next_interact = -log(sample_step) / total_inv_lambda; std::cout << "total_inv_lambda=" << total_inv_lambda << ", next_interact=" << next_interact << std::endl; + // convert next_step from grammage to length + LengthType const distance_interact = + fEnvironment.GetUniverse() + ->GetContainingNode(particle.GetPosition()) + ->GetModelProperties() + .ArclengthFromGrammage(step, next_interact); + // determine the maximum geometric step length - const double distance_max = fProcesseList.MaxStepLength(particle, step); + LengthType const distance_max = fProcessSequence.MaxStepLength(particle, step); std::cout << "distance_max=" << distance_max << std::endl; // determine combined total inverse decay time - const double total_inv_lifetime = fProcesseList.GetTotalInverseLifetime(particle); + InverseTimeType const total_inv_lifetime = + fProcessSequence.GetTotalInverseLifetime(particle); // sample random exponential decay time - const double sample_decay = rmng() / (double)rmng.max(); - const double next_decay = -log(sample_decay) / total_inv_lifetime; + std::exponential_distribution expDistDecay(total_inv_lifetime * 1_s); + TimeType const next_decay = 1_s * expDistDecay(fRNG); std::cout << "total_inv_lifetime=" << total_inv_lifetime << ", next_decay=" << next_decay << std::endl; - // convert next_step from grammage to length [m] - // Environment::GetDistance(step, next_step); - const double distance_interact = next_interact; - // .... - // convert next_decay from time to length [m] // Environment::GetDistance(step, next_decay); - const double distance_decay = next_decay; - // .... + LengthType const distance_decay = next_decay * particle.GetMomentum().norm() / + particle.GetEnergy() * + corsika::units::si::constants::cSquared; // take minimum of geometry, interaction, decay for next step - const double distance_decay_interact = std::min(next_decay, next_interact); - const double distance_next = std::min(distance_decay_interact, distance_max); + auto const min_distance = + std::min({distance_interact, distance_decay, distance_max}); - /// here the particle is actually moved along the trajectory to new position: + // here the particle is actually moved along the trajectory to new position: // std::visit(corsika::setup::ParticleUpdate<Particle>{particle}, step); - particle.SetPosition(step.GetPosition(1)); + particle.SetPosition(step.PositionFromArclength(min_distance)); + // .... also update time, momentum, direction, ... // apply all continuous processes on particle + track corsika::process::EProcessReturn status = - fProcesseList.DoContinuous(particle, step, fStack); + fProcessSequence.DoContinuous(particle, step, fStack); if (status == corsika::process::EProcessReturn::eParticleAbsorbed) { // fStack.Delete(particle); // TODO: check if this is really needed } else { - std::cout << "select process " << (distance_decay_interact < distance_max) - << std::endl; - // check if geometry limits step, then quit this step - if (distance_decay_interact < distance_max) { + std::cout << "sth. happening before geometric limit ?" + << ((min_distance < distance_max) ? "yes" : "no") << std::endl; + + if (min_distance < distance_max) { // interaction to happen within geometric limit // check weather decay or interaction limits this step - if (distance_decay > distance_interact) { + + if (min_distance == distance_interact) { std::cout << "collide" << std::endl; - const double actual_inv_length = - fProcesseList.GetTotalInverseInteractionLength(particle, step); - const double sample_process = rmng() / (double)rmng.max(); - double inv_lambda_count = 0; - fProcesseList.SelectInteraction(particle, fStack, actual_inv_length, - sample_process, inv_lambda_count); + + InverseGrammageType const actual_inv_length = + fProcessSequence.GetTotalInverseInteractionLength(particle, step); + + corsika::random::UniformRealDistribution<InverseGrammageType> uniDist( + actual_inv_length); + const auto sample_process = uniDist(fRNG); + InverseGrammageType inv_lambda_count = 0. * meter * meter / gram; + fProcessSequence.SelectInteraction(particle, fStack, sample_process, + inv_lambda_count); } else { std::cout << "decay" << std::endl; - const double actual_decay_time = - fProcesseList.GetTotalInverseLifetime(particle); - const double sample_process = rmng() / (double)rmng.max(); - double inv_decay_count = 0; - fProcesseList.SelectDecay(particle, fStack, actual_decay_time, sample_process, - inv_decay_count); + InverseTimeType const actual_decay_time = + fProcessSequence.GetTotalInverseLifetime(particle); + + corsika::random::UniformRealDistribution<InverseTimeType> uniDist( + actual_decay_time); + const auto sample_process = uniDist(fRNG); + InverseTimeType inv_decay_count = 0 / second; + fProcessSequence.SelectDecay(particle, fStack, sample_process, + inv_decay_count); } } } @@ -142,8 +153,11 @@ namespace corsika::cascade { private: Tracking& fTracking; - ProcessList& fProcesseList; + ProcessList& fProcessSequence; Stack& fStack; + corsika::environment::Environment const& fEnvironment; + corsika::random::RNG& fRNG = + corsika::random::RNGManager::GetInstance().GetRandomStream("cascade"); }; } // namespace corsika::cascade diff --git a/Framework/Cascade/testCascade.cc b/Framework/Cascade/testCascade.cc index 875ff1df3a387d5665c8c7bb8b4156c1ab929690..3d7d0741948e5a9d3668501ea1c78f4398763b32 100644 --- a/Framework/Cascade/testCascade.cc +++ b/Framework/Cascade/testCascade.cc @@ -26,6 +26,10 @@ #include <corsika/geometry/RootCoordinateSystem.h> #include <corsika/geometry/Vector.h> +#include <corsika/environment/Environment.h> +#include <corsika/environment/HomogeneousMedium.h> +#include <corsika/environment/NuclearComposition.h> + #include <corsika/setup/SetupStack.h> #include <corsika/setup/SetupTrajectory.h> using corsika::setup::Trajectory; @@ -43,6 +47,27 @@ using namespace corsika::geometry; using namespace std; using namespace corsika::units::si; +corsika::environment::Environment MakeDummyEnv() { + corsika::environment::Environment env; // dummy environment + auto& universe = *(env.GetUniverse()); + + auto theMedium = corsika::environment::Environment::CreateNode<Sphere>( + Point{env.GetCoordinateSystem(), 0_m, 0_m, 0_m}, + 1_km * std::numeric_limits<double>::infinity()); + + using MyHomogeneousModel = + corsika::environment::HomogeneousMedium<corsika::environment::IMediumModel>; + theMedium->SetModelProperties<MyHomogeneousModel>( + 1_g / (1_m * 1_m * 1_m), + corsika::environment::NuclearComposition( + std::vector<corsika::particles::Code>{corsika::particles::Code::Proton}, + std::vector<float>{1.})); + + universe.AddChild(std::move(theMedium)); + + return env; +} + static int fCount = 0; class ProcessSplit : public corsika::process::ContinuousProcess<ProcessSplit> { @@ -50,8 +75,8 @@ public: ProcessSplit() {} template <typename Particle, typename T> - double MaxStepLength(Particle&, T&) const { - return 1; + LengthType MaxStepLength(Particle&, T&) const { + return 1_m; } template <typename Particle, typename T, typename Stack> @@ -81,16 +106,9 @@ private: TEST_CASE("Cascade", "[Cascade]") { corsika::random::RNGManager& rmng = corsika::random::RNGManager::GetInstance(); - rmng.RegisterRandomStream("s_rndm"); - - corsika::environment::Environment env; // dummy environment - auto& universe = *(env.GetUniverse()); - auto const radius = 1_m * std::numeric_limits<double>::infinity(); - ; - auto theMedium = corsika::environment::Environment::CreateNode<Sphere>( - Point{env.GetCoordinateSystem(), 0_m, 0_m, 0_m}, radius); - universe.AddChild(std::move(theMedium)); + rmng.RegisterRandomStream("cascade"); + auto env = MakeDummyEnv(); tracking_line::TrackingLine<setup::Stack> tracking(env); stack_inspector::StackInspector<setup::Stack> p0(true); @@ -98,8 +116,9 @@ TEST_CASE("Cascade", "[Cascade]") { const auto sequence = p0 + p1; setup::Stack stack; - corsika::cascade::Cascade EAS(tracking, sequence, stack); - CoordinateSystem& rootCS = RootCoordinateSystem::GetInstance().GetRootCoordinateSystem(); + corsika::cascade::Cascade EAS(env, tracking, sequence, stack); + CoordinateSystem const& rootCS = + RootCoordinateSystem::GetInstance().GetRootCoordinateSystem(); stack.Clear(); auto particle = stack.NewParticle(); diff --git a/Framework/Geometry/Helix.h b/Framework/Geometry/Helix.h index 2c8f6b8792cb204e652d1222b38f7849b70e0792..27e3575d37026e16ed401974788b80cb35b08bde 100644 --- a/Framework/Geometry/Helix.h +++ b/Framework/Geometry/Helix.h @@ -56,6 +56,10 @@ namespace corsika::geometry { (vPerp * (cos(omegaC * t) - 1) + uPerp * sin(omegaC * t)) / omegaC; } + Point PositionFromArclength(corsika::units::si::LengthType l) const { + return GetPosition(TimeFromArclength(l)); + } + auto GetRadius() const { return radius; } corsika::units::si::LengthType ArcLength(corsika::units::si::TimeType t1, @@ -64,8 +68,8 @@ namespace corsika::geometry { } corsika::units::si::TimeType TimeFromArclength( - corsika::units::si::LengthType t) const { - return t / (vPar + vPerp).norm(); + corsika::units::si::LengthType l) const { + return l / (vPar + vPerp).norm(); } }; diff --git a/Framework/Geometry/Line.h b/Framework/Geometry/Line.h index a79ba9ce85167ebdf5cef65622e060e844cc22b4..1b45f535a9c01acaa0084a42ca3b532360fa9b59 100644 --- a/Framework/Geometry/Line.h +++ b/Framework/Geometry/Line.h @@ -32,6 +32,10 @@ namespace corsika::geometry { Point GetPosition(corsika::units::si::TimeType t) const { return r0 + v0 * t; } + Point PositionFromArclength(corsika::units::si::LengthType l) const { + return r0 + v0.normalized() * l; + } + LengthType ArcLength(corsika::units::si::TimeType t1, corsika::units::si::TimeType t2) const { return v0.norm() * (t2 - t1); diff --git a/Framework/Geometry/RootCoordinateSystem.h b/Framework/Geometry/RootCoordinateSystem.h index a9df34edfeda18b9c7a058503ac163a0f18d4c05..3351d104d760e6d1a27269f3aa8cae1eafd1049b 100644 --- a/Framework/Geometry/RootCoordinateSystem.h +++ b/Framework/Geometry/RootCoordinateSystem.h @@ -22,7 +22,9 @@ namespace corsika::geometry { public: corsika::geometry::CoordinateSystem& GetRootCoordinateSystem() { return fRootCS; } - const corsika::geometry::CoordinateSystem& GetRootCoordinateSystem() const { return fRootCS; } + const corsika::geometry::CoordinateSystem& GetRootCoordinateSystem() const { + return fRootCS; + } private: corsika::geometry::CoordinateSystem fRootCS; // THIS IS IT diff --git a/Framework/Geometry/Trajectory.h b/Framework/Geometry/Trajectory.h index 5bfcea0216ee6fd496275003b307cccc3f804ee8..0d142d91251ee15d22cb78c3daa8aeeb148b7699 100644 --- a/Framework/Geometry/Trajectory.h +++ b/Framework/Geometry/Trajectory.h @@ -15,9 +15,6 @@ #include <corsika/geometry/Point.h> #include <corsika/units/PhysicalUnits.h> -using corsika::units::si::LengthType; -using corsika::units::si::TimeType; - namespace corsika::geometry { template <typename T> @@ -39,7 +36,7 @@ namespace corsika::geometry { Point GetPosition(double u) const { return T::GetPosition(fTimeLength * u); } - TimeType GetDuration() const { return fTimeLength; } + corsika::units::si::TimeType GetDuration() const { return fTimeLength; } LengthType GetDistance(corsika::units::si::TimeType t) const { assert(t > fTimeLength); diff --git a/Framework/Geometry/testGeometry.cc b/Framework/Geometry/testGeometry.cc index bf6f8760c267856b8cd46f15590c453cc94db741..f2ac12e13c912bb36d1e5956190db9e450cb7ba9 100644 --- a/Framework/Geometry/testGeometry.cc +++ b/Framework/Geometry/testGeometry.cc @@ -29,7 +29,8 @@ using namespace corsika::units::si; double constexpr absMargin = 1.0e-8; TEST_CASE("transformations between CoordinateSystems") { - CoordinateSystem& rootCS = RootCoordinateSystem::GetInstance().GetRootCoordinateSystem(); + CoordinateSystem& rootCS = + RootCoordinateSystem::GetInstance().GetRootCoordinateSystem(); REQUIRE(CoordinateSystem::GetTransformation(rootCS, rootCS) .isApprox(EigenTransform::Identity())); @@ -128,7 +129,8 @@ TEST_CASE("transformations between CoordinateSystems") { } TEST_CASE("Sphere") { - CoordinateSystem& rootCS = RootCoordinateSystem::GetInstance().GetRootCoordinateSystem(); + CoordinateSystem& rootCS = + RootCoordinateSystem::GetInstance().GetRootCoordinateSystem(); Point center(rootCS, {0_m, 3_m, 4_m}); Sphere sphere(center, 5_m); @@ -147,24 +149,34 @@ TEST_CASE("Sphere") { } TEST_CASE("Trajectories") { - CoordinateSystem& rootCS = RootCoordinateSystem::GetInstance().GetRootCoordinateSystem(); + CoordinateSystem& rootCS = + RootCoordinateSystem::GetInstance().GetRootCoordinateSystem(); Point r0(rootCS, {0_m, 0_m, 0_m}); SECTION("Line") { Vector<SpeedType::dimension_type> v0(rootCS, - {1_m / second, 0_m / second, 0_m / second}); + {3_m / second, 0_m / second, 0_m / second}); Line const line(r0, v0); CHECK( - (line.GetPosition(2_s).GetCoordinates() - QuantityVector<length_d>(2_m, 0_m, 0_m)) + (line.GetPosition(2_s).GetCoordinates() - QuantityVector<length_d>(6_m, 0_m, 0_m)) .norm() .magnitude() == Approx(0).margin(absMargin)); + CHECK((line.PositionFromArclength(4_m).GetCoordinates() - + QuantityVector<length_d>(4_m, 0_m, 0_m)) + .norm() + .magnitude() == Approx(0).margin(absMargin)); + + CHECK((line.GetPosition(7_s) - line.PositionFromArclength(line.ArcLength(0_s, 7_s))) + .norm() + .magnitude() == Approx(0).margin(absMargin)); + auto const t = 1_s; Trajectory<Line> base(line, t); CHECK(line.GetPosition(t).GetCoordinates() == base.GetPosition(1.).GetCoordinates()); - CHECK(base.ArcLength(1_s, 2_s) / 1_m == Approx(1)); + CHECK(base.ArcLength(1_s, 2_s) / 1_m == Approx(3)); } SECTION("Helix") { @@ -174,7 +186,8 @@ TEST_CASE("Trajectories") { Vector<SpeedType::dimension_type> const vPerp( rootCS, {3_m / second, 0_m / second, 0_m / second}); - auto const omegaC = 2 * M_PI / 1_s; + auto const T = 1_s; + auto const omegaC = 2 * M_PI / T; Helix const helix(r0, omegaC, vPar, vPerp); @@ -188,10 +201,15 @@ TEST_CASE("Trajectories") { .norm() .magnitude() == Approx(0).margin(absMargin)); + CHECK( + (helix.GetPosition(7_s) - helix.PositionFromArclength(helix.ArcLength(0_s, 7_s))) + .norm() + .magnitude() == Approx(0).margin(absMargin)); + auto const t = 1234_s; Trajectory<Helix> const base(helix, t); CHECK(helix.GetPosition(t).GetCoordinates() == base.GetPosition(1.).GetCoordinates()); - CHECK(base.ArcLength(1_s, 2_s) / 1_m == Approx(5)); + CHECK(base.ArcLength(0_s, 1_s) / 1_m == Approx(5)); } } diff --git a/Framework/Particles/ParticleProperties.h b/Framework/Particles/ParticleProperties.h index 91bb74eefd485b3f8afbd67fc0eaeabdbf4f7b42..db3f10fe3a411321b67c1f3fded3536a62a3816e 100644 --- a/Framework/Particles/ParticleProperties.h +++ b/Framework/Particles/ParticleProperties.h @@ -54,7 +54,7 @@ namespace corsika::particles { bool constexpr IsNucleus(Code const); int constexpr GetNucleusA(Code const); int constexpr GetNucleusZ(Code const); - + #include <corsika/particles/GeneratedParticleProperties.inc> /*! @@ -84,7 +84,8 @@ namespace corsika::particles { } corsika::units::si::TimeType constexpr GetLifetime(Code const p) { - return detail::lifetime[static_cast<CodeIntType const>(p)] * corsika::units::si::second; + return detail::lifetime[static_cast<CodeIntType const>(p)] * + corsika::units::si::second; } bool constexpr IsNucleus(Code const p) { @@ -92,14 +93,13 @@ namespace corsika::particles { } int constexpr GetNucleusA(Code const p) { - return detail::nucleusA[static_cast<CodeIntType const>(p)]; + return detail::nucleusA[static_cast<CodeIntType const>(p)]; } int constexpr GetNucleusZ(Code const p) { return detail::nucleusZ[static_cast<CodeIntType const>(p)]; } - namespace io { std::ostream& operator<<(std::ostream& stream, Code const p); diff --git a/Framework/Particles/testParticles.cc b/Framework/Particles/testParticles.cc index bf307798b57d4998115a54321de965e6e53d8bb3..219e8dd8904d925eb365b76e38f6b3b9218b5f90 100644 --- a/Framework/Particles/testParticles.cc +++ b/Framework/Particles/testParticles.cc @@ -58,12 +58,12 @@ TEST_CASE("ParticleProperties", "[Particles]") { REQUIRE(GetLifetime(Code::Electron) == std::numeric_limits<double>::infinity() * corsika::units::si::second); REQUIRE(GetLifetime(Code::DPlus) < GetLifetime(Code::Gamma)); - REQUIRE(GetLifetime(Code::RhoPlus)/corsika::units::si::second == - (Approx(4.414566727909413e-24).epsilon(1e-3))); - REQUIRE(GetLifetime(Code::SigmaMinusBar)/corsika::units::si::second == - (Approx(8.018880848563575e-11).epsilon(1e-5))); - REQUIRE(GetLifetime(Code::MuPlus)/corsika::units::si::second == - (Approx(2.1970332555864364e-06).epsilon(1e-5))); + REQUIRE(GetLifetime(Code::RhoPlus) / corsika::units::si::second == + (Approx(4.414566727909413e-24).epsilon(1e-3))); + REQUIRE(GetLifetime(Code::SigmaMinusBar) / corsika::units::si::second == + (Approx(8.018880848563575e-11).epsilon(1e-5))); + REQUIRE(GetLifetime(Code::MuPlus) / corsika::units::si::second == + (Approx(2.1970332555864364e-06).epsilon(1e-5))); } SECTION("Nuclei") { @@ -78,8 +78,5 @@ TEST_CASE("ParticleProperties", "[Particles]") { REQUIRE(GetNucleusA(Code::Tritium) == 3); REQUIRE(Hydrogen::GetNucleusZ() == 1); REQUIRE(Tritium::GetNucleusA() == 3); - - } - } diff --git a/Framework/ProcessSequence/DecayProcess.h b/Framework/ProcessSequence/DecayProcess.h index 8a49803ed49913a1c8cf5c217a5c866de307f4bd..076a32410495f8e7524b265284f7aa1d4f8417d5 100644 --- a/Framework/ProcessSequence/DecayProcess.h +++ b/Framework/ProcessSequence/DecayProcess.h @@ -14,6 +14,7 @@ #include <corsika/process/ProcessReturn.h> // for convenience #include <corsika/setup/SetupTrajectory.h> +#include <corsika/units/PhysicalUnits.h> namespace corsika::process { @@ -38,10 +39,10 @@ namespace corsika::process { inline EProcessReturn DoDecay(Particle&, Stack&) const; template <typename Particle> - inline double GetLifetime(Particle& p) const; + corsika::units::si::TimeType GetLifetime(Particle& p) const; template <typename Particle> - inline double GetInverseLifetime(Particle& p) const { + corsika::units::si::InverseTimeType GetInverseLifetime(Particle& p) const { return 1. / GetRef().GetLifetime(p); } }; diff --git a/Framework/ProcessSequence/InteractionProcess.h b/Framework/ProcessSequence/InteractionProcess.h index b0df1eebb5cc88cdb6a6b207906e0a1f2699bed1..a56edffa5f3def9dc866abead57142ec26db7890 100644 --- a/Framework/ProcessSequence/InteractionProcess.h +++ b/Framework/ProcessSequence/InteractionProcess.h @@ -14,6 +14,7 @@ #include <corsika/process/ProcessReturn.h> // for convenience #include <corsika/setup/SetupTrajectory.h> +#include <corsika/units/PhysicalUnits.h> namespace corsika::process { @@ -37,11 +38,12 @@ namespace corsika::process { template <typename P, typename S> inline EProcessReturn DoInteraction(P&, S&) const; - template <typename P, typename T> - inline double GetInteractionLength(P&, T&) const; + template <typename Particle, typename Track> + corsika::units::si::GrammageType GetInteractionLength(Particle& p, Track& t) const; template <typename Particle, typename Track> - inline double GetInverseInteractionLength(Particle& p, Track& t) const { + corsika::units::si::InverseGrammageType GetInverseInteractionLength(Particle& p, + Track& t) const { return 1. / GetRef().GetInteractionLength(p, t); } }; diff --git a/Framework/ProcessSequence/ProcessSequence.h b/Framework/ProcessSequence/ProcessSequence.h index 014630e1a46c076f5f8347686f1d047771c0b29f..d58c14b5083cfda5db73f468357fa28e38122248 100644 --- a/Framework/ProcessSequence/ProcessSequence.h +++ b/Framework/ProcessSequence/ProcessSequence.h @@ -18,6 +18,7 @@ //#include <corsika/process/DiscreteProcess.h> #include <corsika/process/InteractionProcess.h> #include <corsika/process/ProcessReturn.h> +#include <corsika/units/PhysicalUnits.h> #include <cmath> #include <limits> @@ -160,7 +161,7 @@ namespace corsika::process { // void Hello() const { detail::CallHello<T1,T2>::Call(A, B); } template <typename Particle, typename Track, typename Stack> - inline EProcessReturn DoContinuous(Particle& p, Track& t, Stack& s) const { + EProcessReturn DoContinuous(Particle& p, Track& t, Stack& s) const { EProcessReturn ret = EProcessReturn::eOk; if constexpr (std::is_base_of<ContinuousProcess<T1>, T1>::value || is_process_sequence<T1>::value) { @@ -174,32 +175,41 @@ namespace corsika::process { } template <typename Particle, typename Track> - inline double MaxStepLength(Particle& p, Track& track) const { - double max_length = std::numeric_limits<double>::infinity(); + corsika::units::si::LengthType MaxStepLength(Particle& p, Track& track) const { + corsika::units::si::LengthType max_length = + std::numeric_limits<double>::infinity() * corsika::units::si::meter; if constexpr (std::is_base_of<ContinuousProcess<T1>, T1>::value || is_process_sequence<T1>::value) { - max_length = std::min(max_length, A.MaxStepLength(p, track)); + corsika::units::si::LengthType const len = A.MaxStepLength(p, track); + max_length = std::min(max_length, len); } if constexpr (std::is_base_of<ContinuousProcess<T2>, T2>::value || is_process_sequence<T2>::value) { - max_length = std::min(max_length, B.MaxStepLength(p, track)); + corsika::units::si::LengthType const len = B.MaxStepLength(p, track); + max_length = std::min(max_length, len); } return max_length; } template <typename Particle, typename Track> - inline double GetTotalInteractionLength(Particle& p, Track& t) const { + corsika::units::si::GrammageType GetTotalInteractionLength(Particle& p, + Track& t) const { return 1. / GetInverseInteractionLength(p, t); } template <typename Particle, typename Track> - inline double GetTotalInverseInteractionLength(Particle& p, Track& t) const { + corsika::units::si::InverseGrammageType GetTotalInverseInteractionLength( + Particle& p, Track& t) const { return GetInverseInteractionLength(p, t); } template <typename Particle, typename Track> - inline double GetInverseInteractionLength(Particle& p, Track& t) const { - double tot = 0; + corsika::units::si::InverseGrammageType GetInverseInteractionLength(Particle& p, + Track& t) const { + using namespace corsika::units::si; + + InverseGrammageType tot = 0 * meter * meter / gram; + if constexpr (std::is_base_of<InteractionProcess<T1>, T1>::value || is_process_sequence<T1>::value) { tot += A.GetInverseInteractionLength(p, t); @@ -212,21 +222,21 @@ namespace corsika::process { } template <typename Particle, typename Stack> - inline EProcessReturn SelectInteraction(Particle& p, Stack& s, - const double lambda_inv_tot, - const double rndm_select, - double& lambda_inv_count) const { + EProcessReturn SelectInteraction( + Particle& p, Stack& s, corsika::units::si::InverseGrammageType lambda_select, + corsika::units::si::InverseGrammageType& lambda_inv_count) const { + if constexpr (is_process_sequence<T1>::value) { // if A is a process sequence --> check inside const EProcessReturn ret = - A.SelectInteraction(p, s, lambda_inv_count, rndm_select, lambda_inv_count); + A.SelectInteraction(p, s, lambda_select, lambda_inv_count); // if A did succeed, stop routine if (ret != EProcessReturn::eOk) { return ret; } } else if constexpr (std::is_base_of<InteractionProcess<T1>, T1>::value) { // if this is not a ContinuousProcess --> evaluate probability lambda_inv_count += A.GetInverseInteractionLength(p, s); // check if we should execute THIS process and then EXIT - if (rndm_select < lambda_inv_count / lambda_inv_tot) { + if (lambda_select < lambda_inv_count) { A.DoInteraction(p, s); return EProcessReturn::eInteracted; } @@ -235,14 +245,14 @@ namespace corsika::process { if constexpr (is_process_sequence<T2>::value) { // if A is a process sequence --> check inside const EProcessReturn ret = - B.SelectInteraction(p, s, lambda_inv_count, rndm_select, lambda_inv_count); + B.SelectInteraction(p, s, lambda_select, lambda_inv_count); // if A did succeed, stop routine if (ret != EProcessReturn::eOk) { return ret; } } else if constexpr (std::is_base_of<InteractionProcess<T2>, T2>::value) { // if this is not a ContinuousProcess --> evaluate probability lambda_inv_count += B.GetInverseInteractionLength(p, s); // check if we should execute THIS process and then EXIT - if (rndm_select < lambda_inv_count / lambda_inv_tot) { + if (lambda_select < lambda_inv_count) { B.DoInteraction(p, s); return EProcessReturn::eInteracted; } @@ -251,18 +261,21 @@ namespace corsika::process { } template <typename Particle> - inline double GetTotalLifetime(Particle& p) const { + corsika::units::si::TimeType GetTotalLifetime(Particle& p) const { return 1. / GetInverseLifetime(p); } template <typename Particle> - inline double GetTotalInverseLifetime(Particle& p) const { + corsika::units::si::InverseTimeType GetTotalInverseLifetime(Particle& p) const { return GetInverseLifetime(p); } template <typename Particle> - inline double GetInverseLifetime(Particle& p) const { - double tot = 0; + corsika::units::si::InverseTimeType GetInverseLifetime(Particle& p) const { + using namespace corsika::units::si; + + corsika::units::si::InverseTimeType tot = 0 / second; + if constexpr (std::is_base_of<DecayProcess<T1>, T1>::value || is_process_sequence<T1>::value) { tot += A.GetInverseLifetime(p); @@ -276,20 +289,20 @@ namespace corsika::process { // select decay process template <typename Particle, typename Stack> - inline EProcessReturn SelectDecay(Particle& p, Stack& s, const double decay_inv_tot, - const double rndm_select, - double& decay_inv_count) const { + EProcessReturn SelectDecay( + Particle& p, Stack& s, corsika::units::si::InverseTimeType decay_select, + corsika::units::si::InverseTimeType& decay_inv_count) const { if constexpr (is_process_sequence<T1>::value) { // if A is a process sequence --> check inside - const EProcessReturn ret = - A.SelectDecay(p, s, decay_inv_count, rndm_select, decay_inv_count); + const EProcessReturn ret = A.SelectDecay(p, s, decay_select, decay_inv_count); // if A did succeed, stop routine if (ret != EProcessReturn::eOk) { return ret; } } else if constexpr (std::is_base_of<DecayProcess<T1>, T1>::value) { // if this is not a ContinuousProcess --> evaluate probability decay_inv_count += A.GetInverseLifetime(p); // check if we should execute THIS process and then EXIT - if (rndm_select < decay_inv_count / decay_inv_tot) { + if (decay_select < decay_inv_count) { // more pedagogical: rndm_select < + // decay_inv_count / decay_inv_tot A.DoDecay(p, s); return EProcessReturn::eDecayed; } @@ -297,15 +310,14 @@ namespace corsika::process { if constexpr (is_process_sequence<T2>::value) { // if A is a process sequence --> check inside - const EProcessReturn ret = - B.SelectDecay(p, s, decay_inv_count, rndm_select, decay_inv_count); + const EProcessReturn ret = B.SelectDecay(p, s, decay_select, decay_inv_count); // if A did succeed, stop routine if (ret != EProcessReturn::eOk) { return ret; } } else if constexpr (std::is_base_of<DecayProcess<T2>, T2>::value) { // if this is not a ContinuousProcess --> evaluate probability decay_inv_count += B.GetInverseLifetime(p); // check if we should execute THIS process and then EXIT - if (rndm_select < decay_inv_count / decay_inv_tot) { + if (decay_select < decay_inv_count) { B.DoDecay(p, s); return EProcessReturn::eDecayed; } @@ -314,7 +326,7 @@ namespace corsika::process { } /// TODO the const_cast is not nice, think about the constness here - inline void Init() const { + void Init() const { const_cast<T1*>(&A)->Init(); const_cast<T2*>(&B)->Init(); } @@ -349,7 +361,7 @@ namespace corsika::process { OPSEQ(DecayProcess, DecayProcess) template <typename A, typename B> - struct is_process_sequence<corsika::process::ProcessSequence<A, B> > { + struct is_process_sequence<corsika::process::ProcessSequence<A, B> > { static const bool value = true; }; diff --git a/Framework/ProcessSequence/testProcessSequence.cc b/Framework/ProcessSequence/testProcessSequence.cc index af9bfeeade6c2d149f88b803f0ddd2ebb105e6aa..e8a4828cda371a3bb67e0bd1de6b76b889292622 100644 --- a/Framework/ProcessSequence/testProcessSequence.cc +++ b/Framework/ProcessSequence/testProcessSequence.cc @@ -101,9 +101,9 @@ public: return EProcessReturn::eOk; } template <typename Particle, typename Track> - inline double GetInteractionLength(Particle&, Track&) const { + GrammageType GetInteractionLength(Particle&, Track&) const { cout << "Process2::GetInteractionLength" << endl; - return 3; + return 3_g / (1_cm * 1_cm); } }; @@ -124,9 +124,9 @@ public: return EProcessReturn::eOk; } template <typename Particle, typename Track> - inline double GetInteractionLength(Particle&, Track&) const { + GrammageType GetInteractionLength(Particle&, Track&) const { cout << "Process3::GetInteractionLength" << endl; - return 1.; + return 1_g / (1_cm * 1_cm); } }; @@ -165,8 +165,8 @@ public: globalCount++; } template <typename Particle> - double GetLifetime(Particle&) const { - return 1; + TimeType GetLifetime(Particle&) const { + return 1_s; } template <typename Particle, typename Stack> EProcessReturn DoDecay(Particle&, Stack&) const { @@ -209,9 +209,9 @@ TEST_CASE("Process Sequence", "[Process Sequence]") { DummyTrajectory t; const auto sequence2 = cp1 + m2 + m3; - double tot = sequence2.GetTotalInteractionLength(s, t); - double tot_inv = sequence2.GetTotalInverseInteractionLength(s, t); - cout << "lambda_tot=" << tot << " lambda_tot_inv=" << tot_inv << endl; + GrammageType const tot = sequence2.GetTotalInteractionLength(s, t); + InverseGrammageType const tot_inv = sequence2.GetTotalInverseInteractionLength(s, t); + cout << "lambda_tot=" << tot << "; lambda_tot_inv=" << tot_inv << endl; } SECTION("lifetime") { @@ -223,9 +223,9 @@ TEST_CASE("Process Sequence", "[Process Sequence]") { DummyStack s; const auto sequence2 = cp1 + m2 + m3 + d3; - double tot = sequence2.GetTotalLifetime(s); - double tot_inv = sequence2.GetTotalInverseLifetime(s); - cout << "lambda_tot=" << tot << " lambda_tot_inv=" << tot_inv << endl; + TimeType const tot = sequence2.GetTotalLifetime(s); + InverseTimeType const tot_inv = sequence2.GetTotalInverseLifetime(s); + cout << "lambda_tot=" << tot << "; lambda_tot_inv=" << tot_inv << endl; } SECTION("sectionTwo") { diff --git a/Framework/Random/CMakeLists.txt b/Framework/Random/CMakeLists.txt index 3c1947d2508b318eafe6ab426bceac9af7b9e752..230f84f67f4ed6eb02652c5cb10853955f7de776 100644 --- a/Framework/Random/CMakeLists.txt +++ b/Framework/Random/CMakeLists.txt @@ -7,6 +7,7 @@ set ( set ( CORSIKArandom_HEADERS RNGManager.h + UniformRealDistribution.h ) set ( diff --git a/Framework/Random/UniformRealDistribution.h b/Framework/Random/UniformRealDistribution.h new file mode 100644 index 0000000000000000000000000000000000000000..c90ab674ea41976647320a64095a5e8b68d6484e --- /dev/null +++ b/Framework/Random/UniformRealDistribution.h @@ -0,0 +1,32 @@ +#ifndef _include_random_distributions_h +#define _include_random_distributions_h + +#include <corsika/units/PhysicalUnits.h> +#include <random> + +namespace corsika::random { + + template <class TQuantity> + class UniformRealDistribution { + using RealType = typename TQuantity::value_type; + std::uniform_real_distribution<RealType> dist{RealType(0.), RealType(1.)}; + + TQuantity const a, b; + + public: + UniformRealDistribution(TQuantity b) + : a{TQuantity(phys::units::detail::magnitude_tag, 0)} + , b(b) {} + UniformRealDistribution(TQuantity a, TQuantity b) + : a(a) + , b(b) {} + + template <class Generator> + TQuantity operator()(Generator& g) { + return a + dist(g) * (b - a); + } + }; + +} // namespace corsika::random + +#endif diff --git a/Framework/Random/testRandom.cc b/Framework/Random/testRandom.cc index 041a96c21ff241e3a86a903a887e521ff17c9e29..56d8157a74530d404f5d8ba1c8cf8aefe9f75f99 100644 --- a/Framework/Random/testRandom.cc +++ b/Framework/Random/testRandom.cc @@ -1,4 +1,3 @@ - /** * (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu * @@ -14,7 +13,11 @@ #include <catch2/catch.hpp> #include <corsika/random/RNGManager.h> +#include <corsika/random/UniformRealDistribution.h> +#include <corsika/units/PhysicalUnits.h> #include <iostream> +#include <limits> +#include <random> using namespace corsika::random; @@ -37,3 +40,46 @@ SCENARIO("random-number streams can be registered and retrieved") { } } } + +TEST_CASE("UniformRealDistribution") { + using namespace corsika::units::si; + std::mt19937 rng; + + corsika::random::UniformRealDistribution<LengthType> dist(1_m, 2_m); + + SECTION("range") { + corsika::random::UniformRealDistribution<LengthType> dist(1_m, 2_m); + + LengthType min = + +1_m * std::numeric_limits<typename LengthType::value_type>::infinity(); + LengthType max = + -1_m * std::numeric_limits<typename LengthType::value_type>::infinity(); + + for (int i{0}; i < 1'000'000; ++i) { + LengthType x = dist(rng); + min = std::min(min, x); + max = std::max(max, x); + } + + CHECK(min / 1_m == Approx(1.)); + CHECK(max / 2_m == Approx(1.)); + } + + SECTION("range") { + corsika::random::UniformRealDistribution<LengthType> dist(18_cm); + + LengthType min = + +1_m * std::numeric_limits<typename LengthType::value_type>::infinity(); + LengthType max = + -1_m * std::numeric_limits<typename LengthType::value_type>::infinity(); + + for (int i{0}; i < 1'000'000; ++i) { + LengthType x = dist(rng); + min = std::min(min, x); + max = std::max(max, x); + } + + CHECK(min / 1_m == Approx(0.).margin(1e-3)); + CHECK(max / 18_cm == Approx(1.)); + } +} diff --git a/Framework/Units/PhysicalUnits.h b/Framework/Units/PhysicalUnits.h index 7083ce743811176e2c807f2d421dde2273fbb673..03029541311ccbbe259a2f49901e96ac76a4cdb9 100644 --- a/Framework/Units/PhysicalUnits.h +++ b/Framework/Units/PhysicalUnits.h @@ -39,8 +39,7 @@ namespace corsika::units::si { constexpr phys::units::quantity<momentum_d> newton_second{meter * kilogram / second}; /// defining cross section - using sigma_d = phys::units::dimensions<2, 0, 0>; - constexpr phys::units::quantity<sigma_d> barn{Rep(1.e-28L) * meter * meter}; + constexpr phys::units::quantity<area_d> barn{Rep(1.e-28L) * meter * meter}; /// add the unit-types using LengthType = phys::units::quantity<phys::units::length_d, double>; @@ -54,8 +53,13 @@ namespace corsika::units::si { using MassDensityType = phys::units::quantity<phys::units::mass_density_d, double>; using GrammageType = phys::units::quantity<phys::units::dimensions<-2, 1, 0>, double>; using MomentumType = phys::units::quantity<momentum_d, double>; - using CrossSectionType = phys::units::quantity<sigma_d, double>; - + using CrossSectionType = phys::units::quantity<area_d, double>; + using InverseLengthType = + phys::units::quantity<phys::units::dimensions<-1, 0, 0>, double>; + using InverseTimeType = + phys::units::quantity<phys::units::dimensions<0, 0, -1>, double>; + using InverseGrammageType = + phys::units::quantity<phys::units::dimensions<2, -1, 0>, double>; } // end namespace corsika::units::si /** @@ -73,14 +77,11 @@ namespace phys { QUANTITY_DEFINE_SCALING_LITERALS(eV, energy_d, magnitude(corsika::units::si::constants::eV)) - QUANTITY_DEFINE_SCALING_LITERALS(barn, corsika::units::si::sigma_d, + QUANTITY_DEFINE_SCALING_LITERALS(barn, corsika::units::si::area_d, magnitude(corsika::units::si::constants::barn)) - QUANTITY_DEFINE_SCALING_LITERALS(meter, length_d, - magnitude(corsika::units::si::constants::meter)) - - QUANTITY_DEFINE_SCALING_LITERALS(newton_second, corsika::units::si::momentum_d, - magnitude(corsika::units::si::newton_second)) + QUANTITY_DEFINE_SCALING_LITERALS(Ns, corsika::units::si::momentum_d, + magnitude(1_m * 1_kg / 1_s)) } // namespace literals } // namespace units diff --git a/Framework/Units/testUnits.cc b/Framework/Units/testUnits.cc index 4990cd62462af914744aefe76be86528333a978e..db210a7738a57f373286904624766429e384cc56 100644 --- a/Framework/Units/testUnits.cc +++ b/Framework/Units/testUnits.cc @@ -43,8 +43,8 @@ TEST_CASE("PhysicalUnits", "[Units]") { [[maybe_unused]] std::array<EnergyType, 4> arr3 = {1_GeV, 1_eV, 5_MeV}; - [[maybe_unused]] auto p1 = 10_newton_second; - REQUIRE(p1 == 10_newton_second); + auto p1 = 10_Ns; + REQUIRE(p1 == 10_Ns); } SECTION("Powers in literal units") { @@ -69,6 +69,8 @@ TEST_CASE("PhysicalUnits", "[Units]") { REQUIRE(1_A / 1_EA == Approx(1e-18)); REQUIRE(1_K / 1_ZK == Approx(1e-21)); REQUIRE(1_mol / 1_Ymol == Approx(1e-24)); + + REQUIRE(std::min(1_A, 2_A) == 1_A); } SECTION("Powers and units") { @@ -83,7 +85,7 @@ TEST_CASE("PhysicalUnits", "[Units]") { const MassType m = 1_kg; const SpeedType v = 1_m / 1_s; - REQUIRE(m * v == 1_newton_second); + REQUIRE(m * v == 1_Ns); const double lgE = log10(E2 / 1_GeV); REQUIRE(lgE == Approx(log10(40.))); diff --git a/Processes/NullModel/NullModel.cc b/Processes/NullModel/NullModel.cc index 631891e63d11cca0fc7485c4e549496037e0b19e..313d38034d3c90925eb461aa59b1399af8308e4d 100644 --- a/Processes/NullModel/NullModel.cc +++ b/Processes/NullModel/NullModel.cc @@ -11,7 +11,6 @@ #include <corsika/process/null_model/NullModel.h> - #include <corsika/logging/Logger.h> #include <corsika/setup/SetupTrajectory.h> @@ -31,7 +30,7 @@ NullModel<Stack>::~NullModel() {} template <typename Stack> process::EProcessReturn NullModel<Stack>::DoContinuous(Particle&, setup::Trajectory&, - Stack& ) const { + Stack&) const { return EProcessReturn::eOk; } @@ -41,10 +40,8 @@ double NullModel<Stack>::MaxStepLength(Particle&, setup::Trajectory&) const { } template <typename Stack> -void NullModel<Stack>::Init() { -} +void NullModel<Stack>::Init() {} #include <corsika/setup/SetupStack.h> template class process::null_model::NullModel<setup::Stack>; - diff --git a/Processes/NullModel/NullModel.h b/Processes/NullModel/NullModel.h index e7eac1bb0196c77f0ced559ac6145455615fd00b..367c907f38df5ab6b04bbc23ccaefc24a54df4ad 100644 --- a/Processes/NullModel/NullModel.h +++ b/Processes/NullModel/NullModel.h @@ -31,7 +31,6 @@ namespace corsika::process { void Init(); EProcessReturn DoContinuous(Particle&, corsika::setup::Trajectory&, Stack& s) const; double MaxStepLength(Particle&, corsika::setup::Trajectory&) const; - }; } // namespace null_model diff --git a/Processes/NullModel/testNullModel.cc b/Processes/NullModel/testNullModel.cc index 908d7370224a4237bb1332e6b6149176eace39ee..ffcba5e0351acefa519f6a28e003be7999741f68 100644 --- a/Processes/NullModel/testNullModel.cc +++ b/Processes/NullModel/testNullModel.cc @@ -16,8 +16,8 @@ #include <corsika/process/null_model/NullModel.h> #include <corsika/geometry/Point.h> -#include <corsika/geometry/Vector.h> #include <corsika/geometry/RootCoordinateSystem.h> +#include <corsika/geometry/Vector.h> #include <corsika/units/PhysicalUnits.h> @@ -30,24 +30,24 @@ using namespace corsika; TEST_CASE("NullModel", "[processes]") { - auto const& cs = geometry::RootCoordinateSystem::GetInstance().GetRootCoordinateSystem(); - geometry::Point const origin(cs, {0_m, 0_m, 0_m}); - geometry::Vector<corsika::units::si::SpeedType::dimension_type> v(cs, 0_m / second, - 0_m / second, 1_m / second); + auto const& cs = + geometry::RootCoordinateSystem::GetInstance().GetRootCoordinateSystem(); + geometry::Point const origin(cs, {0_m, 0_m, 0_m}); + geometry::Vector<corsika::units::si::SpeedType::dimension_type> v( + cs, 0_m / second, 0_m / second, 1_m / second); geometry::Line line(origin, v); geometry::Trajectory<geometry::Line> track(line, 10_s); setup::Stack stack; auto particle = stack.NewParticle(); - + SECTION("interface") { NullModel<setup::Stack> model; model.Init(); - [[maybe_unused]] const process::EProcessReturn ret = model.DoContinuous(particle, track, stack); + [[maybe_unused]] const process::EProcessReturn ret = + model.DoContinuous(particle, track, stack); [[maybe_unused]] const double length = model.MaxStepLength(particle, track); - - } } diff --git a/Processes/Sibyll/Decay.h b/Processes/Sibyll/Decay.h index fd1a8f4237c63d7531e07bd865da4de6e1191b53..050466793b518aed2e07bed12a356b9933ba30cf 100644 --- a/Processes/Sibyll/Decay.h +++ b/Processes/Sibyll/Decay.h @@ -1,12 +1,11 @@ #ifndef _include_corsika_process_sibyll_decay_h_ #define _include_corsika_process_sibyll_decay_h_ -#include <corsika/process/sibyll/SibStack.h> -#include <corsika/process/sibyll/ParticleConversion.h> #include <corsika/process/DecayProcess.h> - -#include <corsika/setup/SetupTrajectory.h> +#include <corsika/process/sibyll/ParticleConversion.h> +#include <corsika/process/sibyll/SibStack.h> #include <corsika/setup/SetupStack.h> +#include <corsika/setup/SetupTrajectory.h> #include <corsika/particles/ParticleProperties.h> @@ -59,8 +58,8 @@ namespace corsika::process { void setTrackedParticlesStable() { /* - Sibyll is hadronic generator - only hadrons decay + Sibyll is hadronic generator + only hadrons decay */ // set particles unstable setHadronsUnstable(); @@ -73,12 +72,12 @@ namespace corsika::process { ds.NewParticle().SetPID(particles::Code::KMinus); ds.NewParticle().SetPID(particles::Code::K0Long); ds.NewParticle().SetPID(particles::Code::K0Short); - + for (auto& p : ds) { - int s_id = process::sibyll::ConvertToSibyllRaw(p.GetPID()); - // set particle stable by setting table value negative - s_csydec_.idb[s_id - 1] = (-1) * abs(s_csydec_.idb[s_id - 1]); - p.Delete(); + int s_id = process::sibyll::ConvertToSibyllRaw(p.GetPID()); + // set particle stable by setting table value negative + s_csydec_.idb[s_id - 1] = (-1) * abs(s_csydec_.idb[s_id - 1]); + p.Delete(); } } @@ -86,7 +85,7 @@ namespace corsika::process { public: Decay() {} void Init() { - setHadronsUnstable(); + setHadronsUnstable(); setTrackedParticlesStable(); } @@ -112,11 +111,11 @@ namespace corsika::process { friend void setHadronsUnstable(); template <typename Particle> - double GetLifetime(Particle& p) const { + corsika::units::si::TimeType GetLifetime(Particle& p) const { corsika::units::hep::EnergyType E = p.GetEnergy(); corsika::units::hep::MassType m = corsika::particles::GetMass(p.GetPID()); - //const MassDensityType density = 1.25e-3 * kilogram / (1_cm * 1_cm * 1_cm); + // const MassDensityType density = 1.25e-3 * kilogram / (1_cm * 1_cm * 1_cm); const double gamma = E / m; @@ -128,11 +127,11 @@ namespace corsika::process { // return as column density // const double x0 = density * t0 * gamma * constants::c / kilogram * 1_cm * 1_cm; // cout << "Decay: MinStep: x0: " << x0 << endl; - const double lifetime = gamma*t0 / 1_s; - cout << "Decay: MinStep: tau: " << lifetime << endl; - //int a = 1; - //const double x = -x0 * log(s_rndm_(a)); - //cout << "Decay: next decay: " << x << endl; + corsika::units::si::TimeType const lifetime = gamma * t0; + cout << "Decay: MinStep: tau: " << lifetime << endl; + // int a = 1; + // const double x = -x0 * log(s_rndm_(a)); + // cout << "Decay: next decay: " << x << endl; return lifetime; } diff --git a/Processes/Sibyll/Interaction.h b/Processes/Sibyll/Interaction.h index fa22f7fc71c18705558cab61987dd722fb8aba2d..24401ad7c66867370c18ce4101100d998d62b24e 100644 --- a/Processes/Sibyll/Interaction.h +++ b/Processes/Sibyll/Interaction.h @@ -6,272 +6,256 @@ //#include <corsika/setup/SetupStack.h> //#include <corsika/setup/SetupTrajectory.h> +#include <corsika/process/sibyll/ParticleConversion.h> #include <corsika/process/sibyll/SibStack.h> #include <corsika/process/sibyll/sibyll2.3c.h> -#include <corsika/process/sibyll/ParticleConversion.h> #include <corsika/particles/ParticleProperties.h> -#include <corsika/units/PhysicalUnits.h> #include <corsika/random/RNGManager.h> +#include <corsika/units/PhysicalUnits.h> using namespace corsika; using namespace corsika::process::sibyll; using namespace corsika::units::si; - namespace corsika::process::sibyll { - class Interaction : public corsika::process::InteractionProcess<Interaction> { + class Interaction : public corsika::process::InteractionProcess<Interaction> { public: - Interaction() {} ~Interaction() {} - + void Init() { corsika::random::RNGManager& rmng = corsika::random::RNGManager::GetInstance(); rmng.RegisterRandomStream("s_rndm"); - + // test random number generator std::cout << "Interaction: " - << " test sequence of random numbers." << std::endl; + << " test sequence of random numbers." << std::endl; int a = 0; for (int i = 0; i < 8; ++i) std::cout << i << " " << s_rndm_(a) << std::endl; - + // initialize Sibyll sibyll_ini_(); } - //void setTrackedParticlesStable(); + // void setTrackedParticlesStable(); template <typename Particle, typename Track> - double GetInteractionLength(Particle& p, Track&) const { - - // coordinate system, get global frame of reference - CoordinateSystem& rootCS = RootCoordinateSystem::GetInstance().GetRootCoordinateSystem(); - - const particles::Code corsikaBeamId = p.GetPID(); - - // beam particles for sibyll : 1, 2, 3 for p, pi, k - // read from cross section code table - int kBeam = process::sibyll::GetSibyllXSCode(corsikaBeamId); - - bool kInteraction = process::sibyll::CanInteract(corsikaBeamId); - - /* - the target should be defined by the Environment, - ideally as full particle object so that the four momenta - and the boosts can be defined.. - */ - // target nuclei: A < 18 - // FOR NOW: assume target is oxygen - int kTarget = 16; - - EnergyType Etot = p.GetEnergy() + kTarget * corsika::particles::Proton::GetMass(); - super_stupid::MomentumVector Ptot( - rootCS, {0.0_newton_second, 0.0_newton_second, 0.0_newton_second}); - // FOR NOW: assume target is at rest - super_stupid::MomentumVector pTarget( - rootCS, {0.0_newton_second, 0.0_newton_second, 0.0_newton_second}); - Ptot += p.GetMomentum(); - Ptot += pTarget; - // calculate cm. energy - EnergyType sqs = sqrt(Etot * Etot - Ptot.squaredNorm() * constants::cSquared); - double Ecm = sqs / 1_GeV; - - std::cout << "Interaction: " - << "MinStep: input en: " << p.GetEnergy() / 1_GeV << endl - << " beam can interact:" << kBeam << endl - << " beam XS code:" << kBeam << endl - << " beam pid:" << p.GetPID() << endl - << " target mass number:" << kTarget << std::endl; - - double int_length = 0; - if (kInteraction) { - - double prodCrossSection, dummy, dum1, dum2, dum3, dum4; - double dumdif[3]; - - if (kTarget == 1) - sib_sigma_hp_(kBeam, Ecm, dum1, dum2, prodCrossSection, dumdif, dum3, dum4); - else - sib_sigma_hnuc_(kBeam, kTarget, Ecm, prodCrossSection, dummy); - - std::cout << "Interaction: " - << "MinStep: sibyll return: " << prodCrossSection << std::endl; - CrossSectionType sig = prodCrossSection * 1_mbarn; - std::cout << "Interaction: " - << "MinStep: CrossSection (mb): " << sig / 1_mbarn << std::endl; + corsika::units::si::GrammageType GetInteractionLength(Particle& p, Track&) const { + // coordinate system, get global frame of reference + CoordinateSystem& rootCS = + RootCoordinateSystem::GetInstance().GetRootCoordinateSystem(); - const MassType nucleon_mass = 0.93827_GeV / corsika::units::si::constants::cSquared; - std::cout << "Interaction: " - << "nucleon mass " << nucleon_mass << std::endl; - // calculate interaction length in medium - int_length = kTarget * (nucleon_mass / 1_g) / (sig / 1_cmeter / 1_cmeter); - // pick random step lenth - std::cout << "Interaction: " - << "interaction length (g/cm2): " << int_length << std::endl; - } else - int_length = std::numeric_limits<double>::infinity(); - - /* - what are the units of the output? slant depth or 3space length? - - */ - return int_length; - // - // int a = 0; - // const double next_step = -int_length * log(s_rndm_(a)); - // std::cout << "Interaction: " - // << "next step (g/cm2): " << next_step << std::endl; - // return next_step; - } - + const particles::Code corsikaBeamId = p.GetPID(); - template <typename Particle, typename Stack> - corsika::process::EProcessReturn DoInteraction(Particle& p, Stack& s) const { - cout << "ProcessSibyll: " - << "DoInteraction: " << p.GetPID() << " interaction? " - << process::sibyll::CanInteract(p.GetPID()) << endl; - if (process::sibyll::CanInteract(p.GetPID())) { - cout << "defining coordinates" << endl; - // coordinate system, get global frame of reference - CoordinateSystem& rootCS = RootCoordinateSystem::GetInstance().GetRootCoordinateSystem(); + // beam particles for sibyll : 1, 2, 3 for p, pi, k + // read from cross section code table + int kBeam = process::sibyll::GetSibyllXSCode(corsikaBeamId); - QuantityVector<length_d> const coordinates{0_m, 0_m, 0_m}; - Point pOrig(rootCS, coordinates); + bool kInteraction = process::sibyll::CanInteract(corsikaBeamId); /* the target should be defined by the Environment, ideally as full particle object so that the four momenta and the boosts can be defined.. + */ + // target nuclei: A < 18 + // FOR NOW: assume target is oxygen + int kTarget = 16; + + EnergyType Etot = p.GetEnergy() + kTarget * corsika::particles::Proton::GetMass(); + super_stupid::MomentumVector Ptot(rootCS, {0.0_Ns, 0.0_Ns, 0.0_Ns}); + // FOR NOW: assume target is at rest + super_stupid::MomentumVector pTarget(rootCS, {0.0_Ns, 0.0_Ns, 0.0_Ns}); + Ptot += p.GetMomentum(); + Ptot += pTarget; + // calculate cm. energy + EnergyType sqs = sqrt(Etot * Etot - Ptot.squaredNorm() * constants::cSquared); + double Ecm = sqs / 1_GeV; - here we need: GetTargetMassNumber() or GetTargetPID()?? - GetTargetMomentum() (zero in EAS) - */ - // FOR NOW: set target to proton - int kTarget = 1; // env.GetTargetParticle().GetPID(); - - cout << "defining target momentum.." << endl; - // FOR NOW: target is always at rest - const EnergyType Etarget = 0. * 1_GeV + corsika::particles::Proton::GetMass(); - const auto pTarget = super_stupid::MomentumVector( - rootCS, 0. * 1_GeV / constants::c, 0. * 1_GeV / constants::c, - 0. * 1_GeV / constants::c); - cout << "target momentum (GeV/c): " - << pTarget.GetComponents() / 1_GeV * constants::c << endl; - cout << "beam momentum (GeV/c): " - << p.GetMomentum().GetComponents() / 1_GeV * constants::c << endl; - - // get energy of particle from stack - /* - stack is in GeV in lab. frame - convert to GeV in cm. frame - (assuming proton at rest as target AND - assuming no pT, i.e. shower frame-z is aligned with hadron-int-frame-z) - */ - // total energy: E_beam + E_target - // in lab. frame: E_beam + m_target*c**2 - EnergyType E = p.GetEnergy(); - EnergyType Etot = E + Etarget; - // total momentum - super_stupid::MomentumVector Ptot = p.GetMomentum(); // + pTarget; - // invariant mass, i.e. cm. energy - EnergyType Ecm = sqrt(Etot * Etot - - Ptot.squaredNorm() * - constants::cSquared); // sqrt( 2. * E * 0.93827_GeV ); - /* - get transformation between Stack-frame and SibStack-frame - for EAS Stack-frame is lab. frame, could be different for CRMC-mode - the transformation should be derived from the input momenta - */ - const double gamma = Etot / Ecm; - const auto gambet = Ptot / (Ecm / constants::c); - - std::cout << "Interaction: " - << " DoDiscrete: gamma:" << gamma << endl; std::cout << "Interaction: " - << " DoDiscrete: gambet:" << gambet.GetComponents() << endl; + << "MinStep: input en: " << p.GetEnergy() / 1_GeV << endl + << " beam can interact:" << kBeam << endl + << " beam XS code:" << kBeam << endl + << " beam pid:" << p.GetPID() << endl + << " target mass number:" << kTarget << std::endl; - int kBeam = process::sibyll::ConvertToSibyllRaw(p.GetPID()); + if (kInteraction) { - std::cout << "Interaction: " - << " DoInteraction: E(GeV):" << E / 1_GeV << " Ecm(GeV): " << Ecm / 1_GeV - << std::endl; - if (E < 8.5_GeV || Ecm < 10_GeV) { + double prodCrossSection, dummy, dum1, dum2, dum3, dum4; + double dumdif[3]; + + if (kTarget == 1) + sib_sigma_hp_(kBeam, Ecm, dum1, dum2, prodCrossSection, dumdif, dum3, dum4); + else + sib_sigma_hnuc_(kBeam, kTarget, Ecm, prodCrossSection, dummy); + + std::cout << "Interaction: " + << "MinStep: sibyll return: " << prodCrossSection << std::endl; + CrossSectionType sig = prodCrossSection * 1_mbarn; + std::cout << "Interaction: " + << "MinStep: CrossSection (mb): " << sig / 1_mbarn << std::endl; + + const MassType nucleon_mass = + 0.93827_GeV / corsika::units::si::constants::cSquared; std::cout << "Interaction: " - << " DoInteraction: dropping particle.." << std::endl; - p.Delete(); + << "nucleon mass " << nucleon_mass << std::endl; + // calculate interaction length in medium + GrammageType int_length = kTarget * nucleon_mass / sig; + // pick random step lenth + std::cout << "Interaction: " + << "interaction length (g/cm2): " << int_length << std::endl; + + return int_length; } else { - // Sibyll does not know about units.. - double sqs = Ecm / 1_GeV; - // running sibyll, filling stack - sibyll_(kBeam, kTarget, sqs); - // running decays - //setTrackedParticlesStable(); - decsib_(); - // print final state - int print_unit = 6; - sib_list_(print_unit); - - // delete current particle - p.Delete(); - - // add particles from sibyll to stack - // link to sibyll stack - SibStack ss; - - // SibStack does not know about momentum yet so we need counter to access momentum - // array in Sibyll - int i = -1; - super_stupid::MomentumVector Ptot_final( - rootCS, {0.0_newton_second, 0.0_newton_second, 0.0_newton_second}); - for (auto& psib : ss) { - ++i; - // skip particles that have decayed in Sibyll - if (abs(s_plist_.llist[i]) > 100) continue; - - // transform energy to lab. frame, primitve - // compute beta_vec * p_vec - // arbitrary Lorentz transformation based on sibyll routines - const auto gammaBetaComponents = gambet.GetComponents(); - const auto pSibyllComponents = psib.GetMomentum().GetComponents(); - EnergyType en_lab = 0. * 1_GeV; - MomentumType p_lab_components[3]; - en_lab = psib.GetEnergy() * gamma; - EnergyType pnorm = 0. * 1_GeV; - for (int j = 0; j < 3; ++j) - pnorm += (pSibyllComponents[j] * gammaBetaComponents[j] * constants::c) / - (gamma + 1.); - pnorm += psib.GetEnergy(); - - for (int j = 0; j < 3; ++j) { - p_lab_components[j] = pSibyllComponents[j] - (-1) * pnorm * - gammaBetaComponents[j] / - constants::c; - en_lab -= - (-1) * pSibyllComponents[j] * gammaBetaComponents[j] * constants::c; - } + return std::numeric_limits<double>::infinity() * 1_g / (1_cm * 1_cm); + } + } - // add to corsika stack - auto pnew = s.NewParticle(); - pnew.SetEnergy(en_lab); - pnew.SetPID(process::sibyll::ConvertFromSibyll(psib.GetPID())); + template <typename Particle, typename Stack> + corsika::process::EProcessReturn DoInteraction(Particle& p, Stack& s) const { + cout << "ProcessSibyll: " + << "DoInteraction: " << p.GetPID() << " interaction? " + << process::sibyll::CanInteract(p.GetPID()) << endl; + if (process::sibyll::CanInteract(p.GetPID())) { + cout << "defining coordinates" << endl; + // coordinate system, get global frame of reference + CoordinateSystem& rootCS = + RootCoordinateSystem::GetInstance().GetRootCoordinateSystem(); + + QuantityVector<length_d> const coordinates{0_m, 0_m, 0_m}; + Point pOrig(rootCS, coordinates); + + /* + the target should be defined by the Environment, + ideally as full particle object so that the four momenta + and the boosts can be defined.. + + here we need: GetTargetMassNumber() or GetTargetPID()?? + GetTargetMomentum() (zero in EAS) + */ + // FOR NOW: set target to proton + int kTarget = 1; // env.GetTargetParticle().GetPID(); + + cout << "defining target momentum.." << endl; + // FOR NOW: target is always at rest + const EnergyType Etarget = 0. * 1_GeV + corsika::particles::Proton::GetMass(); + const auto pTarget = super_stupid::MomentumVector( + rootCS, 0. * 1_GeV / constants::c, 0. * 1_GeV / constants::c, + 0. * 1_GeV / constants::c); + cout << "target momentum (GeV/c): " + << pTarget.GetComponents() / 1_GeV * constants::c << endl; + cout << "beam momentum (GeV/c): " + << p.GetMomentum().GetComponents() / 1_GeV * constants::c << endl; + + // get energy of particle from stack + /* + stack is in GeV in lab. frame + convert to GeV in cm. frame + (assuming proton at rest as target AND + assuming no pT, i.e. shower frame-z is aligned with hadron-int-frame-z) + */ + // total energy: E_beam + E_target + // in lab. frame: E_beam + m_target*c**2 + EnergyType E = p.GetEnergy(); + EnergyType Etot = E + Etarget; + // total momentum + super_stupid::MomentumVector Ptot = p.GetMomentum(); // + pTarget; + // invariant mass, i.e. cm. energy + EnergyType Ecm = + sqrt(Etot * Etot - Ptot.squaredNorm() * + constants::cSquared); // sqrt( 2. * E * 0.93827_GeV ); + /* + get transformation between Stack-frame and SibStack-frame + for EAS Stack-frame is lab. frame, could be different for CRMC-mode + the transformation should be derived from the input momenta + */ + const double gamma = Etot / Ecm; + const auto gambet = Ptot / (Ecm / constants::c); + + std::cout << "Interaction: " + << " DoDiscrete: gamma:" << gamma << endl; + std::cout << "Interaction: " + << " DoDiscrete: gambet:" << gambet.GetComponents() << endl; + + int kBeam = process::sibyll::ConvertToSibyllRaw(p.GetPID()); - corsika::geometry::QuantityVector<momentum_d> p_lab_c{ - p_lab_components[0], p_lab_components[1], p_lab_components[2]}; - pnew.SetMomentum(super_stupid::MomentumVector(rootCS, p_lab_c)); - Ptot_final += pnew.GetMomentum(); + std::cout << "Interaction: " + << " DoInteraction: E(GeV):" << E / 1_GeV + << " Ecm(GeV): " << Ecm / 1_GeV << std::endl; + if (E < 8.5_GeV || Ecm < 10_GeV) { + std::cout << "Interaction: " + << " DoInteraction: dropping particle.." << std::endl; + p.Delete(); + } else { + // Sibyll does not know about units.. + double sqs = Ecm / 1_GeV; + // running sibyll, filling stack + sibyll_(kBeam, kTarget, sqs); + // running decays + // setTrackedParticlesStable(); + decsib_(); + // print final state + int print_unit = 6; + sib_list_(print_unit); + + // delete current particle + p.Delete(); + + // add particles from sibyll to stack + // link to sibyll stack + SibStack ss; + + // SibStack does not know about momentum yet so we need counter to access + // momentum array in Sibyll + int i = -1; + super_stupid::MomentumVector Ptot_final(rootCS, {0.0_Ns, 0.0_Ns, 0.0_Ns}); + for (auto& psib : ss) { + ++i; + // skip particles that have decayed in Sibyll + if (abs(s_plist_.llist[i]) > 100) continue; + + // transform energy to lab. frame, primitve + // compute beta_vec * p_vec + // arbitrary Lorentz transformation based on sibyll routines + const auto gammaBetaComponents = gambet.GetComponents(); + const auto pSibyllComponents = psib.GetMomentum().GetComponents(); + EnergyType en_lab = 0. * 1_GeV; + MomentumType p_lab_components[3]; + en_lab = psib.GetEnergy() * gamma; + EnergyType pnorm = 0. * 1_GeV; + for (int j = 0; j < 3; ++j) + pnorm += (pSibyllComponents[j] * gammaBetaComponents[j] * constants::c) / + (gamma + 1.); + pnorm += psib.GetEnergy(); + + for (int j = 0; j < 3; ++j) { + p_lab_components[j] = pSibyllComponents[j] - + (-1) * pnorm * gammaBetaComponents[j] / constants::c; + en_lab -= + (-1) * pSibyllComponents[j] * gammaBetaComponents[j] * constants::c; + } + + // add to corsika stack + auto pnew = s.NewParticle(); + pnew.SetEnergy(en_lab); + pnew.SetPID(process::sibyll::ConvertFromSibyll(psib.GetPID())); + + corsika::geometry::QuantityVector<momentum_d> p_lab_c{ + p_lab_components[0], p_lab_components[1], p_lab_components[2]}; + pnew.SetMomentum(super_stupid::MomentumVector(rootCS, p_lab_c)); + Ptot_final += pnew.GetMomentum(); + } + // cout << "tot. momentum final (GeV/c): " << Ptot_final.GetComponents() / 1_GeV + // * constants::c << endl; } - // cout << "tot. momentum final (GeV/c): " << Ptot_final.GetComponents() / 1_GeV * - // constants::c << endl; } + return process::EProcessReturn::eOk; } - return process::EProcessReturn::eOk; - } - }; - -} + +} // namespace corsika::process::sibyll #endif diff --git a/Processes/Sibyll/ParticleConversion.h b/Processes/Sibyll/ParticleConversion.h index e5e76c3b398e2d93a7af8b8fbe652dacf37ea8cb..cd96f83d5af25e4be078d693458ad3239d741aaf 100644 --- a/Processes/Sibyll/ParticleConversion.h +++ b/Processes/Sibyll/ParticleConversion.h @@ -25,7 +25,7 @@ namespace corsika::process::sibyll { #include <corsika/process/sibyll/Generated.inc> - bool constexpr KnownBySibyll(corsika::particles::Code pCode) { + bool constexpr KnownBySibyll(corsika::particles::Code pCode) { return isKnown[static_cast<corsika::particles::CodeIntType>(pCode)]; } diff --git a/Processes/Sibyll/SibStack.h b/Processes/Sibyll/SibStack.h index 09e97b391f82a5631c7e2111f249b60fe34ef7ed..264cff1b8b97d6b3335bd22f7131b53984ae2ba6 100644 --- a/Processes/Sibyll/SibStack.h +++ b/Processes/Sibyll/SibStack.h @@ -1,8 +1,8 @@ #ifndef _include_sibstack_h_ #define _include_sibstack_h_ -#include <corsika/process/sibyll/sibyll2.3c.h> #include <corsika/process/sibyll/ParticleConversion.h> +#include <corsika/process/sibyll/sibyll2.3c.h> #include <corsika/stack/Stack.h> #include <corsika/units/PhysicalUnits.h> @@ -14,75 +14,76 @@ using namespace corsika::units::si; using namespace corsika::geometry; namespace corsika::process::sibyll { - -class SibStackData { -public: - void Init(); + class SibStackData { + + public: + void Init(); - void Clear() { s_plist_.np = 0; } + void Clear() { s_plist_.np = 0; } - int GetSize() const { return s_plist_.np; } + int GetSize() const { return s_plist_.np; } #warning check actual capacity of sibyll stack - int GetCapacity() const { return 8000; } - - void SetId(const int i, const int v) { s_plist_.llist[i] = v; } - void SetEnergy(const int i, const EnergyType v) { s_plist_.p[3][i] = v / 1_GeV; } - void SetMomentum(const int i, const super_stupid::MomentumVector& v) { - auto tmp = v.GetComponents(); - for (int idx = 0; idx < 3; ++idx) - s_plist_.p[idx][i] = tmp[idx] / 1_GeV * constants::c; - } - - int GetId(const int i) const { return s_plist_.llist[i]; } - - EnergyType GetEnergy(const int i) const { return s_plist_.p[3][i] * 1_GeV; } - - super_stupid::MomentumVector GetMomentum(const int i) const { - CoordinateSystem& rootCS = RootCoordinateSystem::GetInstance().GetRootCoordinateSystem(); - corsika::geometry::QuantityVector<momentum_d> components{ - s_plist_.p[0][i] * 1_GeV / constants::c, - s_plist_.p[1][i] * 1_GeV / constants::c, - s_plist_.p[2][i] * 1_GeV / constants::c}; - super_stupid::MomentumVector v1(rootCS, components); - return v1; - } - - void Copy(const int i1, const int i2) { - s_plist_.llist[i1] = s_plist_.llist[i2]; - s_plist_.p[3][i1] = s_plist_.p[3][i2]; - } - -protected: - void IncrementSize() { s_plist_.np++; } - void DecrementSize() { - if (s_plist_.np > 0) { s_plist_.np--; } - } -}; - -template <typename StackIteratorInterface> -class ParticleInterface : public ParticleBase<StackIteratorInterface> { - using ParticleBase<StackIteratorInterface>::GetStackData; - using ParticleBase<StackIteratorInterface>::GetIndex; - -public: - void SetEnergy(const EnergyType v) { GetStackData().SetEnergy(GetIndex(), v); } - EnergyType GetEnergy() const { return GetStackData().GetEnergy(GetIndex()); } - void SetPID(const int v) { GetStackData().SetId(GetIndex(), v); } - corsika::process::sibyll::SibyllCode GetPID() const { - return static_cast<corsika::process::sibyll::SibyllCode>( - GetStackData().GetId(GetIndex())); - } - super_stupid::MomentumVector GetMomentum() const { - return GetStackData().GetMomentum(GetIndex()); - } - void SetMomentum(const super_stupid::MomentumVector& v) { - GetStackData().SetMomentum(GetIndex(), v); - } -}; - -typedef Stack<SibStackData, ParticleInterface> SibStack; - -} + int GetCapacity() const { return 8000; } + + void SetId(const int i, const int v) { s_plist_.llist[i] = v; } + void SetEnergy(const int i, const EnergyType v) { s_plist_.p[3][i] = v / 1_GeV; } + void SetMomentum(const int i, const super_stupid::MomentumVector& v) { + auto tmp = v.GetComponents(); + for (int idx = 0; idx < 3; ++idx) + s_plist_.p[idx][i] = tmp[idx] / 1_GeV * constants::c; + } + + int GetId(const int i) const { return s_plist_.llist[i]; } + + EnergyType GetEnergy(const int i) const { return s_plist_.p[3][i] * 1_GeV; } + + super_stupid::MomentumVector GetMomentum(const int i) const { + CoordinateSystem& rootCS = + RootCoordinateSystem::GetInstance().GetRootCoordinateSystem(); + corsika::geometry::QuantityVector<momentum_d> components{ + s_plist_.p[0][i] * 1_GeV / constants::c, + s_plist_.p[1][i] * 1_GeV / constants::c, + s_plist_.p[2][i] * 1_GeV / constants::c}; + super_stupid::MomentumVector v1(rootCS, components); + return v1; + } + + void Copy(const int i1, const int i2) { + s_plist_.llist[i1] = s_plist_.llist[i2]; + s_plist_.p[3][i1] = s_plist_.p[3][i2]; + } + + protected: + void IncrementSize() { s_plist_.np++; } + void DecrementSize() { + if (s_plist_.np > 0) { s_plist_.np--; } + } + }; + + template <typename StackIteratorInterface> + class ParticleInterface : public ParticleBase<StackIteratorInterface> { + using ParticleBase<StackIteratorInterface>::GetStackData; + using ParticleBase<StackIteratorInterface>::GetIndex; + + public: + void SetEnergy(const EnergyType v) { GetStackData().SetEnergy(GetIndex(), v); } + EnergyType GetEnergy() const { return GetStackData().GetEnergy(GetIndex()); } + void SetPID(const int v) { GetStackData().SetId(GetIndex(), v); } + corsika::process::sibyll::SibyllCode GetPID() const { + return static_cast<corsika::process::sibyll::SibyllCode>( + GetStackData().GetId(GetIndex())); + } + super_stupid::MomentumVector GetMomentum() const { + return GetStackData().GetMomentum(GetIndex()); + } + void SetMomentum(const super_stupid::MomentumVector& v) { + GetStackData().SetMomentum(GetIndex(), v); + } + }; + + typedef Stack<SibStackData, ParticleInterface> SibStack; + +} // namespace corsika::process::sibyll #endif diff --git a/Processes/Sibyll/sibyll2.3c.cc b/Processes/Sibyll/sibyll2.3c.cc index 336617fbfe42e31dcc00b9d8215e8a6f5e24c485..77ad3052724c066fe474c1d41d44cb013f0786a4 100644 --- a/Processes/Sibyll/sibyll2.3c.cc +++ b/Processes/Sibyll/sibyll2.3c.cc @@ -2,7 +2,6 @@ #include <corsika/random/RNGManager.h> - double s_rndm_(int&) { static corsika::random::RNG& rmng = corsika::random::RNGManager::GetInstance().GetRandomStream("s_rndm"); diff --git a/Processes/Sibyll/testSibyll.cc b/Processes/Sibyll/testSibyll.cc index 5d91a5b4b4f2ba06f93fdc25bad74c095c66fac6..a2cbb9e1b2786acab4fe950549c6a0879744aea1 100644 --- a/Processes/Sibyll/testSibyll.cc +++ b/Processes/Sibyll/testSibyll.cc @@ -9,8 +9,8 @@ * the license. */ -#include <corsika/process/sibyll/Interaction.h> #include <corsika/process/sibyll/Decay.h> +#include <corsika/process/sibyll/Interaction.h> #include <corsika/process/sibyll/ParticleConversion.h> #include <corsika/particles/ParticleProperties.h> @@ -58,12 +58,12 @@ TEST_CASE("Sibyll", "[processes]") { REQUIRE(process::sibyll::GetSibyllXSCode(corsika::particles::Code::K0Long) == 3); REQUIRE(process::sibyll::GetSibyllXSCode(corsika::particles::Code::SigmaPlus) == 1); REQUIRE(process::sibyll::GetSibyllXSCode(corsika::particles::Code::PiMinus) == 2); - } + } } #include <corsika/geometry/Point.h> -#include <corsika/geometry/Vector.h> #include <corsika/geometry/RootCoordinateSystem.h> +#include <corsika/geometry/Vector.h> #include <corsika/units/PhysicalUnits.h> @@ -74,24 +74,26 @@ using namespace corsika::units::si; TEST_CASE("SibyllInterface", "[processes]") { - auto const& cs = geometry::RootCoordinateSystem::GetInstance().GetRootCoordinateSystem(); - geometry::Point const origin(cs, {0_m, 0_m, 0_m}); - geometry::Vector<corsika::units::si::SpeedType::dimension_type> v(cs, 0_m / second, - 0_m / second, 1_m / second); + auto const& cs = + geometry::RootCoordinateSystem::GetInstance().GetRootCoordinateSystem(); + geometry::Point const origin(cs, {0_m, 0_m, 0_m}); + geometry::Vector<corsika::units::si::SpeedType::dimension_type> v( + cs, 0_m / second, 0_m / second, 1_m / second); geometry::Line line(origin, v); geometry::Trajectory<geometry::Line> track(line, 10_s); setup::Stack stack; auto particle = stack.NewParticle(); - + SECTION("InteractionInterface") { Interaction model; model.Init(); - [[maybe_unused]] const process::EProcessReturn ret = model.DoInteraction(particle, stack); - [[maybe_unused]] const double length = model.GetInteractionLength(particle, track); - + [[maybe_unused]] const process::EProcessReturn ret = + model.DoInteraction(particle, stack); + [[maybe_unused]] const GrammageType length = + model.GetInteractionLength(particle, track); } SECTION("DecayInterface") { @@ -99,10 +101,8 @@ TEST_CASE("SibyllInterface", "[processes]") { Decay model; model.Init(); - /*[[maybe_unused]] const process::EProcessReturn ret =*/ model.DoDecay(particle, stack); - [[maybe_unused]] const double length = model.GetLifetime(particle); - + /*[[maybe_unused]] const process::EProcessReturn ret =*/model.DoDecay(particle, + stack); + [[maybe_unused]] const TimeType time = model.GetLifetime(particle); } - } - diff --git a/Processes/StackInspector/StackInspector.cc b/Processes/StackInspector/StackInspector.cc index f062c6e4cf31f0a7b62853160db62b9126ace46b..52fe7e7423dc77f663a4e02c1b74c3c893ab24f8 100644 --- a/Processes/StackInspector/StackInspector.cc +++ b/Processes/StackInspector/StackInspector.cc @@ -44,8 +44,8 @@ process::EProcessReturn StackInspector<Stack>::DoContinuous(Particle&, setup::Tr for (auto& iterP : s) { EnergyType E = iterP.GetEnergy(); Etot += E; - geometry::CoordinateSystem& rootCS = - geometry::RootCoordinateSystem::GetInstance().GetRootCoordinateSystem(); // for printout + geometry::CoordinateSystem& rootCS = geometry::RootCoordinateSystem::GetInstance() + .GetRootCoordinateSystem(); // for printout auto pos = iterP.GetPosition().GetCoordinates(rootCS); cout << "StackInspector: i=" << setw(5) << fixed << (i++) << ", id=" << setw(30) << iterP.GetPID() << " E=" << setw(15) << scientific << (E / 1_GeV) << " GeV, " @@ -58,8 +58,9 @@ process::EProcessReturn StackInspector<Stack>::DoContinuous(Particle&, setup::Tr } template <typename Stack> -double StackInspector<Stack>::MaxStepLength(Particle&, setup::Trajectory&) const { - return std::numeric_limits<double>::infinity(); +corsika::units::si::LengthType StackInspector<Stack>::MaxStepLength( + Particle&, setup::Trajectory&) const { + return std::numeric_limits<double>::infinity() * meter; } template <typename Stack> diff --git a/Processes/StackInspector/StackInspector.h b/Processes/StackInspector/StackInspector.h index d4b9f1faae3b2843b04acf700b6a46084b7658a6..07b987b46f8a03a2683b2d160ac86e24ac251560 100644 --- a/Processes/StackInspector/StackInspector.h +++ b/Processes/StackInspector/StackInspector.h @@ -13,8 +13,8 @@ #define _Physics_StackInspector_StackInspector_h_ #include <corsika/process/ContinuousProcess.h> - #include <corsika/setup/SetupTrajectory.h> +#include <corsika/units/PhysicalUnits.h> namespace corsika::process { @@ -32,7 +32,9 @@ namespace corsika::process { void Init(); EProcessReturn DoContinuous(Particle&, corsika::setup::Trajectory&, Stack& s) const; - double MaxStepLength(Particle&, corsika::setup::Trajectory&) const; + //~ template <typename Particle> + corsika::units::si::LengthType MaxStepLength(Particle&, + corsika::setup::Trajectory&) const; private: bool fReport; diff --git a/Processes/StackInspector/testStackInspector.cc b/Processes/StackInspector/testStackInspector.cc index 51f796a24a92439d2fc11a42c1fac07cc2f8ec30..5ff999c1d13721365f560cf5c9ba741907356651 100644 --- a/Processes/StackInspector/testStackInspector.cc +++ b/Processes/StackInspector/testStackInspector.cc @@ -16,8 +16,8 @@ #include <corsika/process/stack_inspector/StackInspector.h> #include <corsika/geometry/Point.h> -#include <corsika/geometry/Vector.h> #include <corsika/geometry/RootCoordinateSystem.h> +#include <corsika/geometry/Vector.h> #include <corsika/units/PhysicalUnits.h> @@ -28,28 +28,26 @@ using namespace corsika::units::si; using namespace corsika::process::stack_inspector; using namespace corsika; - TEST_CASE("StackInspector", "[processes]") { - auto const& cs = geometry::RootCoordinateSystem::GetInstance().GetRootCoordinateSystem(); - geometry::Point const origin(cs, {0_m, 0_m, 0_m}); - geometry::Vector<corsika::units::si::SpeedType::dimension_type> v(cs, 0_m / second, - 0_m / second, 1_m / second); + auto const& cs = + geometry::RootCoordinateSystem::GetInstance().GetRootCoordinateSystem(); + geometry::Point const origin(cs, {0_m, 0_m, 0_m}); + geometry::Vector<corsika::units::si::SpeedType::dimension_type> v( + cs, 0_m / second, 0_m / second, 1_m / second); geometry::Line line(origin, v); geometry::Trajectory<geometry::Line> track(line, 10_s); setup::Stack stack; auto particle = stack.NewParticle(); - + SECTION("interface") { StackInspector<setup::Stack> model(true); model.Init(); - [[maybe_unused]] const process::EProcessReturn ret = model.DoContinuous(particle, track, stack); - [[maybe_unused]] const double length = model.MaxStepLength(particle, track); - + [[maybe_unused]] const process::EProcessReturn ret = + model.DoContinuous(particle, track, stack); + [[maybe_unused]] const LengthType length = model.MaxStepLength(particle, track); } } - - diff --git a/Processes/TrackingLine/TrackingLine.h b/Processes/TrackingLine/TrackingLine.h index 205991ecf0b2b613bc97192b15494a824636a0ea..157751ea73ab261b083857a68cd2c2444469a583 100644 --- a/Processes/TrackingLine/TrackingLine.h +++ b/Processes/TrackingLine/TrackingLine.h @@ -41,14 +41,14 @@ namespace corsika::process { public: std::optional<std::pair<corsika::units::si::TimeType, corsika::units::si::TimeType>> - TimeOfIntersection(corsika::geometry::Line const& traj, + TimeOfIntersection(corsika::geometry::Line const& line, geometry::Sphere const& sphere) { using namespace corsika::units::si; auto const& cs = fEnvironment.GetCoordinateSystem(); geometry::Point const origin(cs, 0_m, 0_m, 0_m); - auto const r0 = (traj.GetR0() - origin); - auto const v0 = traj.GetV0(); + auto const r0 = (line.GetR0() - origin); + auto const v0 = line.GetV0(); auto const c0 = (sphere.GetCenter() - origin); auto const alpha = r0.dot(v0) - 2 * v0.dot(c0); @@ -74,12 +74,14 @@ namespace corsika::process { : fEnvironment(pEnv) {} void Init() {} - auto GetTrack(Particle& p) { + auto GetTrack(Particle const& p) { using namespace corsika::units::si; geometry::Vector<SpeedType::dimension_type> const velocity = p.GetMomentum() / p.GetEnergy() * corsika::units::si::constants::cSquared; auto const currentPosition = p.GetPosition(); + + // to do: include effect of magnetic field geometry::Line line(currentPosition, velocity); auto const* currentVolumeNode =