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>
#include <corsika/process/tracking_line/TrackingLine.h>
#include <corsika/setup/SetupStack.h>
#include <corsika/setup/SetupTrajectory.h>
#include <corsika/environment/Environment.h>
#include <corsika/environment/HomogeneousMedium.h>
#include <corsika/environment/NuclearComposition.h>
#include <corsika/geometry/Sphere.h>
#include <corsika/process/sibyll/Decay.h>
#include <corsika/process/sibyll/Interaction.h>
#include <corsika/process/track_writer/TrackWriter.h>
#include <corsika/units/PhysicalUnits.h>
Felix Riehn
committed
#include <corsika/random/RNGManager.h>
#include <boost/type_index.hpp>
using boost::typeindex::type_id_with_cvr;
using namespace corsika;
using namespace corsika::process;
using namespace corsika::units;
using namespace corsika::particles;
using namespace corsika::random;
Felix Riehn
committed
using namespace corsika::setup;
using namespace corsika::geometry;
using namespace corsika::environment;
using namespace corsika::units::hep;
class ProcessCut : public corsika::process::ContinuousProcess<ProcessCut> {
EnergyType fECut;
mutable EnergyType fEnergy = 0_GeV;
mutable EnergyType fEmEnergy = 0_GeV;
mutable int fEmCount = 0;
mutable EnergyType fInvEnergy = 0_GeV;
mutable int fInvCount = 0;
ProcessCut(const EnergyType v)
: fECut(v) {}
const EnergyType Ecm = sqrt(2. * p.GetEnergy() * 0.93827_GeV);
if (p.GetEnergy() < fECut || Ecm < 10_GeV)
switch (pCode) {
case Code::Electron:
is_em = true;
break;
ralfulrich
committed
case Code::Positron:
Felix Riehn
committed
is_em = true;
break;
case Code::Gamma:
is_em = true;
break;
default:
break;
void defineEmParticles() const {
// create bool array identifying em particles
switch (pCode) {
case Code::NuE:
is_inv = true;
break;
case Code::NuEBar:
is_inv = true;
break;
case Code::NuMu:
is_inv = true;
break;
case Code::NuMuBar:
is_inv = true;
break;
case Code::MuPlus:
is_inv = true;
break;
case Code::MuMinus:
is_inv = true;
break;
default:
break;
}
return is_inv;
}
template <typename Particle>
LengthType MaxStepLength(Particle& p, setup::Trajectory&) const {
cout << "ProcessCut: MinStep: pid: " << p.GetPID() << endl;
cout << "ProcessCut: MinStep: energy (GeV): " << p.GetEnergy() / 1_GeV << endl;
if (isEmParticle(pid) || isInvisible(pid) || isBelowEnergyCut(p)) {
cout << "ProcessCut: MinStep: next cut: " << 0. << endl;
LengthType next_step = 1_m * std::numeric_limits<double>::infinity();
cout << "ProcessCut: MinStep: next cut: " << next_step << endl;
return next_step;
}
}
template <typename Particle, typename Stack>
ralfulrich
committed
EProcessReturn DoContinuous(Particle& p, setup::Trajectory&, Stack&) const {
const Code pid = p.GetPID();
EnergyType energy = p.GetEnergy();
cout << "ProcessCut: DoContinuous: " << pid << " E= " << energy
<< ", EcutTot=" << (fEmEnergy + fInvEnergy + fEnergy) / 1_GeV << " GeV" << endl;
ralfulrich
committed
if (isEmParticle(pid)) {
cout << "removing em. particle..." << endl;
fEmEnergy += energy;
ralfulrich
committed
fEmCount += 1;
// p.Delete();
ralfulrich
committed
} else if (isInvisible(pid)) {
cout << "removing inv. particle..." << endl;
fInvEnergy += energy;
ralfulrich
committed
fInvCount += 1;
// p.Delete();
ralfulrich
committed
} else if (isBelowEnergyCut(p)) {
cout << "removing low en. particle..." << endl;
fEnergy += energy;
// p.Delete();
ralfulrich
committed
}
void Init() {
fEmEnergy = 0. * 1_GeV;
fEmCount = 0;
fInvCount = 0;
fEnergy = 0. * 1_GeV;
// defineEmParticles();
cout << " ******************************" << endl
<< " energy in em. component (GeV): " << fEmEnergy / 1_GeV << endl
<< " no. of em. particles injected: " << fEmCount << endl
<< " energy in inv. component (GeV): " << fInvEnergy / 1_GeV << endl
<< " no. of inv. particles injected: " << fInvCount << endl
<< " energy below particle cut (GeV): " << fEnergy / 1_GeV << endl
EnergyType GetInvEnergy() const { return fInvEnergy; }
EnergyType GetCutEnergy() const { return fEnergy; }
EnergyType GetEmEnergy() const { return fEmEnergy; }
//
// The example main program for a particle cascade
//
// initialize random number sequence(s)
corsika::random::RNGManager::GetInstance().RegisterRandomStream("cascade");
// setup environment, geometry
corsika::environment::Environment env;
Maximilian Reininghaus
committed
auto& universe = *(env.GetUniverse());
Maximilian Reininghaus
committed
auto theMedium = corsika::environment::Environment::CreateNode<Sphere>(
Point{env.GetCoordinateSystem(), 0_m, 0_m, 0_m},
1_km * std::numeric_limits<double>::infinity());
using MyHomogeneousModel =
corsika::environment::HomogeneousMedium<corsika::environment::IMediumModel>;
theMedium->SetModelProperties<MyHomogeneousModel>(
1_kg / (1_m * 1_m * 1_m),
corsika::environment::NuclearComposition(
std::vector<corsika::particles::Code>{corsika::particles::Code::Oxygen},
Maximilian Reininghaus
committed
universe.AddChild(std::move(theMedium));
const CoordinateSystem& rootCS = env.GetCoordinateSystem();
// setup processes, decays and interactions
tracking_line::TrackingLine<setup::Stack> tracking(env);
stack_inspector::StackInspector<setup::Stack> p0(true);
ralfulrich
committed
corsika::process::sibyll::Interaction sibyll;
corsika::process::sibyll::Decay decay;
ProcessCut cut(8_GeV);
corsika::process::TrackWriter::TrackWriter trackWriter("tracks.dat");
// assemble all processes into an ordered process list
auto sequence = p0 << sibyll << decay << cut << trackWriter;
// cout << "decltype(sequence)=" << type_id_with_cvr<decltype(sequence)>().pretty_name()
// << "\n";
// setup particle stack, and add primary particle
stack.Clear();
const hep::EnergyType E0 = 100_GeV;
double theta = 0.;
{
auto particle = stack.NewParticle();
particle.SetPID(Code::Proton);
hep::MomentumType P0 = sqrt(E0 * E0 - Proton::GetMass() * Proton::GetMass());
auto momentumComponents = [](double theta, double phi, MomentumType& ptot) {
return std::make_tuple(ptot * sin(theta) * cos(phi), ptot * sin(theta) * sin(phi),
};
auto const [px, py, pz] =
momentumComponents(theta / 180. * M_PI, phi / 180. * M_PI, P0);
Felix Riehn
committed
auto plab = stack::super_stupid::MomentumVector(rootCS, {px, py, pz});
cout << "input angles: theta=" << theta << " phi=" << phi << endl;
cout << "input momentum: " << plab.GetComponents() / 1_GeV << endl;
particle.SetEnergy(E0);
particle.SetMomentum(plab);
particle.SetTime(0_ns);
Point p(rootCS, 0_m, 0_m, 0_m);
particle.SetPosition(p);
}
// define air shower object, run simulation
corsika::cascade::Cascade EAS(env, tracking, sequence, stack);
cout << "Result: E0=" << E0 / 1_GeV << endl;
ralfulrich
committed
cut.ShowResults();
ralfulrich
committed
<< (cut.GetCutEnergy() + cut.GetInvEnergy() + cut.GetEmEnergy()) / 1_GeV << endl;