IAP GITLAB

Skip to content
Snippets Groups Projects
cascade_example.cc 8.23 KiB
Newer Older

/**
 * (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu
 *
 * See file AUTHORS for a list of contributors.
 *
 * 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/cascade/Cascade.h>
#include <corsika/process/ProcessSequence.h>
#include <corsika/process/stack_inspector/StackInspector.h>
ralfulrich's avatar
ralfulrich committed
#include <corsika/process/tracking_line/TrackingLine.h>

#include <corsika/setup/SetupStack.h>
#include <corsika/setup/SetupTrajectory.h>

#include <corsika/random/RNGManager.h>
Felix Riehn's avatar
Felix Riehn committed
#include <corsika/cascade/SibStack.h>
ralfulrich's avatar
ralfulrich committed
#include <corsika/cascade/sibyll2.3c.h>
Felix Riehn's avatar
Felix Riehn committed
#include <corsika/process/sibyll/ParticleConversion.h>
#include <corsika/units/PhysicalUnits.h>
using namespace corsika;
using namespace corsika::process;
using namespace corsika::units;
using namespace corsika::particles;
using namespace corsika::random;

#include <iostream>
ralfulrich's avatar
ralfulrich committed
#include <typeinfo>
using namespace std;

static int fCount = 0;

class ProcessSplit : public corsika::process::BaseProcess<ProcessSplit> {
public:
  ProcessSplit() {}

  template <typename Particle>
ralfulrich's avatar
ralfulrich committed
  double MinStepLength(Particle& p, setup::Trajectory&) const {
    // beam particles for sibyll : 1, 2, 3 for p, pi, k
ralfulrich's avatar
ralfulrich committed
    int kBeam = 1;

    /*
       the target should be defined by the Environment,
ralfulrich's avatar
ralfulrich committed
       ideally as full particle object so that the four momenta
       and the boosts can be defined..
     */
    // target nuclei: A < 18
    // FOR NOW: assume target is oxygen
ralfulrich's avatar
ralfulrich committed
    double beamEnergy = p.GetEnergy() / 1_GeV;
    std::cout << "ProcessSplit: "
              << "MinStep: en: " << beamEnergy << " pid:" << kBeam << std::endl;
    double prodCrossSection, dummy, dum1, dum2, dum3, dum4;
ralfulrich's avatar
ralfulrich committed
    if (kTarget == 1)
      sib_sigma_hp_(kBeam, beamEnergy, dum1, dum2, prodCrossSection, dumdif, dum3, dum4);
ralfulrich's avatar
ralfulrich committed
      sib_sigma_hnuc_(kBeam, kTarget, beamEnergy, prodCrossSection, dummy);

    std::cout << "ProcessSplit: "
              << "MinStep: sibyll return: " << prodCrossSection << std::endl;
    CrossSectionType sig = prodCrossSection * 1_mbarn;
ralfulrich's avatar
ralfulrich committed
    std::cout << "ProcessSplit: "
              << "MinStep: CrossSection (mb): " << sig / 1_mbarn << std::endl;
    const MassType nucleon_mass = 0.93827_GeV / corsika::units::si::constants::cSquared;
ralfulrich's avatar
ralfulrich committed
    std::cout << "ProcessSplit: "
              << "nucleon mass " << nucleon_mass << std::endl;
    // calculate interaction length in medium
ralfulrich's avatar
ralfulrich committed
    double int_length = kTarget * (nucleon_mass / 1_g) / (sig / 1_cmeter / 1_cmeter);
    // pick random step lenth
ralfulrich's avatar
ralfulrich committed
    std::cout << "ProcessSplit: "
              << "interaction length (g/cm2): " << int_length << std::endl;
    // add exponential sampling
    int a = 0;
    const double next_step = -int_length * log(s_rndm_(a));
    /*
      what are the units of the output? slant depth or 3space length?
ralfulrich's avatar
ralfulrich committed

ralfulrich's avatar
ralfulrich committed
    std::cout << "ProcessSplit: "
              << "next step (g/cm2): " << next_step << std::endl;
ralfulrich's avatar
ralfulrich committed
  template <typename Particle, typename Stack>
  EProcessReturn DoContinuous(Particle&, Trajectory&, Stack&) const {
    // corsika::utls::ignore(p);
    return EProcessReturn::eOk;
  }

  template <typename Particle, typename Stack>
  void DoDiscrete(Particle& p, Stack& s) const {
ralfulrich's avatar
ralfulrich committed
    cout << "DoDiscrete: " << p.GetPID() << " interaction? "
         << process::sibyll::CanInteract(p.GetPID()) << endl;
    if (process::sibyll::CanInteract(p.GetPID())) {
ralfulrich's avatar
ralfulrich committed
      // get energy of particle from stack
Felix Riehn's avatar
Felix Riehn committed
      /*
ralfulrich's avatar
ralfulrich committed
        stack is in GeV in lab. frame
        convert to GeV in cm. frame
        (assuming proton at rest as target AND
        assuming no pT, i.e. shower frame-z is aligned with hadron-int-frame-z)
Felix Riehn's avatar
Felix Riehn committed
      */
