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/hadronic_elastic_model/HadronicElasticModel.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/sibyll/NuclearInteraction.h>
#include <corsika/process/track_writer/TrackWriter.h>
#include <corsika/units/PhysicalUnits.h>
Felix Riehn
committed
#include <corsika/random/RNGManager.h>
#include <corsika/utl/CorsikaFenv.h>
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::si;
class ProcessCut : public process::ContinuousProcess<ProcessCut> {
HEPEnergyType fECut;
HEPEnergyType fEnergy = 0_GeV;
HEPEnergyType fEmEnergy = 0_GeV;
ralfulrich
committed
int fEmCount = 0;
HEPEnergyType fInvEnergy = 0_GeV;
ralfulrich
committed
int fInvCount = 0;
ProcessCut(const HEPEnergyType cut)
: fECut(cut) {}
auto const ElabNuc = p.GetEnergy() / p.GetNuclearA();
auto const EcmNN = sqrt(2. * ElabNuc * 0.93827_GeV);
if (ElabNuc < fECut || EcmNN < 10_GeV)
return true;
else
return false;
} else {
// TODO: center-of-mass energy hard coded
const HEPEnergyType Ecm = sqrt(2. * p.GetEnergy() * 0.93827_GeV);
if (p.GetEnergy() < fECut || Ecm < 10_GeV)
return true;
else
return false;
}
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;
case Code::Neutron:
is_inv = true;
break;
case Code::AntiNeutron:
is_inv = true;
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&) {
ralfulrich
committed
const Code pid = p.GetPID();
HEPEnergyType 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
HEPEnergyType GetInvEnergy() const { return fInvEnergy; }
HEPEnergyType GetCutEnergy() const { return fEnergy; }
HEPEnergyType GetEmEnergy() const { return fEmEnergy; }
struct MyBoundaryCrossingProcess
: public BoundaryCrossingProcess<MyBoundaryCrossingProcess> {
template <typename Particle>
EProcessReturn DoBoundaryCrossing(Particle&, environment::BaseNodeType const& from,
environment::BaseNodeType const& to) {
std::cout << "boundary crossing! from:" << &from << "; to: " << &to << std::endl;
return EProcessReturn::eOk;
}
void Init() {}
};
//
// The example main program for a particle cascade
//
feenableexcept(FE_INVALID);
// initialize random number sequence(s)
random::RNGManager::GetInstance().RegisterRandomStream("cascade");
// setup environment, geometry
Maximilian Reininghaus
committed
auto& universe = *(env.GetUniverse());
auto outerMedium = environment::Environment::CreateNode<Sphere>(
Point{env.GetCoordinateSystem(), 0_m, 0_m, 0_m},
1_km * std::numeric_limits<double>::infinity());
// fraction of oxygen
const float fox = 0.20946;
using MyHomogeneousModel = environment::HomogeneousMedium<environment::IMediumModel>;
outerMedium->SetModelProperties<MyHomogeneousModel>(
1_kg / (1_m * 1_m * 1_m),
environment::NuclearComposition(
std::vector<particles::Code>{particles::Code::Nitrogen,
particles::Code::Oxygen},
auto innerMedium = environment::Environment::CreateNode<Sphere>(
Point{env.GetCoordinateSystem(), 0_m, 0_m, 0_m}, 10_m);
innerMedium->SetModelProperties<MyHomogeneousModel>(
1_kg / (1_m * 1_m * 1_m),
environment::NuclearComposition(
std::vector<particles::Code>{particles::Code::Nitrogen,
particles::Code::Oxygen},
std::vector<float>{(float)1. - fox, fox}));
outerMedium->AddChild(std::move(innerMedium));
universe.AddChild(std::move(outerMedium));
const CoordinateSystem& rootCS = env.GetCoordinateSystem();
// setup processes, decays and interactions
tracking_line::TrackingLine<setup::Stack, setup::Trajectory> tracking(env);
stack_inspector::StackInspector<setup::Stack> p0(true);
random::RNGManager::GetInstance().RegisterRandomStream("s_rndm");
process::sibyll::Interaction sibyll(env);
process::sibyll::NuclearInteraction sibyllNuc(env, sibyll);
process::sibyll::Decay decay;
Felix Riehn
committed
ProcessCut cut(20_GeV);
random::RNGManager::GetInstance().RegisterRandomStream("HadronicElasticModel");
process::HadronicElasticModel::HadronicElasticInteraction hadronicElastic(env);
process::TrackWriter::TrackWriter trackWriter("tracks.dat");
// assemble all processes into an ordered process list
// auto sequence = p0 << sibyll << decay << hadronicElastic << cut << trackWriter;
auto sequence = p0 << sibyll << sibyllNuc << decay << cut << MyBoundaryCrossingProcess()
<< trackWriter;
// setup particle stack, and add primary particle
stack.Clear();
const Code beamCode = Code::Nucleus;
const int nuclA = 56;
const int nuclZ = int(nuclA / 2.15 + 0.7);
const HEPMassType mass = particles::Proton::GetMass() * nuclZ +
(nuclA - nuclZ) * particles::Neutron::GetMass();
const HEPEnergyType E0 = nuclA * 100_GeV;
double theta = 27.234;
{
auto elab2plab = [](HEPEnergyType Elab, HEPMassType m) {
return sqrt(Elab * Elab - m * m);
};
HEPMomentumType P0 = elab2plab(E0, mass);
auto momentumComponents = [](double theta, double phi, HEPMomentumType 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);
auto plab = corsika::stack::MomentumVector(rootCS, {px, py, pz});
Felix Riehn
committed
cout << "input particle: " << beamCode << endl;
Felix Riehn
committed
cout << "input angles: theta=" << theta << " phi=" << phi << endl;
cout << "input momentum: " << plab.GetComponents() / 1_GeV << endl;
stack.AddParticle(std::tuple<particles::Code, units::si::HEPEnergyType,
corsika::stack::MomentumVector, geometry::Point,
units::si::TimeType, unsigned short, unsigned short>{
beamCode, E0, plab, pos, 0_ns, nuclA, nuclZ});
}
// define air shower object, run simulation
cascade::Cascade EAS(env, tracking, sequence, stack);
cout << "Result: E0=" << E0 / 1_GeV << endl;
ralfulrich
committed
cut.ShowResults();
const HEPEnergyType Efinal =
cut.GetCutEnergy() + cut.GetInvEnergy() + cut.GetEmEnergy();
cout << "total energy (GeV): " << Efinal / 1_GeV << endl
<< "relative difference (%): " << (Efinal / E0 - 1.) * 100 << endl;