IAP GITLAB

Skip to content
Snippets Groups Projects
em_shower.cpp 7.49 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/core/Cascade.hpp>
#include <corsika/framework/utility/SaveBoostHistogram.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/process/ProcessSequence.hpp>
#include <corsika/framework/random/RNGManager.hpp>
#include <corsika/framework/core/PhysicalUnits.hpp>
#include <corsika/framework/utility/CorsikaFenv.hpp>
#include <corsika/framework/process/InteractionCounter.hpp>
ralfulrich's avatar
ralfulrich committed
#include <corsika/framework/core/Logging.hpp>
ralfulrich's avatar
ralfulrich committed
#include <corsika/output/OutputManager.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>

#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
  auto builder = make_layered_spherical_atmosphere_builder<
      setup::EnvironmentInterface, MyExtraEnv>::create(center,
                                                       constants::EarthRadius::Mean,
                                                       Medium::AirDry1Atm,
                                                       Vector{rootCS, 0_T, 50_uT, 0_T});
ralfulrich's avatar
ralfulrich committed
  builder.setNuclearComposition(
ralfulrich's avatar
ralfulrich committed
      {{Code::Nitrogen, Code::Oxygen},
ralfulrich's avatar
ralfulrich committed
       {0.7847f, 1.f - 0.7847f}}); // values taken from AIRES manual, Ar removed for now

  builder.addExponentialLayer(1222.6562_g / (1_cm * 1_cm), 994186.38_cm, 4_km);
  builder.addExponentialLayer(1144.9069_g / (1_cm * 1_cm), 878153.55_cm, 10_km);
  builder.addExponentialLayer(1305.5948_g / (1_cm * 1_cm), 636143.04_cm, 40_km);
  builder.addExponentialLayer(540.1778_g / (1_cm * 1_cm), 772170.16_cm, 100_km);
  builder.addLinearLayer(1e9_cm, 112.8_km);
  builder.assemble(env);

  // 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;

  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);
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

  auto const observationHeight = 1.4_km + builder.getEarthRadius();
  auto const injectionHeight = 112.75_km + builder.getEarthRadius();
  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, plab, injectionPos, 0_ns));
ralfulrich's avatar
ralfulrich committed

ralfulrich's avatar
ralfulrich committed
  std::cout << "shower axis length: " << (showerCore - injectionPos).getNorm() * 1.02
ralfulrich's avatar
ralfulrich committed
            << std::endl;

ralfulrich's avatar
ralfulrich committed
  OutputManager output("em_shower_outputs");
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

  // setup processes, decays and interactions

ralfulrich's avatar
ralfulrich committed
  ParticleCut cut(60_GeV, 60_GeV, 100_PeV, 100_PeV, true);
ralfulrich's avatar
ralfulrich committed
  corsika::proposal::Interaction emCascade(env);
  corsika::proposal::ContinuousProcess emContinuous(env);
  InteractionCounter emCascadeCounted(emCascade);
ralfulrich's avatar
ralfulrich committed

  TrackWriter trackWriter;
ralfulrich's avatar
ralfulrich committed
  output.add("tracks", trackWriter); // register TrackWriter
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 longprof{showerAxis};
ralfulrich's avatar
ralfulrich committed

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

ralfulrich's avatar
ralfulrich committed
  auto sequence = make_sequence(emCascadeCounted, emContinuous, longprof, cut,
ralfulrich's avatar
ralfulrich committed
                                observationLevel, trackWriter);
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
  cut.showResults();
ralfulrich's avatar
ralfulrich committed
  emContinuous.showResults();
ralfulrich's avatar
ralfulrich committed
  observationLevel.showResults();
  const HEPEnergyType Efinal = cut.getCutEnergy() + cut.getInvEnergy() +
ralfulrich's avatar
ralfulrich committed
                               cut.getEmEnergy() + emContinuous.getEnergyLost() +
ralfulrich's avatar
ralfulrich committed
                               observationLevel.getEnergyGround();
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
  observationLevel.reset();
  cut.reset();
ralfulrich's avatar
ralfulrich committed
  emContinuous.reset();
ralfulrich's avatar
ralfulrich committed

ralfulrich's avatar
ralfulrich committed
  auto const hists = emCascadeCounted.getHistogram();
  save_hist(hists.labHist(), "inthist_lab_emShower.npz", true);
  save_hist(hists.CMSHist(), "inthist_cms_emShower.npz", true);
ralfulrich's avatar
ralfulrich committed
  longprof.save("longprof_emShower.txt");
ralfulrich's avatar
ralfulrich committed

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