From 212176621f67da274819011babd65fb32a0a979b Mon Sep 17 00:00:00 2001
From: ralfulrich <ralf.ulrich@kit.edu>
Date: Sun, 7 Apr 2019 18:05:48 +0200
Subject: [PATCH] make StackInspector a StackProcess, add tests, adapt examples

---
 Documentation/Examples/cascade_example.cc     |  2 +-
 Framework/Cascade/testCascade.cc              |  2 +-
 Framework/ProcessSequence/ProcessSequence.h   | 17 +++++++--
 Framework/ProcessSequence/StackProcess.h      | 20 ++++++++++-
 .../ProcessSequence/testProcessSequence.cc    | 35 +++++++++++++++++++
 Processes/StackInspector/StackInspector.cc    |  5 +--
 Processes/StackInspector/StackInspector.h     |  2 +-
 .../StackInspector/testStackInspector.cc      |  2 +-
 8 files changed, 76 insertions(+), 9 deletions(-)

diff --git a/Documentation/Examples/cascade_example.cc b/Documentation/Examples/cascade_example.cc
index 66b1aa0b7..269ee60c3 100644
--- a/Documentation/Examples/cascade_example.cc
+++ b/Documentation/Examples/cascade_example.cc
@@ -274,7 +274,7 @@ int main() {
 
   // setup processes, decays and interactions
   tracking_line::TrackingLine tracking;
-  stack_inspector::StackInspector<setup::Stack> stackInspect(true);
+  stack_inspector::StackInspector<setup::Stack> stackInspect(1, true);
 
   const std::vector<particles::Code> trackedHadrons = {
       particles::Code::PiPlus, particles::Code::PiMinus, particles::Code::KPlus,
diff --git a/Framework/Cascade/testCascade.cc b/Framework/Cascade/testCascade.cc
index 3f95c7a3a..89fd65ef4 100644
--- a/Framework/Cascade/testCascade.cc
+++ b/Framework/Cascade/testCascade.cc
@@ -138,7 +138,7 @@ TEST_CASE("Cascade", "[Cascade]") {
   auto env = MakeDummyEnv();
   tracking_line::TrackingLine tracking;
 
-  stack_inspector::StackInspector<TestCascadeStack> stackInspect(true);
+  stack_inspector::StackInspector<TestCascadeStack> stackInspect(1, true);
   null_model::NullModel nullModel;
 
   const GrammageType X0 = 20_g / square(1_cm);
diff --git a/Framework/ProcessSequence/ProcessSequence.h b/Framework/ProcessSequence/ProcessSequence.h
index ee154d8ae..3bd759c04 100644
--- a/Framework/ProcessSequence/ProcessSequence.h
+++ b/Framework/ProcessSequence/ProcessSequence.h
@@ -119,16 +119,29 @@ namespace corsika::process {
       return ret;
     }
 
+    bool CheckStep() {
+      bool ret = false;
+      if constexpr (std::is_base_of<StackProcess<T1type>, T1type>::value ||
+                    is_process_sequence<T1>::value) {
+        ret |= A.CheckStep();
+      }
+      if constexpr (std::is_base_of<StackProcess<T2type>, T2type>::value ||
+                    is_process_sequence<T2>::value) {
+        ret |= B.CheckStep();
+      }
+      return ret;
+    }
+
     template <typename TStack>
     EProcessReturn DoStack(TStack& vS) {
       EProcessReturn ret = EProcessReturn::eOk;
       if constexpr (std::is_base_of<StackProcess<T1type>, T1type>::value ||
                     is_process_sequence<T1>::value) {
-        ret |= A.DoStack(vS);
+        if (A.CheckStep()) { ret |= A.DoStack(vS); }
       }
       if constexpr (std::is_base_of<StackProcess<T2type>, T2type>::value ||
                     is_process_sequence<T2>::value) {
-        ret |= B.DoStack(vS);
+        if (B.CheckStep()) { ret |= B.DoStack(vS); }
       }
       return ret;
     }
diff --git a/Framework/ProcessSequence/StackProcess.h b/Framework/ProcessSequence/StackProcess.h
index 0b8775d71..1458fa75c 100644
--- a/Framework/ProcessSequence/StackProcess.h
+++ b/Framework/ProcessSequence/StackProcess.h
@@ -28,7 +28,12 @@ namespace corsika::process {
    */
 
   template <typename derived>
-  struct StackProcess {
+  class StackProcess {
+
+  public:
+    StackProcess() = delete;
+    StackProcess(const unsigned int nStep)
+        : fNStep(nStep) {}
 
     derived& GetRef() { return static_cast<derived&>(*this); }
     const derived& GetRef() const { return static_cast<const derived&>(*this); }
@@ -37,6 +42,19 @@ namespace corsika::process {
     // -> enforce derived to implement DoStack...
     template <typename TStack>
     inline EProcessReturn DoStack(TStack&);
+
+    bool CheckStep() { return !((++fIStep) % fNStep); }
+
+  private:
+    /**
+       @name The number of "steps" during the cascade processing after
+       which this StackProcess is going to be executed. The logic is
+       "fIStep modulo fNStep"
+       @{
+     */
+    unsigned int fNStep = 0;
+    unsigned long int fIStep = 0;
+    //! @}
   };
 
   // overwrite the default trait class, to mark BaseProcess<T> as useful process
diff --git a/Framework/ProcessSequence/testProcessSequence.cc b/Framework/ProcessSequence/testProcessSequence.cc
index 583c6a1ad..aa78ee89c 100644
--- a/Framework/ProcessSequence/testProcessSequence.cc
+++ b/Framework/ProcessSequence/testProcessSequence.cc
@@ -174,6 +174,21 @@ public:
   }
 };
 
+class Stack1 : public StackProcess<Stack1> {
+  int fCount = 0;
+
+public:
+  Stack1(const int n)
+      : StackProcess(n) {}
+  template <typename TStack>
+  EProcessReturn DoStack(TStack&) {
+    fCount++;
+    return EProcessReturn::eOk;
+  }
+  int GetCount() const { return fCount; }
+};
+
+struct DummyStack {};
 struct DummyData {
   double p[nData] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
 };
@@ -257,4 +272,24 @@ TEST_CASE("Process Sequence", "[Process Sequence]") {
     }
     cout << "done" << endl;
   }
+
+  SECTION("StackProcess") {
+
+    ContinuousProcess1 cp1(0);
+    ContinuousProcess2 cp2(3);
+    Process2 m2(1);
+    Process3 m3(2);
+    Stack1 s1(1);
+    Stack1 s2(2);
+
+    auto sequence = s1 << s2;
+
+    DummyStack stack;
+
+    const int nLoop = 20;
+    for (int i = 0; i < nLoop; ++i) { sequence.DoStack(stack); }
+
+    CHECK(s1.GetCount() == 20);
+    CHECK(s2.GetCount() == 10);
+  }
 }
diff --git a/Processes/StackInspector/StackInspector.cc b/Processes/StackInspector/StackInspector.cc
index f192926ca..6917b1239 100644
--- a/Processes/StackInspector/StackInspector.cc
+++ b/Processes/StackInspector/StackInspector.cc
@@ -28,8 +28,9 @@ using namespace corsika::units::si;
 using namespace corsika::process::stack_inspector;
 
 template <typename Stack>
-StackInspector<Stack>::StackInspector(const bool aReport)
-    : fReport(aReport)
+StackInspector<Stack>::StackInspector(const int nStep, const bool aReport)
+    : StackProcess<StackInspector<Stack>>(nStep)
+    , fReport(aReport)
     , fCountStep(0) {}
 
 template <typename Stack>
diff --git a/Processes/StackInspector/StackInspector.h b/Processes/StackInspector/StackInspector.h
index 4674a591b..6eb70c709 100644
--- a/Processes/StackInspector/StackInspector.h
+++ b/Processes/StackInspector/StackInspector.h
@@ -26,7 +26,7 @@ namespace corsika::process {
       typedef typename Stack::ParticleType Particle;
 
     public:
-      StackInspector(const bool aReport);
+      StackInspector(const int nStep, const bool aReport);
       ~StackInspector();
 
       void Init();
diff --git a/Processes/StackInspector/testStackInspector.cc b/Processes/StackInspector/testStackInspector.cc
index d1cc10739..832bea00a 100644
--- a/Processes/StackInspector/testStackInspector.cc
+++ b/Processes/StackInspector/testStackInspector.cc
@@ -50,7 +50,7 @@ TEST_CASE("StackInspector", "[processes]") {
 
   SECTION("interface") {
 
-    StackInspector<TestCascadeStack> model(true);
+    StackInspector<TestCascadeStack> model(1, true);
 
     model.Init();
     [[maybe_unused]] const process::EProcessReturn ret = model.DoStack(stack);
-- 
GitLab