From 8c4d946ce3393c11284c6614967e3c71003df41c Mon Sep 17 00:00:00 2001
From: Jochem Snuverink <jochem.snuverink@psi.ch>
Date: Tue, 4 Feb 2020 19:58:28 +0100
Subject: [PATCH] Resolve "Make
 `src/Classic/Solvers/GreenWakeFunction::testApply()` a unit test"

---
 src/Classic/Solvers/GreenWakeFunction.cpp     | 84 -------------------
 src/Classic/Solvers/GreenWakeFunction.hh      | 11 ++-
 tests/classic_src/CMakeLists.txt              |  8 +-
 tests/classic_src/Solvers/CMakeLists.txt      | 17 ++++
 .../Solvers/GreenWakeFunctionTest.cpp         | 75 +++++++++++++++++
 .../classic_src}/Solvers/TestLambda.h         |  0
 6 files changed, 103 insertions(+), 92 deletions(-)
 create mode 100644 tests/classic_src/Solvers/CMakeLists.txt
 create mode 100644 tests/classic_src/Solvers/GreenWakeFunctionTest.cpp
 rename {src/Classic => tests/classic_src}/Solvers/TestLambda.h (100%)

diff --git a/src/Classic/Solvers/GreenWakeFunction.cpp b/src/Classic/Solvers/GreenWakeFunction.cpp
index 2fceb5237..5753f800d 100644
--- a/src/Classic/Solvers/GreenWakeFunction.cpp
+++ b/src/Classic/Solvers/GreenWakeFunction.cpp
@@ -2,11 +2,6 @@
 #include "Algorithms/PartBunchBase.h"
 #include "Utilities/GeneralClassicException.h"
 
-// :FIXME: do we need this tests?
-#ifdef ENABLE_WAKE_TESTS
-#include "Solvers/TestLambda.h" // used for tests
-#endif
-
 #include <fstream>
 #include <string>
 #include <vector>
@@ -21,10 +16,7 @@ using namespace std;
 //IFF: TEST
 //#define ENABLE_WAKE_DEBUG
 //#define ENABLE_WAKE_DUMP
-//#define ENABLE_WAKE_TESTS
 //#define ENABLE_WAKE_TESTS_FFT_OUT
-//#define readWakeFromFile
-//#define WakeFile "test.sdds"
 
 
 /**
@@ -110,10 +102,6 @@ pair<int, int> GreenWakeFunction::distrIndices(int vectLen) {
 }
 
 void GreenWakeFunction::apply(PartBunchBase<double, 3> *bunch) {
-#ifdef ENABLE_WAKE_TESTS
-    // overwrite the line density
-    testApply(bunch);
-#else
 
     Vector_t rmin, rmax;
     double charge = bunch->getChargePerParticle();
@@ -236,51 +224,7 @@ void GreenWakeFunction::apply(PartBunchBase<double, 3> *bunch) {
     f2.flush();
     f2.close();
 #endif
-
-#endif //ENABLE_WAKE_TESTS
-}
-
-/**
- * @brief   Just a test function
- */
-#ifdef ENABLE_WAKE_TESTS
-void GreenWakeFunction::testApply(PartBunchBase<double, 3> *bunch) {
-    double spacing;
-    // determine K and charge
-    double charge = 0.8e-9; // nC
-    double K = 0.20536314319923724e-9; //K normalizes nC data in lambda.h?
-    spacing = 1e-6; //IFF: charge in testLambda.h in 1um spacings
-    NBin_m = 294;
-    std::vector<double> OutEnergy(NBin_m);
-
-    if(FftWField_m.empty()) {
-        FftWField_m.resize(2*NBin_m - 1);
-        CalcWakeFFT(spacing);
-    } else if(!constLength_m) {
-        CalcWakeFFT(spacing);
-    }
-
-    compEnergy(K, charge, testLambda, OutEnergy.data());
-
-    ofstream  f2("OutEnergy.dat");
-    f2 << "# Energy of the Wake calculated in Opal\n"
-       << "# Z0 = " << Z0_m << "\n"
-       << "# radius = " << radius_m << "\n"
-       << "# sigma = " << sigma_m << "\n"
-       << "# acMode = " << acMode_m << "\n"
-       << "# tau = " << tau_m << "\n"
-       << "# direction = " << direction_m << "\n"
-       << "# spacing = " << spacing_m << "\n"
-       << "# Lbunch = " << NBin_m << "\n";
-    for(int i = 0; i < NBin_m; i++) {
-        f2 << i + 1 << " " << OutEnergy[i] << "\n";
-    }
-    f2.flush();
-    f2.close();
 }
-#else
-void GreenWakeFunction::testApply(PartBunchBase<double, 3> *) {}
-#endif
 
 /**
  * @brief   just a Testfunction!  Calculate the energy of the Wakefunction with the lambda
@@ -421,23 +365,6 @@ void GreenWakeFunction::CalcWakeFFT(double spacing) {
     const int lowIndex = myDist.first;
     const int hiIndex  = myDist.second;
 
-#ifdef ENABLE_WAKE_TESTS
-    ofstream file;
-
-    if(Ippl::myNode() == 0) {
-        file.open("wake.dat");
-        file << "# Wake calculated in Opal" << "\n"
-             << "# Z0 = " << Z0_m << "\n"
-             << "# radius = " << radius_m << "\n"
-             << "# sigma = " << sigma_m << "\n"
-             << "# mode = " << acMode_m << "\n"
-             << "# tau = " << tau_m << "\n"
-             << "# direction = " << direction_m << "\n"
-             << "# spacing = " << spacing << "\n"
-             << "# Lbunch = " << NBin_m << "\n";
-    }
-#endif
-
     for(int i = 0; i < M; i ++) {
         FftWField_m[i] = 0.0;
     }
@@ -464,17 +391,6 @@ void GreenWakeFunction::CalcWakeFFT(double spacing) {
       */
     reduce(&(FftWField_m[0]), &(FftWField_m[0]) + NBin_m, &(FftWField_m[0]), OpAddAssign());
 
