diff --git a/Documentation/Examples/CMakeLists.txt b/Documentation/Examples/CMakeLists.txt index 97acd45670ef02ca00f234d9bac8419be033ed4d..81c6fc535538d6789ee6170fbe44e6b2fb7fedd5 100644 --- a/Documentation/Examples/CMakeLists.txt +++ b/Documentation/Examples/CMakeLists.txt @@ -90,11 +90,14 @@ target_link_libraries (vertical_EAS CORSIKAlogging CORSIKArandom ProcessSibyll + ProcessPythia + ProcessUrQMD + ProcessSwitch CORSIKAcascade ProcessEnergyLoss + ProcessObservationPlane ProcessTrackWriter ProcessTrackingLine - ProcessHadronicElasticModel ProcessParticleCut ProcessStackInspector CORSIKAprocesses diff --git a/Documentation/Examples/boundary_example.cc b/Documentation/Examples/boundary_example.cc index 7b990016bbcb4e2a2a0794fddf16aa2a92399d37..edc1faf9b67dfb155684ad392fa3f5ec6a4be512 100644 --- a/Documentation/Examples/boundary_example.cc +++ b/Documentation/Examples/boundary_example.cc @@ -177,8 +177,4 @@ int main() { cut.GetCutEnergy() + cut.GetInvEnergy() + cut.GetEmEnergy(); cout << "total energy (GeV): " << Efinal / 1_GeV << endl << "relative difference (%): " << (Efinal / E0 - 1.) * 100 << endl; - - // basic check for unit-tests - assert(cut.GetNumberEmParticles() == 29785); - assert(cut.GetNumberInvParticles() == 26697); } diff --git a/Documentation/Examples/cascade_example.cc b/Documentation/Examples/cascade_example.cc index d5a7097b17d0e6ca6112b1143ed7d9f9a8f191e1..f5c09343babcf62f87135a2fadb124c74a144f7e 100644 --- a/Documentation/Examples/cascade_example.cc +++ b/Documentation/Examples/cascade_example.cc @@ -103,6 +103,10 @@ int main() { double theta = 0.; double phi = 0.; + Point const injectionPos( + rootCS, 0_m, 0_m, + height_atmosphere); // this is the CORSIKA 7 start of atmosphere/universe + { auto elab2plab = [](HEPEnergyType Elab, HEPMassType m) { return sqrt((Elab - m) * (Elab + m)); @@ -118,12 +122,10 @@ int main() { cout << "input particle: " << beamCode << endl; cout << "input angles: theta=" << theta << " phi=" << phi << endl; cout << "input momentum: " << plab.GetComponents() / 1_GeV << endl; - Point pos(rootCS, 0_m, 0_m, - height_atmosphere); // this is the CORSIKA 7 start of atmosphere/universe stack.AddParticle(std::tuple<particles::Code, units::si::HEPEnergyType, corsika::stack::MomentumVector, geometry::Point, units::si::TimeType, unsigned short, unsigned short>{ - beamCode, E0, plab, pos, 0_ns, nuclA, nuclZ}); + beamCode, E0, plab, injectionPos, 0_ns, nuclA, nuclZ}); } // setup processes, decays and interactions @@ -139,7 +141,8 @@ int main() { process::particle_cut::ParticleCut cut(80_GeV); process::track_writer::TrackWriter trackWriter("tracks.dat"); - process::energy_loss::EnergyLoss eLoss; + process::energy_loss::EnergyLoss eLoss( + injectionPos, geometry::Vector<dimensionless_d>(rootCS, {0, 0, -1})); // assemble all processes into an ordered process list auto sequence = stackInspect << sibyll << sibyllNuc << decay << eLoss << cut diff --git a/Documentation/Examples/stopping_power.cc b/Documentation/Examples/stopping_power.cc index edbd2bc3219017a7f05e94a429f51a7b3225050b..5e2423b0c63c557ccf18369677fb1bff5be5b1e5 100644 --- a/Documentation/Examples/stopping_power.cc +++ b/Documentation/Examples/stopping_power.cc @@ -40,7 +40,13 @@ int main() { const CoordinateSystem& rootCS = env.GetCoordinateSystem(); - process::energy_loss::EnergyLoss eLoss; + Point const injectionPos( + rootCS, 0_m, 0_m, + 112.8_km); // this is the CORSIKA 7 start of atmosphere/universe + + Vector<dimensionless_d> showerAxis(rootCS, {0, 0, -1}); + + process::energy_loss::EnergyLoss eLoss(injectionPos, showerAxis); setup::Stack stack; @@ -68,12 +74,11 @@ int main() { cout << "input particle: " << beamCode << endl; cout << "input angles: theta=" << theta << " phi=" << phi << endl; cout << "input momentum: " << plab.GetComponents() / 1_GeV << endl; - Point pos(rootCS, 0_m, 0_m, - 112.8_km); // this is the CORSIKA 7 start of atmosphere/universe + stack.AddParticle( std::tuple<particles::Code, units::si::HEPEnergyType, corsika::stack::MomentumVector, geometry::Point, units::si::TimeType>{ - beamCode, E0, plab, pos, 0_ns}); + beamCode, E0, plab, injectionPos, 0_ns}); auto const p = stack.GetNextParticle(); HEPEnergyType dE = eLoss.TotalEnergyLoss(p, 1_g / square(1_cm)); diff --git a/Documentation/Examples/vertical_EAS.cc b/Documentation/Examples/vertical_EAS.cc index 0b3d4641a8fa6db56ea407049ceef2332d185228..78972df91f591a56a23c0bf6aeb6e8022a293549 100644 --- a/Documentation/Examples/vertical_EAS.cc +++ b/Documentation/Examples/vertical_EAS.cc @@ -10,24 +10,31 @@ #include <corsika/cascade/Cascade.h> #include <corsika/process/ProcessSequence.h> +#include <corsika/process/StackProcess.h> #include <corsika/process/energy_loss/EnergyLoss.h> -#include <corsika/process/hadronic_elastic_model/HadronicElasticModel.h> -#include <corsika/process/stack_inspector/StackInspector.h> +#include <corsika/process/observation_plane/ObservationPlane.h> +#include <corsika/process/particle_cut/ParticleCut.h> +#include <corsika/process/switch_process/SwitchProcess.h> #include <corsika/process/tracking_line/TrackingLine.h> #include <corsika/setup/SetupStack.h> #include <corsika/setup/SetupTrajectory.h> #include <corsika/environment/Environment.h> -#include <corsika/environment/HomogeneousMedium.h> +#include <corsika/environment/FlatExponential.h> #include <corsika/environment/NuclearComposition.h> +#include <corsika/geometry/Plane.h> #include <corsika/geometry/Sphere.h> -#include <corsika/process/sibyll/Decay.h> +//~ #include <corsika/process/sibyll/Decay.h> #include <corsika/process/sibyll/Interaction.h> #include <corsika/process/sibyll/NuclearInteraction.h> +#include <corsika/process/pythia/Decay.h> + +#include <corsika/process/urqmd/UrQMD.h> + #include <corsika/process/particle_cut/ParticleCut.h> #include <corsika/process/track_writer/TrackWriter.h> @@ -37,9 +44,7 @@ #include <corsika/utl/CorsikaFenv.h> -#include <boost/type_index.hpp> -using boost::typeindex::type_id_with_cvr; - +#include <iomanip> #include <iostream> #include <limits> #include <typeinfo> @@ -56,88 +61,125 @@ using namespace corsika::environment; using namespace std; using namespace corsika::units::si; -// -// The example main program for a particle cascade -// +void registerRandomStreams() { + random::RNGManager::GetInstance().RegisterRandomStream("cascade"); + random::RNGManager::GetInstance().RegisterRandomStream("s_rndm"); + random::RNGManager::GetInstance().RegisterRandomStream("pythia"); + random::RNGManager::GetInstance().RegisterRandomStream("UrQMD"); + + random::RNGManager::GetInstance().SeedAll(); +} + int main() { feenableexcept(FE_INVALID); // initialize random number sequence(s) - random::RNGManager::GetInstance().RegisterRandomStream("cascade"); + registerRandomStreams(); // setup environment, geometry using EnvType = Environment<setup::IEnvironmentModel>; EnvType env; + const CoordinateSystem& rootCS = env.GetCoordinateSystem(); auto& universe = *(env.GetUniverse()); - auto theMedium = - EnvType::CreateNode<Sphere>(Point{env.GetCoordinateSystem(), 0_m, 0_m, 0_m}, - 1_km * std::numeric_limits<double>::infinity()); - - // fraction of oxygen - const float fox = 0.20946; - using MyHomogeneousModel = HomogeneousMedium<environment::IMediumModel>; - theMedium->SetModelProperties<MyHomogeneousModel>( - 1_kg / (1_m * 1_m * 1_m), + auto theMedium = EnvType::CreateNode<Sphere>( + Point{rootCS, 0_m, 0_m, 0_m}, 1_km * std::numeric_limits<double>::infinity()); + + auto constexpr temperature = 295_K; // AIRES default temperature for isothermal model + auto constexpr lambda = + -constants::R * temperature / (constants::g_sub_n * 28.966_g / mole); + // 1036 g/cm² taken from AIRES code + auto constexpr rho0 = -1036_g / square(1_cm) / lambda; + using FlatExp = environment::FlatExponential<environment::IMediumModel>; + theMedium->SetModelProperties<FlatExp>( + Point{rootCS, 0_m, 0_m, 0_m}, Vector<dimensionless_d>{rootCS, {0., 0., 1.}}, rho0, + lambda, environment::NuclearComposition( std::vector<particles::Code>{particles::Code::Nitrogen, particles::Code::Oxygen}, - std::vector<float>{(float)1. - fox, fox})); - - universe.AddChild(std::move(theMedium)); - - const CoordinateSystem& rootCS = env.GetCoordinateSystem(); + std::vector<float>{ + 0.7847f, + 1.f - 0.7847f})); // values taken from AIRES manual, Ar removed for now // setup particle stack, and add primary particle setup::Stack stack; stack.Clear(); - const Code beamCode = Code::Nucleus; - const int nuclA = 4; - const int nuclZ = int(nuclA / 2.15 + 0.7); - const HEPMassType mass = GetNucleusMass(nuclA, nuclZ); - const HEPEnergyType E0 = nuclA * 10_TeV; + const Code beamCode = Code::Proton; + auto const mass = particles::GetMass(beamCode); + const HEPEnergyType E0 = 0.1_PeV; double theta = 0.; double phi = 0.; - { - auto elab2plab = [](HEPEnergyType Elab, HEPMassType m) { - return sqrt((Elab - m) * (Elab + m)); - }; - HEPMomentumType P0 = elab2plab(E0, mass); - auto momentumComponents = [](double theta, double phi, HEPMomentumType ptot) { - return std::make_tuple(ptot * sin(theta) * cos(phi), ptot * sin(theta) * sin(phi), - -ptot * cos(theta)); - }; - auto const [px, py, pz] = - momentumComponents(theta / 180. * M_PI, phi / 180. * M_PI, P0); - auto plab = corsika::stack::MomentumVector(rootCS, {px, py, pz}); - cout << "input particle: " << beamCode << endl; - cout << "input angles: theta=" << theta << " phi=" << phi << endl; - cout << "input momentum: " << plab.GetComponents() / 1_GeV << endl; - Point pos(rootCS, 0_m, 0_m, - 112.8_km); // this is the CORSIKA 7 start of atmosphere/universe - stack.AddParticle(std::tuple<particles::Code, units::si::HEPEnergyType, - corsika::stack::MomentumVector, geometry::Point, - units::si::TimeType, unsigned short, unsigned short>{ - beamCode, E0, plab, pos, 0_ns, nuclA, nuclZ}); - } + Point const injectionPos( + rootCS, 0_m, 0_m, 112.8_km); // this is the CORSIKA 7 start of atmosphere/universe + + // { + auto elab2plab = [](HEPEnergyType Elab, HEPMassType m) { + return sqrt((Elab - m) * (Elab + m)); + }; + HEPMomentumType P0 = elab2plab(E0, mass); + auto momentumComponents = [](double theta, double phi, HEPMomentumType ptot) { + return std::make_tuple(ptot * sin(theta) * cos(phi), ptot * sin(theta) * sin(phi), + -ptot * cos(theta)); + }; + auto const [px, py, pz] = + momentumComponents(theta / 180. * M_PI, phi / 180. * M_PI, P0); + auto plab = corsika::stack::MomentumVector(rootCS, {px, py, pz}); + cout << "input particle: " << beamCode << endl; + cout << "input angles: theta=" << theta << " phi=" << phi << endl; + cout << "input momentum: " << plab.GetComponents() / 1_GeV << endl; + + stack.AddParticle( + std::tuple<particles::Code, units::si::HEPEnergyType, + corsika::stack::MomentumVector, geometry::Point, units::si::TimeType>{ + beamCode, E0, plab, injectionPos, 0_ns}); + // } + + Line const line(injectionPos, plab.normalized() * 1_m * 1_Hz); + auto const velocity = line.GetV0().norm(); + + auto const observationHeight = 1.425_km; + + setup::Trajectory const showerAxis(line, (112.8_km - observationHeight) / velocity); + + auto const grammage = theMedium->GetModelProperties().IntegratedGrammage( + showerAxis, (112.8_km - observationHeight)); + std::cout << "Grammage to ground: " << grammage / (1_g / square(1_cm)) << " g/cm²" + << std::endl; + + universe.AddChild(std::move(theMedium)); // setup processes, decays and interactions - tracking_line::TrackingLine tracking; - stack_inspector::StackInspector<setup::Stack> stackInspect(1, true, E0); - random::RNGManager::GetInstance().RegisterRandomStream("s_rndm"); + const std::vector<particles::Code> trackedHadrons = { + particles::Code::PiPlus, particles::Code::PiMinus, particles::Code::KPlus, + particles::Code::KMinus, particles::Code::K0Long, particles::Code::K0Short}; + process::sibyll::Interaction sibyll; process::sibyll::NuclearInteraction sibyllNuc(sibyll, env); - process::sibyll::Decay decay; - process::particle_cut::ParticleCut cut(20_GeV); + //~ process::sibyll::Decay decay(trackedHadrons); + + process::pythia::Decay decay(trackedHadrons); + process::particle_cut::ParticleCut cut(5_GeV); process::track_writer::TrackWriter trackWriter("tracks.dat"); - process::energy_loss::EnergyLoss eLoss; + process::energy_loss::EnergyLoss eLoss(showerAxis); + + Plane const obsPlane(Point(rootCS, 0_m, 0_m, observationHeight), + Vector<dimensionless_d>(rootCS, {0., 0., 1.})); + process::observation_plane::ObservationPlane observationLevel(obsPlane, + "particles.dat"); // assemble all processes into an ordered process list - auto sequence = sibyll << sibyllNuc << decay << eLoss << cut << stackInspect; + + process::UrQMD::UrQMD urqmd; + + auto sibyllSequence = sibyll << sibyllNuc; + process::switch_process::SwitchProcess switchProcess(urqmd, sibyllSequence, 55_GeV); + auto sequence = switchProcess << decay << eLoss << cut << observationLevel + << trackWriter; // define air shower object, run simulation + tracking_line::TrackingLine tracking; cascade::Cascade EAS(env, tracking, sequence, stack); EAS.Init(); EAS.Run(); @@ -151,4 +193,7 @@ int main() { << "relative difference (%): " << (Efinal / E0 - 1) * 100 << endl; cout << "total dEdX energy (GeV): " << eLoss.GetTotal() / 1_GeV << endl << "relative difference (%): " << eLoss.GetTotal() / E0 * 100 << endl; + + std::ofstream finish("finished"); + finish << "run completed without error" << std::endl; } diff --git a/Environment/BaseExponential.h b/Environment/BaseExponential.h index 462c73c26a0713233e7b3c37b30d25cb3f57bcb4..331a09c33b79ce5f40285b3bb91609b6cf1b9a9d 100644 --- a/Environment/BaseExponential.h +++ b/Environment/BaseExponential.h @@ -53,6 +53,8 @@ namespace corsika::environment { units::si::GrammageType IntegratedGrammage( geometry::Trajectory<geometry::Line> const& vLine, units::si::LengthType vL, geometry::Vector<units::si::dimensionless_d> const& vAxis) const { + if (vL == units::si::LengthType::zero()) { return units::si::GrammageType::zero(); } + auto const uDotA = vLine.NormalizedDirection().dot(vAxis).magnitude(); auto const rhoStart = GetImplementation().GetMassDensity(vLine.GetR0()); diff --git a/Environment/IMediumModel.h b/Environment/IMediumModel.h index 25cc2ffaac9c92553a8503b76e4d642856bec45c..b8cda38c3e2688fdd0f8096ddbaeba7884266fd6 100644 --- a/Environment/IMediumModel.h +++ b/Environment/IMediumModel.h @@ -27,7 +27,7 @@ namespace corsika::environment { corsika::geometry::Point const&) const = 0; // todo: think about the mixin inheritance of the trajectory vs the BaseTrajectory - // approach for now, only lines are supported + // approach; for now, only lines are supported virtual corsika::units::si::GrammageType IntegratedGrammage( corsika::geometry::Trajectory<corsika::geometry::Line> const&, corsika::units::si::LengthType) const = 0; diff --git a/Environment/NuclearComposition.h b/Environment/NuclearComposition.h index d97ba380880ddf018e685d010e688a9f639bd0ac..4c2a4f6705c4d1cf74403934acd39c151cc38cdf 100644 --- a/Environment/NuclearComposition.h +++ b/Environment/NuclearComposition.h @@ -15,6 +15,7 @@ #include <corsika/units/PhysicalUnits.h> #include <cassert> +#include <functional> #include <numeric> #include <random> #include <stdexcept> @@ -85,7 +86,6 @@ namespace corsika::environment { auto WeightedSum(TFunction func) const { using ResultQuantity = decltype(func(*fComponents.cbegin())); - auto const sum = [](auto x, auto y) { return x + y; }; auto const prod = [&](auto const compID, auto const fraction) { return func(compID) * fraction; }; @@ -94,12 +94,12 @@ namespace corsika::environment { return std::inner_product( fComponents.cbegin(), fComponents.cend(), fNumberFractions.cbegin(), ResultQuantity::zero(), // .zero() is defined for quantity types only - sum, prod); + std::plus<ResultQuantity>(), prod); } else { return std::inner_product( fComponents.cbegin(), fComponents.cend(), fNumberFractions.cbegin(), ResultQuantity(0), // in other cases we have to use a bare 0 - sum, prod); + std::plus<ResultQuantity>(), prod); } } diff --git a/Framework/Cascade/Cascade.h b/Framework/Cascade/Cascade.h index 99c28b6c97819a7d6c2a92bb21590aa9244fcae6..0caa88ae6fd495258c0c1c473f2e29cf685c0cc4 100644 --- a/Framework/Cascade/Cascade.h +++ b/Framework/Cascade/Cascade.h @@ -122,7 +122,9 @@ namespace corsika::cascade { while (!fStack.IsEmpty()) { while (!fStack.IsEmpty()) { auto pNext = fStack.GetNextParticle(); + std::cout << "========= next: " << pNext.GetPID() << std::endl; Step(pNext); + std::cout << "========= stack ============" << std::endl; fProcessSequence.DoStack(fStack); } // do cascade equations, which can put new particles on Stack, diff --git a/Framework/Geometry/Plane.h b/Framework/Geometry/Plane.h index f6c201177989866ff7fbfec15253f911e592ec79..f82e883a5ebcf5c56f3dc16a8dc6c47b8567a93a 100644 --- a/Framework/Geometry/Plane.h +++ b/Framework/Geometry/Plane.h @@ -26,11 +26,16 @@ namespace corsika::geometry { public: Plane(Point const& vCenter, DimLessVec const& vNormal) : fCenter(vCenter) - , fNormal(vNormal) {} + , fNormal(vNormal.normalized()) {} + bool IsAbove(Point const& vP) const { return fNormal.dot(vP - fCenter) > corsika::units::si::LengthType::zero(); } + units::si::LengthType DistanceTo(geometry::Point const& vP) const { + return (fNormal * (vP - fCenter).dot(fNormal)).norm(); + } + Point const& GetCenter() const { return fCenter; } DimLessVec const& GetNormal() const { return fNormal; } }; diff --git a/Framework/ProcessSequence/ProcessSequence.h b/Framework/ProcessSequence/ProcessSequence.h index c379e493bfc483481dbad4783f7504be9667eab4..35fa6dae14301213e428a4ddf2585535e6f810cd 100644 --- a/Framework/ProcessSequence/ProcessSequence.h +++ b/Framework/ProcessSequence/ProcessSequence.h @@ -341,7 +341,6 @@ namespace corsika::process { /// marker to identify objectas ProcessSequence template <typename A, typename B> struct is_process_sequence<corsika::process::ProcessSequence<A, B>> : std::true_type {}; - } // namespace corsika::process #endif diff --git a/Framework/Utilities/sgn.h b/Framework/Utilities/sgn.h index b0084ee04827345548384b00cd73ea4c76209086..84fca4e550d80f3e9749c513566f80e66b5f15f9 100644 --- a/Framework/Utilities/sgn.h +++ b/Framework/Utilities/sgn.h @@ -1,4 +1,3 @@ - /* * (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu * diff --git a/Processes/EnergyLoss/EnergyLoss.cc b/Processes/EnergyLoss/EnergyLoss.cc index febabc7764039da77c2012a627ae31de49daf87d..c9bf6afd5af77f67a64ec9f219be7813c48b22c6 100644 --- a/Processes/EnergyLoss/EnergyLoss.cc +++ b/Processes/EnergyLoss/EnergyLoss.cc @@ -15,7 +15,10 @@ #include <corsika/setup/SetupStack.h> #include <corsika/setup/SetupTrajectory.h> +#include <corsika/geometry/Line.h> + #include <cmath> +#include <fstream> #include <iostream> #include <limits> @@ -32,11 +35,6 @@ namespace corsika::process::energy_loss { return sqrt((Elab - m) * (Elab + m)); }; - EnergyLoss::EnergyLoss() - : fEnergyLossTot(0_GeV) - , fdX(10_g / square(1_cm)) // profile binning - {} - /** * PDG2018, passage of particles through matter * @@ -163,6 +161,7 @@ namespace corsika::process::energy_loss { process::EProcessReturn EnergyLoss::DoContinuous(SetupParticle& p, SetupTrack const& t) { if (p.GetChargeNumber() == 0) return process::EProcessReturn::eOk; + GrammageType const dX = p.GetNode()->GetModelProperties().IntegratedGrammage(t, t.GetLength()); cout << "EnergyLoss " << p.GetPID() << ", z=" << p.GetChargeNumber() @@ -183,7 +182,7 @@ namespace corsika::process::energy_loss { p.SetEnergy(Enew); MomentumUpdate(p, Enew); fEnergyLossTot += dE; - GetXbin(p, t, dE); + FillProfile(p, t, dE); return status; } @@ -211,37 +210,63 @@ namespace corsika::process::energy_loss { vP.SetMomentum(pnew * Pnew / pnew.GetNorm()); } -#include <corsika/geometry/CoordinateSystem.h> - - int EnergyLoss::GetXbin(SetupParticle const& vP, SetupTrack const& vTrack, - const HEPEnergyType dE) { + void EnergyLoss::FillProfile(SetupParticle const& vP, SetupTrack const& vTrack, + const HEPEnergyType dE) { using namespace corsika::geometry; - CoordinateSystem const& rootCS = - RootCoordinateSystem::GetInstance().GetRootCoordinateSystem(); - Point const pos1(rootCS, 0_m, 0_m, 0_m); - Point const pos2(rootCS, 0_m, 0_m, vTrack.GetPosition(0).GetCoordinates()[2]); - auto const delta = (pos2 - pos1) / 1_s; - Trajectory const t(Line(pos1, delta), 1_s); + auto const toStart = vTrack.GetPosition(0) - fInjectionPoint; + auto const toEnd = vTrack.GetPosition(1) - fInjectionPoint; + + auto const v1 = (toStart * 1_Hz).dot(fShowerAxisDirection); + auto const v2 = (toEnd * 1_Hz).dot(fShowerAxisDirection); + geometry::Line const lineToStartBin(fInjectionPoint, fShowerAxisDirection * v1); + geometry::Line const lineToEndBin(fInjectionPoint, fShowerAxisDirection * v2); + + SetupTrack const trajToStartBin(lineToStartBin, 1_s); + SetupTrack const trajToEndBin(lineToEndBin, 1_s); + + GrammageType const grammageStart = + vP.GetNode()->GetModelProperties().IntegratedGrammage(trajToStartBin, + trajToStartBin.GetLength()); + GrammageType const grammageEnd = + vP.GetNode()->GetModelProperties().IntegratedGrammage(trajToEndBin, + trajToEndBin.GetLength()); - GrammageType const grammage = - vP.GetNode()->GetModelProperties().IntegratedGrammage(t, t.GetLength()); + const int binStart = grammageStart / fdX; + const int binEnd = grammageEnd / fdX; - const int bin = grammage / fdX; + std::cout << "energy deposit of " << -dE << " between " << grammageStart << " and " + << grammageEnd << std::endl; + + auto energyCount = HEPEnergyType::zero(); + + auto fill = [&](int bin, GrammageType weight) { + auto const increment = -dE * weight / (grammageEnd - grammageStart); + fProfile[bin] += increment; + energyCount += increment; + + std::cout << "filling bin " << bin << " with weight " << weight << ": " << increment + << std::endl; + }; // fill longitudinal profile - if (!fProfile.count(bin)) { cout << "EnergyLoss new x bin " << bin << endl; } - fProfile[bin] += -dE / 1_GeV; - return bin; + fill(binStart, (1 + binStart) * fdX - grammageStart); + fill(binEnd, grammageEnd - binEnd * fdX); + + if (binStart == binEnd) { fill(binStart, -fdX); } + + for (int bin = binStart + 1; bin < binEnd; ++bin) { fill(bin, fdX); } + + std::cout << "total energy added to histogram: " << energyCount << std::endl; } void EnergyLoss::PrintProfile() const { - - cout << "EnergyLoss PrintProfile X-bin [g/cm2] dE/dX [GeV/g/cm2] " << endl; + std::ofstream file("EnergyLossProfile.dat"); + cout << "# EnergyLoss PrintProfile X-bin [g/cm2] dE/dX [GeV/g/cm2] " << endl; double const deltaX = fdX / 1_g * square(1_cm); for (auto v : fProfile) { - cout << v.first * deltaX << " " << v.second / deltaX << endl; + file << v.first * deltaX << " " << v.second / (deltaX * 1_GeV) << endl; } } diff --git a/Processes/EnergyLoss/EnergyLoss.h b/Processes/EnergyLoss/EnergyLoss.h index 4380a8ddcda43d3925df0ab839d010f3c0e0cad4..5061c7c616e34f6137693d2f16b04019ee389ddb 100644 --- a/Processes/EnergyLoss/EnergyLoss.h +++ b/Processes/EnergyLoss/EnergyLoss.h @@ -11,6 +11,8 @@ #ifndef _Processes_EnergyLoss_h_ #define _Processes_EnergyLoss_h_ +#include <corsika/geometry/Point.h> +#include <corsika/geometry/Vector.h> #include <corsika/process/ContinuousProcess.h> #include <corsika/units/PhysicalUnits.h> @@ -29,13 +31,20 @@ namespace corsika::process::energy_loss { void MomentumUpdate(setup::Stack::ParticleType&, units::si::HEPEnergyType Enew); public: - EnergyLoss(); + template <typename TDim> + EnergyLoss(geometry::Point const& injectionPoint, + geometry::Vector<TDim> const& direction) + : fInjectionPoint(injectionPoint) + , fShowerAxisDirection(direction.normalized()) {} + + EnergyLoss(setup::Trajectory const& trajectory) + : EnergyLoss(trajectory.GetPosition(0), trajectory.GetV0()){}; + void Init() {} process::EProcessReturn DoContinuous(setup::Stack::ParticleType&, setup::Trajectory const&); units::si::LengthType MaxStepLength(setup::Stack::ParticleType const&, setup::Trajectory const&) const; - units::si::HEPEnergyType GetTotal() const { return fEnergyLossTot; } void PrintProfile() const; static units::si::HEPEnergyType BetheBloch(setup::Stack::ParticleType const&, @@ -46,12 +55,19 @@ namespace corsika::process::energy_loss { const units::si::GrammageType); private: - int GetXbin(setup::Stack::ParticleType const&, setup::Trajectory const&, - units::si::HEPEnergyType); + void FillProfile(setup::Stack::ParticleType const&, setup::Trajectory const&, + units::si::HEPEnergyType); + // void FillProfileAbsorbed(setup::Stack::ParticleType const&, setup::Trajectory + // const&); - units::si::HEPEnergyType fEnergyLossTot; - units::si::GrammageType fdX; // profile binning - std::map<int, double> fProfile; // longitudinal profile + units::si::HEPEnergyType fEnergyLossTot = units::si::HEPEnergyType::zero(); + units::si::GrammageType const fdX = std::invoke([]() { + using namespace units::si; + return 10_g / square(1_cm); + }); // profile binning + std::map<int, units::si::HEPEnergyType> fProfile; // longitudinal profile + geometry::Point const fInjectionPoint; + geometry::Vector<units::si::dimensionless_d> const fShowerAxisDirection; }; } // namespace corsika::process::energy_loss diff --git a/Processes/ParticleCut/CMakeLists.txt b/Processes/ParticleCut/CMakeLists.txt index d5a92febd68757f2978c97eee38022b38c22b53a..eed2c18f29e715c8794310f420ed58cc0dff03c1 100644 --- a/Processes/ParticleCut/CMakeLists.txt +++ b/Processes/ParticleCut/CMakeLists.txt @@ -29,6 +29,7 @@ target_link_libraries ( ProcessParticleCut CORSIKAunits CORSIKAparticles + CORSIKAprocesssequence CORSIKAsetup ) diff --git a/Processes/ParticleCut/ParticleCut.cc b/Processes/ParticleCut/ParticleCut.cc index 1c9ad8c671ade7fdfbc056be1d7f4eb8df38708b..5783c05fd32e31b691bb930931d9c98e49509dae 100644 --- a/Processes/ParticleCut/ParticleCut.cc +++ b/Processes/ParticleCut/ParticleCut.cc @@ -48,40 +48,16 @@ namespace corsika::process { } bool ParticleCut::ParticleIsInvisible(Code vCode) const { - bool is_inv = false; - // FOR NOW: switch switch (vCode) { case Code::NuE: - is_inv = true; - break; case Code::NuEBar: - is_inv = true; - break; case Code::NuMu: - is_inv = true; - break; case Code::NuMuBar: - is_inv = true; - break; - case Code::MuPlus: - is_inv = true; - break; - case Code::MuMinus: - is_inv = true; - break; - - case Code::Neutron: - is_inv = true; - break; - - case Code::AntiNeutron: - is_inv = true; - break; + return true; default: - break; + return false; } - return is_inv; } EProcessReturn ParticleCut::DoSecondaries(corsika::setup::StackView& vS) { diff --git a/Processes/ParticleCut/testParticleCut.cc b/Processes/ParticleCut/testParticleCut.cc index c6948f27a4e865744c7efec9e6d276aebbc45c83..2375600c8bacb5908950dbeab0efdd0b46c19b3f 100644 --- a/Processes/ParticleCut/testParticleCut.cc +++ b/Processes/ParticleCut/testParticleCut.cc @@ -46,7 +46,7 @@ TEST_CASE("ParticleCut", "[processes]") { particles::Code::Electron, particles::Code::MuPlus, particles::Code::NuE, particles::Code::Neutron}; - SECTION("cut invisible") { + SECTION("cut on particle type") { ParticleCut cut(20_GeV); @@ -73,7 +73,7 @@ TEST_CASE("ParticleCut", "[processes]") { cut.DoSecondaries(view); - REQUIRE(view.GetSize() == 6); + REQUIRE(view.GetSize() == 8); } SECTION("cut low energy") { diff --git a/Processes/Pythia/Decay.cc b/Processes/Pythia/Decay.cc index 20d2aaa5044e484b2727e5cdc03f011fe36be83b..eed8d5e9e0e9d345bb572b945721d540f69fa112 100644 --- a/Processes/Pythia/Decay.cc +++ b/Processes/Pythia/Decay.cc @@ -74,7 +74,7 @@ namespace corsika::process::pythia { using namespace units::si; HEPEnergyType E = p.GetEnergy(); - HEPMassType m = particles::GetMass(p.GetPID()); + HEPMassType m = p.GetMass(); const double gamma = E / m; diff --git a/Processes/Pythia/Interaction.cc b/Processes/Pythia/Interaction.cc index 043b1d40524876c3ecdf3ad2003edcada07e0934..70565f0f82d793f028b520dcd849f99de9215b39 100644 --- a/Processes/Pythia/Interaction.cc +++ b/Processes/Pythia/Interaction.cc @@ -212,26 +212,12 @@ namespace corsika::process::pythia { const auto mediumComposition = currentNode->GetModelProperties().GetNuclearComposition(); // determine average interaction length - // weighted sum - int i = -1; - si::CrossSectionType weightedProdCrossSection = 0_mb; - // get weights of components from environment/medium - const auto& w = mediumComposition.GetFractions(); - // loop over components in medium - for (auto const targetId : mediumComposition.GetComponents()) { - i++; - cout << "Interaction: get interaction length for target: " << targetId << endl; - - auto const [productionCrossSection, elaCrossSection] = - GetCrossSection(corsikaBeamId, targetId, ECoM); - [[maybe_unused]] const auto& dummy_elaCrossSection = elaCrossSection; - - cout << "Interaction: IntLength: pythia return (mb): " - << productionCrossSection / 1_mb << endl - << "Interaction: IntLength: weight : " << w[i] << endl; - - weightedProdCrossSection += w[i] * productionCrossSection; - } + + auto const weightedProdCrossSection = + mediumComposition.WeightedSum([=](auto vTargetID) { + return std::get<0>(this->GetCrossSection(corsikaBeamId, vTargetID, ECoM)); + }); + cout << "Interaction: IntLength: weighted CrossSection (mb): " << weightedProdCrossSection / 1_mb << endl << "Interaction: IntLength: average mass number: " diff --git a/Processes/UrQMD/urqmd.f b/Processes/UrQMD/urqmd.f index 9319dae63135f3fbe34fa422cd0ec0fc88f8a04c..b9951571ebedbad6d6c30f9833f2e4fbe1f5e5c7 100644 --- a/Processes/UrQMD/urqmd.f +++ b/Processes/UrQMD/urqmd.f @@ -338,6 +338,7 @@ cdh write(*,*)'(W) No collision in event ',event c~ stop endif if (noc.ge.50000) then + print *,'UrQMD terminating...' call exit(2) ! think of a better way to hand over the error ! to C++ endif diff --git a/Tools/plot_tracks.sh b/Tools/plot_tracks.sh index 135b410dc8d80523c8a5f340bf3c26634e35bb7f..16ecf4a6e961115ca11542e3d328d81f15ed4a9c 100755 --- a/Tools/plot_tracks.sh +++ b/Tools/plot_tracks.sh @@ -11,28 +11,34 @@ # with this script you can plot an animation of output of TrackWriter track_dat=$1 -if [ -z "$track_dat" ]; then - echo "usage: $0 <track.dat> [output.gif]" >&2 +muon_dat=$2 + +if [ -z "$track_dat" ] || [ -z "$muon_dat" ]; then + echo "usage: $0 <hadron.dat> <muon.dat> [output.gif]" >&2 exit 1 fi -output=$2 +output=$3 if [ -z "$output" ]; then output="$track_dat.gif" fi cat <<EOF | gnuplot -set term gif animate size 600,600 -set output "$output" +set term png size 900,900 +#set output "$output" +#set zrange [0:40e3] +#set xrange [-10:10] +#set yrange [-10:10] set xlabel "x / m" set ylabel "y / m" set zlabel "z / m" set title "CORSIKA 8 preliminary" -do for [t=0:360:1] { - set view 60, t - splot "$track_dat" u 3:4:5:6:7:8 w vectors nohead t "" +do for [t=0:359:1] { + set output sprintf("%03d_$output", t) + set view 90, t + splot "$muon_dat" u 3:4:5:6:7:8 w vectors nohead lt rgb "red" t "", "$track_dat" u 3:4:5:6:7:8 w vectors nohead lc rgb "black" t "" } EOF