From 7c3d873d23561fb256a03915240cbce7bffe5cc0 Mon Sep 17 00:00:00 2001 From: Nikos Karastathis <n.karastathis@kit.edu> Date: Sun, 10 Jul 2022 15:34:23 +0200 Subject: [PATCH] update radio_em_shower.cpp after rebasing --- examples/radio_em_shower.cpp | 477 ++++++++++++++++++----------------- 1 file changed, 241 insertions(+), 236 deletions(-) diff --git a/examples/radio_em_shower.cpp b/examples/radio_em_shower.cpp index 49bb306ff..c96421173 100644 --- a/examples/radio_em_shower.cpp +++ b/examples/radio_em_shower.cpp @@ -1,10 +1,10 @@ /* - * (c) Copyright 2020 CORSIKA Project, corsika-project@lists.kit.edu - * - * This software is distributed under the terms of the GNU General Public - * Licence version 3 (GPL Version 3). See file LICENSE for a full version of - * the license. - */ +* (c) Copyright 2022 CORSIKA Project, corsika-project@lists.kit.edu +* +* This software is distributed under the terms of the GNU General Public +* Licence version 3 (GPL Version 3). See file LICENSE for a full version of +* the license. +*/ #include <corsika/framework/process/ProcessSequence.hpp> #include <corsika/framework/process/SwitchProcessSequence.hpp> @@ -39,6 +39,7 @@ #include <corsika/modules/ObservationPlane.hpp> #include <corsika/modules/ParticleCut.hpp> #include <corsika/modules/TrackWriter.hpp> +#include <corsika/modules/Sibyll.hpp> #include <corsika/modules/PROPOSAL.hpp> #include <corsika/modules/radio/RadioProcess.hpp> @@ -62,248 +63,252 @@ #include <typeinfo> /* - NOTE, WARNING, ATTENTION + NOTE, WARNING, ATTENTION - The .../Random.hpppp implement the hooks of external modules to the C8 random - number generator. It has to occur excatly ONCE per linked - executable. If you include the header below multiple times and - link this togehter, it will fail. - */ -#include <corsika/modules/sibyll/Random.hpp> -#include <corsika/modules/urqmd/Random.hpp> + The .../Random.hpppp implement the hooks of external modules to the C8 random + number generator. It has to occur excatly ONCE per linked + executable. If you include the header below multiple times and + link this togehter, it will fail. +*/ +#include <corsika/modules/Random.hpp> using namespace corsika; using namespace std; void registerRandomStreams(int seed) { - RNGManager<>::getInstance().registerRandomStream("cascade"); - RNGManager<>::getInstance().registerRandomStream("proposal"); - if (seed == 0) { - std::random_device rd; - seed = rd(); - cout << "new random seed (auto) " << seed << endl; - } - RNGManager<>::getInstance().setSeed(seed); + RNGManager<>::getInstance().registerRandomStream("cascade"); + RNGManager<>::getInstance().registerRandomStream("proposal"); + RNGManager<>::getInstance().registerRandomStream("sibyll"); + if (seed == 0) { + std::random_device rd; + seed = rd(); + cout << "new random seed (auto) " << seed << endl; + } + RNGManager<>::getInstance().setSeed(seed); } template <typename TInterface> using MyExtraEnv = - UniformRefractiveIndex<MediumPropertyModel<UniformMagneticField<TInterface>>>; + UniformRefractiveIndex<MediumPropertyModel<UniformMagneticField<TInterface>>>; int main(int argc, char** argv) { - logging::set_level(logging::level::info); - - if (argc != 3) { - std::cerr - << "usage: radio_em_shower <energy/GeV> <seed> - put seed=0 to use random seed" - << std::endl; - return 1; - } - - int seed{static_cast<int>(std::stof(std::string(argv[2])))}; - std::cout << "Seed: " << seed << std::endl; - feenableexcept(FE_INVALID); - // initialize random number sequence(s) - registerRandomStreams(seed); - - // setup environment, geometry - using EnvironmentInterface = - IRefractiveIndexModel<IMediumPropertyModel<IMagneticFieldModel<IMediumModel>>>; - using EnvType = Environment<EnvironmentInterface>; - EnvType env; - CoordinateSystemPtr const& rootCS = env.getCoordinateSystem(); - Point const center{rootCS, 0_m, 0_m, 0_m}; - - create_5layer_atmosphere<EnvironmentInterface, MyExtraEnv>( - env, AtmosphereId::LinsleyUSStd, center, 1.000327, Medium::AirDry1Atm, - MagneticFieldVector{rootCS, 50_uT, 0_T, 0_T}); - - std::unordered_map<Code, HEPEnergyType> energy_resolution = { - {Code::Electron, 10_MeV}, - {Code::Positron, 10_MeV}, - {Code::Photon, 10_MeV}, - }; - for (auto [pcode, energy] : energy_resolution) - set_energy_production_threshold(pcode, energy); - - // setup particle stack, and add primary particle - setup::Stack<EnvType> stack; - stack.clear(); - const Code beamCode = Code::Electron; - auto const mass = get_mass(beamCode); - const HEPEnergyType E0 = 1_GeV * std::stof(std::string(argv[1])); - double theta = 0.; - auto const thetaRad = theta / 180. * M_PI; - - HEPMomentumType P0 = calculate_momentum(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 = 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.getNorm() << endl; - - auto const observationHeight = 1.4_km + constants::EarthRadius::Mean; - auto const injectionHeight = 112.75_km + constants::EarthRadius::Mean; - auto const t = -observationHeight * cos(thetaRad) + - sqrt(-static_pow<2>(sin(thetaRad) * observationHeight) + - static_pow<2>(injectionHeight)); - Point const showerCore{rootCS, 0_m, 0_m, observationHeight}; - Point const injectionPos = - showerCore + DirectionVector{rootCS, {-sin(thetaRad), 0, cos(thetaRad)}} * t; - - std::cout << "point of injection: " << injectionPos.getCoordinates() << std::endl; - - stack.addParticle(std::make_tuple( - beamCode, calculate_kinetic_energy(plab.getNorm(), get_mass(beamCode)), - plab.normalized(), injectionPos, 0_ns)); - - CORSIKA_LOG_INFO("shower axis length: {} ", - (showerCore - injectionPos).getNorm() * 1.02); - - ShowerAxis const showerAxis{injectionPos, (showerCore - injectionPos) * 1.02, env, - false, 1000}; - - TimeType const groundHitTime{(showerCore - injectionPos).getNorm() / constants::c}; - - // int ring_number {std::stof(std::string(argv[2]))}; - // std::cout << "Ring number : " << ring_number << std::endl; - // auto const radius_ {ring_number * 25_m}; - // std::cout << "Radius = " << radius_ << std::endl; - // const int rr_ = static_cast<int>(radius_ / 1_m); - std::string outname_ = "radio_em_shower_outputs"; // + std::to_string(rr_); - OutputManager output(outname_); - - // Radio objects - // the antenna time variables - const TimeType duration_{1e-6_s}; - const InverseTimeType sampleRate_{1e+9_Hz}; - - // the detector (aka antenna collection) for CoREAS and ZHS - AntennaCollection<TimeDomainAntenna> detectorCoREAS; - AntennaCollection<TimeDomainAntenna> detectorZHS; - - auto const showerCoreX_{showerCore.getCoordinates().getX()}; - auto const showerCoreY_{showerCore.getCoordinates().getY()}; - auto const injectionPosX_{injectionPos.getCoordinates().getX()}; - auto const injectionPosY_{injectionPos.getCoordinates().getY()}; - auto const injectionPosZ_{injectionPos.getCoordinates().getZ()}; - auto const triggerpoint_{Point(rootCS, injectionPosX_, injectionPosY_, injectionPosZ_)}; - std::cout << "Trigger Point is: " << triggerpoint_ << std::endl; - - // // setup CoREAS antennas - for (auto radius_1 = 25_m; radius_1 <= 500_m; radius_1 += 25_m) { - for (auto phi_1 = 0; phi_1 <= 315; phi_1 += 45) { - // auto radius_1 = 200_m; - // auto phi_1 = 45; - auto phiRad_1 = phi_1 / 180. * M_PI; - auto rr_1 = static_cast<int>(radius_1 / 1_m); - auto const point_1{Point(rootCS, showerCoreX_ + radius_1 * cos(phiRad_1), - showerCoreY_ + radius_1 * sin(phiRad_1), - constants::EarthRadius::Mean)}; - std::cout << "Antenna point: " << point_1 << std::endl; - auto triggertime_1{(triggerpoint_ - point_1).getNorm() / constants::c}; - std::string name_1 = "CoREAS_R=" + std::to_string(rr_1) + - "_m--Phi=" + std::to_string(phi_1) + "degrees"; - TimeDomainAntenna antenna_1(name_1, point_1, rootCS, triggertime_1, duration_, sampleRate_, - triggertime_1); - detectorCoREAS.addAntenna(antenna_1); - } - } - - // primary particle times -> t ground - // setup ZHS antennas - for (auto radius_ = 25_m; radius_ <= 500_m; radius_ += 25_m) { - for (auto phi_ = 0; phi_ <= 315; phi_ += 45) { - // auto radius_ = 200_m; - // auto phi_ = 45; - auto phiRad_ = phi_ / 180. * M_PI; - auto rr_ = static_cast<int>(radius_ / 1_m); - auto const point_{Point(rootCS, showerCoreX_ + radius_ * cos(phiRad_), - showerCoreY_ + radius_ * sin(phiRad_), + logging::set_level(logging::level::info); + + if (argc != 3) { + std::cerr + << "usage: radio_em_shower <energy/GeV> <seed> - put seed=0 to use random seed" + << std::endl; + return 1; + } + + int seed{static_cast<int>(std::stof(std::string(argv[2])))}; + std::cout << "Seed: " << seed << std::endl; + feenableexcept(FE_INVALID); + // initialize random number sequence(s) + registerRandomStreams(seed); + + // setup environment, geometry + using EnvironmentInterface = + IRefractiveIndexModel<IMediumPropertyModel<IMagneticFieldModel<IMediumModel>>>; + using EnvType = Environment<EnvironmentInterface>; + EnvType env; + CoordinateSystemPtr const& rootCS = env.getCoordinateSystem(); + Point const center{rootCS, 0_m, 0_m, 0_m}; + + create_5layer_atmosphere<EnvironmentInterface, MyExtraEnv>( + env, AtmosphereId::LinsleyUSStd, center, 1.000327, Medium::AirDry1Atm, + MagneticFieldVector{rootCS, 50_uT, 0_T, 0_T}); + + std::unordered_map<Code, HEPEnergyType> energy_resolution = { + {Code::Electron, 5_MeV}, + {Code::Positron, 5_MeV}, + {Code::Photon, 5_MeV}, + }; + for (auto [pcode, energy] : energy_resolution) + set_energy_production_threshold(pcode, energy); + + // setup particle stack, and add primary particle + setup::Stack<EnvType> stack; + stack.clear(); + const Code beamCode = Code::Electron; + auto const mass = get_mass(beamCode); + const HEPEnergyType E0 = 1_GeV * std::stof(std::string(argv[1])); + double theta = 0.; + auto const thetaRad = theta / 180. * M_PI; + + HEPMomentumType P0 = calculate_momentum(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 = 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.getNorm() << endl; + + auto const observationHeight = 1.4_km + constants::EarthRadius::Mean; + auto const injectionHeight = 112.75_km + constants::EarthRadius::Mean; + auto const t = -observationHeight * cos(thetaRad) + + sqrt(-static_pow<2>(sin(thetaRad) * observationHeight) + + static_pow<2>(injectionHeight)); + Point const showerCore{rootCS, 0_m, 0_m, observationHeight}; + Point const injectionPos = + showerCore + DirectionVector{rootCS, {-sin(thetaRad), 0, cos(thetaRad)}} * t; + + std::cout << "point of injection: " << injectionPos.getCoordinates() << std::endl; + + stack.addParticle(std::make_tuple( + beamCode, calculate_kinetic_energy(plab.getNorm(), get_mass(beamCode)), + plab.normalized(), injectionPos, 0_ns)); + + CORSIKA_LOG_INFO("shower axis length: {} ", + (showerCore - injectionPos).getNorm() * 1.02); + + ShowerAxis const showerAxis{injectionPos, (showerCore - injectionPos) * 1.02, env, + false, 1000}; + + TimeType const groundHitTime{(showerCore - injectionPos).getNorm() / constants::c}; + + // int ring_number {std::stof(std::string(argv[2]))}; + // std::cout << "Ring number : " << ring_number << std::endl; + // auto const radius_ {ring_number * 25_m}; + // std::cout << "Radius = " << radius_ << std::endl; + // const int rr_ = static_cast<int>(radius_ / 1_m); + std::string outname_ = "radio_em_shower_outputs"; // + std::to_string(rr_); + OutputManager output(outname_); + + // Radio objects + // the antenna time variables + const TimeType duration_{1e-6_s}; + const InverseTimeType sampleRate_{1e+9_Hz}; + + // the detector (aka antenna collection) for CoREAS and ZHS + AntennaCollection<TimeDomainAntenna> detectorCoREAS; + AntennaCollection<TimeDomainAntenna> detectorZHS; + + auto const showerCoreX_{showerCore.getCoordinates().getX()}; + auto const showerCoreY_{showerCore.getCoordinates().getY()}; + auto const injectionPosX_{injectionPos.getCoordinates().getX()}; + auto const injectionPosY_{injectionPos.getCoordinates().getY()}; + auto const injectionPosZ_{injectionPos.getCoordinates().getZ()}; + auto const triggerpoint_{Point(rootCS, injectionPosX_, injectionPosY_, injectionPosZ_)}; + std::cout << "Trigger Point is: " << triggerpoint_ << std::endl; + + // // setup CoREAS antennas + for (auto radius_1 = 25_m; radius_1 <= 500_m; radius_1 += 25_m) { + for (auto phi_1 = 0; phi_1 <= 315; phi_1 += 45) { + // auto radius_1 = 200_m; + // auto phi_1 = 45; + auto phiRad_1 = phi_1 / 180. * M_PI; + auto rr_1 = static_cast<int>(radius_1 / 1_m); + auto const point_1{Point(rootCS, showerCoreX_ + radius_1 * cos(phiRad_1), + showerCoreY_ + radius_1 * sin(phiRad_1), constants::EarthRadius::Mean)}; - auto triggertime_{(triggerpoint_ - point_).getNorm() / constants::c}; - std::string name_ = - "ZHS_R=" + std::to_string(rr_) + "_m--Phi=" + std::to_string(phi_) + "degrees"; - TimeDomainAntenna antenna_(name_, point_, rootCS, triggertime_, duration_, sampleRate_, - triggertime_); - detectorZHS.addAntenna(antenna_); - } - } - - // ----------------------- Radio objects - // -------------------------------------------------------------------- - - // setup processes, decays and interactions - - EnergyLossWriter dEdX{showerAxis, 10_g / square(1_cm), 200}; - // register energy losses as output - output.add("dEdX", dEdX); - - ParticleCut<SubWriter<decltype(dEdX)>> cut(5_MeV, 5_MeV, 100_GeV, 100_GeV, true, dEdX); - corsika::proposal::Interaction emCascade(env); - corsika::proposal::ContinuousProcess<SubWriter<decltype(dEdX)>> emContinuous(env, dEdX); - // BetheBlochPDG<SubWriter<decltype(dEdX)>> emContinuous{dEdX}; - - // NOT possible right now, due to interface differenc in PROPOSAL - // InteractionCounter emCascadeCounted(emCascade); - - TrackWriter tracks; - output.add("tracks", tracks); - - // long. profile - LongitudinalWriter profile{showerAxis, 10_g / square(1_cm), 200}; - output.add("profile", profile); - LongitudinalProfile<SubWriter<decltype(profile)>> longprof{profile}; - - // initiate CoREAS - RadioProcess<decltype(detectorCoREAS), - CoREAS<decltype(detectorCoREAS), decltype(SimplePropagator(env))>, - decltype(SimplePropagator(env))> - coreas(detectorCoREAS, env); - - // register CoREAS with the output manager - output.add("CoREAS", coreas); - - // initiate ZHS - RadioProcess<decltype(detectorZHS), - ZHS<decltype(detectorZHS), decltype(SimplePropagator(env))>, - decltype(SimplePropagator(env))> - zhs(detectorZHS, env); - - // // register ZHS with the output manager - output.add("ZHS", zhs); - - Plane const obsPlane(showerCore, DirectionVector(rootCS, {0., 0., 1.})); - ObservationPlane<setup::Tracking, ParticleWriterParquet> observationLevel{ - obsPlane, DirectionVector(rootCS, {1., 0., 0.})}; - output.add("particles", observationLevel); - - // auto sequence = make_sequence(emCascade, emContinuous, longprof, cut, coreas, zhs); - auto sequence = make_sequence(emCascade, emContinuous, longprof, cut, coreas, zhs, - observationLevel, tracks); - // define air shower object, run simulation - setup::Tracking tracking; - - output.startOfLibrary(); - Cascade EAS(env, tracking, sequence, output, stack); - - // to fix the point of first interaction, uncomment the following two lines: - // EAS.forceInteraction(); - - EAS.run(); - - HEPEnergyType const Efinal = dEdX.getEnergyLost() + observationLevel.getEnergyGround(); - - CORSIKA_LOG_INFO( - "total energy budget (GeV): {}, " - "relative difference (%): {}", - Efinal / 1_GeV, (Efinal / E0 - 1) * 100); - - output.endOfLibrary(); + std::cout << "Antenna point: " << point_1 << std::endl; + auto triggertime_1{(triggerpoint_ - point_1).getNorm() / constants::c}; + std::string name_1 = "CoREAS_R=" + std::to_string(rr_1) + + "_m--Phi=" + std::to_string(phi_1) + "degrees"; + TimeDomainAntenna antenna_1(name_1, point_1, rootCS, triggertime_1, duration_, sampleRate_, + triggertime_1); + detectorCoREAS.addAntenna(antenna_1); + } + } + + // primary particle times -> t ground + // setup ZHS antennas + for (auto radius_ = 25_m; radius_ <= 500_m; radius_ += 25_m) { + for (auto phi_ = 0; phi_ <= 315; phi_ += 45) { + // auto radius_ = 200_m; + // auto phi_ = 45; + auto phiRad_ = phi_ / 180. * M_PI; + auto rr_ = static_cast<int>(radius_ / 1_m); + auto const point_{Point(rootCS, showerCoreX_ + radius_ * cos(phiRad_), + showerCoreY_ + radius_ * sin(phiRad_), + constants::EarthRadius::Mean)}; + auto triggertime_{(triggerpoint_ - point_).getNorm() / constants::c}; + std::string name_ = + "ZHS_R=" + std::to_string(rr_) + "_m--Phi=" + std::to_string(phi_) + "degrees"; + TimeDomainAntenna antenna_(name_, point_, rootCS, triggertime_, duration_, sampleRate_, + triggertime_); + detectorZHS.addAntenna(antenna_); + } + } + + // ----------------------- Radio objects + // -------------------------------------------------------------------- + + // setup processes, decays and interactions + + EnergyLossWriter dEdX{showerAxis, 10_g / square(1_cm), 200}; + // register energy losses as output + output.add("dEdX", dEdX); + + ParticleCut<SubWriter<decltype(dEdX)>> cut(5_MeV, 5_MeV, 100_GeV, 100_GeV, true, dEdX); + + corsika::sibyll::Interaction sibyll{env}; + HEPEnergyType heThresholdNN = 80_GeV; + corsika::proposal::Interaction emCascade(env, sibyll.getHadronInteractionModel(), + heThresholdNN); + corsika::proposal::ContinuousProcess<SubWriter<decltype(dEdX)>> emContinuous(env, dEdX); + // BetheBlochPDG<SubWriter<decltype(dEdX)>> emContinuous{dEdX}; + + // NOT possible right now, due to interface differenc in PROPOSAL + // InteractionCounter emCascadeCounted(emCascade); + + TrackWriter tracks; + output.add("tracks", tracks); + + // long. profile + LongitudinalWriter profile{showerAxis, 10_g / square(1_cm), 200}; + output.add("profile", profile); + LongitudinalProfile<SubWriter<decltype(profile)>> longprof{profile}; + + // initiate CoREAS + RadioProcess<decltype(detectorCoREAS), + CoREAS<decltype(detectorCoREAS), decltype(SimplePropagator(env))>, + decltype(SimplePropagator(env))> + coreas(detectorCoREAS, env); + + // register CoREAS with the output manager + output.add("CoREAS", coreas); + + // initiate ZHS + RadioProcess<decltype(detectorZHS), + ZHS<decltype(detectorZHS), decltype(SimplePropagator(env))>, + decltype(SimplePropagator(env))> + zhs(detectorZHS, env); + + // // register ZHS with the output manager + output.add("ZHS", zhs); + + Plane const obsPlane(showerCore, DirectionVector(rootCS, {0., 0., 1.})); + ObservationPlane<setup::Tracking, ParticleWriterParquet> observationLevel{ + obsPlane, DirectionVector(rootCS, {1., 0., 0.})}; + output.add("particles", observationLevel); + + // auto sequence = make_sequence(emCascade, emContinuous, longprof, cut, coreas, zhs); + auto sequence = make_sequence(emCascade, emContinuous, longprof, cut, coreas, zhs, + observationLevel, tracks); + // define air shower object, run simulation + setup::Tracking tracking; + + output.startOfLibrary(); + Cascade EAS(env, tracking, sequence, output, stack); + + // to fix the point of first interaction, uncomment the following two lines: + // EAS.forceInteraction(); + + EAS.run(); + + HEPEnergyType const Efinal = dEdX.getEnergyLost() + observationLevel.getEnergyGround(); + + CORSIKA_LOG_INFO( + "total energy budget (GeV): {}, " + "relative difference (%): {}", + Efinal / 1_GeV, (Efinal / E0 - 1) * 100); + + output.endOfLibrary(); } \ No newline at end of file -- GitLab