From 4419ceef6eea7aaee014c25a7a079ee3421474d7 Mon Sep 17 00:00:00 2001 From: ralfulrich <ralf.ulrich@kit.edu> Date: Wed, 7 Oct 2020 18:42:36 +0200 Subject: [PATCH] fixed failing tests --- Documentation/Examples/CMakeLists.txt | 34 +++- Documentation/Examples/hybrid_MC.cc | 281 ++++++++++++++++++++++++++ Processes/Pythia/testPythia8.cc | 2 +- Processes/QGSJetII/testQGSJetII.cc | 7 +- Processes/Sibyll/testSibyll.cc | 21 +- Setup/SetupStack.h | 4 +- 6 files changed, 333 insertions(+), 16 deletions(-) create mode 100644 Documentation/Examples/hybrid_MC.cc diff --git a/Documentation/Examples/CMakeLists.txt b/Documentation/Examples/CMakeLists.txt index 62c9d6bd3..87d6fb3ee 100644 --- a/Documentation/Examples/CMakeLists.txt +++ b/Documentation/Examples/CMakeLists.txt @@ -67,7 +67,6 @@ if (Pythia8_FOUND) ProcessPythia8 ProcessUrQMD CORSIKAcascade - ProcessCONEXSourceCut ProcessEnergyLoss ProcessTrackWriter ProcessStackInspector @@ -106,7 +105,39 @@ if (Pythia8_FOUND) ProcessOnShellCheck ProcessStackInspector ProcessLongitudinalProfile + CORSIKAprocesses + CORSIKAcascade + CORSIKAparticles + CORSIKAgeometry + CORSIKAenvironment + CORSIKAprocesssequence + CORSIKAhistory # for HistoryObservationPlane + ) + + CORSIKA_ADD_EXAMPLE (hybrid_MC) + target_link_libraries (hybrid_MC + CORSIKAsetup + CORSIKAunits + CORSIKAlogging + CORSIKArandom + CORSIKAhistory ProcessCONEXSourceCut + ProcessInteractionCounter + ProcessSibyll + ProcessPythia8 + ProcessUrQMD + ProcessSwitch + CORSIKAcascade + ProcessPythia8 + ProcessObservationPlane + ProcessInteractionCounter + ProcessTrackWriter + ProcessEnergyLoss + ProcessTrackingLine + ProcessParticleCut + ProcessOnShellCheck + ProcessStackInspector + ProcessLongitudinalProfile CORSIKAprocesses CORSIKAcascade CORSIKAparticles @@ -146,7 +177,6 @@ target_link_libraries (em_shower ProcessPythia8 ProcessUrQMD CORSIKAcascade - ProcessCONEXSourceCut ProcessEnergyLoss ProcessObservationPlane ProcessInteractionCounter diff --git a/Documentation/Examples/hybrid_MC.cc b/Documentation/Examples/hybrid_MC.cc new file mode 100644 index 000000000..93531a2a0 --- /dev/null +++ b/Documentation/Examples/hybrid_MC.cc @@ -0,0 +1,281 @@ +/* + * (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu + * + * This software is distributed under the terms of the GNU General Public + * Licence version 3 (GPL Version 3). See file LICENSE for a full version of + * the license. + */ + +/* clang-format off */ +// InteractionCounter used boost/histogram, which +// fails if boost/type_traits have been included before. Thus, we have +// to include it first... +#include <corsika/process/interaction_counter/InteractionCounter.hpp> +/* clang-format on */ +#include <corsika/cascade/Cascade.h> +#include <corsika/environment/Environment.h> +#include <corsika/environment/FlatExponential.h> +#include <corsika/environment/LayeredSphericalAtmosphereBuilder.h> +#include <corsika/environment/NuclearComposition.h> +#include <corsika/environment/ShowerAxis.h> +#include <corsika/geometry/Plane.h> +#include <corsika/geometry/Sphere.h> +#include <corsika/logging/Logging.h> +#include <corsika/process/ProcessSequence.h> +#include <corsika/process/StackProcess.h> +#include <corsika/process/energy_loss/EnergyLoss.h> +#include <corsika/process/longitudinal_profile/LongitudinalProfile.h> +#include <corsika/process/observation_plane/ObservationPlane.h> +#include <corsika/process/on_shell_check/OnShellCheck.h> +#include <corsika/process/energy_loss/EnergyLoss.h> +#include <corsika/process/particle_cut/ParticleCut.h> +#include <corsika/process/pythia/Decay.h> +#include <corsika/process/sibyll/Decay.h> +#include <corsika/process/sibyll/Interaction.h> +#include <corsika/process/sibyll/NuclearInteraction.h> +#include <corsika/process/switch_process/SwitchProcess.h> +#include <corsika/process/conex_source_cut/CONEXSourceCut.h> +#include <corsika/process/tracking_line/TrackingLine.h> +#include <corsika/process/urqmd/UrQMD.h> +#include <corsika/random/RNGManager.h> +#include <corsika/setup/SetupStack.h> +#include <corsika/setup/SetupTrajectory.h> +#include <corsika/units/PhysicalUnits.h> +#include <corsika/utl/CorsikaFenv.h> + +#include <iomanip> +#include <iostream> +#include <limits> +#include <string> + +using namespace corsika; +using namespace corsika::process; +using namespace corsika::units; +using namespace corsika::particles; +using namespace corsika::random; +using namespace corsika::geometry; +using namespace corsika::environment; + +using namespace std; +using namespace corsika::units::si; + +void registerRandomStreams(const int seed) { + random::RNGManager::GetInstance().RegisterRandomStream("cascade"); + random::RNGManager::GetInstance().RegisterRandomStream("qgsjet"); + random::RNGManager::GetInstance().RegisterRandomStream("sibyll"); + random::RNGManager::GetInstance().RegisterRandomStream("pythia"); + random::RNGManager::GetInstance().RegisterRandomStream("urqmd"); + random::RNGManager::GetInstance().RegisterRandomStream("proposal"); + + if (seed == 0) + random::RNGManager::GetInstance().SeedAll(); + else + random::RNGManager::GetInstance().SeedAll(seed); +} + +template <typename T> +using MEnv = environment::UniformMediumType<environment::UniformMagneticField<T>>; + + +int main(int argc, char** argv) { + + logging::SetLevel(logging::level::info); + + C8LOG_INFO("vertical_EAS"); + + if (argc < 4) { + std::cerr << "usage: vertical_EAS <A> <Z> <energy/GeV> [seed]" << std::endl; + std::cerr << " if no seed is given, a random seed is chosen" << std::endl; + return 1; + } + feenableexcept(FE_INVALID); + + int seed = 0; + if (argc > 4) seed = std::stoi(std::string(argv[4])); + // initialize random number sequence(s) + registerRandomStreams(seed); + + // setup environment, geometry + using EnvType = setup::Environment; + EnvType env; + const CoordinateSystem& rootCS = env.GetCoordinateSystem(); + Point const center{rootCS, 0_m, 0_m, 0_m}; + environment::LayeredSphericalAtmosphereBuilder<setup::EnvironmentInterface> builder{center}; + builder.setNuclearComposition( + {{particles::Code::Nitrogen, particles::Code::Oxygen}, + {0.7847f, 1.f - 0.7847f}}); // values taken from AIRES manual, Ar removed for now + + builder.addExponentialLayer<MEnv>(1222.6562_g / (1_cm * 1_cm), 994186.38_cm, 4_km, + environment::EMediumType::eAir, + geometry::Vector(rootCS, 0_T, 0_T, 1_T)); + builder.addExponentialLayer<MEnv>(1144.9069_g / (1_cm * 1_cm), 878153.55_cm, 10_km, + environment::EMediumType::eAir, + geometry::Vector(rootCS, 0_T, 0_T, 1_T)); + builder.addExponentialLayer<MEnv>(1305.5948_g / (1_cm * 1_cm), 636143.04_cm, 40_km, + environment::EMediumType::eAir, + geometry::Vector(rootCS, 0_T, 0_T, 1_T)); + builder.addExponentialLayer<MEnv>(540.1778_g / (1_cm * 1_cm), 772170.16_cm, 100_km, + environment::EMediumType::eAir, + geometry::Vector(rootCS, 0_T, 0_T, 1_T)); + builder.addLinearLayer<MEnv>(1e9_cm, 112.8_km, environment::EMediumType::eAir, + geometry::Vector(rootCS, 0_T, 0_T, 1_T)); + + builder.assemble(env); + + // setup particle stack, and add primary particle + setup::Stack stack; + stack.Clear(); + const Code beamCode = Code::Nucleus; + unsigned short const A = std::stoi(std::string(argv[1])); + unsigned short Z = std::stoi(std::string(argv[2])); + auto const mass = particles::GetNucleusMass(A, Z); + const HEPEnergyType E0 = 1_GeV * std::stof(std::string(argv[3])); + double theta = 0.; + auto const thetaRad = theta / 180. * M_PI; + + auto elab2plab = [](HEPEnergyType Elab, HEPMassType m) { + return sqrt((Elab - m) * (Elab + m)); + }; + HEPMomentumType P0 = elab2plab(E0, mass); + auto momentumComponents = [](double thetaRad, HEPMomentumType ptot) { + return std::make_tuple(ptot * sin(thetaRad), 0_eV, -ptot * cos(thetaRad)); + }; + + auto const [px, py, pz] = momentumComponents(thetaRad, P0); + auto plab = corsika::stack::MomentumVector(rootCS, {px, py, pz}); + cout << "input particle: " << beamCode << endl; + cout << "input angles: theta=" << theta << endl; + cout << "input momentum: " << plab.GetComponents() / 1_GeV << ", norm = " << plab.norm() + << endl; + + auto const observationHeight = 0_km + builder.getEarthRadius(); + auto const injectionHeight = 112.75_km + builder.getEarthRadius(); + auto const t = -observationHeight * cos(thetaRad) + + sqrt(-units::static_pow<2>(sin(thetaRad) * observationHeight) + + units::static_pow<2>(injectionHeight)); + Point const showerCore{rootCS, 0_m, 0_m, observationHeight}; + Point const injectionPos = + showerCore + + Vector<dimensionless_d>{rootCS, {-sin(thetaRad), 0, cos(thetaRad)}} * t; + + std::cout << "point of injection: " << injectionPos.GetCoordinates() << std::endl; + + if (A != 1) { + stack.AddParticle(std::tuple<particles::Code, units::si::HEPEnergyType, + corsika::stack::MomentumVector, geometry::Point, + units::si::TimeType, unsigned short, unsigned short>{ + beamCode, E0, plab, injectionPos, 0_ns, A, Z}); + + } else { + stack.AddParticle( + std::tuple<particles::Code, units::si::HEPEnergyType, + corsika::stack::MomentumVector, geometry::Point, units::si::TimeType>{ + particles::Code::Proton, E0, plab, injectionPos, 0_ns}); + } + + std::cout << "shower axis length: " << (showerCore - injectionPos).norm() * 1.02 + << std::endl; + + environment::ShowerAxis const showerAxis{injectionPos, + (showerCore - injectionPos) * 1.02, env}; + + // setup processes, decays and interactions + + process::sibyll::Interaction sibyll; + process::interaction_counter::InteractionCounter sibyllCounted(sibyll); + + process::sibyll::NuclearInteraction sibyllNuc(sibyll, env); + process::interaction_counter::InteractionCounter sibyllNucCounted(sibyllNuc); + + process::pythia::Decay decayPythia; + + // use sibyll decay routine for decays of particles unknown to pythia + process::sibyll::Decay decaySibyll{{ + Code::N1440Plus, + Code::N1440MinusBar, + Code::N1440_0, + Code::N1440_0Bar, + Code::N1710Plus, + Code::N1710MinusBar, + Code::N1710_0, + Code::N1710_0Bar, + + Code::Pi1300Plus, + Code::Pi1300Minus, + Code::Pi1300_0, + + Code::KStar0_1430_0, + Code::KStar0_1430_0Bar, + Code::KStar0_1430_Plus, + Code::KStar0_1430_MinusBar, + }}; + + decaySibyll.PrintDecayConfig(); + + process::particle_cut::ParticleCut cut{60_GeV, false, true}; + process::energy_loss::EnergyLoss eLoss{showerAxis, cut.GetECut()}; + + corsika::process::conex_source_cut::CONEXSourceCut conex( + center, showerAxis, t, injectionHeight, E0, + particles::GetPDG(particles::Code::Proton)); + + process::on_shell_check::OnShellCheck reset_particle_mass(1.e-3, 1.e-1, false); + + process::longitudinal_profile::LongitudinalProfile longprof{showerAxis}; + + Plane const obsPlane(showerCore, Vector<dimensionless_d>(rootCS, {0., 0., 1.})); + process::observation_plane::ObservationPlane observationLevel(obsPlane, + "particles.dat"); + + process::UrQMD::UrQMD urqmd; + process::interaction_counter::InteractionCounter urqmdCounted{urqmd}; + + // assemble all processes into an ordered process list + + auto sibyllSequence = sibyllNucCounted << sibyllCounted; + process::switch_process::SwitchProcess switchProcess(urqmdCounted, sibyllSequence, + 55_GeV); + auto decaySequence = decayPythia << decaySibyll; + + auto sequence = switchProcess << reset_particle_mass << decaySequence + << eLoss << cut << conex << longprof << observationLevel; + + // define air shower object, run simulation + tracking_line::TrackingLine tracking; + cascade::Cascade EAS(env, tracking, sequence, stack); + + // to fix the point of first interaction, uncomment the following two lines: + // EAS.SetNodes(); + // EAS.forceInteraction(); + + EAS.Run(); + + cut.ShowResults(); + //eLoss.ShowResults(); + observationLevel.ShowResults(); + const HEPEnergyType Efinal = cut.GetCutEnergy() + cut.GetInvEnergy() + + cut.GetEmEnergy() + //eLoss.GetEnergyLost() + + observationLevel.GetEnergyGround(); + cout << "total cut energy (GeV): " << Efinal / 1_GeV << endl + << "relative difference (%): " << (Efinal / E0 - 1) * 100 << endl; + observationLevel.Reset(); + cut.Reset(); + //eLoss.Reset(); + + //conex.addParticle(0, E0, 0_eV, emPosition, momentum.normalized(), 0_s); + conex.SolveCE(); + + auto const hists = sibyllCounted.GetHistogram() + sibyllNucCounted.GetHistogram() + + urqmdCounted.GetHistogram(); + + hists.saveLab("inthist_lab.txt"); + hists.saveCMS("inthist_cms.txt"); + + hists.saveLab("inthist_lab.txt"); + hists.saveCMS("inthist_cms.txt"); + + longprof.save("longprof.txt"); + + std::ofstream finish("finished"); + finish << "run completed without error" << std::endl; +} diff --git a/Processes/Pythia/testPythia8.cc b/Processes/Pythia/testPythia8.cc index 0019fdf0b..f64de2b0c 100644 --- a/Processes/Pythia/testPythia8.cc +++ b/Processes/Pythia/testPythia8.cc @@ -101,7 +101,7 @@ auto sumMomentum(TStackView const& view, geometry::CoordinateSystem const& vCS) TEST_CASE("pythia process") { - auto [env, csPtr, nodePtr] = setup::testing::setupEnvironment(particles::Code::Oxygen); + auto [env, csPtr, nodePtr] = setup::testing::setupEnvironment(particles::Code::Proton); auto const& cs = *csPtr; [[maybe_unused]] auto const& env_dummy = env; [[maybe_unused]] auto const& node_dummy = nodePtr; diff --git a/Processes/QGSJetII/testQGSJetII.cc b/Processes/QGSJetII/testQGSJetII.cc index 9a3fd1bc0..c281d9908 100644 --- a/Processes/QGSJetII/testQGSJetII.cc +++ b/Processes/QGSJetII/testQGSJetII.cc @@ -127,7 +127,6 @@ using namespace corsika; TEST_CASE("QgsjetIIInterface", "[processes]") { auto [env, csPtr, nodePtr] = setup::testing::setupEnvironment(particles::Code::Oxygen); - auto const& cs = *csPtr; [[maybe_unused]] auto const& env_dummy = env; [[maybe_unused]] auto const& node_dummy = nodePtr; @@ -137,17 +136,17 @@ TEST_CASE("QgsjetIIInterface", "[processes]") { auto [stackPtr, secViewPtr] = setup::testing::setupStack(particles::Code::Proton, 0,0, 110_GeV, nodePtr, *csPtr); - const auto& view = *secViewPtr; + setup::StackView& view = *(secViewPtr.get()); auto particle = stackPtr->first(); auto projectile = secViewPtr->GetProjectile(); auto const projectileMomentum = projectile.GetMomentum(); Interaction model; - [[maybe_unused]] const process::EProcessReturn ret = model.DoInteraction(*secViewPtr); + [[maybe_unused]] const process::EProcessReturn ret = model.DoInteraction(view); [[maybe_unused]] const GrammageType length = model.GetInteractionLength(particle); - CHECK(length / (1_g / square(1_cm)) == Approx(93.47).margin(0.1)); + CHECK(length / (1_g / square(1_cm)) == Approx(93.04).margin(0.1)); /*********************************** It as turned out already two times (#291 and #307) that the detailed output of diff --git a/Processes/Sibyll/testSibyll.cc b/Processes/Sibyll/testSibyll.cc index 1a7722805..69cde670f 100644 --- a/Processes/Sibyll/testSibyll.cc +++ b/Processes/Sibyll/testSibyll.cc @@ -106,15 +106,16 @@ TEST_CASE("SibyllInterface", "[processes]") { SECTION("InteractionInterface - low energy") { const HEPEnergyType P0 = 60_GeV; - auto [stack, view] = setup::testing::setupStack(particles::Code::Proton, 0,0, P0, nodePtr, cs); + auto [stack, viewPtr] = setup::testing::setupStack(particles::Code::Proton, 0,0, P0, nodePtr, cs); const auto plab = corsika::stack::MomentumVector(cs, {P0, 0_eV, 0_eV}); // this is secret knowledge about setupStack + setup::StackView& view = *viewPtr; auto particle = stack->first(); Interaction model; - [[maybe_unused]] const process::EProcessReturn ret = model.DoInteraction(*view); - auto const pSum = sumMomentum(*view, cs); + [[maybe_unused]] const process::EProcessReturn ret = model.DoInteraction(view); + auto const pSum = sumMomentum(view, cs); /* Interactions between hadrons (h) and nuclei (A) in Sibyll are treated in the @@ -179,23 +180,29 @@ TEST_CASE("SibyllInterface", "[processes]") { CHECK((pSum - plab).norm() / 1_GeV == Approx(0).margin(plab.norm() * 0.05 / 1_GeV)); CHECK(pSum.norm() / P0 == Approx(1).margin(0.05)); [[maybe_unused]] const GrammageType length = model.GetInteractionLength(particle); + CHECK(length/1_g*1_cm*1_cm == Approx(88.7).margin(0.1)); + CHECK(view.getSize() == 20); } SECTION("NuclearInteractionInterface") { - auto [stack, view] = setup::testing::setupStack(particles::Code::Nucleus, 4, 2, 100_GeV, nodePtr, cs); + auto [stack, viewPtr] = setup::testing::setupStack(particles::Code::Nucleus, 4, 2, 500_GeV, nodePtr, cs); + setup::StackView& view = *viewPtr; auto particle = stack->first(); Interaction hmodel; NuclearInteraction model(hmodel, *env); - [[maybe_unused]] const process::EProcessReturn ret = model.DoInteraction(*view); + [[maybe_unused]] const process::EProcessReturn ret = model.DoInteraction(view); [[maybe_unused]] const GrammageType length = model.GetInteractionLength(particle); + CHECK(length/1_g*1_cm*1_cm == Approx(44.2).margin(.1)); + CHECK(view.getSize() == 11); } SECTION("DecayInterface") { - auto [stackPtr, view] = setup::testing::setupStack(particles::Code::Lambda0, 0,0, 10_GeV, nodePtr, cs); + auto [stackPtr, viewPtr] = setup::testing::setupStack(particles::Code::Lambda0, 0,0, 10_GeV, nodePtr, cs); + setup::StackView& view = *viewPtr; auto& stack = *stackPtr; auto particle = stack.first(); @@ -203,7 +210,7 @@ TEST_CASE("SibyllInterface", "[processes]") { model.PrintDecayConfig(); [[maybe_unused]] const TimeType time = model.GetLifetime(particle); - /*[[maybe_unused]] const process::EProcessReturn ret =*/model.DoDecay(*view); + /*[[maybe_unused]] const process::EProcessReturn ret =*/model.DoDecay(view); // run checks // lambda decays into proton and pi- or neutron and pi+ CHECK(stack.getEntries() == 3); diff --git a/Setup/SetupStack.h b/Setup/SetupStack.h index 1431c5dd5..9b4cb8712 100644 --- a/Setup/SetupStack.h +++ b/Setup/SetupStack.h @@ -159,7 +159,7 @@ namespace corsika::setup::testing { particle.SetNode(vNodePtr); return std::make_tuple( std::move(stack), - std::make_unique<decltype(corsika::stack::SecondaryView(particle))>(particle)); + std::make_unique<setup::StackView>(particle)); } else { // not a nucleus HEPEnergyType const E0 = sqrt( units::static_pow<2>(particles::GetMass(vProjectileType)) + pLab.squaredNorm()); @@ -168,7 +168,7 @@ namespace corsika::setup::testing { particle.SetNode(vNodePtr); return std::make_tuple( std::move(stack), - std::make_unique<decltype(corsika::stack::SecondaryView(particle))>(particle)); + std::make_unique<setup::StackView>(particle)); } } -- GitLab