diff --git a/COAST/COASTStack.h b/COAST/COASTStack.h index 66f669db801da633432e1b9273a8dce4a47f72fa..9db80c271a728d8bd0e1f4dc199a1686235e17ef 100644 --- a/COAST/COASTStack.h +++ b/COAST/COASTStack.h @@ -92,11 +92,12 @@ namespace corsika::coast { const crs::CParticle* fParticle2 = 0; public: - void Init() {} - void SetParticle(const crs::CParticle* v1, const crs::CParticle* v2) { + COASTStackImpl(const crs::CParticle* v1, const crs::CParticle* v2) { fParticle1 = v1; fParticle2 = v2; } + + void Init() {} void Clear() {} // there is one particle only @@ -177,11 +178,10 @@ namespace corsika::coast { */ void Swap(const int, const int) {} - protected: - // size cannot be increased + // size cannot be increased, do nothing void IncrementSize() {} - // size cannot be decremented + // size cannot be decremented, do nothing void DecrementSize() {} }; // end class COASTStackImpl diff --git a/COAST/COASTUserLib.cc b/COAST/COASTUserLib.cc index deb3d490dcba40e2b0e236428d5fb4b4fafbe06c..230d10a5c899ee15e8382f608d3f5d098dd5cccb 100644 --- a/COAST/COASTUserLib.cc +++ b/COAST/COASTUserLib.cc @@ -32,7 +32,6 @@ using namespace std; using namespace corsika; using namespace corsika::units::si; -coast::COASTStack gCOASTStack; corsika::coast::COASTProcess gCorsikaProcess; /* @@ -94,14 +93,14 @@ extern "C" void track_([[maybe_unused]] const crs::CParticle& pre, int particleId; int hadronicGeneration; */ - gCOASTStack.SetParticle(&pre, &post); - const auto particle = gCOASTStack.GetNextParticle(); + coast::COASTStack stack(&pre, &post); + const auto particle = stack.GetNextParticle(); const geometry::CoordinateSystem& rootCS = geometry::RootCoordinateSystem::GetInstance().GetRootCoordinateSystem(); geometry::Line const line(particle.GetPosition(rootCS), particle.GetVelocity(rootCS)); const TimeType time = particle.GetTimeInterval(); const geometry::Trajectory<geometry::Line> track(line, time); - gCorsikaProcess.DoContinuous(particle, track, gCOASTStack); + gCorsikaProcess.DoContinuous(particle, track, stack); } extern "C" void tabularizedatmosphere_([[maybe_unused]] const int& nPoints, diff --git a/Documentation/Doxygen/Doxyfile.in b/Documentation/Doxygen/Doxyfile.in index 0cf0cd506c4b9f63021354ab85b63b3329aea6c0..77031e96dc0e9d9f1b17cb4fed4f0e2201deb284 100644 --- a/Documentation/Doxygen/Doxyfile.in +++ b/Documentation/Doxygen/Doxyfile.in @@ -3,6 +3,7 @@ PROJECT_NUMBER = 0.0.0 GENERATE_HTML = YES GENERATE_LATEX = YES +GENERATE_XML = YES OUTPUT_DIRECTORY = @CMAKE_CURRENT_BINARY_DIR@/ INPUT = @PROJECT_SOURCE_DIR@ @PROJECT_BINARY_DIR@/Framework diff --git a/Documentation/Examples/stack_example.cc b/Documentation/Examples/stack_example.cc index 3d28e5566b2f53df940bf2769e85c4331d276e87..3431db4594474e0e25c0ddbe41a1ccdbef108ee9 100644 --- a/Documentation/Examples/stack_example.cc +++ b/Documentation/Examples/stack_example.cc @@ -19,9 +19,10 @@ #include <iomanip> #include <iostream> +using namespace corsika; using namespace corsika::units::si; using namespace corsika::stack; -using namespace corsika; +using namespace corsika::geometry; using namespace std; void fill(corsika::stack::super_stupid::SuperStupidStack& s) { diff --git a/Environment/FlatAtmosphere/FlatAtmosphere.h b/Environment/FlatAtmosphere/FlatAtmosphere.h index 6839def48c2f6fddfafd0beb5fd4ca46058ebd09..4227e0de4f5490ee2ac5a90857d68c5653e865ec 100644 --- a/Environment/FlatAtmosphere/FlatAtmosphere.h +++ b/Environment/FlatAtmosphere/FlatAtmosphere.h @@ -8,3 +8,5 @@ * Licence version 3 (GPL Version 3). See file LICENSE for a full version of * the license. */ + + diff --git a/Framework/Cascade/Cascade.h b/Framework/Cascade/Cascade.h index 3adaac2bc3cdb0b0fc23b4f1f986c4e9863a7f65..deb90070dadd72c7d9a3f305ba31803b18d18910 100644 --- a/Framework/Cascade/Cascade.h +++ b/Framework/Cascade/Cascade.h @@ -22,8 +22,33 @@ #include <cmath> #include <iostream> +/** + * The cascade namespace assembles all objects needed to simulate full particles cascades. + */ + namespace corsika::cascade { + /** + * The Cascade class is constructed from template arguments making + * it very versatile. Via the template arguments physics models are + * plugged into the cascade simulation. + * + * <b>Tracking</b> must be a class according to the + * TrackingInterface providing the functions: <code>void + * Init();</code> and <code>auto GetTrack(Particle const& p)</auto>, + * where the latter has a return type of <code> + * geometry::Trajectory<corsika::geometry::Line or Helix> </code> + * + * <b>ProcessList</b> must be a ProcessSequence. + * TimeOfIntersection(corsika::geometry::Line const& line, + * + * <b>Stack</b> is the storage object for particle data, i.e. with + * Particle class type <code>Stack::ParticleType</code> + * + * + + */ + template <typename Tracking, typename ProcessList, typename Stack> class Cascade { using Particle = typename Stack::ParticleType; @@ -31,6 +56,10 @@ namespace corsika::cascade { Cascade() = delete; public: + /** + * Cascade class cannot be default constructed, but needs a valid + * list of physics processes for configuration at construct time. + */ Cascade(corsika::environment::Environment const& env, Tracking& tr, ProcessList& pl, Stack& stack) : fEnvironment(env) @@ -38,12 +67,20 @@ namespace corsika::cascade { , fProcessSequence(pl) , fStack(stack) {} + /** + * The Init function is called before the actual cascade simulations. + * All components of the Cascade simulation must be configured here. + */ void Init() { fTracking.Init(); fProcessSequence.Init(); fStack.Init(); } + /** + * The Run function is the main simulation loop, which processes + * particles from the Stack until the Stack is empty. + */ void Run() { while (!fStack.IsEmpty()) { while (!fStack.IsEmpty()) { @@ -57,6 +94,16 @@ namespace corsika::cascade { } private: + /** + * The Step function is executed for each particle from the + * stack. It will calcualte geometric transport of the particles, + * and apply continuous and stochastic processes to it, which may + * lead to energy losses, scattering, absorption, decays and the + * production of secondary particles. + * + * New particles produced in one step are subject to further + * processing, e.g. thinning, etc. + */ void Step(Particle& particle) { using namespace corsika::units::si; diff --git a/Framework/Logging/Logger.h b/Framework/Logging/Logger.h index 7b9adc8d5686a3bc8bb60f4429df9015872b706c..be6b3800a6b1c6dd2862bba48d31673b5d4f0250 100644 --- a/Framework/Logging/Logger.h +++ b/Framework/Logging/Logger.h @@ -31,9 +31,6 @@ #include <corsika/logging/NoSink.h> #include <corsika/logging/Sink.h> -using namespace std; -using namespace boost; - namespace corsika::logging { /** diff --git a/Framework/StackInterface/CMakeLists.txt b/Framework/StackInterface/CMakeLists.txt index 6fce751dbccdeacfd2cdad6a98302208cfa77afa..b3e45fe644a71cd556f5ad5cfb3ec1036befc183 100644 --- a/Framework/StackInterface/CMakeLists.txt +++ b/Framework/StackInterface/CMakeLists.txt @@ -1,6 +1,7 @@ set ( CORSIKAstackinterface_HEADERS Stack.h + SecondaryView.h StackIteratorInterface.h ParticleBase.h ) diff --git a/Framework/StackInterface/ParticleBase.h b/Framework/StackInterface/ParticleBase.h index 59b133a96dbf81071b1c821dc79a0c5da2d59dbd..417ca49c63bc6a03051416219193a41ea2d4ace1 100644 --- a/Framework/StackInterface/ParticleBase.h +++ b/Framework/StackInterface/ParticleBase.h @@ -12,7 +12,7 @@ #ifndef _include_particleBase_h_ #define _include_particleBase_h_ -class StackData; // forward decl +#include <type_traits> namespace corsika::stack { @@ -89,19 +89,21 @@ namespace corsika::stack { protected: /** - @name Access to underlying stack data + @name Access to underlying stack data, these are service + function for user classes. User code can only rely on GetIndex + and GetStackData to retrieve data @{ */ auto& GetStackData() { return GetIterator().GetStackData(); } const auto& GetStackData() const { return GetIterator().GetStackData(); } auto& GetStack() { return GetIterator().GetStack(); } const auto& GetStack() const { return GetIterator().GetStack(); } - ///@} /** * return the index number of the underlying iterator object */ - unsigned int GetIndex() const { return GetIterator().GetIndex(); } + unsigned int GetIndex() const { return GetIterator().GetIndexFromIterator(); } + ///@} }; } // namespace corsika::stack diff --git a/Framework/StackInterface/SecondaryView.h b/Framework/StackInterface/SecondaryView.h new file mode 100644 index 0000000000000000000000000000000000000000..29b25a1b7140c7e8fe76b3a98b8d38f3fb1daa4a --- /dev/null +++ b/Framework/StackInterface/SecondaryView.h @@ -0,0 +1,191 @@ +#ifndef _include_corsika_stack_secondaryview_h_ +#define _include_corsika_stack_secondaryview_h_ + +#include <corsika/stack/Stack.h> + +#include <algorithm> +#include <vector> + +namespace corsika::stack { + + /** + * @class SecondaryView + * + * SecondaryView can only be constructed by giving a valid + * Projectile particle, following calls to AddSecondary will + * populate the original Stack, but will be directly accessible via + * the SecondaryView, e.g. + + This allows to write code like + \verbatim + auto projectileInput = mainStack.GetNextParticle(); + const unsigned int nMain = mainStack.GetSize(); + SecondaryView<StackData, ParticleInterface> mainStackView(projectileInput); + mainStackView.AddSecondary(...data...); + mainStackView.AddSecondary(...data...); + mainStackView.AddSecondary(...data...); + mainStackView.AddSecondary(...data...); + assert(mainStackView.GetSize() == 4); + assert(mainStack.GetSize() = nMain+4); + \endverbatim + + All operations possible on a Stack object are also possible on a + SecondaryView object. This means you can add, delete, copy, swap, + iterate, etc. + */ + + /* INTERNAL NOTE FOR DEVELOPERS The secondary particle indices are + stored in a std::vector fIndices, the index of the primary projectle + particle is explicitly stored in fProjectileIndex. StackIterator + indices are refering to those numbers, where + StackIterator::GetIndex()==0 refers to the fProjectileIndex and + StackIterator::GetIndex()>0 to fIndices[i+1], see function GetIndexFromIterator. + */ + + template <typename StackDataType, template <typename> typename ParticleInterface> + class SecondaryView : public Stack<StackDataType&, ParticleInterface> { + + using ViewType = SecondaryView<StackDataType, ParticleInterface>; + + private: + /** + * Helper type for inside this class + */ + using InnerStackType = Stack<StackDataType&, ParticleInterface>; + + /** + * @name We need this "special" types with non-reference StackData for + * the constructor of the SecondaryView class + * @{ + */ + using InnerStackTypeV = Stack<StackDataType, ParticleInterface>; + typedef StackIteratorInterface<typename std::remove_reference<StackDataType>::type, + ParticleInterface, InnerStackTypeV> + StackIteratorV; + /// @} + + public: + using StackIterator = + StackIteratorInterface<typename std::remove_reference<StackDataType>::type, + ParticleInterface, ViewType>; + using ConstStackIterator = + ConstStackIteratorInterface<typename std::remove_reference<StackDataType>::type, + ParticleInterface, ViewType>; + + /** + * this is the full type of the declared ParticleInterface: typedef typename + */ + using ParticleType = typename StackIterator::ParticleInterfaceType; + + friend class StackIteratorInterface< + typename std::remove_reference<StackDataType>::type, ParticleInterface, ViewType>; + + friend class ConstStackIteratorInterface< + typename std::remove_reference<StackDataType>::type, ParticleInterface, ViewType>; + + private: + /** + * This is not accessible, since we don't want to allow creating a + * new stack. + */ + template <typename... Args> + SecondaryView(Args... args); + + public: + SecondaryView(StackIteratorV& vP) + : Stack<StackDataType&, ParticleInterface>(vP.GetStackData()) + , fProjectileIndex(vP.GetIndex()) {} + + auto GetProjectile() { + // NOTE: 0 is special marker here for PROJECTILE, see GetIndexFromIterator + return StackIterator(*this, 0); + } + + template <typename... Args> + auto AddSecondary(const Args... v) { + InnerStackType::GetStackData().IncrementSize(); + const unsigned int idSec = GetSize(); + const unsigned int index = InnerStackType::GetStackData().GetSize() - 1; + fIndices.push_back(index); + StackIterator proj = GetProjectile(); + // NOTE: "+1" is since "0" is special marker here for PROJECTILE, see + // GetIndexFromIterator + return StackIterator(*this, idSec + 1, proj, v...); + } + + /** + * overwrite Stack::GetSize to return actual number of secondaries + */ + unsigned int GetSize() const { return fIndices.size(); } + + /** + * @name These are functions required by std containers and std loops + * The Stack-versions must be overwritten, since here we need the correct + * SecondaryView::GetSize + * @{ + */ + // NOTE: the "+1" is since "0" is special marker here for PROJECTILE, see + // GetIndexFromIterator + auto begin() { return StackIterator(*this, 0 + 1); } + auto end() { return StackIterator(*this, GetSize() + 1); } + auto last() { return StackIterator(*this, GetSize() - 1 + 1); } + + auto begin() const { return ConstStackIterator(*this, 0 + 1); } + auto end() const { return ConstStackIterator(*this, GetSize() + 1); } + auto last() const { return ConstStackIterator(*this, GetSize() - 1 + 1); } + + auto cbegin() const { return ConstStackIterator(*this, 0 + 1); } + auto cend() const { return ConstStackIterator(*this, GetSize() + 1); } + auto clast() const { return ConstStackIterator(*this, GetSize() - 1 + 1); } + /// @} + + /** + * need overwrite Stack::Delete, since we want to call SecondaryView::DeleteLast + */ + void Delete(StackIterator p) { + if (IsEmpty()) { /* error */ + throw std::runtime_error("Stack, cannot delete entry since size is zero"); + } + if (p.GetIndex() < GetSize() - 1) + InnerStackType::GetStackData().Copy(GetSize() - 1, p.GetIndex()); + DeleteLast(); + } + + /** + * need overwrite Stack::Delete, since we want to call SecondaryView::DeleteLast + */ + void Delete(ParticleType p) { Delete(p.GetIterator()); } + + /** + * delete last particle on stack by decrementing stack size + */ + void DeleteLast() { + fIndices.pop_back(); + InnerStackType::GetStackData().DecrementSize(); + } + + /** + * return next particle from stack, need to overwrtie Stack::GetNextParticle to get + * right reference + */ + StackIterator GetNextParticle() { return last(); } + + /** + * check if there are no further particles on stack + */ + bool IsEmpty() { return GetSize() == 0; } + + protected: + unsigned int GetIndexFromIterator(const unsigned int vI) const { + if (vI == 0) return fProjectileIndex; + return fIndices[vI - 1]; + } + + private: + unsigned int fProjectileIndex; + std::vector<unsigned int> fIndices; + }; + +} // namespace corsika::stack + +#endif diff --git a/Framework/StackInterface/Stack.h b/Framework/StackInterface/Stack.h index ff92fa2383e2614b2f6fa4438d6ca492d77608e6..aba9049a086f8996d8bdf692efe9a14f437c6538 100644 --- a/Framework/StackInterface/Stack.h +++ b/Framework/StackInterface/Stack.h @@ -15,6 +15,25 @@ #include <corsika/stack/StackIteratorInterface.h> #include <stdexcept> +#include <type_traits> + +#include <corsika/stack/SecondaryView.h> + +// SFINAE test +template <typename T> +class HasGetIndexFromIterator { +private: + typedef char YesType[1]; + typedef char NoType[2]; + + template <typename C> + static YesType& test(decltype(&C::GetIndexFromIterator)); + template <typename C> + static NoType& test(...); + +public: + enum { value = sizeof(test<T>(0)) == sizeof(YesType) }; +}; /** All classes around management of particles on a stack. @@ -36,7 +55,7 @@ namespace corsika::stack { /** The Stack class provides (and connects) the main particle data storage machinery. - The StackData type is the user-provided bare data storage + The StackDataType type is the user-provided bare data storage object. This can be of any complexity, from a simple struct (fortran common block), to a combination of different and distributed data sources. @@ -44,23 +63,48 @@ namespace corsika::stack { The user-provided ParticleInterface template type is the base class type of the StackIteratorInterface class (CRTP) and must provide all functions to read single particle data from the - StackData, given an 'unsigned int' index. + StackDataType, given an 'unsigned int' index. The Stack implements the std-type begin/end function to allow integration in normal for loops, ranges, etc. */ - template <typename StackData, template <typename> typename ParticleInterface> - class Stack : public StackData { + template <typename StackDataType, template <typename> typename ParticleInterface> + class Stack { + + using StackType = Stack<StackDataType, ParticleInterface>; + + StackDataType fData; ///< this in general holds all the data and can be quite big + + private: + Stack(Stack&) = delete; ///< since Stack can be very big, we don't want to copy it + Stack& operator=(Stack&) = + delete; ///< since Stack can be very big, we don't want to copy it + + public: + // template<typename = std::enable_if_t<std::is_reference<StackDataType>{}>> + Stack(StackDataType vD) + : fData(vD) {} + + /** + * This constructor takes any argument and passes it on to the + * StackDataType user class. If the user did not provide a suited + * constructor this will fail with an error message. + */ + template <typename... Args, + typename = std::enable_if_t<!std::is_reference<StackDataType>{}>> + Stack(Args... args) + : fData(args...) {} + // , typename std::enable_if<!std::is_reference<StackDataType>::value, + // std::nullptr_t>::type = nullptr) public: - typedef StackData StackImpl; ///< this is the type of the user-provided data structure + typedef StackDataType + StackImpl; ///< this is the type of the user-provided data structure + template <typename SI> using PIType = ParticleInterface<SI>; - // typedef ParticleInterface<StackIteratorInterface> StackParticleInterface; ///< - // this is the type of the user-provided ParticleInterface typedef Stack<StackData, - // ParticleInterface> StackType; /** * Via the StackIteratorInterface and ConstStackIteratorInterface @@ -69,33 +113,44 @@ namespace corsika::stack { * object. Using CRTP, this also determines the type of * ParticleInterface template class simultaneously. */ - typedef StackIteratorInterface<StackData, ParticleInterface> StackIterator; - typedef ConstStackIteratorInterface<StackData, ParticleInterface> ConstStackIterator; + using StackIterator = + StackIteratorInterface<typename std::remove_reference<StackDataType>::type, + ParticleInterface, StackType>; + using ConstStackIterator = + ConstStackIteratorInterface<typename std::remove_reference<StackDataType>::type, + ParticleInterface, StackType>; + /** * this is the full type of the declared ParticleInterface: typedef typename */ typedef typename StackIterator::ParticleInterfaceType ParticleType; - friend class StackIteratorInterface<StackData, ParticleInterface>; - friend class ConstStackIteratorInterface<StackData, ParticleInterface>; + friend class StackIteratorInterface< + typename std::remove_reference<StackDataType>::type, ParticleInterface, + StackType>; - protected: - using StackData::Copy; - using StackData::Swap; + friend class ConstStackIteratorInterface< + typename std::remove_reference<StackDataType>::type, ParticleInterface, + StackType>; public: - using StackData::GetCapacity; - using StackData::GetSize; + unsigned int GetCapacity() const { return fData.GetCapacity(); } + unsigned int GetSize() const { return fData.GetSize(); } - using StackData::Clear; - - using StackData::DecrementSize; - using StackData::IncrementSize; - - using StackData::Init; + template <typename... Args> + auto Init(Args... args) { + return fData.Init(args...); + } + template <typename... Args> + auto Clear(Args... args) { + return fData.Clear(args...); + } public: - /// these are functions required by std containers and std loops + /** + * @name These are functions required by std containers and std loops + * @{ + */ StackIterator begin() { return StackIterator(*this, 0); } StackIterator end() { return StackIterator(*this, GetSize()); } StackIterator last() { return StackIterator(*this, GetSize() - 1); } @@ -107,43 +162,81 @@ namespace corsika::stack { ConstStackIterator cbegin() const { return ConstStackIterator(*this, 0); } ConstStackIterator cend() const { return ConstStackIterator(*this, GetSize()); } ConstStackIterator clast() const { return ConstStackIterator(*this, GetSize() - 1); } + /// @} - /// increase stack size, create new particle at end of stack + /** + * increase stack size, create new particle at end of stack + */ template <typename... Args> StackIterator AddParticle(const Args... v) { - IncrementSize(); + fData.IncrementSize(); return StackIterator(*this, GetSize() - 1, v...); } + + /** + * increase stack size, create new particle at end of stack, related to parent + * particle/projectile + */ template <typename... Args> StackIterator AddSecondary(StackIterator& parent, const Args... v) { - IncrementSize(); + fData.IncrementSize(); return StackIterator(*this, GetSize() - 1, parent, v...); } - void Swap(StackIterator a, StackIterator b) { Swap(a.GetIndex(), b.GetIndex()); } + + void Swap(StackIterator a, StackIterator b) { + fData.Swap(a.GetIndex(), b.GetIndex()); + } void Swap(ConstStackIterator a, ConstStackIterator b) { - Swap(a.GetIndex(), b.GetIndex()); + fData.Swap(a.GetIndex(), b.GetIndex()); } - void Copy(StackIterator a, StackIterator b) { Copy(a.GetIndex(), b.GetIndex()); } - void Copy(ConstStackIterator a, StackIterator b) { Copy(a.GetIndex(), b.GetIndex()); } - /// delete this particle + void Copy(StackIterator a, StackIterator b) { + fData.Copy(a.GetIndex(), b.GetIndex()); + } + void Copy(ConstStackIterator a, StackIterator b) { + fData.Copy(a.GetIndex(), b.GetIndex()); + } + + /** + * delete this particle + */ void Delete(StackIterator p) { if (GetSize() == 0) { /*error*/ throw std::runtime_error("Stack, cannot delete entry since size is zero"); } - if (p.GetIndex() < GetSize() - 1) Copy(GetSize() - 1, p.GetIndex()); + if (p.GetIndex() < GetSize() - 1) fData.Copy(GetSize() - 1, p.GetIndex()); DeleteLast(); // p.SetInvalid(); } + /** + * delete this particle + */ void Delete(ParticleType p) { Delete(p.GetIterator()); } - /// delete last particle on stack by decrementing stack size - void DeleteLast() { DecrementSize(); } - /// check if there are no further particles on stack + + /** + * delete last particle on stack by decrementing stack size + */ + void DeleteLast() { fData.DecrementSize(); } + + /** + * check if there are no further particles on stack + */ bool IsEmpty() { return GetSize() == 0; } + + /** + * return next particle from stack + */ StackIterator GetNextParticle() { return last(); } protected: - StackData& GetStackData() { return static_cast<StackData&>(*this); } - const StackData& GetStackData() const { return static_cast<const StackData&>(*this); } + // typename std::enable_if<HasGetIndexFromIterator<T>::value, unsigned int>::type + // typename std::enable_if<std::is_base_of<decltype(*this)>, + // SecondaryView<StackDataType, ParticleInterface>>::value, unsigned int>::type + unsigned int GetIndexFromIterator(const unsigned int vI) const { return vI; } + + typename std::remove_reference<StackDataType>::type& GetStackData() { return fData; } + const typename std::remove_reference<StackDataType>::type& GetStackData() const { + return fData; + } }; } // namespace corsika::stack diff --git a/Framework/StackInterface/StackIteratorInterface.h b/Framework/StackInterface/StackIteratorInterface.h index 74f1a7802e1d55c0739686496d0ba568557785ac..124fa158c6c0b4cb741980580c709e89bb43168b 100644 --- a/Framework/StackInterface/StackIteratorInterface.h +++ b/Framework/StackInterface/StackIteratorInterface.h @@ -16,13 +16,14 @@ #include <type_traits> -class StackData; // forward decl - namespace corsika::stack { - template <typename StackData, template <typename> typename ParticleInterface> + template <typename StackDataType, template <typename> typename ParticleInterface> class Stack; // forward decl + template <typename StackDataType, template <typename> typename ParticleInterface> + class SecondaryView; // forward decl + /** @class StackIteratorInterface @@ -47,22 +48,32 @@ namespace corsika::stack { for a particle entry at any index fIndex. */ - template <typename StackData, template <typename> typename ParticleInterface> + template <typename StackDataType, template <typename> typename ParticleInterface, + typename StackType = Stack<StackDataType, ParticleInterface>> class StackIteratorInterface - : public ParticleInterface<StackIteratorInterface<StackData, ParticleInterface>> { + : public ParticleInterface< + StackIteratorInterface<StackDataType, ParticleInterface, StackType>> { public: - typedef Stack<StackData, ParticleInterface> StackType; + typedef StackDataType SD; + // typedef Stack<StackDataType, ParticleInterface> StackType; /*typedef - typename std::conditional<std::is_const<StackData>::value, - const Stack<const StackData, ParticleInterface>&, - Stack<StackData, ParticleInterface>&>::type StackType;*/ + typename std::conditional<std::is_const<StackDataType>::value, + const Stack<const StackDataType, ParticleInterface>&, + Stack<StackDataType, ParticleInterface>&>::type + StackType;*/ - typedef ParticleInterface<StackIteratorInterface<StackData, ParticleInterface>> + typedef ParticleInterface< + StackIteratorInterface<StackDataType, ParticleInterface, StackType>> ParticleInterfaceType; - friend class Stack<StackData, ParticleInterface>; // for access to GetIndex - friend class ParticleBase<StackIteratorInterface>; // for access to GetStackData + friend class Stack<StackDataType, + ParticleInterface>; // for access to GetIndex for Stack + friend class Stack<StackDataType&, ParticleInterface>; // for access to GetIndex + // SecondaryView : public Stack + friend class ParticleBase<StackIteratorInterface>; // for access to GetStackDataType + friend class SecondaryView<StackDataType, + ParticleInterface>; // access for SecondaryView private: unsigned int fIndex = 0; @@ -92,7 +103,8 @@ namespace corsika::stack { StackIteratorInterface(StackType& data, const unsigned int index, const Args... args) : fIndex(index) , fData(&data) { - (**this).SetParticleData(args...); + ParticleInterfaceType& p = **this; + p.SetParticleData(args...); } /** constructor that also sets new values on particle data object, including reference @@ -110,7 +122,8 @@ namespace corsika::stack { StackIteratorInterface& parent, const Args... args) : fIndex(index) , fData(&data) { - (**this).SetParticleData(*parent, args...); + ParticleInterfaceType& p = **this; + p.SetParticleData(*parent, args...); } public: @@ -131,30 +144,42 @@ namespace corsika::stack { } bool operator==(const StackIteratorInterface& rhs) { return fIndex == rhs.fIndex; } bool operator!=(const StackIteratorInterface& rhs) { return fIndex != rhs.fIndex; } - /// Convert to value type + + /** + * Convert iterator to value type, where value type is the user-provided particle + * readout class + */ ParticleInterfaceType& operator*() { return static_cast<ParticleInterfaceType&>(*this); } - /// Convert to const value type + /** + * Convert iterator to const value type, where value type is the user-provided + * particle readout class + */ const ParticleInterfaceType& operator*() const { return static_cast<const ParticleInterfaceType&>(*this); } ///@} protected: - /** @name Stack data access + /** + * @name Stack data access + * @{ */ - ///@{ /// Get current particle index inline unsigned int GetIndex() const { return fIndex; } /// Get current particle Stack object inline StackType& GetStack() { return *fData; } /// Get current particle const Stack object inline const StackType& GetStack() const { return *fData; } - /// Get current user particle StackData object - inline StackData& GetStackData() { return fData->GetStackData(); } - /// Get current const user particle StackData object - inline const StackData& GetStackData() const { return fData->GetStackData(); } + /// Get current user particle StackDataType object + inline StackDataType& GetStackData() { return fData->GetStackData(); } + /// Get current const user particle StackDataType object + inline const StackDataType& GetStackData() const { return fData->GetStackData(); } + /// Get data index as mapped in Stack class + inline unsigned int GetIndexFromIterator() const { + return fData->GetIndexFromIterator(fIndex); + } ///@} }; // end class StackIterator @@ -164,18 +189,20 @@ namespace corsika::stack { This is the iterator class for const-access to stack data */ - template <typename StackData, template <typename> typename ParticleInterface> + template <typename StackDataType, template <typename> typename ParticleInterface, + typename StackType = Stack<StackDataType, ParticleInterface>> class ConstStackIteratorInterface : public ParticleInterface< - ConstStackIteratorInterface<StackData, ParticleInterface>> { + ConstStackIteratorInterface<StackDataType, ParticleInterface, StackType>> { public: - typedef Stack<StackData, ParticleInterface> StackType; - typedef ParticleInterface<ConstStackIteratorInterface<StackData, ParticleInterface>> + typedef ParticleInterface< + ConstStackIteratorInterface<StackDataType, ParticleInterface, StackType>> ParticleInterfaceType; - friend class Stack<StackData, ParticleInterface>; // for access to GetIndex - friend class ParticleBase<ConstStackIteratorInterface>; // for access to GetStackData + friend class Stack<StackDataType, ParticleInterface>; // for access to GetIndex + friend class ParticleBase<ConstStackIteratorInterface>; // for access to + // GetStackDataType private: unsigned int fIndex = 0; @@ -238,7 +265,11 @@ namespace corsika::stack { ///@{ inline unsigned int GetIndex() const { return fIndex; } inline const StackType& GetStack() const { return *fData; } - inline const StackData& GetStackData() const { return fData->GetStackData(); } + inline const StackDataType& GetStackData() const { return fData->GetStackData(); } + /// Get data index as mapped in Stack class + inline unsigned int GetIndexFromIterator() const { + return fData->GetIndexFromIterator(fIndex); + } ///@} }; // end class ConstStackIterator diff --git a/Framework/StackInterface/testStackInterface.cc b/Framework/StackInterface/testStackInterface.cc index 3a5e945c46e4faa552724ee743241de935f48a41..293aa591463e3255aaa246f3f57ad4bf470bcab3 100644 --- a/Framework/StackInterface/testStackInterface.cc +++ b/Framework/StackInterface/testStackInterface.cc @@ -9,8 +9,18 @@ * the license. */ +#include <corsika/stack/SecondaryView.h> #include <corsika/stack/Stack.h> +#include <boost/type_index.hpp> +#include <type_traits> +using boost::typeindex::type_id_with_cvr; + +template <typename T> +struct ID { + typedef T type; +}; + #include <iomanip> #include <iostream> #include <vector> @@ -42,7 +52,6 @@ public: void SetData(const int i, const double v) { fData[i] = v; } double GetData(const int i) const { return fData[i]; } -protected: // these functions are also needed by the Stack interface void IncrementSize() { fData.push_back(0.); } void DecrementSize() { @@ -64,15 +73,26 @@ class TestParticleInterface : public ParticleBase<StackIteratorInterface> { using ParticleBase<StackIteratorInterface>::GetIterator; public: - // one version - StackIteratorInterface& AddSecondary(const double v) { - GetStack().AddParticle(v); - return GetIterator(); - } - // another version - void AddSecondary(const double v, const double p) { GetStack().AddParticle(v + p); } + /* normally this function does not need to be specified here, it is + part of ParticleBase<StackIteratorInterface>. + + However, when overloading this function again with a different + parameter set, as here, seems to require also the declaration of + the original function here... + */ + // default version for particle-creation from input data void SetParticleData(const double v) { SetData(v); } + void SetParticleData(TestParticleInterface<StackIteratorInterface>& /*parent*/, + const double v) { + SetData(v); + } + /// alternative set-particle data for non-standard construction from different inputs + void SetParticleData(const double v, const double p) { SetData(v + p); } + void SetParticleData(TestParticleInterface<StackIteratorInterface>& /*parent*/, + const double v, const double p) { + SetData(v + p); + } void SetData(const double v) { GetStackData().SetData(GetIndex(), v); } double GetData() const { return GetStackData().GetData(GetIndex()); } @@ -96,13 +116,10 @@ TEST_CASE("Stack", "[Stack]") { StackTest s; s.Init(); s.Clear(); - s.IncrementSize(); + s.AddParticle(0.); s.Copy(s.cbegin(), s.begin()); s.Swap(s.begin(), s.begin()); - s.GetCapacity(); REQUIRE(s.GetSize() == 1); - s.DecrementSize(); - REQUIRE(s.GetSize() == 0); } SECTION("construct") { @@ -156,4 +173,81 @@ TEST_CASE("Stack", "[Stack]") { for (auto& p : s) { v += p.GetData(); } REQUIRE(v == 9.9 + 4.4 + 3.3 + 2.2); } + + SECTION("get next particle") { + StackTest s; + REQUIRE(s.GetSize() == 0); + s.AddParticle(9.9); + s.AddParticle(8.8); + auto particle = s.GetNextParticle(); // first particle + REQUIRE(particle.GetData() == 8.8); + + particle.Delete(); + auto particle2 = s.GetNextParticle(); // first particle + REQUIRE(particle2.GetData() == 9.9); + particle2.Delete(); + + REQUIRE(s.GetSize() == 0); + } + + SECTION("secondary view") { + StackTest s; + REQUIRE(s.GetSize() == 0); + s.AddParticle(9.9); + s.AddParticle(8.8); + const double sumS = 9.9 + 8.8; + + auto particle = s.GetNextParticle(); + + typedef SecondaryView<TestStackData, TestParticleInterface> StackTestView; + StackTestView v(particle); + REQUIRE(v.GetSize() == 0); + + { + auto proj = v.GetProjectile(); + REQUIRE(proj.GetData() == particle.GetData()); + } + + v.AddSecondary(4.4); + v.AddSecondary(4.5); + v.AddSecondary(4.6); + + REQUIRE(v.GetSize() == 3); + REQUIRE(s.GetSize() == 5); + REQUIRE(!v.IsEmpty()); + + auto sumView = [](const StackTestView& stack) { + double v = 0; + for (const auto& p : stack) { v += p.GetData(); } + return v; + }; + + REQUIRE(sum(s) == sumS + 4.4 + 4.5 + 4.6); + REQUIRE(sumView(v) == 4.4 + 4.5 + 4.6); + + v.DeleteLast(); + REQUIRE(v.GetSize() == 2); + REQUIRE(s.GetSize() == 4); + + REQUIRE(sum(s) == sumS + 4.4 + 4.5); + REQUIRE(sumView(v) == 4.4 + 4.5); + + auto pDel = v.GetNextParticle(); + v.Delete(pDel); + REQUIRE(v.GetSize() == 1); + REQUIRE(s.GetSize() == 3); + + REQUIRE(sum(s) == sumS + 4.4 + 4.5 - pDel.GetData()); + REQUIRE(sumView(v) == 4.4 + 4.5 - pDel.GetData()); + + v.Delete(v.GetNextParticle()); + REQUIRE(sum(s) == sumS); + REQUIRE(sumView(v) == 0); + REQUIRE(v.IsEmpty()); + + { + auto proj = v.GetProjectile(); + REQUIRE(proj.GetData() == particle.GetData()); + } + } } diff --git a/Main/Environment.h b/Main/Environment.h index 6839def48c2f6fddfafd0beb5fd4ca46058ebd09..4227e0de4f5490ee2ac5a90857d68c5653e865ec 100644 --- a/Main/Environment.h +++ b/Main/Environment.h @@ -8,3 +8,5 @@ * Licence version 3 (GPL Version 3). See file LICENSE for a full version of * the license. */ + + diff --git a/Main/Stack.h b/Main/Stack.h index 6839def48c2f6fddfafd0beb5fd4ca46058ebd09..4227e0de4f5490ee2ac5a90857d68c5653e865ec 100644 --- a/Main/Stack.h +++ b/Main/Stack.h @@ -8,3 +8,5 @@ * Licence version 3 (GPL Version 3). See file LICENSE for a full version of * the license. */ + + diff --git a/Processes/Sibyll/Decay.h b/Processes/Sibyll/Decay.h index 3998cb791110b42668da128030043f7b63cf8e30..eddae6138fea423d37ba3a58876894694cd75fcd 100644 --- a/Processes/Sibyll/Decay.h +++ b/Processes/Sibyll/Decay.h @@ -90,7 +90,6 @@ namespace corsika::process { using std::cout; using std::endl; - // using namespace corsika::io; using namespace corsika::units::si; // name? also makes EM particles stable diff --git a/Processes/Sibyll/Interaction.h b/Processes/Sibyll/Interaction.h index 557eade5e6ea1ef9f9f85d84718f825c5cf0d270..966c2f7f03afd4a60dd1dfc7dab66540d1f636b8 100644 --- a/Processes/Sibyll/Interaction.h +++ b/Processes/Sibyll/Interaction.h @@ -150,6 +150,8 @@ namespace corsika::process::sibyll { auto const [productionCrossSection, elaCrossSection, numberOfNucleons] = GetCrossSection(corsikaBeamId, targetId, ECoM); + [[maybe_unused]] auto elaCrossSectionCopy = + elaCrossSection; // ONLY TO AVOID COMPILER WARNING std::cout << "Interaction: " << " IntLength: sibyll return (mb): " @@ -278,8 +280,10 @@ namespace corsika::process::sibyll { const auto [sigProd, sigEla, nNuc] = GetCrossSection(corsikaBeamId, targetId, Ecm); cross_section_of_components[i] = sigProd; - int ideleteme = nNuc; // to avoid not used warning in array binding - ideleteme = ideleteme; // to avoid not used warning in array binding + [[maybe_unused]] int ideleteme = + nNuc; // to avoid not used warning in array binding + [[maybe_unused]] auto sigElaCopy = + sigEla; // to avoid not used warning in array binding } const auto targetCode = currentNode->GetModelProperties().SampleTarget( diff --git a/Processes/Sibyll/NuclearInteraction.h b/Processes/Sibyll/NuclearInteraction.h index 572f17683e88876535898cb8038fa7229c8d7d4d..50384ddeba4657bcc6988dc50acd4a0614e22a6c 100644 --- a/Processes/Sibyll/NuclearInteraction.h +++ b/Processes/Sibyll/NuclearInteraction.h @@ -176,6 +176,7 @@ namespace corsika::process::sibyll { // TODO: remove number of nucleons, avg target mass is available in environment auto const [productionCrossSection, elaCrossSection, numberOfNucleons] = GetCrossSection(corsikaBeamId, targetId, ECoM); + [[maybe_unused]] auto elaCrossSectionCopy = elaCrossSection; std::cout << "NuclearInteraction: " << "IntLength: nuclib return (mb): " @@ -322,6 +323,8 @@ namespace corsika::process::sibyll { cout << "beam id: " << targetId << endl; const auto [sigProd, sigEla, nNuc] = GetCrossSection(beamId, targetId, EcmNN); cross_section_of_components[i] = sigProd; + [[maybe_unused]] auto sigElaCopy = sigEla; // ONLY TO AVOID COMPILER WARNINGS + [[maybe_unused]] auto sigNucCopy = nNuc; // ONLY TO AVOID COMPILER WARNINGS } const auto targetCode = currentNode->GetModelProperties().SampleTarget( @@ -350,6 +353,7 @@ namespace corsika::process::sibyll { const auto protonId = corsika::particles::Proton::GetCode(); const auto [prodCrossSection, elaCrossSection, dum] = fHadronicInteraction.GetCrossSection(protonId, protonId, EcmNN); + [[maybe_unused]] auto dumCopy = dum; // ONLY TO AVOID COMPILER WARNING const double sigProd = prodCrossSection / 1_mbarn; const double sigEla = elaCrossSection / 1_mbarn; // sample number of interactions (only input variables, output in common cnucms) diff --git a/Processes/Sibyll/SibStack.h b/Processes/Sibyll/SibStack.h index 95f7011e9a922eace00bf7e0b7c07e95a5d8b181..9b168f6eb97957b369f87a5c2066b9c601d039f5 100644 --- a/Processes/Sibyll/SibStack.h +++ b/Processes/Sibyll/SibStack.h @@ -80,7 +80,6 @@ namespace corsika::process::sibyll { std::swap(s_plist_.p[i][i1], s_plist_.p[i][i2]); } - protected: void IncrementSize() { s_plist_.np++; } void DecrementSize() { if (s_plist_.np > 0) { s_plist_.np--; } diff --git a/Processes/Sibyll/sibyll2.3c.h b/Processes/Sibyll/sibyll2.3c.h index 913cc3c6e71de0096a386c85cf9464746bd2c264..756a94bd2f05d6b14eaada201b4d75e4476c0f9b 100644 --- a/Processes/Sibyll/sibyll2.3c.h +++ b/Processes/Sibyll/sibyll2.3c.h @@ -70,7 +70,6 @@ extern struct { int lun; } s_debug_; - // lund random generator setup // extern struct {int mrlu[6]; float rrlu[100]; }ludatr_; @@ -79,7 +78,7 @@ void sibyll_(const int&, const int&, const double&); // subroutine to initiate sibyll void sibyll_ini_(); - + // subroutine to SET DECAYS void dec_ini_(); @@ -106,7 +105,5 @@ double get_sibyll_mass2(int&); // phojet random generator setup void pho_rndin_(int&, int&, int&, int&); - - } #endif diff --git a/Processes/TrackingLine/TrackingLine.h b/Processes/TrackingLine/TrackingLine.h index b829814766625213c5ed115471a7b50b5ecaaf80..02126ee12e41a98964fc997ec3f07a8a89332bcf 100644 --- a/Processes/TrackingLine/TrackingLine.h +++ b/Processes/TrackingLine/TrackingLine.h @@ -29,8 +29,6 @@ #include <stdexcept> #include <utility> -using namespace corsika; - namespace corsika::process { namespace tracking_line { diff --git a/Setup/SetupStack.h b/Setup/SetupStack.h index bae7163e259538571b5192338158471865975fb5..fdfde3d8bbc572b05703a10b1e983873bc30fd04 100644 --- a/Setup/SetupStack.h +++ b/Setup/SetupStack.h @@ -17,14 +17,17 @@ // this is an auxiliary help typedef, which I don't know how to put // into NuclearStackExtension.h where it belongs... -template<typename StackIter> using ExtendedParticleInterfaceType = - corsika::stack::nuclear_extension::NuclearParticleInterface<corsika::stack::super_stupid::SuperStupidStack::PIType, StackIter>; +template <typename StackIter> +using ExtendedParticleInterfaceType = + corsika::stack::nuclear_extension::NuclearParticleInterface< + corsika::stack::super_stupid::SuperStupidStack::PIType, StackIter>; namespace corsika::setup { - using Stack = corsika::stack::nuclear_extension::NuclearStackExtension<corsika::stack::super_stupid::SuperStupidStack, ExtendedParticleInterfaceType>; + using Stack = corsika::stack::nuclear_extension::NuclearStackExtension< + corsika::stack::super_stupid::SuperStupidStack, ExtendedParticleInterfaceType>; // typedef corsika::stack::super_stupid::SuperStupidStack Stack; -} +} // namespace corsika::setup #endif diff --git a/Stack/NuclearStackExtension/NuclearStackExtension.h b/Stack/NuclearStackExtension/NuclearStackExtension.h index 4cdd876925d748c4ddbb6688f1dae5c56512b8d2..a08dad1d72efbe061630419b17261b84c00cb297 100644 --- a/Stack/NuclearStackExtension/NuclearStackExtension.h +++ b/Stack/NuclearStackExtension/NuclearStackExtension.h @@ -12,8 +12,6 @@ #ifndef _include_stack_nuclearstackextension_h_ #define _include_stack_nuclearstackextension_h_ -#include <corsika/stack/super_stupid/SuperStupidStack.h> - #include <corsika/particles/ParticleProperties.h> #include <corsika/stack/Stack.h> #include <corsika/units/PhysicalUnits.h> @@ -39,9 +37,9 @@ namespace corsika::stack { class NuclearParticleInterface : public InnerParticleInterface<StackIteratorInterface> { - public: - using ExtendedParticleInterface = - NuclearParticleInterface<InnerParticleInterface, StackIteratorInterface>; + // public: + // using ExtendedParticleInterface = + // NuclearParticleInterface<InnerParticleInterface, StackIteratorInterface>; protected: using InnerParticleInterface<StackIteratorInterface>::GetStackData; @@ -52,8 +50,8 @@ namespace corsika::stack { const corsika::units::si::HEPEnergyType vDataE, const MomentumVector& vMomentum, const corsika::geometry::Point& vPosition, - const corsika::units::si::TimeType vTime, const int vA = 0, - const int vZ = 0) { + const corsika::units::si::TimeType vTime, + const unsigned short vA = 0, const unsigned short vZ = 0) { if (vDataPID == corsika::particles::Code::Nucleus) { if (vA == 0 || vZ == 0) { std::ostringstream err; @@ -67,8 +65,8 @@ namespace corsika::stack { } else { SetNuclearRef(-1); // this is not a nucleus } - InnerParticleInterface<StackIteratorInterface>:: - SetParticleData(vDataPID, vDataE, vMomentum, vPosition, vTime); + InnerParticleInterface<StackIteratorInterface>::SetParticleData( + vDataPID, vDataE, vMomentum, vPosition, vTime); } void SetParticleData(InnerParticleInterface<StackIteratorInterface>&, @@ -76,8 +74,8 @@ namespace corsika::stack { const corsika::units::si::HEPEnergyType vDataE, const MomentumVector& vMomentum, const corsika::geometry::Point& vPosition, - const corsika::units::si::TimeType vTime, const int vA = 0, - const int vZ = 0) { + const corsika::units::si::TimeType vTime, + const unsigned short vA = 0, const unsigned short vZ = 0) { SetParticleData(vDataPID, vDataE, vMomentum, vPosition, vTime, vA, vZ); } @@ -85,8 +83,12 @@ namespace corsika::stack { * @name individual setters * @{ */ - void SetNuclearA(const int vA) { GetStackData().SetNuclearA(GetIndex(), vA); } - void SetNuclearZ(const int vZ) { GetStackData().SetNuclearZ(GetIndex(), vZ); } + void SetNuclearA(const unsigned short vA) { + GetStackData().SetNuclearA(GetIndex(), vA); + } + void SetNuclearZ(const unsigned short vZ) { + GetStackData().SetNuclearZ(GetIndex(), vZ); + } /// @} /** @@ -120,10 +122,10 @@ namespace corsika::stack { unsigned int GetSize() const { return fNuclearRef.size(); } unsigned int GetCapacity() const { return fNuclearRef.size(); } - void SetNuclearA(const unsigned int i, const int vA) { + void SetNuclearA(const unsigned int i, const unsigned short vA) { fNuclearA[GetNucleusRef(i)] = vA; } - void SetNuclearZ(const unsigned int i, const int vZ) { + void SetNuclearZ(const unsigned int i, const unsigned short vZ) { fNuclearZ[GetNucleusRef(i)] = vZ; } void SetNuclearRef(const unsigned int i, const int v) { fNuclearRef[i] = v; } @@ -213,7 +215,6 @@ namespace corsika::stack { } } - protected: void IncrementSize() { InnerStackImpl::IncrementSize(); fNuclearRef.push_back(-1); @@ -239,8 +240,8 @@ namespace corsika::stack { /// the actual memory to store particle data std::vector<int> fNuclearRef; - std::vector<int> fNuclearA; - std::vector<int> fNuclearZ; + std::vector<unsigned short> fNuclearA; + std::vector<unsigned short> fNuclearZ; }; // end class NuclearStackExtensionImpl diff --git a/Stack/SuperStupidStack/SuperStupidStack.h b/Stack/SuperStupidStack/SuperStupidStack.h index 3daa825abcabef8d81bbb058cf62d2338933d1df..61ef97a96d3a3305156894f13cfd69b1f59b5a0e 100644 --- a/Stack/SuperStupidStack/SuperStupidStack.h +++ b/Stack/SuperStupidStack/SuperStupidStack.h @@ -176,7 +176,6 @@ namespace corsika::stack { std::swap(fTime[i2], fTime[i1]); } - protected: void IncrementSize() { using corsika::geometry::Point; using corsika::particles::Code; diff --git a/do-copyright.py b/do-copyright.py index da81b79521919a69805f63df66bffc1766c0af4f..3f0a63f46f469bf1cd53f7e860d3c381b1a59630 100755 --- a/do-copyright.py +++ b/do-copyright.py @@ -66,7 +66,7 @@ def checkNote(filename): return # add (new) copyright notice here: - + print ("File: " + filename + ", make copy to " + filename+".bak") os.rename(filename, filename+".bak") with open(filename, "w") as file: diff --git a/test.cc b/test.cc deleted file mode 100644 index 6839def48c2f6fddfafd0beb5fd4ca46058ebd09..0000000000000000000000000000000000000000 --- a/test.cc +++ /dev/null @@ -1,10 +0,0 @@ - -/* - * (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. - */