IAP GITLAB

Skip to content
Snippets Groups Projects
em_shower.cpp 7.05 KiB
Newer Older
ralfulrich's avatar
ralfulrich committed
/*
 * (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.
 */

ralfulrich's avatar
ralfulrich committed
#include <corsika/framework/process/ProcessSequence.hpp>
#include <corsika/framework/process/SwitchProcessSequence.hpp>
#include <corsika/framework/process/InteractionCounter.hpp>
ralfulrich's avatar
ralfulrich committed
#include <corsika/framework/core/Cascade.hpp>
ralfulrich's avatar
ralfulrich committed
#include <corsika/framework/core/PhysicalUnits.hpp>
#include <corsika/framework/core/Logging.hpp>
#include <corsika/framework/core/EnergyMomentumOperations.hpp>
#include <corsika/framework/random/RNGManager.hpp>
#include <corsika/framework/geometry/Sphere.hpp>
ralfulrich's avatar
ralfulrich committed
#include <corsika/framework/geometry/Plane.hpp>
#include <corsika/framework/geometry/Sphere.hpp>
#include <corsika/framework/geometry/PhysicalGeometry.hpp>
#include <corsika/framework/utility/CorsikaFenv.hpp>
ralfulrich's avatar
ralfulrich committed
#include <corsika/framework/utility/SaveBoostHistogram.hpp>
ralfulrich's avatar
ralfulrich committed
#include <corsika/output/OutputManager.hpp>
ralfulrich's avatar
ralfulrich committed
#include <corsika/modules/writers/SubWriter.hpp>
#include <corsika/modules/writers/EnergyLossWriter.hpp>
#include <corsika/modules/writers/EnergyLossWriterParquet.hpp>
ralfulrich's avatar
ralfulrich committed

#include <corsika/media/Environment.hpp>
#include <corsika/media/LayeredSphericalAtmosphereBuilder.hpp>
#include <corsika/media/NuclearComposition.hpp>
#include <corsika/media/ShowerAxis.hpp>
#include <corsika/media/MediumPropertyModel.hpp>
#include <corsika/media/UniformMagneticField.hpp>
ralfulrich's avatar
ralfulrich committed
#include <corsika/media/CORSIKA7Atmospheres.hpp>
ralfulrich's avatar
ralfulrich committed

#include <corsika/modules/LongitudinalProfile.hpp>
#include <corsika/modules/ObservationPlane.hpp>
#include <corsika/modules/ParticleCut.hpp>
#include <corsika/modules/TrackWriter.hpp>
#include <corsika/modules/PROPOSAL.hpp>

#include <corsika/setup/SetupStack.hpp>
#include <corsika/setup/SetupTrajectory.hpp>
ralfulrich's avatar
ralfulrich committed

#include <iomanip>
#include <iostream>
#include <limits>
#include <string>
#include <typeinfo>