-
-#ifdef ENABLE_WAKE_TESTS
-    if(Ippl::myNode() == 0) {
-        for(int i = 0; i < NBin_m; i++) {
-            file << i + 1 << "   " << FftWField_m[i] << "\n";
-        }
-        file.flush();
-        file.close();
-    }
-#endif
-
 #ifdef ENABLE_WAKE_TESTS_FFT_OUT
     std::vector<double> wf(2*NBin_m-1);
     for(int i = 0; i < 2 * NBin_m - 1; ++ i) {
diff --git a/src/Classic/Solvers/GreenWakeFunction.hh b/src/Classic/Solvers/GreenWakeFunction.hh
index 44fdda51e..a9bac2b33 100644
--- a/src/Classic/Solvers/GreenWakeFunction.hh
+++ b/src/Classic/Solvers/GreenWakeFunction.hh
@@ -12,13 +12,13 @@
 #include <string>
 #include <complex>
 
-//#define USE_FFTW
+#ifdef WITH_UNIT_TESTS
+#include <gtest/gtest_prod.h>
+#endif
 
 enum { TRANSVERSAL, LONGITUDINAL };
 typedef std::map<std::string, int> FilterOptions;
 
-class SavitzkyGolayFilter;
-
 class GreenWakeFunction: public WakeFunction {
 public:
     ~GreenWakeFunction();
@@ -44,6 +44,10 @@ public:
     virtual const std::string getType() const;
 
 private:
+#ifdef WITH_UNIT_TESTS
+    FRIEND_TEST(GreenWakeFunctionTest, TestApply);
+#endif
+
     class Wake {
 
     public:
@@ -164,7 +168,6 @@ private:
 
     std::vector<Filter *> filters_m;
 
-    void testApply(PartBunchBase<double, 3> *bunch);
     void compEnergy(const double K, const double charge, const double *lambda, double *OutEnergy);
     void compEnergy(const double K, const double charge, std::vector<double> lambda, double *OutEnergy);
     void CalcWakeFFT(double spacing);
diff --git a/tests/classic_src/CMakeLists.txt b/tests/classic_src/CMakeLists.txt
index 55f65940e..c025c9673 100644
--- a/tests/classic_src/CMakeLists.txt
+++ b/tests/classic_src/CMakeLists.txt
@@ -1,15 +1,15 @@
 add_subdirectory (AbsBeamline)
 add_subdirectory (Algorithms)
-add_subdirectory (Utilities)
 add_subdirectory (Fields)
-
+add_subdirectory (Solvers)
+add_subdirectory (Utilities)
 
 set (TEST_SRCS_LOCAL ${TEST_SRCS_LOCAL} PARENT_SCOPE)
 
 # vi: set et ts=4 sw=4 sts=4:
-  
+
 # Local Variables:
 # mode: cmake
 # cmake-tab-width: 4
 # indent-tabs-mode: nil
-# End:
+# End:
\ No newline at end of file
diff --git a/tests/classic_src/Solvers/CMakeLists.txt b/tests/classic_src/Solvers/CMakeLists.txt
new file mode 100644
index 000000000..65fdb1eb4
--- /dev/null
+++ b/tests/classic_src/Solvers/CMakeLists.txt
@@ -0,0 +1,17 @@
+set (_SRCS
+    GreenWakeFunctionTest.cpp
+)
+
+include_directories (
+  ${CMAKE_CURRENT_SOURCE_DIR}
+)
+
+add_sources(${_SRCS})
+
+# vi: set et ts=4 sw=4 sts=4:
+
+# Local Variables:
+# mode: cmake
+# cmake-tab-width: 4
+# indent-tabs-mode: nil
+# End:
\ No newline at end of file
diff --git a/tests/classic_src/Solvers/GreenWakeFunctionTest.cpp b/tests/classic_src/Solvers/GreenWakeFunctionTest.cpp
new file mode 100644
index 000000000..e6b4a98dd
--- /dev/null
+++ b/tests/classic_src/Solvers/GreenWakeFunctionTest.cpp
@@ -0,0 +1,75 @@
+#include "gtest/gtest.h"
+
+#include "opal_test_utilities/SilenceTest.h"
+
+#include "Solvers/GreenWakeFunction.hh"
+
+#include "TestLambda.h" // Profile of the bunch
+
+#include <iostream>
+
+TEST(GreenWakeFunctionTest, TestApply)
+{
+    OpalTestUtilities::SilenceTest silencer;
+
+    // wake types with green wake function
+    std::vector<std::string> types      = {"LONG-SHORT-RANGE", "TRANSV-SHORT-RANGE"};
+    std::vector<int> acmodes = {1, 2}; // 1: ac, 2: dc
+    std::vector<Filter *> filters;
+    // not sure if values are realistic, but couldn't find code example
+    double Z0     = 1e3;
+    int nbin      = 100;
+    double radius = 0.1;
+    double sigma  = 1;
+    double tau    = 1;
+    bool const_length = true;
+    std::string fname = "";
+
+    std::vector<double> finalWakeValues   = {1.61757e+10,  2.78525e+19};
+    std::vector<double> finalEnergyValues = {-0.00125303, -2.15739e+06};
+    std::vector<double> relativeErrorWake   = {1e+6, 1e+15};
+    std::vector<double> relativeErrorEnergy = {1e-7, 1e+2};
+
+    for (int acmode : acmodes) {
+        GreenWakeFunction gwf("opal", nullptr, filters, nbin, Z0, radius, sigma, acmode, tau, 0, const_length, fname);
+
+        double spacing = 1e-6; //IFF: charge in testLambda.h in 1um spacings
+        // determine K and charge
+        double charge = 0.8e-9; // nC
+        double K = 0.20536314319923724e-9; //K normalizes nC data in lambda.h?
+        gwf.NBin_m = 294;
+
+        std::cout << "# Z0 = "        << gwf.Z0_m        << std::endl
+                  << "# radius = "    << gwf.radius_m    << std::endl
+                  << "# sigma = "     << gwf.sigma_m     << std::endl
+                  << "# acMode = "    << gwf.acMode_m    << std::endl
+                  << "# tau = "       << gwf.tau_m       << std::endl
+                  << "# direction = " << gwf.direction_m << std::endl
+                  << "# spacing = "   << spacing         << std::endl
+                  << "# Lbunch = "    << gwf.NBin_m      << std::endl;
+
+        if(gwf.FftWField_m.empty()) {
+            gwf.FftWField_m.resize(2*gwf.NBin_m - 1);
+            gwf.CalcWakeFFT(spacing);
+        } else if(!gwf.constLength_m) {
+            gwf.CalcWakeFFT(spacing);
+        }
+
+        std::cout << "# Wake calculated in Opal" << std::endl;
+        for(int i = 0; i < gwf.NBin_m; i++) {
+            std::cout << i + 1 << "   " << gwf.FftWField_m[i] << std::endl;
+        }
+
+        std::vector<double> OutEnergy(gwf.NBin_m);
+        gwf.compEnergy(K, charge, testLambda, OutEnergy.data());
+
+        std::cout << "# Energy of the Wake calculated in Opal\n";
+
+        for(int i = 0; i < gwf.NBin_m; i++) {
+            std::cout << i + 1 << " " << OutEnergy[i] << std::endl;
+        }
+
+        EXPECT_NEAR(gwf.FftWField_m[gwf.NBin_m-1],   finalWakeValues[acmode-1], relativeErrorWake[acmode-1]);
+        EXPECT_NEAR(      OutEnergy[gwf.NBin_m-1], finalEnergyValues[acmode-1], relativeErrorEnergy[acmode-1]);
+    }
+}
\ No newline at end of file
diff --git a/src/Classic/Solvers/TestLambda.h b/tests/classic_src/Solvers/TestLambda.h
similarity index 100%
rename from src/Classic/Solvers/TestLambda.h
rename to tests/classic_src/Solvers/TestLambda.h
-- 
GitLab