IAP GITLAB

Skip to content
Snippets Groups Projects
Commit 1ac28973 authored by ralfulrich's avatar ralfulrich Committed by Ralf Ulrich
Browse files

a lot of docs update. Sphinx.

parent 2860bbed
No related branches found
No related tags found
1 merge request!334readthedocs and better error messages
Showing
with 490 additions and 73 deletions
CORSIKA 8 Framework for Particle Cascades in Astroparticle Physics
===================================================================
The purpose of CORSIKA is to simulate any particle cascades in
astroparticle physics or astrophysical context. A lot of emphasis is
put on modularity, flexibility, completeness, validation and
correctness. To boost computational efficiency different techniques
are provided, like thinning or cascade equations. The aim is that
CORSIKA remains the most comprehensive framework for simulating
particle cascades with stochastic and continuous processes.
The software makes extensive use of static design patterns and
compiler optimization. Thus, the most fundamental configuration
decision of the user must be performed at compile time. At run time
model parameters can still be changed.
CORSIKA 8 is by default released under the GPLv3 license. See `license
file <https://gitlab.ikp.kit.edu/AirShowerPhysics/corsika/blob/master/LICENSE>`_
which is part of every release and the source code.
If you use, or want to refer to, CORSIKA 8 please cite `"Towards a Next
Generation of CORSIKA: A Framework for the Simulation of Particle
Cascades in Astroparticle Physics", Comput.Softw.Big Sci. 3 (2019)
2 <https://doi.org/10.1007/s41781-018-0013-0>`_. We kindly ask (and
require) any relevant improvement or addition to be offered or
contributed to the main CORSIKA 8 repository for the benefit of the
whole community.
When you plan to contribute to CORSIKA 8 check the guidelines outlined here:
`coding
guidelines <https://gitlab.ikp.kit.edu/AirShowerPhysics/corsika/blob/master/CONTRIBUTING.md>`_. Code
that fails the review by the CORSIKA author group must be improved
before it can be merged in the official code base. After your code has
been accepted and merged, you become a contributor of the CORSIKA 8
project (code author).
IMPORTANT: Before you contribute, you need to read and agree to the
`collaboration agreement
<https://gitlab.ikp.kit.edu/AirShowerPhysics/corsika/blob/master/COLLABORATION_AGREEMENT.md>`_. The
agreement can be discussed, and eventually improved.
We also want to point you to the `MCnet guidelines
<https://gitlab.ikp.kit.edu/AirShowerPhysics/corsika/blob/master/MCNET_GUIDELINES>`_,
which are very useful also for us.
Get in contact
--------------
* Connect to https://gitlab.ikp.kit.edu register yourself and join the "Air Shower Physics" group. Write to me (ralf.ulrich@kit.edu) only in case there are problems with that.
* Connect to corsika-devel@lists.kit.edu (self-register at
https://www.lists.kit.edu/sympa/subscribe/corsika-devel) to get in
touch with the project.
* Register on the corsika slack channel.
Installation
------------
CORSIKA 8 is tested regularly at least on gcc7.3.0 and clang-8.0.0.
Prerequisites
~~~~~~~~~~~~~
You will also need:
- Python 3 (supported versions are Python >= 3.6), with pip
- conan (via pip)
- cmake
- git
- g++, gfortran, binutils, make
On a bare Ubuntu 20.04, just add:
::
sudo apt-get install python3 python3-pip cmake g++ gfortran git doxygen graphviz
On a bare CentOS 7 install python3, pip3 (pip from python3) and cmake3. Any of the devtools 7, 8, 9 should work (at least).
Also initialize devtools, before building CORSIKA 8:
::
source /opt/rh/devtoolset-9/enable
CORSIKA 8 uses the `conan <https://conan.io/>`_ package manager to
manage our dependencies. If you do not have Conan installed, it can be
installed with:
::
pip install --user conan
Compiling
~~~~~~~~~
Once Conan is installed, follow these steps to download and install CORSIKA 8:
::
git clone --recursive git@gitlab.ikp.kit.edu:AirShowerPhysics/corsika.git
mkdir corsika-build
cd corsika-build
cmake ../corsika -DCMAKE_INSTALL_PREFIX=../corsika-install
make -j8
make install
Installation (using docker containers)
--------------------------------------
There are docker containers prepared that bring all the environment and packages you need to run CORSIKA. See `docker hub <https://hub.docker.com/repository/docker/corsika/devel>`_ for a complete overview.
Prerequisites
~~~~~~~~~~~~~
You only need docker, e.g. on Ubuntu: :code:`sudo apt-get install docker` and of course root access.
Compiling
---------
Follow these steps to download and install CORSIKA 8, master development version
::
git clone --recursive https://gitlab.ikp.kit.edu/AirShowerPhysics/corsika.git
sudo docker run -v $PWD:/corsika -it corsika/devel:clang-8 /bin/bash
mkdir build
cd build
cmake ../corsika -DCMAKE_INSTALL_PREFIX=../corsika-install
make -j8
make install
Runing Unit Tests
-----------------
Note, before you run *any* executbale you must also define the
:code:`CORSIKA_DATA` environment variable to point to the location where you
cloned corsika :code:`modules/data`, thus typically
::
export CORSIKA_DATA=$PWD/../corsika/modules/data
To run the Unit Tests, just type :code:`ctest` in your build area.
Running examples
----------------
To see how a relatively simple hadron cascade develops,
see :code:`examples/cascade_example.cpp` for a starting point.
To run the cascade_example, or any other CORSIKA 8 application, you
must first compile it wrt. to the CORSIKA 8 header-only framework. This
can be done best by copying
e.g. :code:`corsika-install/share/corsika/examples/` to your working place
(e.g. :code:`corsika-work`).
Next, you need to define the environment variable :code:`corsika_DIR` to point to, either,
your build, or your install area. Thus, e.g.
::
export corsika_DIR=<dir where you installed CORSIKA 8 to, or where you buld it">
Then compile your example/application with
::
cd corsika-work
cmake .
make
bin/cascade_example
Visualize output (needs gnuplot installed):
::
bash $corsika_DIR/share/corsika/tools/plot_tracks.sh tracks.dat
firefox tracks.dat.gif
(note, if you use the corsika_DIR to point to the build area: the script :code:`plot_tracks.sh` is
not copied to the build area, it is only part of the source tree at :code:`tools/plot_tracks.sh`)
Or also consider the :code:`vertical_EAS` example in the same directory,
which can be configured with command line options.
Run :code:`bin/vertical_EAS` to get basic help.
Generating doxygen documentation
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To generate the documentation, you need doxygen and graphviz. If you work with
the docker corsika/devel containers this is already included.
Otherwise, e.g. on Ubuntu 18.04, do:
::
sudo apt-get install doxygen graphviz
Switch to the corsika build directory and do
::
make doxygen
make install
open with firefox:
::
firefox ../corsika-install/share/corsika/doc/html/index.html
#pragma once
namespace corsika {
namespace detail {
/**
Helper traits class (partial) for static compile time checking.
Note, this is a poor replacement for C++20 concepts... they are
eagerly awaited!
It defines the default body of a generic test function returning
std::false_type.
In addition it defines the pattern for class-method matching with a
return type TReturn and function arguments TArgs... . Right now
both method signatures, "const" and "not const", are matched.
*/
template <typename TReturn, typename... TArgs>
struct has_method_signature {
template <class T>
static std::true_type testSignature(TReturn (T::*)(TArgs&&...));
template <class T>
static std::true_type testSignature(TReturn (T::*)(TArgs&&...) const);
template <class T>
static std::false_type test(...);
};
} // namespace detail
template <class TProcess, typename TReturn, typename... TArgs>
struct has_method_doInteract : public detail::has_method_signature<TReturn, TArgs...> {
using detail::has_method_signature<TReturn, TArgs...>::testSignature;
template <class T>
static decltype(testSignature(&T::template doInteraction<TArgs...>)) test(
std::nullptr_t);
template <class T>
static decltype(testSignature(&T::doInteraction)) test(std::nullptr_t);
public:
using type = decltype(test<std::decay_t<TProcess>>(nullptr));
static const bool value = type::value;
};
template <class TProcess, typename TReturn, typename... TArgs>
bool constexpr has_method_doInteract_v =
has_method_doInteract<TProcess, TReturn, TArgs...>::value;
template <class TProcess, typename TReturn, typename... TArgs>
struct has_method_getInteractionLength
: public detail::has_method_signature<TReturn, TArgs...> {
using detail::has_method_signature<TReturn, TArgs...>::testSignature;
template <class T>
static decltype(testSignature(&T::template getInteractionLength<TArgs...>)) test(
std::nullptr_t);
template <class T>
static decltype(testSignature(&T::getInteractionLength)) test(std::nullptr_t);
public:
using type = decltype(test<std::decay_t<TProcess>>(nullptr));
static const bool value = type::value;
};
template <class TProcess, typename TReturn, typename... TArgs>
bool constexpr has_method_getInteractionLength_v =
has_method_getInteractionLength<TProcess, TReturn, TArgs...>::value;
} // namespace corsika
......@@ -181,7 +181,7 @@ namespace corsika {
[[maybe_unused]] InverseGrammageType lambda_inv_select,
[[maybe_unused]] InverseGrammageType lambda_inv_sum) {
// TODO: add check for lambda_inv_select>lambda_inv_tot
// TODO: add check for lambda_inv_select > lambda_inv_tot
if constexpr (t1ProcSeq) {
// if A is a process sequence --> check inside
......@@ -195,7 +195,14 @@ namespace corsika {
lambda_inv_sum += A_.getInverseInteractionLength(view.parent());
// check if we should execute THIS process and then EXIT
if (lambda_inv_select <= lambda_inv_sum) {
A_.doInteraction(view);
// interface checking on TProcess1
static_assert(has_method_doInteract_v<TProcess1, void, TSecondaryView&>,
"TDerived has no method with correct signature \"void "
"doInteraction(TSecondaryView&)\" required for "
"InteractionProcess<TDerived>. ");
A_.template doInteraction(view);
return ProcessReturn::Interacted;
}
} // end branch A
......@@ -210,6 +217,13 @@ namespace corsika {
// soon as SecondaryView::parent() is migrated!
// check if we should execute THIS process and then EXIT
if (lambda_inv_select <= lambda_inv_sum) {
// interface checking on TProcess1
static_assert(has_method_doInteract_v<TProcess2, void, TSecondaryView&>,
"TDerived has no method with correct signature \"void "
"doInteraction(TSecondaryView&)\" required for "
"InteractionProcess<TDerived>. ");
B_.doInteraction(view);
return ProcessReturn::Interacted;
}
......
......@@ -31,7 +31,7 @@ namespace corsika {
}
template <typename TParticle, typename TTrack>
inline ProcessReturn TrackWriter::doContinuous(const TParticle& vP, const TTrack& vT,
inline ProcessReturn TrackWriter::doContinuous(TParticle const& vP, TTrack const& vT,
bool const) {
auto const start = vT.getPosition(0).getCoordinates();
auto const delta = vT.getPosition(1).getCoordinates() - start;
......@@ -54,7 +54,7 @@ namespace corsika {
}
template <typename TParticle, typename TTrack>
inline LengthType TrackWriter::getMaxStepLength(const TParticle&, const TTrack&) {
inline LengthType TrackWriter::getMaxStepLength(TParticle const&, TTrack const&) {
return meter * std::numeric_limits<double>::infinity();
}
......
......@@ -90,8 +90,9 @@ namespace corsika {
, sequence_(pl)
, stack_(stack) {
CORSIKA_LOG_INFO(c8_ascii_);
CORSIKA_LOG_INFO("Tracking algorithm: {} (version {})", TTracking::getName(), TTracking::getVersion());
if constexpr (TStackView::has_event) {
CORSIKA_LOG_INFO(" - With full cascade HISTORY.");
CORSIKA_LOG_INFO("Stack - with full cascade HISTORY.");
}
}
//! \}
......
......@@ -7,7 +7,7 @@
*/
/**
* @File Logging.hpp
* @file Logging.hpp
*
* CORSIKA8 logging utilities.
*
......
......@@ -10,11 +10,6 @@
@file ParticleProperties.hpp
Interface to particle properties
The properties of all particles are saved in static and flat
arrays. There is a enum corsika::Code to identify each
particles, and each individual particles has its own static class,
which can be used to retrieve its physical properties.
*/
#pragma once
......@@ -29,21 +24,46 @@
#include <corsika/framework/core/PhysicalUnits.hpp>
namespace corsika {
/**
* \file ParticleProperties.hpp
*
* The properties of all elementary particles are accessible here. The data
* are taken from the Pythia ParticleData.xml file.
*
@defgroup Particles Particle Properties
The properties of all particles are saved in static and flat
arrays. There is a enum corsika::Code to identify each
particles, and each individual particles has its own static class,
which can be used to retrieve its physical properties.
The properties of all elementary particles are accessible here. The data
are taken from the Pythia ParticleData.xml file.
Particle data can be accessed via global function in namespace corsika, or via
static classes for each particle type. These classes all have the interface (example for
the class corsika::Electron):
@code{.cpp}
static constexpr Code code{Code::Electron};
static constexpr Code anti_code{Code::Positron};
static constexpr HEPMassType mass{corsika::get_mass(code)};
static constexpr ElectricChargeType charge{corsika::get_charge(code)};
static constexpr int charge_number{corsika::get_charge_number(code)};
static constexpr std::string_view name{corsika::get_name(code)};
static constexpr bool is_nucleus{corsika::is_nucleus(code)};
@endcode
The names, relations and properties of all particles known to CORSIKA 8 are listed below.
@addtogroup Particles
@{
*/
namespace corsika {
/**
* @enum Code
* The Code enum is the actual place to define CORSIKA 8 particle codes.
*/
/** The Code enum is the actual place to define CORSIKA 8 particle codes. */
enum class Code : int16_t;
/** Specifically for PDG ids */
enum class PDGCode : int32_t;
using CodeIntType = std::underlying_type<Code>::type;
using PDGCodeType = std::underlying_type<PDGCode>::type;
......@@ -92,6 +112,9 @@ namespace corsika {
//! the output stream operator for human-readable particle codes
std::ostream& operator<<(std::ostream&, corsika::Code);
/** @}*/
} // namespace corsika
// data arrays, etc., as generated automatically
......@@ -101,3 +124,4 @@ namespace corsika {
// constants in namespaces-like static classes, generated automatically
#include <corsika/framework/core/GeneratedParticleClasses.inc>
......@@ -17,11 +17,14 @@ namespace corsika {
class TDerived; // fwd decl
/**
@ingroup Processes
@{
Each process in C8 must derive from BaseProcess
The structural base type of a process object in a
ProcessSequence. Both, the ProcessSequence and all its elements
are of type BaseProcess<T>
are of type BaseProcess
\todo rename BaseProcess into just Process
\todo rename _BaseProcess, or find better alternative in FIXME
......@@ -67,4 +70,6 @@ namespace corsika {
static unsigned int constexpr count = N + 1;
};
//! @}
} // namespace corsika
......@@ -15,15 +15,11 @@
namespace corsika {
/*
struct passepartout {
template <typename T>
operator T&();
template <typename T>
operator T &&();
};*/
/** @ingroup Processes
@{
*/
template <typename TDerived>
class BoundaryCrossingProcess : public BaseProcess<TDerived> {
......@@ -42,4 +38,6 @@ namespace corsika {
typename TParticle::node_type const& to);
};
//! @}
} // namespace corsika
......@@ -16,6 +16,9 @@
namespace corsika {
/**
@ingroup Processes
@{
Processes with continuous effects along a particle Trajectory
The structural base type of a process object in a
......@@ -67,4 +70,6 @@ namespace corsika {
enum { count = N + 1 };
};
/** @} */
} // namespace corsika
......@@ -11,9 +11,11 @@
namespace corsika {
/**
* To index individual processes (continuous processes) inside a
* ProcessSequence.
*
@ingroup Processes
To index individual processes (continuous processes) inside a
ProcessSequence.
**/
class ContinuousProcessIndex {
......
......@@ -14,9 +14,11 @@
namespace corsika {
/**
* To store step length in LengthType and unique index in ProcessSequence of shortest
* step ContinuousProcess.
*
@ingroup Processes
To store step length in LengthType and unique index in ProcessSequence of shortest
step ContinuousProcess.
**/
class ContinuousProcessStepLength {
......
......@@ -14,6 +14,9 @@
namespace corsika {
/**
@ingroup Processes
@{
Process decribing the decay of particles
The structural base type of a process object in a
......@@ -41,4 +44,6 @@ namespace corsika {
}
};
/** @} */
} // namespace corsika
......@@ -14,6 +14,9 @@
namespace corsika {
/*!
@ingroup Processes
@{
* Wrapper around an InteractionProcess that fills histograms of the number
* of calls to DoInteraction() binned in projectile energy (both in
* lab and center-of-mass frame) and species
......@@ -33,11 +36,15 @@ namespace corsika {
InteractionHistogram const& getHistogram() const;
void blob(int) {}
private:
TCountedProcess& process_;
InteractionHistogram histogram_;
};
//! @}
} // namespace corsika
#include <corsika/detail/framework/process/InteractionCounter.inl>
......@@ -23,6 +23,10 @@
namespace corsika {
/** @ingroup Processes
@{
*/
class InteractionHistogram {
static double constexpr lower_edge_cms = 1e3, upper_edge_cms = 1e17; // eV sqrt s
static double constexpr lower_edge_lab = 1e3, upper_edge_lab = 1e21; // eV lab
......@@ -47,6 +51,8 @@ namespace corsika {
InteractionHistogram operator+(InteractionHistogram other) const;
};
/** @} */
} // namespace corsika
#include <corsika/detail/framework/process/InteractionHistogram.inl> // for implementation
......@@ -11,34 +11,62 @@
#include <corsika/framework/process/BaseProcess.hpp>
#include <corsika/framework/core/PhysicalUnits.hpp>
#include <corsika/detail/framework/process/InteractionProcess.hpp> // for extra traits, method/interface checking
namespace corsika {
/**
@ingroup Processes
@{
Process describing the interaction of particles
The structural base type of a process object in a
ProcessSequence. Both, the ProcessSequence and all its elements
are of type InteractionProcess<T>
The structural base type for any interaction process in a
ProcessSequence.
Create a new InteractionProcess, e.g. for XYModel, via
\code
class XYModel : public InteractionProcess<XYModel> {};
\endcode
and provide the two necessary interface methods
\code
template <typename TSecondaryView>
void doInteraction(TSecondaryView&);
template <typename TParticle>
GrammageType getInteractionLength(TParticle const&)
\endcode
Where, of course, SecondaryView and Particle are the valid
classes to access particles on the Stack. Those two methods do
not need to be templated, they could use the types
e.g. corsika::setup::Stack::particle_type -- but by the cost of
loosing all flexibility otherwise provided.
(For your potential interest, InteractionProcess is based on the
CRTP C++ design pattern)
*/
template <typename TDerived>
class InteractionProcess : public BaseProcess<TDerived> {
public:
using BaseProcess<TDerived>::ref;
/// here starts the interface-definition part
// -> enforce TDerived to implement DoInteraction...
template <typename TParticle>
void doInteraction(TParticle&);
template <typename TParticle>
GrammageType getInteractionLength(TParticle const&);
template <typename TParticle>
InverseGrammageType getInverseInteractionLength(TParticle const& particle) {
// interface checking on TProcess1
static_assert(has_method_getInteractionLength_v<TDerived, GrammageType, TParticle const&>,
"TDerived has no method with correct signature \"GrammageType "
"getInteractionLength(TParticle const&)\" required for "
"InteractionProcess<TDerived>. ");
return 1. / ref().getInteractionLength(particle);
}
};
/** @} */
} // namespace corsika
......@@ -13,7 +13,10 @@
namespace corsika {
/**
* Process that does nothing
@ingroup Processes
@{
Process that does nothing
*/
class NullModel : public BaseProcess<NullModel> {
......@@ -23,4 +26,6 @@ namespace corsika {
~NullModel() = default;
};
//! @}
} // namespace corsika
......@@ -15,6 +15,9 @@
namespace corsika {
/**
@ingroup
@{
since in a process sequence many status updates can accumulate
for a single particle, this enum should define only bit-flags
that can be accumulated easily with "|="
......@@ -59,4 +62,6 @@ namespace corsika {
return static_cast<int>(a & ProcessReturn::Interacted);
}
//! @}
} // namespace corsika
......@@ -9,7 +9,7 @@
#pragma once
/**
* \file ProcessSequence.hpp
* @file ProcessSequence.hpp
*/
#include <corsika/framework/process/BaseProcess.hpp>
......@@ -28,6 +28,7 @@
namespace corsika {
// traits class to statically count processes in the sequence
template <typename TProcess, int N>
struct count_continuous<TProcess, N,
typename std::enable_if_t<is_process_sequence_v<TProcess>>> {
......@@ -35,6 +36,7 @@ namespace corsika {
N + std::decay_t<TProcess>::getNumberOfProcesses();
};
// traits class to statically count processes in the sequence
template <typename TProcess, int N>
struct count_processes<TProcess, N,
typename std::enable_if_t<is_process_v<TProcess> &&
......@@ -43,6 +45,27 @@ namespace corsika {
N + std::decay_t<TProcess>::getNumberOfProcesses();
};
/**
@defgroup Processes Physics Processes and Modules
Physics processes in CORSIKA 8 are clustered in ProcessSequence and SwitchProcessSequence containers.
The former is a mere (ordered) collection, while the latter has the option to switch between two
alternative ProcessSequences.
Depending on the type of data to act on and on the allowed actions of processes there are several
interface options:
- InteractionProcess
- DecayProcess
- ContinuousProcess
- StackProcess
- SecondariesProcess
@ingroup Processes
@{
*/
/**
*
* Definition of a static process list/sequence
......@@ -63,7 +86,7 @@ namespace corsika {
* - TProcess1 is of type BaseProcess, either a dedicatd process, or a ProcessSequence
* - TProcess2 is of type BaseProcess, either a dedicatd process, or a ProcessSequence
* - ProcessIndexOffset, IndexOfProcess1, IndexOfProcess2 are to count and index each
*ContinuousProcess in the entire process-chain
* ContinuousProcess in the entire process-chain
**/
template <typename TProcess1, typename TProcess2 = NullModel,
......@@ -195,27 +218,27 @@ namespace corsika {
};
/**
* Factory function to create ProcessSequence
*
* to construct ProcessSequences in a flexible and dynamic way the
* `sequence` factory functions are provided
*
* Any objects of type
* - BaseProcess,
* - ContinuousProcess, and
* - Interaction/DecayProcess,
* - StackProcess,
* - SecondariesProcess
* can be assembled into a ProcessSequence, all
* combinatorics are allowed.
* The sequence function checks that all its arguments are all of
* types derived from BaseProcess. Also the ProcessSequence itself
* is derived from type BaseProcess
*
* \param vA needs to derive from BaseProcess or ProcessSequence
* \param vB paramter-pack, needs to derive BaseProcess or ProcessSequence
*
Factory function to create a ProcessSequence
to construct ProcessSequences in a flexible and dynamic way the
`sequence` factory functions are provided
Any objects of type
- BaseProcess,
- ContinuousProcess, and
- InteractionProcess/DecayProcess,
- StackProcess,
- SecondariesProcess
can be assembled into a ProcessSequence, all
combinatorics are allowed.
The sequence function checks that all its arguments are all of
types derived from BaseProcess. Also the ProcessSequence itself
is derived from type BaseProcess
\param vA needs to derive from BaseProcess or ProcessSequence
\param vB paramter-pack, needs to derive BaseProcess or ProcessSequence
**/
template <typename... TProcesses, typename TProcess1>
......@@ -270,6 +293,8 @@ namespace corsika {
is_process_sequence() {}
};
/** @} */
} // namespace corsika
#include <corsika/detail/framework/process/ProcessSequence.inl>
......@@ -14,12 +14,13 @@
namespace corsika {
/**
@ingroup Processes
@{
Process that modifies a list of secondaries of other processes
The structural base type of a process object in a
ProcessSequence. Both, the ProcessSequence and all its elements
are of type SecondariesProcess<T>
*/
template <typename TDerived>
......@@ -31,4 +32,6 @@ namespace corsika {
void doSecondaries(TSecondaries&);
};
//! @}
} // namespace corsika
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment