diff --git a/Documentation/Examples/boundary_example.cc b/Documentation/Examples/boundary_example.cc index 26a8239bda592c1b9d45ed2536677cdf31f00e34..40c60ebed365e24d8e4aed8595968581fa7252e7 100644 --- a/Documentation/Examples/boundary_example.cc +++ b/Documentation/Examples/boundary_example.cc @@ -81,6 +81,9 @@ private: // The example main program for a particle cascade // int main() { + + std::cout << "boundary_example" << std::endl; + feenableexcept(FE_INVALID); // initialize random number sequence(s) random::RNGManager::GetInstance().RegisterRandomStream("cascade"); diff --git a/Documentation/Examples/cascade_example.cc b/Documentation/Examples/cascade_example.cc index 03ebe5e69cf0737e78445956c7d2b6350969c48a..fe8e05d87460d23d3517f4028a686198205dff30 100644 --- a/Documentation/Examples/cascade_example.cc +++ b/Documentation/Examples/cascade_example.cc @@ -56,6 +56,8 @@ using namespace corsika::units::si; // int main() { + std::cout << "cascade_example" << std::endl; + const LengthType height_atmosphere = 112.8_km; feenableexcept(FE_INVALID); diff --git a/Documentation/Examples/cascade_proton_example.cc b/Documentation/Examples/cascade_proton_example.cc index 12f758a0d02653905a62df5d0d229b395cf74c59..6050f7fcfae52c7a5f77e76928abbf44113c276d 100644 --- a/Documentation/Examples/cascade_proton_example.cc +++ b/Documentation/Examples/cascade_proton_example.cc @@ -58,6 +58,9 @@ using namespace corsika::units::si; // The example main program for a particle cascade // int main() { + + std::cout << "cascade_proton_example" << std::endl; + feenableexcept(FE_INVALID); // initialize random number sequence(s) random::RNGManager::GetInstance().RegisterRandomStream("cascade"); diff --git a/Documentation/Examples/geometry_example.cc b/Documentation/Examples/geometry_example.cc index c4d55058be5218130659d7263fd39a5204e02969..4c38d1dbfce534385482f480804ec1cd4ed62ae5 100644 --- a/Documentation/Examples/geometry_example.cc +++ b/Documentation/Examples/geometry_example.cc @@ -21,6 +21,9 @@ using namespace corsika::geometry; using namespace corsika::units::si; int main() { + + std::cout << "geometry_example" << std::endl; + // define the root coordinate system geometry::CoordinateSystem& root = geometry::RootCoordinateSystem::GetInstance().GetRootCoordinateSystem(); diff --git a/Documentation/Examples/helix_example.cc b/Documentation/Examples/helix_example.cc index 61759311979810c76a656aa4808112be7a5a8a32..d200cc99678942c427bc3e1a769430d9810ac833 100644 --- a/Documentation/Examples/helix_example.cc +++ b/Documentation/Examples/helix_example.cc @@ -20,6 +20,9 @@ using namespace corsika::geometry; using namespace corsika::units::si; int main() { + + std::cout << "helix_example" << std::endl; + geometry::CoordinateSystem& root = geometry::RootCoordinateSystem::GetInstance().GetRootCoordinateSystem(); diff --git a/Documentation/Examples/particle_list_example.cc b/Documentation/Examples/particle_list_example.cc index 8fb4d45a84d3282fb3d893c296d48aed9ff63000..5aefdd41401a4b6ecd67e737f1984166534c3bf3 100644 --- a/Documentation/Examples/particle_list_example.cc +++ b/Documentation/Examples/particle_list_example.cc @@ -25,6 +25,9 @@ using namespace std; // The example main program for a particle list // int main() { + + std::cout << "particle_list_example" << std::endl; + cout << "------------------------------------------" << "particles in CORSIKA" << "------------------------------------------" << endl; diff --git a/Documentation/Examples/stack_example.cc b/Documentation/Examples/stack_example.cc index 0b8d5b3a31cd2997cb5a689df8aa22c391f6eb2a..dd7de9274ab51f2d0b2d6af55deea35ded47be42 100644 --- a/Documentation/Examples/stack_example.cc +++ b/Documentation/Examples/stack_example.cc @@ -36,7 +36,7 @@ void fill(corsika::stack::super_stupid::SuperStupidStack& s) { } void read(corsika::stack::super_stupid::SuperStupidStack& s) { - assert(s.GetSize() == 11); // stack has 11 particles + assert(s.getEntries() == 11); // stack has 11 particles HEPEnergyType total_energy; int i = 0; @@ -49,6 +49,9 @@ void read(corsika::stack::super_stupid::SuperStupidStack& s) { } int main() { + + std::cout << "stack_example" << std::endl; + corsika::stack::super_stupid::SuperStupidStack s; fill(s); read(s); diff --git a/Documentation/Examples/staticsequence_example.cc b/Documentation/Examples/staticsequence_example.cc index 8e8542829ea91132635f476a0f99498958f1e3ec..5959ca5f8fb0c5bcb2dba8a371995cdcb7b4116b 100644 --- a/Documentation/Examples/staticsequence_example.cc +++ b/Documentation/Examples/staticsequence_example.cc @@ -100,6 +100,9 @@ void modular() { } int main() { + + std::cout << "staticsequence_example" << std::endl; + modular(); return 0; } diff --git a/Documentation/Examples/stopping_power.cc b/Documentation/Examples/stopping_power.cc index 6054b38ac9c0da1ec5fe34143fbebd7683cff7aa..6da3663dca95b830f20bd9ded7beb02b4be0b89f 100644 --- a/Documentation/Examples/stopping_power.cc +++ b/Documentation/Examples/stopping_power.cc @@ -33,6 +33,9 @@ using namespace corsika::units::si; // This example demonstrates the energy loss of muons as function of beta*gamma (=p/m) // int main() { + + std::cout << "stopping_power" << std::endl; + feenableexcept(FE_INVALID); // setup environment, geometry diff --git a/Documentation/Examples/vertical_EAS.cc b/Documentation/Examples/vertical_EAS.cc index 9e833addea3f599f6835bd511062540fe7de58cf..f7f45e5eab17e9c836ac756421bdcc9f0505cfb3 100644 --- a/Documentation/Examples/vertical_EAS.cc +++ b/Documentation/Examples/vertical_EAS.cc @@ -55,7 +55,7 @@ using namespace corsika::environment; using namespace std; using namespace corsika::units::si; -void registerRandomStreams() { +void registerRandomStreams(const int seed) { random::RNGManager::GetInstance().RegisterRandomStream("cascade"); random::RNGManager::GetInstance().RegisterRandomStream("qgsjet"); random::RNGManager::GetInstance().RegisterRandomStream("sibyll"); @@ -63,17 +63,28 @@ void registerRandomStreams() { random::RNGManager::GetInstance().RegisterRandomStream("urqmd"); random::RNGManager::GetInstance().RegisterRandomStream("proposal"); - random::RNGManager::GetInstance().SeedAll(); + if (seed==0) + random::RNGManager::GetInstance().SeedAll(); + else + random::RNGManager::GetInstance().SeedAll(seed); } int main(int argc, char** argv) { - if (argc != 4) { - std::cerr << "usage: vertical_EAS <A> <Z> <energy/GeV>" << std::endl; + + std::cout << "vertical_EAS" << std::endl; + + if (argc < 4) { + std::cerr << "usage: vertical_EAS <A> <Z> <energy/GeV> [seed]" << std::endl; + std::cerr << " if no seed is given, a random seed is chosen" << std::endl; return 1; } feenableexcept(FE_INVALID); + + int seed = 0; + if (argc>4) + seed = std::stoi(std::string(argv[4])); // initialize random number sequence(s) - registerRandomStreams(); + registerRandomStreams(seed); // setup environment, geometry using EnvType = Environment<setup::IEnvironmentModel>; diff --git a/Framework/Cascade/Cascade.h b/Framework/Cascade/Cascade.h index 653dc62ff43ec90d89fb6191e7581f557778ea76..91174f881f4913cf963873d2c7137db3b08290da 100644 --- a/Framework/Cascade/Cascade.h +++ b/Framework/Cascade/Cascade.h @@ -111,7 +111,9 @@ namespace corsika::cascade { while (!fStack.IsEmpty()) { while (!fStack.IsEmpty()) { auto pNext = fStack.GetNextParticle(); - std::cout << "========= next: " << pNext.GetPID() << std::endl; + std::cout << "========= next: pid=" << pNext.GetPID() + << ", stack entries=" << fStack.getEntries() + << ", stack deleted=" << fStack.getDeleted() << std::endl; Step(pNext); std::cout << "========= stack ============" << std::endl; fProcessSequence.DoStack(fStack); @@ -253,7 +255,7 @@ namespace corsika::cascade { assert(min_distance == distance_decay); decay(vParticle, projectile); // make sure particle actually did decay if it should have done so - if (secondaries.GetSize() == 1 && + if (secondaries.getSize() == 1 && projectile.GetPID() == secondaries.GetNextParticle().GetPID()) throw std::runtime_error( fmt::format("Cascade: {} decayed into itself!", diff --git a/Framework/Cascade/testCascade.cc b/Framework/Cascade/testCascade.cc index a22cfbcb4f2746607fd0498c094d85eee3d69f2e..57f715ef5b0e6a71f541390e2fc96d49ebca9826 100644 --- a/Framework/Cascade/testCascade.cc +++ b/Framework/Cascade/testCascade.cc @@ -106,11 +106,10 @@ public: if (E < fEcrit) { p.Delete(); fCount++; - } else { - ++p; // next particle } + ++p; // next particle } - cout << "ProcessCut::DoSecondaries size=" << vS.GetSize() << " count=" << fCount + cout << "ProcessCut::DoSecondaries size=" << vS.getEntries() << " count=" << fCount << endl; return EProcessReturn::eOk; } @@ -162,7 +161,7 @@ TEST_CASE("Cascade", "[Cascade]") { SECTION("forced interaction") { EAS.SetNodes(); EAS.forceInteraction(); - CHECK(stack.GetSize() == 2); + CHECK(stack.getEntries() == 2); CHECK(split.GetCalls() == 1); } } diff --git a/Framework/StackInterface/ParticleBase.h b/Framework/StackInterface/ParticleBase.h index 9bda7aebb821cc450604dd9e5d4a42731febe2b1..b5c19bca9a067ce3c179ced1dcaacb34a98820f1 100644 --- a/Framework/StackInterface/ParticleBase.h +++ b/Framework/StackInterface/ParticleBase.h @@ -63,6 +63,11 @@ namespace corsika::stack { */ void Delete() { GetIterator().GetStack().Delete(GetIterator()); } + /** + * Method to retrieve the status of the Particle. Is it already deleted? Or not. + */ + bool isDeleted() const { return GetIterator().GetStack().isDeleted(GetIterator()); } + /** * Add a secondary particle based on *this on the stack @param * args is a variadic list of input data that has to match the diff --git a/Framework/StackInterface/SecondaryView.h b/Framework/StackInterface/SecondaryView.h index 546ae571a317c4ec151f8cc23fd34a27fbf44f24..dc7d33ae7fe45a3879150209774d6244f3681ca8 100644 --- a/Framework/StackInterface/SecondaryView.h +++ b/Framework/StackInterface/SecondaryView.h @@ -63,6 +63,7 @@ namespace corsika::stack { * Helper type for inside this class */ using InnerStackType = Stack<StackDataType&, ParticleInterface>; + using InnerStackType::getDeleted; /** * @name We need this "special" types with non-reference StackData for @@ -104,6 +105,11 @@ namespace corsika::stack { template <typename... Args> SecondaryView(Args... args) = delete; + private: + InnerStackTypeValue& innerstack_; + unsigned int fProjectileIndex; + std::vector<unsigned int> fIndices; + public: /** SecondaryView can only be constructed passing it a valid @@ -111,6 +117,7 @@ namespace corsika::stack { **/ SecondaryView(StackIteratorValue& vI) : Stack<StackDataType&, ParticleInterface>(vI.GetStackData()) + , innerstack_(vI.GetStack()) , fProjectileIndex(vI.GetIndex()) {} StackIterator GetProjectile() { @@ -128,8 +135,9 @@ namespace corsika::stack { auto AddSecondary(StackIterator& proj, const Args... v) { // make space on stack InnerStackType::GetStackData().IncrementSize(); + innerstack_.deleted_.push_back(false); // get current number of secondaries on stack - const unsigned int idSec = GetSize(); + const unsigned int idSec = getSize(); // determine index on (inner) stack where new particle will be located const unsigned int index = InnerStackType::GetStackData().GetSize() - 1; fIndices.push_back(index); @@ -141,27 +149,65 @@ namespace corsika::stack { /** * overwrite Stack::GetSize to return actual number of secondaries */ - unsigned int GetSize() const { return fIndices.size(); } + unsigned int getSize() const { return fIndices.size(); } + unsigned int getEntries() const { return getSize() - getDeleted(); } + bool IsEmpty() const { return getEntries() == 0; } /** * @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 + * 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); } + StackIterator begin() { + unsigned int i = 0; + for (; i < getSize(); ++i) { + if (!isDeleted(i)) break; + } + return StackIterator(*this, i + 1); + } + auto end() { return StackIterator(*this, getSize() + 1); } + auto last() { + unsigned int i = 0; + for (; i < getSize(); ++i) { + if (!isDeleted(getSize() - 1 - i)) break; + } + return StackIterator(*this, getSize() - 1 - i + 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 begin() const { + unsigned int i = 0; + for (; i < getSize(); ++i) { + if (!isDeleted(i)) break; + } + return ConstStackIterator(*this, i + 1); + } + auto end() const { return ConstStackIterator(*this, getSize() + 1); } + auto last() const { + unsigned int i = 0; + for (; i < getSize(); ++i) { + if (!isDeleted(getSize() - 1 - i)) break; + } + return ConstStackIterator(*this, getSize() - 1 - i + 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); } + auto cbegin() const { + unsigned int i = 0; + for (; i < getSize(); ++i) { + if (!isDeleted(i)) break; + } + return ConstStackIterator(*this, i + 1); + } + auto cend() const { return ConstStackIterator(*this, getSize()); } + auto clast() const { + unsigned int i = 0; + for (; i < getSize(); ++i) { + if (!isDeleted(getSize() - 1 - i)) break; + } + return ConstStackIterator(*this, getSize() - 1 - i + 1); + } /// @} /** @@ -177,42 +223,91 @@ namespace corsika::stack { * */ void Delete(StackIterator p) { - if (IsEmpty()) { /* error */ + if (IsEmpty()) { /*error*/ throw std::runtime_error("Stack, cannot delete entry since size is zero"); } - const int innerSize = InnerStackType::GetSize(); - const int innerIndex = GetIndexFromIterator(p.GetIndex()); - if (innerIndex < innerSize - 1) - InnerStackType::GetStackData().Copy(innerSize - 1, - GetIndexFromIterator(p.GetIndex())); - DeleteLast(); + if (isDeleted(p.GetIndex() - 1)) { /*error*/ + throw std::runtime_error("Stack, cannot delete entry since already deleted"); + } + innerstack_.Delete(GetIndexFromIterator(p.GetIndex())); + InnerStackType::nDeleted_++; // also count in SecondaryView } /** * need overwrite Stack::Delete, since we want to call SecondaryView::DeleteLast */ - void Delete(ParticleInterfaceType p) { Delete(p.GetIterator()); } + // void Delete(ParticleInterfaceType p) { Delete(p.GetIterator()); } /** - * delete last particle on stack by decrementing stack size + * return next particle from stack, need to overwrtie Stack::GetNextParticle to get + * right reference */ - void DeleteLast() { - fIndices.pop_back(); - InnerStackType::GetStackData().DecrementSize(); + StackIterator GetNextParticle() { + while (purgeLastIfDeleted()) {} + return last(); } /** - * return next particle from stack, need to overwrtie Stack::GetNextParticle to get - * right reference + * check if this particle was already deleted + * + * need to re-implement for SecondaryView since StackIterator types are a bit + * different + */ + bool isDeleted(const StackIterator& p) const { return isDeleted(p.GetIndex() - 1); } + bool isDeleted(const ConstStackIterator& p) const { + return isDeleted(p.GetIndex() - 1); + } + /** + * delete this particle */ - StackIterator GetNextParticle() { return last(); } + bool isDeleted(const ParticleInterfaceType& p) const { + return isDeleted(p.GetIterator()); + } + + /** + * Function to ultimatively remove the last entry from the stack, + * if it was marked as deleted before. If this is not the case, + * the function will just return false and do nothing. + */ + bool purgeLastIfDeleted() { + if (!isDeleted(getSize() - 1)) + return false; // the last particle is not marked for deletion. Do nothing. + innerstack_.purge(GetIndexFromIterator(getSize())); + InnerStackType::nDeleted_--; + fIndices.pop_back(); + return true; + } /** - * check if there are no further particles on stack + * Function to ultimatively remove all entries from the stack + * marked as deleted. + * + * Careful: this will re-order the entries on the stack, since + * "gaps" in the stack are filled with entries from the back + * (copied). */ - bool IsEmpty() { return GetSize() == 0; } + void purge() { + unsigned int iStack = 0; + unsigned int size = getSize(); + while (iStack < size) { + if (isDeleted(iStack)) { + innerstack_.purge(iStack); + fIndices.erase(fIndices.begin() + iStack); + } + size = getSize(); + iStack++; + } + InnerStackType::nDeleted_ = 0; + } protected: + // forward to inner stack + // this also checks the allowed bounds of 'i' + bool isDeleted(unsigned int i) const { + if (i >= fIndices.size()) return false; + return innerstack_.isDeleted(GetIndexFromIterator(i + 1)); + } + /** * We only want to 'see' secondaries indexed in fIndices. In this * function the conversion form iterator-index to stack-index is @@ -222,10 +317,6 @@ namespace corsika::stack { if (vI == 0) return fProjectileIndex; return fIndices[vI - 1]; } - - private: - unsigned int fProjectileIndex; - std::vector<unsigned int> fIndices; }; /* diff --git a/Framework/StackInterface/Stack.h b/Framework/StackInterface/Stack.h index c4ce61945f955365d22d2d115bff175988d228e1..4c4e1be75f52d6f5068d7194e551afede821c02f 100644 --- a/Framework/StackInterface/Stack.h +++ b/Framework/StackInterface/Stack.h @@ -10,11 +10,12 @@ #include <corsika/stack/StackIteratorInterface.h> // must be after StackIteratorInterface -#include <corsika/stack/SecondaryView.h> +// #include <corsika/stack/SecondaryView.h> #include <corsika/utl/MetaProgramming.h> #include <stdexcept> #include <type_traits> +#include <vector> /** All classes around management of particles on a stack. @@ -51,11 +52,15 @@ namespace corsika::stack { loops, ranges, etc. */ - template <typename StackDataType, template <typename> typename ParticleInterface> + template <typename TStackData, template <typename> typename TParticleInterface> class Stack { - using StackDataValueType = std::remove_reference_t<StackDataType>; + using StackDataValueType = std::remove_reference_t<TStackData>; - StackDataType fData; ///< this in general holds all the data and can be quite big + private: + TStackData data_; ///< this in general holds all the data and can be quite big + std::vector<bool> deleted_; ///< bit field to flag deleted entries + protected: + unsigned int nDeleted_ = 0; private: Stack(Stack&) = delete; ///< since Stack can be very big, we don't want to copy it @@ -64,48 +69,52 @@ namespace corsika::stack { public: /** - * if StackDataType is a reference member we *HAVE* to initialize + * if TStackData is a reference member we *HAVE* to initialize * it in the constructor, this is typically needed for SecondaryView */ - template <typename _ = StackDataType, typename = utl::enable_if<std::is_reference<_>>> - Stack(StackDataType vD) - : fData(vD) {} + template <typename _ = TStackData, typename = utl::enable_if<std::is_reference<_>>> + Stack(TStackData vD) + : data_(vD) + , deleted_(std::vector<bool>(data_.GetSize(), false)) + , nDeleted_(0) {} /** * This constructor takes any argument and passes it on to the - * StackDataType user class. If the user did not provide a suited + * TStackData user class. If the user did not provide a suited * constructor this will fail with an error message. * * Furthermore, this is disabled with enable_if for SecondaryView * stacks, where the inner data container is always a reference * and cannot be initialized here. */ - template <typename... Args, typename _ = StackDataType, + template <typename... Args, typename _ = TStackData, typename = utl::disable_if<std::is_reference<_>>> Stack(Args... args) - : fData(args...) {} + : data_(args...) + , deleted_(std::vector<bool>(data_.GetSize(), false)) + , nDeleted_(0) {} public: - typedef StackDataType + typedef TStackData StackImpl; ///< this is the type of the user-provided data structure template <typename SI> - using PIType = ParticleInterface<SI>; + using PIType = TParticleInterface<SI>; /** * Via the StackIteratorInterface and ConstStackIteratorInterface * specialization, the type of the StackIterator * template class is declared for a particular stack data * object. Using CRTP, this also determines the type of - * ParticleInterface template class simultaneously. + * TParticleInterface template class simultaneously. */ using StackIterator = - StackIteratorInterface<StackDataValueType, ParticleInterface, Stack>; + StackIteratorInterface<StackDataValueType, TParticleInterface, Stack>; using ConstStackIterator = - ConstStackIteratorInterface<StackDataValueType, ParticleInterface, Stack>; + ConstStackIteratorInterface<StackDataValueType, TParticleInterface, Stack>; /** - * this is the full type of the user-declared ParticleInterface + * this is the full type of the user-declared TParticleInterface */ using ParticleInterfaceType = typename StackIterator::ParticleInterfaceType; /** @@ -115,21 +124,25 @@ namespace corsika::stack { using ParticleType = StackIterator; // friends are needed since they need access to protected members - friend class StackIteratorInterface<StackDataValueType, ParticleInterface, Stack>; - friend class ConstStackIteratorInterface<StackDataValueType, ParticleInterface, + friend class StackIteratorInterface<StackDataValueType, TParticleInterface, Stack>; + friend class ConstStackIteratorInterface<StackDataValueType, TParticleInterface, Stack>; + friend class SecondaryView<StackDataValueType, TParticleInterface>; public: /** - * @name Most generic proxy methods for StackDataType fData + * @name Most generic proxy methods for TStackData data_ * @{ */ - unsigned int GetCapacity() const { return fData.GetCapacity(); } - unsigned int GetSize() const { return fData.GetSize(); } + unsigned int GetCapacity() const { return data_.GetCapacity(); } + unsigned int getDeleted() const { return nDeleted_; } + unsigned int getEntries() const { return getSize() - getDeleted(); } template <typename... Args> - auto Clear(Args... args) { - return fData.Clear(args...); + void Clear(Args... args) { + data_.Clear(args...); + deleted_ = std::vector<bool>(data_.GetSize(), false); + nDeleted_ = 0; } ///@} @@ -138,26 +151,68 @@ namespace corsika::stack { * @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); } + StackIterator begin() { + unsigned int i = 0; + for (; i < getSize(); ++i) { + if (!deleted_[i]) break; + } + return StackIterator(*this, i); + } + StackIterator end() { return StackIterator(*this, getSize()); } + StackIterator last() { + unsigned int i = 0; + for (; i < getSize(); ++i) { + if (!deleted_[getSize() - 1 - i]) break; + } + return StackIterator(*this, getSize() - 1 - i); + } - ConstStackIterator begin() const { return ConstStackIterator(*this, 0); } - ConstStackIterator end() const { return ConstStackIterator(*this, GetSize()); } - ConstStackIterator last() const { return ConstStackIterator(*this, GetSize() - 1); } + ConstStackIterator begin() const { + unsigned int i = 0; + for (; i < getSize(); ++i) { + if (!deleted_[i]) break; + } + return ConstStackIterator(*this, i); + } + ConstStackIterator end() const { return ConstStackIterator(*this, getSize()); } + ConstStackIterator last() const { + unsigned int i = 0; + for (; i < getSize(); ++i) { + if (!deleted_[getSize() - 1 - i]) break; + } + return ConstStackIterator(*this, getSize() - 1 - i); + } - ConstStackIterator cbegin() const { return ConstStackIterator(*this, 0); } - ConstStackIterator cend() const { return ConstStackIterator(*this, GetSize()); } - ConstStackIterator clast() const { return ConstStackIterator(*this, GetSize() - 1); } + ConstStackIterator cbegin() const { + unsigned int i = 0; + for (; i < getSize(); ++i) { + if (!deleted_[i]) break; + } + return ConstStackIterator(*this, 0); + } + ConstStackIterator cend() const { return ConstStackIterator(*this, getSize()); } + ConstStackIterator clast() const { + unsigned int i = 0; + for (; i < getSize(); ++i) { + if (!deleted_[getSize() - 1 - i]) break; + } + return ConstStackIterator(*this, getSize() - 1 - i); + } /// @} + StackIterator GetNextParticle() { + while (purgeLastIfDeleted()) {} + return last(); + } + /** * increase stack size, create new particle at end of stack */ template <typename... Args> StackIterator AddParticle(const Args... v) { - fData.IncrementSize(); - return StackIterator(*this, GetSize() - 1, v...); + data_.IncrementSize(); + deleted_.push_back(false); + return StackIterator(*this, getSize() - 1, v...); } /** @@ -166,32 +221,44 @@ namespace corsika::stack { */ template <typename... Args> StackIterator AddSecondary(StackIterator& parent, const Args... v) { - fData.IncrementSize(); - return StackIterator(*this, GetSize() - 1, parent, v...); + data_.IncrementSize(); + deleted_.push_back(false); + return StackIterator(*this, getSize() - 1, parent, v...); } void Swap(StackIterator a, StackIterator b) { - fData.Swap(a.GetIndex(), b.GetIndex()); + data_.Swap(a.GetIndex(), b.GetIndex()); + std::swap(deleted_[a.GetIndex()], deleted_[b.GetIndex()]); } void Swap(ConstStackIterator a, ConstStackIterator b) { - fData.Swap(a.GetIndex(), b.GetIndex()); + data_.Swap(a.GetIndex(), b.GetIndex()); + std::swap(deleted_[a.GetIndex()], deleted_[b.GetIndex()]); } void Copy(StackIterator a, StackIterator b) { - fData.Copy(a.GetIndex(), b.GetIndex()); + data_.Copy(a.GetIndex(), b.GetIndex()); + if (deleted_[b.GetIndex()] && !deleted_[a.GetIndex()]) nDeleted_--; + if (!deleted_[b.GetIndex()] && deleted_[a.GetIndex()]) nDeleted_++; + deleted_[b.GetIndex()] = deleted_[a.GetIndex()]; } void Copy(ConstStackIterator a, StackIterator b) { - fData.Copy(a.GetIndex(), b.GetIndex()); + data_.Copy(a.GetIndex(), b.GetIndex()); + if (deleted_[b.GetIndex()] && !deleted_[a.GetIndex()]) nDeleted_--; + if (!deleted_[b.GetIndex()] && deleted_[a.GetIndex()]) nDeleted_++; + deleted_[b.GetIndex()] = deleted_[a.GetIndex()]; } /** * delete this particle */ + public: void Delete(StackIterator p) { - if (GetSize() == 0) { /*error*/ + if (IsEmpty()) { /*error*/ throw std::runtime_error("Stack, cannot delete entry since size is zero"); } - if (p.GetIndex() < GetSize() - 1) fData.Copy(GetSize() - 1, p.GetIndex()); - DeleteLast(); + if (deleted_[p.GetIndex()]) { /*error*/ + throw std::runtime_error("Stack, cannot delete entry since already deleted"); + } + Delete(p.GetIndex()); } /** * delete this particle @@ -199,35 +266,99 @@ namespace corsika::stack { void Delete(ParticleInterfaceType p) { Delete(p.GetIterator()); } /** - * delete last particle on stack by decrementing stack size + * check if there are no further non-deleted particles on stack */ - void DeleteLast() { fData.DecrementSize(); } + bool IsEmpty() { return getEntries() == 0; } /** - * check if there are no further particles on stack + * check if this particle was already deleted */ - bool IsEmpty() { return GetSize() == 0; } + public: + bool isDeleted(const StackIterator& p) { return isDeleted(p.GetIndex()); } + bool isDeleted(const ConstStackIterator& p) const { return isDeleted(p.GetIndex()); } + bool isDeleted(const ParticleInterfaceType& p) { return isDeleted(p.GetIterator()); } /** - * return next particle from stack + * Function to ultimatively remove the last entry from the stack, + * if it was marked as deleted before. If this is not the case, + * the function will just return false and do nothing. */ - StackIterator GetNextParticle() { return last(); } + bool purgeLastIfDeleted() { + if (!deleted_.back()) + return false; // the last particle is not marked for deletion. Do nothing. + data_.DecrementSize(); + nDeleted_--; + deleted_.pop_back(); + return true; + } + + /** + * Function to ultimatively remove all entries from the stack + * marked as deleted. + * + * Careful: this will re-order the entries on the stack, since + * "gaps" in the stack are filled with entries from the back + * (copied). + */ + void purge() { + unsigned int iStackFront = 0; + unsigned int iStackBack = getSize() - 1; + for (unsigned int iDeleted = 0; iDeleted < getDeleted(); ++iDeleted) { + // search first delete entry on stack + while (!deleted_[iStackFront]) { iStackFront++; } + // search for last non-deleted particle on stack + while (deleted_[iStackBack]) { iStackBack--; } + // copy entry from iStackBack to iStackFront + data_.Copy(iStackBack, iStackFront); + data_.DecrementSize(); + } + deleted_.clear(); + nDeleted_ = 0; + } protected: + unsigned int getSize() const { return data_.GetSize(); } + + bool isDeleted(unsigned int i) const { + if (i >= deleted_.size()) return false; + return deleted_.at(i); + } + + void Delete(unsigned int i) { + deleted_[i] = true; + nDeleted_++; + } + + /** + * will remove from storage the element i. This is a helper + * function for SecondaryView. + */ + void purge(unsigned int i) { + unsigned int iStackBack = getSize() - 1; + // search for last non-deleted particle on stack + while (deleted_[iStackBack]) { iStackBack--; } + // copy entry from iStackBack to iStackFront + data_.Copy(iStackBack, i); + if (deleted_[i]) nDeleted_--; + deleted_[i] = deleted_[iStackBack]; + data_.DecrementSize(); + deleted_.pop_back(); + } + /** * Function to perform eventual transformation from * StackIterator::GetIndex() to index in data stored in - * StackDataType fData. By default (and in almost all cases) this + * TStackData data_. By default (and in almost all cases) this * should just be identiy. See class SecondaryView for an alternative implementation. */ unsigned int GetIndexFromIterator(const unsigned int vI) const { return vI; } /** - * @name Return reference to StackDataType object fData for data access + * @name Return reference to TStackData object data_ for data access * @{ */ - StackDataValueType& GetStackData() { return fData; } - const StackDataValueType& GetStackData() const { return fData; } + StackDataValueType& GetStackData() { return data_; } + const StackDataValueType& GetStackData() const { return data_; } ///@} }; diff --git a/Framework/StackInterface/StackIteratorInterface.h b/Framework/StackInterface/StackIteratorInterface.h index 2aa5de8897c89e2b52c71a9d67b6066cdb5ba9ef..3955cafd4c2c07cc4abcdc232735769c864eb534 100644 --- a/Framework/StackInterface/StackIteratorInterface.h +++ b/Framework/StackInterface/StackIteratorInterface.h @@ -17,10 +17,10 @@ namespace corsika::history { namespace corsika::stack { - template <typename StackDataType, template <typename> typename ParticleInterface> + template <typename TStackData, template <typename> typename TParticleInterface> class Stack; // forward decl - template <typename StackDataType, template <typename> typename ParticleInterface> + template <typename TStackData, template <typename> typename TParticleInterface> class SecondaryView; // forward decl /** @@ -39,54 +39,50 @@ namespace corsika::stack { The template argument Stack determines the type of Stack object the data is stored in. A pointer to the Stack object is part of the StackIteratorInterface. In addition to Stack the iterator only knows - the index fIndex in the Stack data. + the index index_ in the Stack data. - The template argument `ParticleInterface` acts as a policy to provide - readout function of Particle data from the stack. The ParticleInterface + The template argument `TParticleInterface` acts as a policy to provide + readout function of Particle data from the stack. The TParticleInterface class must know how to retrieve information from the Stack data - for a particle entry at any index fIndex. + for a particle entry at any index index_. - The ParticleInterface class must be written and provided by the + The TParticleInterface class must be written and provided by the user, it contains methods like <code> auto GetData() const { return GetStackData().GetData(GetIndex()); }</code>, where StackIteratorInterface::GetStackData() return a reference to the - object storing the particle data of type StackDataType. And + object storing the particle data of type TStackData. And StackIteratorInterface::GetIndex() provides the iterator index to - be readout. The StackDataType is another user-provided class to + be readout. The TStackData is another user-provided class to store data and must implement functions compatible with - ParticleInterface, in this example StackDataType::GetData(const unsigned int + TParticleInterface, in this example TStackData::GetData(const unsigned int vIndex). For two examples see stack_example.cc, or the corsika::processes::sibyll::SibStack class */ - template <typename StackDataType, template <typename> typename ParticleInterface, - typename StackType = Stack<StackDataType, ParticleInterface>> + template <typename TStackData, template <typename> typename TParticleInterface, + typename StackType = Stack<TStackData, TParticleInterface>> class StackIteratorInterface - : public ParticleInterface< - StackIteratorInterface<StackDataType, ParticleInterface, StackType>> { + : public TParticleInterface< + StackIteratorInterface<TStackData, TParticleInterface, StackType>> { public: using ParticleInterfaceType = - ParticleInterface<corsika::stack::StackIteratorInterface< - StackDataType, ParticleInterface, StackType>>; + TParticleInterface<corsika::stack::StackIteratorInterface< + TStackData, TParticleInterface, StackType>>; // friends are needed for access to protected methods - 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 - - template <typename T> - friend class corsika::history::HSecondaryView; - + friend class Stack<TStackData, + TParticleInterface>; // for access to GetIndex for Stack + friend class Stack<TStackData&, TParticleInterface>; // for access to GetIndex + // SecondaryView : public Stack + friend class ParticleBase<StackIteratorInterface>; // for access to GetStackData + friend class SecondaryView<TStackData, + TParticleInterface>; // access for SecondaryView private: - unsigned int fIndex = 0; - StackType* fData = 0; // info: Particles and StackIterators become invalid when parent + unsigned int index_ = 0; + StackType* data_ = 0; // info: Particles and StackIterators become invalid when parent // Stack is copied or deleted! // it is not allowed to create a "dangling" stack iterator @@ -94,12 +90,12 @@ namespace corsika::stack { public: StackIteratorInterface(StackIteratorInterface const& vR) - : fIndex(vR.fIndex) - , fData(vR.fData) {} + : index_(vR.index_) + , data_(vR.data_) {} StackIteratorInterface& operator=(StackIteratorInterface const& vR) { - fIndex = vR.fIndex; - fData = vR.fData; + index_ = vR.index_; + data_ = vR.data_; return *this; } @@ -108,8 +104,8 @@ namespace corsika::stack { @param index index on stack */ StackIteratorInterface(StackType& data, const unsigned int index) - : fIndex(index) - , fData(&data) {} + : index_(index) + , data_(&data) {} /** constructor that also sets new values on particle data object @param data reference to the stack [rw] @@ -120,8 +116,8 @@ namespace corsika::stack { */ template <typename... Args> StackIteratorInterface(StackType& data, const unsigned int index, const Args... args) - : fIndex(index) - , fData(&data) { + : index_(index) + , data_(&data) { (**this).SetParticleData(args...); } @@ -138,29 +134,37 @@ namespace corsika::stack { template <typename... Args> StackIteratorInterface(StackType& data, const unsigned int index, StackIteratorInterface& parent, const Args... args) - : fIndex(index) - , fData(&data) { + : index_(index) + , data_(&data) { (**this).SetParticleData(*parent, args...); } + bool isDeleted() const { return GetStack().isDeleted(*this); } + public: /** @name Iterator interface @{ */ StackIteratorInterface& operator++() { - ++fIndex; + do { + ++index_; + } while ( + GetStack().isDeleted(*this)); // this also check the allowed bounds of index_ return *this; } StackIteratorInterface operator++(int) { StackIteratorInterface tmp(*this); - ++fIndex; + do { + ++index_; + } while ( + GetStack().isDeleted(*this)); // this also check the allowed bounds of index_ return tmp; } StackIteratorInterface operator+(int delta) { - return StackIteratorInterface(*fData, fIndex + delta); + return StackIteratorInterface(*data_, index_ + delta); } - bool operator==(const StackIteratorInterface& rhs) { return fIndex == rhs.fIndex; } - bool operator!=(const StackIteratorInterface& rhs) { return fIndex != rhs.fIndex; } + bool operator==(const StackIteratorInterface& rhs) { return index_ == rhs.index_; } + bool operator!=(const StackIteratorInterface& rhs) { return index_ != rhs.index_; } /** * Convert iterator to value type, where value type is the user-provided particle @@ -184,18 +188,18 @@ namespace corsika::stack { * @{ */ /// Get current particle index - inline unsigned int GetIndex() const { return fIndex; } + inline unsigned int GetIndex() const { return index_; } /// Get current particle Stack object - inline StackType& GetStack() { return *fData; } + inline StackType& GetStack() { return *data_; } /// Get current particle const Stack object - inline const StackType& GetStack() const { return *fData; } - /// 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(); } + inline const StackType& GetStack() const { return *data_; } + /// Get current user particle TStackData object + inline TStackData& GetStackData() { return data_->GetStackData(); } + /// Get current const user particle TStackData object + inline const TStackData& GetStackData() const { return data_->GetStackData(); } /// Get data index as mapped in Stack class inline unsigned int GetIndexFromIterator() const { - return fData->GetIndexFromIterator(fIndex); + return data_->GetIndexFromIterator(index_); } ///@} }; // end class StackIterator @@ -206,24 +210,29 @@ namespace corsika::stack { This is the iterator class for const-access to stack data */ - template <typename StackDataType, template <typename> typename ParticleInterface, - typename StackType = Stack<StackDataType, ParticleInterface>> + template <typename TStackData, template <typename> typename TParticleInterface, + typename StackType = Stack<TStackData, TParticleInterface>> class ConstStackIteratorInterface - : public ParticleInterface< - ConstStackIteratorInterface<StackDataType, ParticleInterface, StackType>> { + : public TParticleInterface< + ConstStackIteratorInterface<TStackData, TParticleInterface, StackType>> { public: - typedef ParticleInterface< - ConstStackIteratorInterface<StackDataType, ParticleInterface, StackType>> + typedef TParticleInterface< + ConstStackIteratorInterface<TStackData, TParticleInterface, StackType>> ParticleInterfaceType; - friend class Stack<StackDataType, ParticleInterface>; // for access to GetIndex - friend class ParticleBase<ConstStackIteratorInterface>; // for access to - // GetStackDataType + // friends are needed for access to protected methods + friend class Stack<TStackData, + TParticleInterface>; // for access to GetIndex for Stack + friend class Stack<TStackData&, TParticleInterface>; // for access to GetIndex + // SecondaryView : public Stack + friend class ParticleBase<ConstStackIteratorInterface>; // for access to GetStackData + friend class SecondaryView<TStackData, + TParticleInterface>; // access for SecondaryView private: - unsigned int fIndex = 0; - const StackType* fData = 0; // info: Particles and StackIterators become invalid when + unsigned int index_ = 0; + const StackType* data_ = 0; // info: Particles and StackIterators become invalid when // parent Stack is copied or deleted! // we don't want to allow dangling iterators to exist @@ -231,8 +240,8 @@ namespace corsika::stack { public: ConstStackIteratorInterface(const StackType& data, const unsigned int index) - : fIndex(index) - , fData(&data) {} + : index_(index) + , data_(&data) {} /** @class ConstStackIteratorInterface @@ -247,27 +256,36 @@ namespace corsika::stack { See documentation of StackIteratorInterface for more details. */ + bool isDeleted() const { return GetStack().isDeleted(*this); } + public: /** @name Iterator interface */ ///@{ ConstStackIteratorInterface& operator++() { - ++fIndex; + do { + ++index_; + } while ( + GetStack().isDeleted(*this)); // this also check the allowed bounds of index_ return *this; } ConstStackIteratorInterface operator++(int) { ConstStackIteratorInterface tmp(*this); - ++fIndex; + do { + ++index_; + } while ( + GetStack().isDeleted(*this)); // this also check the allowed bounds of index_ return tmp; } - ConstStackIteratorInterface operator+(int delta) { - return ConstStackIteratorInterface(*fData, fIndex + delta); + ConstStackIteratorInterface operator+(const int delta) { + for (int i = 0; i < delta; ++i) operator++(); + return ConstStackIteratorInterface(*data_, index_); } bool operator==(const ConstStackIteratorInterface& rhs) { - return fIndex == rhs.fIndex; + return index_ == rhs.index_; } bool operator!=(const ConstStackIteratorInterface& rhs) { - return fIndex != rhs.fIndex; + return index_ != rhs.index_; } const ParticleInterfaceType& operator*() const { @@ -280,12 +298,12 @@ namespace corsika::stack { Only the const versions for read-only access */ ///@{ - inline unsigned int GetIndex() const { return fIndex; } - inline const StackType& GetStack() const { return *fData; } - inline const StackDataType& GetStackData() const { return fData->GetStackData(); } + inline unsigned int GetIndex() const { return index_; } + inline const StackType& GetStack() const { return *data_; } + inline const TStackData& GetStackData() const { return data_->GetStackData(); } /// Get data index as mapped in Stack class inline unsigned int GetIndexFromIterator() const { - return fData->GetIndexFromIterator(fIndex); + return data_->GetIndexFromIterator(index_); } ///@} }; // end class ConstStackIterator diff --git a/Framework/StackInterface/testCombinedStack.cc b/Framework/StackInterface/testCombinedStack.cc index 6f4a9c17fe216133be861149887f87e7dd235a1d..e5a8932ecf5de4244f8ee6470e409d56c7481047 100644 --- a/Framework/StackInterface/testCombinedStack.cc +++ b/Framework/StackInterface/testCombinedStack.cc @@ -6,6 +6,8 @@ * the license. */ +#define protected public // to also test the internal state of objects + #include <corsika/stack/CombinedStack.h> #include <corsika/stack/SecondaryView.h> #include <corsika/stack/Stack.h> @@ -107,7 +109,7 @@ TEST_CASE("Combined Stack", "[stack]") { s.AddParticle(std::tuple{0.}); s.Copy(s.cbegin(), s.begin()); s.Swap(s.begin(), s.begin()); - REQUIRE(s.GetSize() == 1); + CHECK(s.getSize() == 1); } SECTION("construct") { @@ -120,72 +122,99 @@ TEST_CASE("Combined Stack", "[stack]") { StackTest s; s.AddParticle(std::tuple{9.9}); - REQUIRE(sum2(s) == 0.); - REQUIRE(sum(s) == 9.9); + CHECK(sum2(s) == 0.); + CHECK(sum(s) == 9.9); } SECTION("delete from stack") { StackTest s; - REQUIRE(s.GetSize() == 0); + CHECK(s.getSize() == 0); StackTest::StackIterator p = s.AddParticle(std::tuple{0.}); // valid way to access particle data p.SetData(8.9); p.SetData2(3.); - REQUIRE(sum2(s) == 3.); - REQUIRE(sum(s) == 8.9); - REQUIRE(s.GetSize() == 1); + CHECK(sum2(s) == 3.); + CHECK(sum(s) == 8.9); + CHECK(s.getSize() == 1); + CHECK(s.getEntries() == 1); s.Delete(p); - REQUIRE(s.GetSize() == 0); + CHECK(s.getSize() == 1); + CHECK(s.getEntries() == 0); } SECTION("delete particle") { StackTest s; - REQUIRE(s.GetSize() == 0); + CHECK(s.getSize() == 0); auto p = s.AddParticle( std::tuple{9.9}); // also valid way to access particle data, identical to above - REQUIRE(s.GetSize() == 1); + CHECK(s.getSize() == 1); + CHECK(s.getEntries() == 1); p.Delete(); - REQUIRE(s.GetSize() == 0); + CHECK(s.getSize() == 1); + CHECK(s.getEntries() == 0); } SECTION("create secondaries") { StackTest s; - REQUIRE(s.GetSize() == 0); + CHECK(s.getSize() == 0); auto iter = s.AddParticle(std::tuple{9.9}); iter.SetData2(2); - REQUIRE(s.GetSize() == 1); + CHECK(s.getSize() == 1); + CHECK(s.getEntries() == 1); iter.AddSecondary(std::tuple{4.4}); - REQUIRE(s.GetSize() == 2); + CHECK(s.getSize() == 2); + CHECK(s.getEntries() == 2); // p.AddSecondary(3.3, 2.2, 1.); - // REQUIRE(s.GetSize() == 3); + // CHECK(s.getSize() == 3); double v = 0; for (const auto& i : s) { v += i.GetData(); - REQUIRE(i.GetData2() == 2); + CHECK(i.GetData2() == 2); } - REQUIRE(v == 9.9 + 4.4); + CHECK(v == 9.9 + 4.4); } SECTION("get next particle") { StackTest s; - REQUIRE(s.GetSize() == 0); + CHECK(s.getSize() == 0); + CHECK(s.getEntries() == 0); + CHECK(s.IsEmpty()); + auto p1 = s.AddParticle(std::tuple{9.9}); auto p2 = s.AddParticle(std::tuple{8.8}); p1.SetData2(20.2); p2.SetData2(20.3); - auto particle = s.GetNextParticle(); // first particle - REQUIRE(particle.GetData() == 8.8); - REQUIRE(particle.GetData2() == 20.3); + CHECK(s.getSize() == 2); + CHECK(s.getEntries() == 2); + CHECK(!s.IsEmpty()); - particle.Delete(); + auto particle = s.GetNextParticle(); // first particle + CHECK(particle.GetData() == 8.8); + CHECK(particle.GetData2() == 20.3); + + particle.Delete(); // only marks (last) particle as "deleted" + CHECK(s.getSize() == 2); + CHECK(s.getEntries() == 1); + CHECK(!s.IsEmpty()); + + /* + This following call to GetNextParticle will realize that the + current last particle on the stack was marked "deleted" and will + purge it: stack size is reduced by one. + */ auto particle2 = s.GetNextParticle(); // first particle - REQUIRE(particle2.GetData() == 9.9); - REQUIRE(particle2.GetData2() == 20.2); - particle2.Delete(); - - REQUIRE(s.GetSize() == 0); + CHECK(s.getSize() == 1); + CHECK(s.getEntries() == 1); + CHECK(!s.IsEmpty()); + CHECK(particle2.GetData() == 9.9); + CHECK(particle2.GetData2() == 20.2); + + particle2.Delete(); // also mark this particle as "deleted" + CHECK(s.getSize() == 1); + CHECK(s.getEntries() == 0); + CHECK(s.IsEmpty()); } } @@ -199,7 +228,7 @@ class TestStackData3 { public: // these functions are needed for the Stack interface void Clear() { fData3.clear(); } - unsigned int GetSize() const { return fData3.size(); } + unsigned int getSize() const { return fData3.size(); } unsigned int GetCapacity() const { return fData3.size(); } void Copy(const int i1, const int i2) { fData3[i2] = fData3[i1]; } void Swap(const int i1, const int i2) { @@ -259,11 +288,17 @@ TEST_CASE("Combined Stack - multi", "[stack]") { SECTION("create secondaries") { StackTest2 s; - REQUIRE(s.GetSize() == 0); + CHECK(s.getSize() == 0); + CHECK(s.IsEmpty()); // size = entries = 0 + // add new particle, only provide tuple data for StackTest auto p1 = s.AddParticle(std::tuple{9.9}); // add new particle, provide tuple data for both StackTest and TestStackData3 auto p2 = s.AddParticle(std::tuple{8.8}, std::tuple{0.1}); + + CHECK(s.getSize() == 2); + CHECK(!s.IsEmpty()); // size = entries = 2 + // examples to explicitly change data on stack p2.SetData2(0.1); // not clear why this is needed, need to check // SetParticleData workflow for more complicated @@ -271,32 +306,46 @@ TEST_CASE("Combined Stack - multi", "[stack]") { p1.SetData3(20.2); p2.SetData3(10.3); - REQUIRE(p1.GetData() == 9.9); - REQUIRE(p1.GetData2() == 0.); + CHECK(p1.GetData() == 9.9); + CHECK(p1.GetData2() == 0.); p1.SetData2(10.2); - REQUIRE(p1.GetData2() == 10.2); - REQUIRE(p1.GetData3() == 20.2); + CHECK(p1.GetData2() == 10.2); + CHECK(p1.GetData3() == 20.2); - REQUIRE(p2.GetData() == 8.8); - REQUIRE(p2.GetData2() == 0.1); - REQUIRE(p2.GetData3() == 10.3); + CHECK(p2.GetData() == 8.8); + CHECK(p2.GetData2() == 0.1); + CHECK(p2.GetData3() == 10.3); auto particle = s.GetNextParticle(); // first particle - REQUIRE(particle.GetData() == 8.8); - REQUIRE(particle.GetData2() == 0.1); - REQUIRE(particle.GetData3() == 10.3); + CHECK(particle.GetData() == 8.8); + CHECK(particle.GetData2() == 0.1); + CHECK(particle.GetData3() == 10.3); - REQUIRE(s.GetSize() == 2); auto sec = particle.AddSecondary(std::tuple{4.4}); - REQUIRE(s.GetSize() == 3); - REQUIRE(sec.GetData() == 4.4); - REQUIRE(sec.GetData2() == 0.1); - REQUIRE(sec.GetData3() == 10.3); - - sec.Delete(); - s.DeleteLast(); - s.GetNextParticle().Delete(); - REQUIRE(s.GetSize() == 0); + CHECK(s.getSize() == 3); + CHECK(s.getEntries() == 3); + CHECK(sec.GetData() == 4.4); + CHECK(sec.GetData2() == 0.1); + CHECK(sec.GetData3() == 10.3); + + sec.Delete(); // mark for deletion: size=3, entries=2 + CHECK(s.getSize() == 3); + CHECK(s.getEntries() == 2); + CHECK(!s.IsEmpty()); + + s.last().Delete(); // mark for deletion: size=3, entries=1 + CHECK(s.getSize() == 3); + CHECK(s.getEntries() == 1); + CHECK(!s.IsEmpty()); + + /* + GetNextParticle will find two entries marked as "deleted" and + will purge this from the end of the stack: size = 1 + */ + s.GetNextParticle().Delete(); // mark for deletion: size=3, entries=0 + CHECK(s.getSize() == 1); + CHECK(s.getEntries() == 0); + CHECK(s.IsEmpty()); } } @@ -341,6 +390,6 @@ TEST_CASE("Combined Stack - secondary view") { auto projectile = view.GetProjectile(); projectile.AddSecondary(std::tuple{8.8}); - REQUIRE(stack.GetSize() == 2); + CHECK(stack.getSize() == 2); } } diff --git a/Framework/StackInterface/testSecondaryView.cc b/Framework/StackInterface/testSecondaryView.cc index 356a0bd5555b8a9274dc206cd1da064153764dc8..fb27467dd260630538680bbcc610ce8bce673cb0 100644 --- a/Framework/StackInterface/testSecondaryView.cc +++ b/Framework/StackInterface/testSecondaryView.cc @@ -6,6 +6,8 @@ * the license. */ +#define protected public // to also test the internal state of objects + #include <corsika/stack/SecondaryView.h> #include <corsika/stack/Stack.h> @@ -45,73 +47,90 @@ TEST_CASE("SecondaryStack", "[stack]") { // helper function for sum over stack data auto sum = [](const StackTest& stack) { double v = 0; - for (const auto& p : stack) v += p.GetData(); + for (const auto& p : stack) { v += p.GetData(); } return v; }; + auto sumView = [](const StackTestView& stack) { + double value = 0; + for (const auto& p : stack) { value += p.GetData(); } + return value; + }; + SECTION("secondary view") { StackTest s; - REQUIRE(s.GetSize() == 0); + CHECK(s.getSize() == 0); + CHECK(s.IsEmpty()); + s.AddParticle(std::tuple{9.9}); s.AddParticle(std::tuple{8.8}); - const double sumS = 9.9 + 8.8; + const double sumS = 9.9 + 8.8; // helper, see below + CHECK(s.getSize() == 2); + CHECK(s.getEntries() == 2); + CHECK(!s.IsEmpty()); auto particle = s.GetNextParticle(); StackTestView view(particle); - REQUIRE(view.GetSize() == 0); + CHECK(view.getSize() == 0); + CHECK(view.getEntries() == 0); + CHECK(view.IsEmpty()); { auto proj = view.GetProjectile(); - REQUIRE(proj.GetData() == particle.GetData()); + CHECK(proj.GetData() == particle.GetData()); proj.AddSecondary(std::tuple{4.4}); } + CHECK(view.getSize() == 1); + CHECK(view.getEntries() == 1); + CHECK(!view.IsEmpty()); + CHECK(s.getSize() == 3); + CHECK(s.getEntries() == 3); + CHECK(!s.IsEmpty()); view.AddSecondary(std::tuple{4.5}); view.AddSecondary(std::tuple{4.6}); + CHECK(view.getSize() == 3); + CHECK(view.getEntries() == 3); + CHECK(!view.IsEmpty()); + CHECK(s.getSize() == 5); + CHECK(s.getEntries() == 5); + CHECK(!s.IsEmpty()); - REQUIRE(view.GetSize() == 3); - REQUIRE(s.GetSize() == 5); - REQUIRE(!view.IsEmpty()); - - auto sumView = [](const StackTestView& stack) { - double value = 0; - for (const auto& p : stack) { value += p.GetData(); } - return value; - }; - - REQUIRE(sum(s) == sumS + 4.4 + 4.5 + 4.6); - REQUIRE(sumView(view) == 4.4 + 4.5 + 4.6); + CHECK(sum(s) == sumS + 4.4 + 4.5 + 4.6); + CHECK(sumView(view) == 4.4 + 4.5 + 4.6); - view.DeleteLast(); - REQUIRE(view.GetSize() == 2); - REQUIRE(s.GetSize() == 4); + view.last().Delete(); + CHECK(view.getSize() == 3); + CHECK(view.getEntries() == 2); + CHECK(s.getSize() == 5); + CHECK(s.getEntries() == 4); - REQUIRE(sum(s) == sumS + 4.4 + 4.5); - REQUIRE(sumView(view) == 4.4 + 4.5); + CHECK(sum(s) == sumS + 4.4 + 4.5); + CHECK(sumView(view) == 4.4 + 4.5); auto pDel = view.GetNextParticle(); view.Delete(pDel); - REQUIRE(view.GetSize() == 1); - REQUIRE(s.GetSize() == 3); + CHECK(view.getSize() == 2); + CHECK(s.getSize() == 4); - REQUIRE(sum(s) == sumS + 4.4 + 4.5 - pDel.GetData()); - REQUIRE(sumView(view) == 4.4 + 4.5 - pDel.GetData()); + CHECK(sum(s) == sumS + 4.4 + 4.5 - pDel.GetData()); + CHECK(sumView(view) == 4.4 + 4.5 - pDel.GetData()); view.Delete(view.GetNextParticle()); - REQUIRE(sum(s) == sumS); - REQUIRE(sumView(view) == 0); - REQUIRE(view.IsEmpty()); + CHECK(sum(s) == sumS); + CHECK(sumView(view) == 0); + CHECK(view.IsEmpty()); { auto proj = view.GetProjectile(); - REQUIRE(proj.GetData() == particle.GetData()); + CHECK(proj.GetData() == particle.GetData()); } } SECTION("secondary view, construct from ParticleType") { StackTest s; - REQUIRE(s.GetSize() == 0); + CHECK(s.getSize() == 0); s.AddParticle(std::tuple{9.9}); s.AddParticle(std::tuple{8.8}); @@ -119,11 +138,11 @@ TEST_CASE("SecondaryStack", "[stack]") { typename StackTest::ParticleType& particle = iterator; // as in corsika::Cascade StackTestView view(particle); - REQUIRE(view.GetSize() == 0); + CHECK(view.getSize() == 0); view.AddSecondary(std::tuple{4.4}); - REQUIRE(view.GetSize() == 1); + CHECK(view.getSize() == 1); } SECTION("deletion") { @@ -141,21 +160,20 @@ TEST_CASE("SecondaryStack", "[stack]") { proj.AddSecondary(std::tuple{1.}); proj.AddSecondary(std::tuple{2.}); - CHECK(stack.GetSize() == 6); // -99, 0, -2, -1, 1, 2 - CHECK(view.GetSize() == 4); // -2, -1, 1, 2 + CHECK(stack.getSize() == 6); // -99, 0, -2, -1, 1, 2 + CHECK(view.getSize() == 4); // -2, -1, 1, 2 // now delete all negative entries, i.e. -1 and -2 auto p = view.begin(); while (p != view.end()) { auto data = p.GetData(); - if (data < 0) { - p.Delete(); - } else { - ++p; - } + if (data < 0) { p.Delete(); } + ++p; } - CHECK(stack.GetSize() == 4); // -99, 0, 2, 1 (order changes during deletion) - CHECK(view.GetSize() == 2); // 2, 1 + CHECK(stack.getSize() == 6); + CHECK(stack.getEntries() == 4); // -99, 0, 2, 1 (order changes during deletion) + CHECK(view.getSize() == 4); + CHECK(view.getEntries() == 2); // 2, 1 } // repeat @@ -175,17 +193,15 @@ TEST_CASE("SecondaryStack", "[stack]") { auto p = view.begin(); while (p != view.end()) { auto data = p.GetData(); - if (data < 0) { - p.Delete(); - } else { - ++p; - } + if (data < 0) { p.Delete(); } + ++p; } // stack should contain -99, 0, 2, 1, [2, 1] // view should contain 1, 2 - CHECK(stack.GetSize() == 6); + CHECK(stack.getEntries() == 6); + CHECK(stack.getSize() == 10); } } } diff --git a/Framework/StackInterface/testStackInterface.cc b/Framework/StackInterface/testStackInterface.cc index 1ef504f60255ec5a45d540560f6e9fc19822bc29..e4e78a24f17c0a1914a7f5c946a9bffa16cd0c91 100644 --- a/Framework/StackInterface/testStackInterface.cc +++ b/Framework/StackInterface/testStackInterface.cc @@ -6,6 +6,8 @@ * the license. */ +#define protected public // to also test the internal state of objects + #include <corsika/stack/Stack.h> #include <testTestStack.h> // simple test-stack for testing. This is @@ -42,7 +44,7 @@ TEST_CASE("Stack", "[Stack]") { s.AddParticle(std::tuple{0.}); s.Copy(s.cbegin(), s.begin()); s.Swap(s.begin(), s.begin()); - REQUIRE(s.GetSize() == 1); + CHECK(s.getSize() == 1); } SECTION("construct") { @@ -56,62 +58,108 @@ TEST_CASE("Stack", "[Stack]") { StackTest s; s.AddParticle(std::tuple{9.9}); const double v = sum(s); - REQUIRE(v == 9.9); + CHECK(v == 9.9); } SECTION("delete from stack") { StackTest s; - REQUIRE(s.GetSize() == 0); + CHECK(s.getSize() == 0); StackTest::StackIterator p = s.AddParticle(std::tuple{0.}); // valid way to access particle data p.SetData(9.9); - REQUIRE(s.GetSize() == 1); + CHECK(s.getSize() == 1); + CHECK(s.getEntries() == 1); s.Delete(p); - REQUIRE(s.GetSize() == 0); + CHECK(s.getSize() == 1); + CHECK(s.getEntries() == 0); } SECTION("delete particle") { StackTest s; - REQUIRE(s.GetSize() == 0); + CHECK(s.getSize() == 0); + s.AddParticle(std::tuple{8.9}); + s.AddParticle(std::tuple{7.9}); auto p = s.AddParticle( std::tuple{9.9}); // also valid way to access particle data, identical to above - REQUIRE(s.GetSize() == 1); - p.Delete(); - REQUIRE(s.GetSize() == 0); + + CHECK(s.getSize() == 3); + CHECK(s.getEntries() == 3); + CHECK(!s.IsEmpty()); + + p.Delete(); // mark for deletion: size=3, entries=2 + CHECK(s.getSize() == 3); + CHECK(s.getEntries() == 2); + CHECK(!s.IsEmpty()); + + s.last().Delete(); // mark for deletion: size=3, entries=1 + CHECK(s.getSize() == 3); + CHECK(s.getEntries() == 1); + CHECK(!s.IsEmpty()); + + /* + GetNextParticle will find two entries marked as "deleted" and + will purge this from the end of the stack: size = 1 + */ + s.GetNextParticle().Delete(); // mark for deletion: size=3, entries=0 + CHECK(s.getSize() == 1); + CHECK(s.getEntries() == 0); + CHECK(s.IsEmpty()); } SECTION("create secondaries") { StackTest s; - REQUIRE(s.GetSize() == 0); + CHECK(s.getSize() == 0); auto iter = s.AddParticle(std::tuple{9.9}); StackTest::ParticleInterfaceType& p = *iter; // also this is valid to access particle data - REQUIRE(s.GetSize() == 1); + CHECK(s.getSize() == 1); p.AddSecondary(std::tuple{4.4}); - REQUIRE(s.GetSize() == 2); + CHECK(s.getSize() == 2); /*p.AddSecondary(3.3, 2.2); - REQUIRE(s.GetSize() == 3); + CHECK(s.getSize() == 3); double v = 0; for (auto& p : s) { v += p.GetData(); } - REQUIRE(v == 9.9 + 4.4 + 3.3 + 2.2);*/ + CHECK(v == 9.9 + 4.4 + 3.3 + 2.2);*/ } SECTION("get next particle") { StackTest s; - REQUIRE(s.GetSize() == 0); + CHECK(s.getSize() == 0); + CHECK(s.getEntries() == 0); + CHECK(s.IsEmpty()); + s.AddParticle(std::tuple{9.9}); s.AddParticle(std::tuple{8.8}); - auto particle = s.GetNextParticle(); // first particle - REQUIRE(particle.GetData() == 8.8); + CHECK(s.getSize() == 2); + CHECK(s.getEntries() == 2); + CHECK(!s.IsEmpty()); - particle.Delete(); + auto particle = s.GetNextParticle(); // first particle + CHECK(particle.GetData() == 8.8); + + particle.Delete(); // only marks (last) particle as deleted + CHECK(s.getSize() == 2); + CHECK(s.getEntries() == 1); + CHECK(!s.IsEmpty()); + + /* + This following call to GetNextParticle will realize that the + current last particle on the stack was marked "deleted" and will + purge it: stack size is reduced by one. + */ auto particle2 = s.GetNextParticle(); // first particle - REQUIRE(particle2.GetData() == 9.9); - particle2.Delete(); + CHECK(particle2.GetData() == 9.9); + CHECK(s.getSize() == 1); + CHECK(s.getEntries() == 1); + CHECK(!s.IsEmpty()); + + particle2.Delete(); // also mark this particle as deleted - REQUIRE(s.GetSize() == 0); + CHECK(s.getSize() == 1); + CHECK(s.getEntries() == 0); + CHECK(s.IsEmpty()); } } diff --git a/Processes/CONEXSourceCut/CONEXSourceCut.cc b/Processes/CONEXSourceCut/CONEXSourceCut.cc index 77fffb0e65363aada42d45b4f5ab1c6ba7aa9a47..7a0da45a726bbf40e69aab6264baa288968d47ec 100644 --- a/Processes/CONEXSourceCut/CONEXSourceCut.cc +++ b/Processes/CONEXSourceCut/CONEXSourceCut.cc @@ -29,17 +29,17 @@ corsika::process::EProcessReturn CONEXSourceCut::DoSecondaries( auto const it = std::find_if(egs_em_codes_.cbegin(), egs_em_codes_.cend(), [=](auto const& p) { return pid == p.first; }); - if (it == egs_em_codes_.cend()) { - ++p; - continue; // no EM particle - } - - auto const egs_pid = it->second; + if (it != egs_em_codes_.cend()) { + // EM particle + + auto const egs_pid = it->second; - addParticle(egs_pid, p.GetEnergy(), p.GetMass(), p.GetPosition(), - p.GetMomentum().normalized(), p.GetTime()); + addParticle(egs_pid, p.GetEnergy(), p.GetMass(), p.GetPosition(), + p.GetMomentum().normalized(), p.GetTime()); - p.Delete(); + p.Delete(); + } + ++p; } return corsika::process::EProcessReturn::eOk; diff --git a/Processes/InteractionCounter/testInteractionCounter.cc b/Processes/InteractionCounter/testInteractionCounter.cc index 8b47f1bf67b1a411315d5ac6303cfb5c365583fb..13bf34c1714c0554363b87296cf7f8584fa90127 100644 --- a/Processes/InteractionCounter/testInteractionCounter.cc +++ b/Processes/InteractionCounter/testInteractionCounter.cc @@ -121,8 +121,8 @@ TEST_CASE("InteractionCounter") { SECTION("DoInteraction nucleus") { unsigned short constexpr A = 14, Z = 7; auto [stackPtr, secViewPtr] = setupStack(A, Z, 105_TeV, nodePtr, *csPtr); - REQUIRE(stackPtr->GetSize() == 1); - REQUIRE(secViewPtr->GetSize() == 0); + REQUIRE(stackPtr->getEntries() == 1); + REQUIRE(secViewPtr->getEntries() == 0); auto projectile = secViewPtr->GetProjectile(); auto const ret = countedProcess.DoInteraction(projectile); @@ -141,8 +141,8 @@ TEST_CASE("InteractionCounter") { auto constexpr code = particles::Code::Lambda0; auto constexpr codeInt = static_cast<particles::CodeIntType>(code); auto [stackPtr, secViewPtr] = setupStack(code, 105_TeV, nodePtr, *csPtr); - REQUIRE(stackPtr->GetSize() == 1); - REQUIRE(secViewPtr->GetSize() == 0); + REQUIRE(stackPtr->getEntries() == 1); + REQUIRE(secViewPtr->getEntries() == 0); auto projectile = secViewPtr->GetProjectile(); auto const ret = countedProcess.DoInteraction(projectile); diff --git a/Processes/ParticleCut/ParticleCut.cc b/Processes/ParticleCut/ParticleCut.cc index 1616f6248740d7b8e6f23a8c31405f57fff16eb8..69a0216e22e7e42d9aa89ee68360ec2b3081e0e3 100644 --- a/Processes/ParticleCut/ParticleCut.cc +++ b/Processes/ParticleCut/ParticleCut.cc @@ -95,6 +95,7 @@ namespace corsika::process { } else { ++particle; // next entry in SecondaryView } + ++p; // next entry in SecondaryView } return EProcessReturn::eOk; } diff --git a/Processes/ParticleCut/testParticleCut.cc b/Processes/ParticleCut/testParticleCut.cc index e7647a55d7a1b3884d6672adc42f02757577be38..2ed4c1d1d15c5b1b2bf6954e73231589b6c68149 100644 --- a/Processes/ParticleCut/testParticleCut.cc +++ b/Processes/ParticleCut/testParticleCut.cc @@ -129,6 +129,7 @@ TEST_CASE("ParticleCut", "[processes]") { cut.DoSecondaries(view); - CHECK(view.GetSize() == 0); + REQUIRE(view.getEntries() == 0); + REQUIRE(view.getSize() == 10); } } diff --git a/Processes/Pythia/testPythia8.cc b/Processes/Pythia/testPythia8.cc index f947a8b813fbe20add8fbc869f79313fb527b7f1..680b8cadeb838a4f5e500d273a50b5aef185732c 100644 --- a/Processes/Pythia/testPythia8.cc +++ b/Processes/Pythia/testPythia8.cc @@ -137,7 +137,7 @@ TEST_CASE("pythia process") { [[maybe_unused]] const TimeType time = model.GetLifetime(particle); model.DoDecay(projectile); - CHECK(stack.GetSize() == 3); + CHECK(stack.getEntries() == 3); auto const pSum = sumMomentum(view, cs); CHECK((pSum - plab).norm() / 1_GeV == Approx(0).margin(1e-4)); CHECK((pSum.norm() - plab.norm()) / 1_GeV == Approx(0).margin(1e-4)); diff --git a/Processes/QGSJetII/Interaction.cc b/Processes/QGSJetII/Interaction.cc index c7a2ffc1846e96fdeb4df54bd044ddad33ce834a..4f2f1ca34ecbc6bbcc175040e9e99387f942e1ff 100644 --- a/Processes/QGSJetII/Interaction.cc +++ b/Processes/QGSJetII/Interaction.cc @@ -396,7 +396,7 @@ namespace corsika::process::qgsjetII { << QGSJetIIFragmentsStackData::GetWoundedNucleonsTarget() << ", N_wounded,proj=" << QGSJetIIFragmentsStackData::GetWoundedNucleonsProjectile() - << ", N_fragm,proj=" << qfs.GetSize() << endl; + << ", N_fragm,proj=" << qfs.getEntries() << endl; } return process::EProcessReturn::eOk; } diff --git a/Processes/Sibyll/testSibyll.cc b/Processes/Sibyll/testSibyll.cc index dee7ee31b722aaabdde09e864c0bbfe80d0b36b3..bd7454856560ba6b6bccda22d820faaff311a0a9 100644 --- a/Processes/Sibyll/testSibyll.cc +++ b/Processes/Sibyll/testSibyll.cc @@ -282,7 +282,7 @@ TEST_CASE("SibyllInterface", "[processes]") { // run checks // lambda decays into proton and pi- or neutron and pi+ - CHECK(stack.GetSize() == 3); + CHECK(stack.getEntries() == 3); } SECTION("DecayConfiguration") { diff --git a/Processes/StackInspector/StackInspector.cc b/Processes/StackInspector/StackInspector.cc index af2270ecf32a185f66ae9464acf5885676fb7260..da4a91baafaf6253137956d57297cf198ba238c4 100644 --- a/Processes/StackInspector/StackInspector.cc +++ b/Processes/StackInspector/StackInspector.cc @@ -74,7 +74,7 @@ process::EProcessReturn StackInspector<TStack>::DoStack(const TStack& vS) { << " time=" << std::put_time(std::localtime(&now_time), "%T") << ", running=" << elapsed_seconds.count() << " seconds" << " (" << setw(3) << int(progress * 100) << "%)" - << ", nStep=" << GetStep() << ", stackSize=" << vS.GetSize() + << ", nStep=" << GetStep() << ", stackEntries=" << vS.getEntries() << ", Estack=" << Etot / 1_GeV << " GeV" << ", ETA=" << std::put_time(std::localtime(&eta_time), "%T") << endl; return process::EProcessReturn::eOk; diff --git a/Processes/SwitchProcess/testSwitchProcess.cc b/Processes/SwitchProcess/testSwitchProcess.cc index 0cff57f16fca233f3f75a38e22f006a4759341fe..9ee148e1855edc2b45c81594425e8786e2434d09 100644 --- a/Processes/SwitchProcess/testSwitchProcess.cc +++ b/Processes/SwitchProcess/testSwitchProcess.cc @@ -172,7 +172,7 @@ TEST_CASE("SwitchProcess from InteractionProcess") { InverseGrammageType invLambda = 0 / kgMSq; switchProcess.SelectInteraction(p, projectile, 0.01 / kgMSq, invLambda); - REQUIRE(view.GetSize() == 2); + REQUIRE(view.getSize() == 2); } } } @@ -214,7 +214,7 @@ TEST_CASE("SwitchProcess from ProcessSequence") { InverseGrammageType accumulator = 0 / kgMSq; completeSeq.SelectInteraction(p, projectile, invLambda, accumulator); - numberOfSecondaries.push_back(view.GetSize()); + numberOfSecondaries.push_back(view.getSize()); } auto const mean = @@ -248,7 +248,7 @@ TEST_CASE("SwitchProcess from ProcessSequence") { InverseGrammageType accumulator = 0 / kgMSq; completeSeq.SelectInteraction(p, projectile, invLambda, accumulator); - numberOfSecondaries.push_back(view.GetSize()); + numberOfSecondaries.push_back(view.getSize()); } auto const mean = diff --git a/Processes/UrQMD/testUrQMD.cc b/Processes/UrQMD/testUrQMD.cc index fd947e83f60776d36fe986f0471ec827603e116b..11f11adfd621894c95a50e8ea4cf234ba0ba66c3 100644 --- a/Processes/UrQMD/testUrQMD.cc +++ b/Processes/UrQMD/testUrQMD.cc @@ -146,8 +146,8 @@ TEST_CASE("UrQMD") { for (auto code : validProjectileCodes) { auto [stack, view] = setupStack(code, 100_GeV, nodePtr, cs); - REQUIRE(stack->GetSize() == 1); - REQUIRE(view->GetSize() == 0); + REQUIRE(stack->getEntries() == 1); + REQUIRE(view->getEntries() == 0); // simple check whether the cross-section is non-vanishing // only nuclei with available tabluated data so far @@ -162,8 +162,8 @@ TEST_CASE("UrQMD") { unsigned short constexpr A = 14, Z = 7; auto [stackPtr, secViewPtr] = setupStack(A, Z, 400_GeV, nodePtr, *csPtr); - REQUIRE(stackPtr->GetSize() == 1); - REQUIRE(secViewPtr->GetSize() == 0); + REQUIRE(stackPtr->getEntries() == 1); + REQUIRE(secViewPtr->getEntries() == 0); // must be assigned to variable, cannot be used as rvalue?! auto projectile = secViewPtr->GetProjectile(); @@ -186,8 +186,8 @@ TEST_CASE("UrQMD") { auto [stackPtr, secViewPtr] = setupStack(particles::Code::PiPlus, 400_GeV, nodePtr, *csPtr); - REQUIRE(stackPtr->GetSize() == 1); - REQUIRE(secViewPtr->GetSize() == 0); + REQUIRE(stackPtr->getEntries() == 1); + REQUIRE(secViewPtr->getEntries() == 0); // must be assigned to variable, cannot be used as rvalue?! auto projectile = secViewPtr->GetProjectile(); @@ -212,8 +212,8 @@ TEST_CASE("UrQMD") { auto [stackPtr, secViewPtr] = setupStack(particles::Code::K0Long, 400_GeV, nodePtr, *csPtr); - REQUIRE(stackPtr->GetSize() == 1); - REQUIRE(secViewPtr->GetSize() == 0); + REQUIRE(stackPtr->getEntries() == 1); + REQUIRE(secViewPtr->getEntries() == 0); // must be assigned to variable, cannot be used as rvalue?! auto projectile = secViewPtr->GetProjectile(); diff --git a/Stack/NuclearStackExtension/testNuclearStackExtension.cc b/Stack/NuclearStackExtension/testNuclearStackExtension.cc index fe30f2ce45487b18e2d52a9b616d39720038de51..a29fe580924cf0584950f7bec2115ad248fbd695 100644 --- a/Stack/NuclearStackExtension/testNuclearStackExtension.cc +++ b/Stack/NuclearStackExtension/testNuclearStackExtension.cc @@ -35,7 +35,7 @@ TEST_CASE("NuclearStackExtension", "[stack]") { particles::Code::Electron, 1.5_GeV, corsika::stack::MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}), Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s}); - REQUIRE(s.GetSize() == 1); + REQUIRE(s.getEntries() == 1); } SECTION("write nucleus") { @@ -48,7 +48,7 @@ TEST_CASE("NuclearStackExtension", "[stack]") { particles::Code::Nucleus, 1.5_GeV, corsika::stack::MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}), Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s, 10, 10}); - REQUIRE(s.GetSize() == 1); + REQUIRE(s.getEntries() == 1); } SECTION("write invalid nucleus") { @@ -127,9 +127,9 @@ TEST_CASE("NuclearStackExtension", "[stack]") { } } - REQUIRE(s.GetSize() == 99); + REQUIRE(s.getEntries() == 99); for (int i = 0; i < 99; ++i) s.GetNextParticle().Delete(); - REQUIRE(s.GetSize() == 0); + REQUIRE(s.getEntries() == 0); } SECTION("stack operations") { @@ -224,7 +224,7 @@ TEST_CASE("NuclearStackExtension", "[stack]") { REQUIRE(p59.GetNuclearZ() == 29 / 2); } - for (int i = 0; i < 99; ++i) s.DeleteLast(); - REQUIRE(s.GetSize() == 0); + for (int i = 0; i < 99; ++i) s.last().Delete(); + REQUIRE(s.getEntries() == 0); } } diff --git a/Stack/SuperStupidStack/testSuperStupidStack.cc b/Stack/SuperStupidStack/testSuperStupidStack.cc index da419ed792342ec7c7485caa57d7ee04c5455578..5f50a153f74d68520eced3640f6302433f40a69c 100644 --- a/Stack/SuperStupidStack/testSuperStupidStack.cc +++ b/Stack/SuperStupidStack/testSuperStupidStack.cc @@ -6,6 +6,8 @@ * the license. */ +#define protected public // to also test the internal state of objects + #include <corsika/geometry/RootCoordinateSystem.h> #include <corsika/stack/super_stupid/SuperStupidStack.h> #include <corsika/units/PhysicalUnits.h> @@ -37,7 +39,8 @@ TEST_CASE("SuperStupidStack", "[stack]") { Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s}); // read - CHECK(s.GetSize() == 1); + CHECK(s.getEntries() == 1); + CHECK(s.getSize() == 1); auto pout = s.GetNextParticle(); CHECK(pout.GetPID() == particles::Code::Electron); CHECK(pout.GetEnergy() == 1.5_GeV); @@ -59,10 +62,11 @@ TEST_CASE("SuperStupidStack", "[stack]") { corsika::stack::MomentumVector(dummyCS, {1_GeV, 1_GeV, 1_GeV}), Point(dummyCS, {1 * meter, 1 * meter, 1 * meter}), 100_s}); - CHECK(s.GetSize() == 99); + CHECK(s.getSize() == 99); for (int i = 0; i < 99; ++i) s.GetNextParticle().Delete(); - CHECK(s.GetSize() == 0); + CHECK(s.getEntries() == 0); + CHECK(s.getSize() == 1); } }