ralfulrich's avatar
ralfulrich committed
      EnergyType E = p.GetEnergy();
      EnergyType Ecm = sqrt(2. * E * 0.93827_GeV);

      int kBeam = process::sibyll::ConvertToSibyllRaw(p.GetPID());

      /*
         the target should be defined by the Environment,
         ideally as full particle object so that the four momenta
         and the boosts can be defined..
       */
      // FOR NOW: set target to proton
      int kTarget = 1; // p.GetPID();

      std::cout << "ProcessSplit: "
                << " DoDiscrete: E(GeV):" << E / 1_GeV << " Ecm(GeV): " << Ecm / 1_GeV
                << std::endl;
      if (E < 8.5_GeV || Ecm < 10_GeV) {
        std::cout << "ProcessSplit: "
                  << " DoDiscrete: dropping particle.." << std::endl;
        p.Delete();
        fCount++;
      } else {
        // Sibyll does not know about units..
        double sqs = Ecm / 1_GeV;
        // running sibyll, filling stack
        sibyll_(kBeam, kTarget, sqs);
        // running decays
        // decsib_();
        // print final state
        int print_unit = 6;
        sib_list_(print_unit);

        // delete current particle
        p.Delete();

        // add particles from sibyll to stack
        // link to sibyll stack
        SibStack ss;
        /*
          get transformation between Stack-frame and SibStack-frame
          for EAS Stack-frame is lab. frame, could be different for CRMC-mode
          the transformation should be derived from the input momenta
          in general transformation is rotation + boost
        */
        const EnergyType proton_mass = 0.93827_GeV;
        const double gamma = (E + proton_mass) / (Ecm);
        const double gambet = sqrt(E * E - proton_mass * proton_mass) / Ecm;

        // SibStack does not know about momentum yet so we need counter to access momentum
        // array in Sibyll
        int i = -1;
        for (auto& p : ss) {
          ++i;
          // transform to lab. frame, primitve
          const double en_lab = gambet * s_plist_.p[2][i] + gamma * p.GetEnergy();
          // add to corsika stack
          auto pnew = s.NewParticle();
          pnew.SetEnergy(en_lab * 1_GeV);
          pnew.SetPID(process::sibyll::ConvertFromSibyll(p.GetPID()));
        }
ralfulrich's avatar
ralfulrich committed
    } else
ralfulrich's avatar
ralfulrich committed

  void Init() {
    // define reference frame? --> defines boosts between corsika stack and model stack.
ralfulrich's avatar
ralfulrich committed

    // initialize random numbers for sibyll
    // FOR NOW USE SIBYLL INTERNAL !!!
    //    rnd_ini_();
ralfulrich's avatar
ralfulrich committed

    corsika::random::RNGManager& rmng = corsika::random::RNGManager::GetInstance();
    ;
    const std::string str_name = "s_rndm";
    rmng.RegisterRandomStream(str_name);
ralfulrich's avatar
ralfulrich committed

    // //    corsika::random::RNG srng;
    // auto srng = rmng.GetRandomStream("s_rndm");

    // test random number generator
ralfulrich's avatar
ralfulrich committed
    std::cout << "ProcessSplit: "
              << " test sequence of random numbers." << std::endl;
ralfulrich's avatar
ralfulrich committed
    for (int i = 0; i < 8; ++i) std::cout << i << " " << s_rndm_(a) << std::endl;

    // initialize Sibyll

    // set particles stable / unstable
ralfulrich's avatar
ralfulrich committed
    ds.NewParticle().SetPID(Code::Proton);
    ds.NewParticle().SetPID(Code::Neutron);
    ds.NewParticle().SetPID(Code::PiPlus);
    ds.NewParticle().SetPID(Code::PiMinus);
    ds.NewParticle().SetPID(Code::KPlus);
    ds.NewParticle().SetPID(Code::KMinus);
    ds.NewParticle().SetPID(Code::K0Long);
    ds.NewParticle().SetPID(Code::K0Short);

    for (auto& p : ds) {
      int s_id = process::sibyll::ConvertToSibyllRaw(p.GetPID());
      // set particle stable by setting table value negative
ralfulrich's avatar
ralfulrich committed
      cout << "ProcessSplit: Init: setting " << p.GetPID() << "(" << s_id << ")"
           << " stable in Sibyll .." << endl;
      s_csydec_.idb[s_id] = -s_csydec_.idb[s_id - 1];
ralfulrich's avatar
ralfulrich committed

  int GetCount() { return fCount; }

private:
};

ralfulrich's avatar
ralfulrich committed
double s_rndm_(int&) {
  static corsika::random::RNG& rmng =
      corsika::random::RNGManager::GetInstance().GetRandomStream("s_rndm");
  ;
  return rmng() / (double)rmng.max();
ralfulrich's avatar
ralfulrich committed
int main() {
ralfulrich's avatar
ralfulrich committed
  tracking_line::TrackingLine<setup::Stack> tracking;
  stack_inspector::StackInspector<setup::Stack> p0(true);
  ProcessSplit p1;
  const auto sequence = p0 + p1;
  setup::Stack stack;

ralfulrich's avatar
ralfulrich committed
  corsika::cascade::Cascade EAS(tracking, sequence, stack);

  stack.Clear();
  auto particle = stack.NewParticle();
  EnergyType E0 = 100_GeV;
  particle.SetEnergy(E0);
ralfulrich's avatar
ralfulrich committed
  particle.SetPID(Code::Proton);
  EAS.Init();
  EAS.Run();
  cout << "Result: E0=" << E0 / 1_GeV << "GeV, count=" << p1.GetCount() << endl;
}