ralfulrich's avatar
ralfulrich committed
/*
  NOTE, WARNING, ATTENTION
ralfulrich's avatar
ralfulrich committed

ralfulrich's avatar
ralfulrich committed
  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>

using namespace corsika;
ralfulrich's avatar
ralfulrich committed
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);
ralfulrich's avatar
ralfulrich committed
}

template <typename T>
ralfulrich's avatar
ralfulrich committed
using MyExtraEnv = MediumPropertyModel<UniformMagneticField<T>>;
ralfulrich's avatar
ralfulrich committed

int main(int argc, char** argv) {

ralfulrich's avatar
ralfulrich committed
  logging::set_level(logging::level::info);
ralfulrich's avatar
ralfulrich committed

  if (argc != 2) {
    std::cerr << "usage: em_shower <energy/GeV>" << std::endl;
    return 1;
  }
  feenableexcept(FE_INVALID);
  // initialize random number sequence(s)
  int seed = 44;
  registerRandomStreams(seed);
ralfulrich's avatar
ralfulrich committed

  // setup environment, geometry
  using EnvType = setup::Environment;
  EnvType env;
ralfulrich's avatar
ralfulrich committed
  CoordinateSystemPtr const& rootCS = env.getCoordinateSystem();
ralfulrich's avatar
ralfulrich committed
  Point const center{rootCS, 0_m, 0_m, 0_m};
ralfulrich's avatar
ralfulrich committed

  // build a Linsley US Standard atmosphere into `env`
  create_5layer_atmosphere<setup::EnvironmentInterface, MyExtraEnv>(
      env, AtmosphereId::LinsleyUSStd, center, Medium::AirDry1Atm,
      MagneticFieldVector{rootCS, 0_T, 50_uT, 0_T});
ralfulrich's avatar
ralfulrich committed

  // setup particle stack, and add primary particle
  setup::Stack stack;
ralfulrich's avatar
ralfulrich committed
  stack.clear();
ralfulrich's avatar
ralfulrich committed
  const Code beamCode = Code::Electron;
ralfulrich's avatar
ralfulrich committed
  auto const mass = get_mass(beamCode);
ralfulrich's avatar
ralfulrich committed
  const HEPEnergyType E0 = 1_GeV * std::stof(std::string(argv[1]));
  double theta = 0.;
  auto const thetaRad = theta / 180. * M_PI;

ralfulrich's avatar
ralfulrich committed
  HEPMomentumType P0 = calculate_momentum(E0, mass);
ralfulrich's avatar
ralfulrich committed
  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);
ralfulrich's avatar
ralfulrich committed
  auto plab = MomentumVector(rootCS, {px, py, pz});
ralfulrich's avatar
ralfulrich committed
  cout << "input particle: " << beamCode << endl;
  cout << "input angles: theta=" << theta << endl;
ralfulrich's avatar
ralfulrich committed
  cout << "input momentum: " << plab.getComponents() / 1_GeV
       << ", norm = " << plab.getNorm() << endl;
ralfulrich's avatar
ralfulrich committed

ralfulrich's avatar
ralfulrich committed
  auto const observationHeight = 1.4_km + constants::EarthRadius::Mean;
  auto const injectionHeight = 112.75_km + constants::EarthRadius::Mean;
ralfulrich's avatar
ralfulrich committed
  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 =
ralfulrich's avatar
ralfulrich committed
      showerCore + DirectionVector{rootCS, {-sin(thetaRad), 0, cos(thetaRad)}} * t;
ralfulrich's avatar
ralfulrich committed

ralfulrich's avatar
ralfulrich committed
  std::cout << "point of injection: " << injectionPos.getCoordinates() << std::endl;
ralfulrich's avatar
ralfulrich committed

ralfulrich's avatar
ralfulrich committed
  stack.addParticle(std::make_tuple(
      beamCode, calculate_kinetic_energy(plab.getNorm(), get_mass(beamCode)),
      plab.normalized(), injectionPos, 0_ns));
ralfulrich's avatar
ralfulrich committed

ralfulrich's avatar
ralfulrich committed
  CORSIKA_LOG_INFO("shower axis length: {} ",
                   (showerCore - injectionPos).getNorm() * 1.02);
ralfulrich's avatar
ralfulrich committed

ralfulrich's avatar
ralfulrich committed
  ShowerAxis const showerAxis{injectionPos, (showerCore - injectionPos) * 1.02, env,
ralfulrich's avatar
ralfulrich committed
                              false, 1000};
ralfulrich's avatar
ralfulrich committed

ralfulrich's avatar
ralfulrich committed
  OutputManager output("em_shower_outputs");

ralfulrich's avatar
ralfulrich committed
  EnergyLossWriter dEdX{showerAxis, 10_g / square(1_cm), 200};
ralfulrich's avatar
ralfulrich committed
  // register energy losses as output
ralfulrich's avatar
ralfulrich committed
  output.add("dEdX", dEdX);
ralfulrich's avatar
ralfulrich committed
  // setup processes, decays and interactions

ralfulrich's avatar
ralfulrich committed
  ParticleCut<SubWriter<decltype(dEdX)>> cut(60_GeV, 60_GeV, 100_PeV, 100_PeV, true,
ralfulrich's avatar
ralfulrich committed
                                             dEdX);
ralfulrich's avatar
ralfulrich committed
  corsika::proposal::Interaction emCascade(env);
  corsika::proposal::ContinuousProcess emContinuous(env);
ralfulrich's avatar
ralfulrich committed
  //  BetheBlochPDG<SubWriter<decltype(dEdX)>> emContinuous{dEdX};
ralfulrich's avatar
ralfulrich committed

  //  NOT possible right now, due to interface differenc in PROPOSAL
  //  InteractionCounter emCascadeCounted(emCascade);
ralfulrich's avatar
ralfulrich committed

ralfulrich's avatar
ralfulrich committed
  TrackWriter tracks;
ralfulrich's avatar
ralfulrich committed
  output.add("tracks", tracks);
ralfulrich's avatar
ralfulrich committed

Fan Hu's avatar
Fan Hu committed
  // long. profile; columns for photon, e+, e- still need to be added
ralfulrich's avatar
ralfulrich committed
  LongitudinalProfile<corsika::LongitudinalProfileWriterParquet> longprof{
      showerAxis, 10_g / square(1_cm), 200};
  output.add("profile", longprof);
ralfulrich's avatar
ralfulrich committed

ralfulrich's avatar
ralfulrich committed
  Plane const obsPlane(showerCore, DirectionVector(rootCS, {0., 0., 1.}));
ralfulrich's avatar
ralfulrich committed
  ObservationPlane<setup::Tracking, ParticleWriterParquet> observationLevel{
      obsPlane, DirectionVector(rootCS, {1., 0., 0.})};
  output.add("particles", observationLevel);
ralfulrich's avatar
ralfulrich committed

ralfulrich's avatar
ralfulrich committed
  auto sequence =
      make_sequence(emCascade, emContinuous, longprof, cut, observationLevel, tracks);
ralfulrich's avatar
ralfulrich committed
  // define air shower object, run simulation
  setup::Tracking tracking;
  Cascade EAS(env, tracking, sequence, output, stack);
ralfulrich's avatar
ralfulrich committed

  // to fix the point of first interaction, uncomment the following two lines:
ralfulrich's avatar
ralfulrich committed
  //  EAS.setNodes();
ralfulrich's avatar
ralfulrich committed
  //  EAS.forceInteraction();

  output.startOfShower();
ralfulrich's avatar
ralfulrich committed
  EAS.run();
  output.endOfShower();
ralfulrich's avatar
ralfulrich committed

ralfulrich's avatar
ralfulrich committed
  const HEPEnergyType Efinal = dEdX.getTotal();
ralfulrich's avatar
ralfulrich committed
  cout << "total cut energy (GeV): " << Efinal / 1_GeV << endl
       << "relative difference (%): " << (Efinal / E0 - 1) * 100 << endl;

ralfulrich's avatar
ralfulrich committed
  output.endOfLibrary();
ralfulrich's avatar
ralfulrich committed
}