From 0fddbe18ffc147aa8d9ab67dc3501ef3f38a5b09 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (l)" <j.wuttke@fz-juelich.de>
Date: Wed, 30 Dec 2020 21:12:35 +0100
Subject: [PATCH] + Polygon test

---
 Sample/HardParticle/PolyhedralComponents.cpp  | 15 +++++--
 Sample/HardParticle/PolyhedralComponents.h    |  2 +
 .../Numeric/FormFactorTriangleTest.cpp        | 41 +++++++++++++++++++
 auto/Wrap/doxygenSample.i                     |  6 +++
 4 files changed, 61 insertions(+), 3 deletions(-)
 create mode 100644 Tests/UnitTests/Numeric/FormFactorTriangleTest.cpp

diff --git a/Sample/HardParticle/PolyhedralComponents.cpp b/Sample/HardParticle/PolyhedralComponents.cpp
index 6c19b2b83df..78319c48525 100644
--- a/Sample/HardParticle/PolyhedralComponents.cpp
+++ b/Sample/HardParticle/PolyhedralComponents.cpp
@@ -371,11 +371,10 @@ complex_t PolyhedralFace::ff_2D(cvector_t qpa) const
         return m_area;
     } else if (qpa_red < qpa_limit_series && !sym_S2) {
         // summation of power series
-        return m_area + expansion(1., 1., qpa, std::abs(m_area));
+        return ff_2D_expanded(qpa);
     } else {
         // direct evaluation of analytic formula
-        complex_t ff = edge_sum_ff(qpa, qpa, false);
-        complex_t ret = (sym_S2 ? 4. : 2. / I) * ff / qpa.mag2();
+        complex_t ret = ff_2D_direct(qpa);
 #ifdef POLYHEDRAL_DIAGNOSTIC
         if (diagnosis.debmsg >= 2)
             std::cout << std::setprecision(16) << "    ret=" << ret << " ff=" << ff << "\n";
@@ -384,6 +383,16 @@ complex_t PolyhedralFace::ff_2D(cvector_t qpa) const
     }
 }
 
+complex_t PolyhedralFace::ff_2D_direct(cvector_t qpa) const
+{
+    return (sym_S2 ? 4. : 2. / I) * edge_sum_ff(qpa, qpa, false) / qpa.mag2();
+}
+
+complex_t PolyhedralFace::ff_2D_expanded(cvector_t qpa) const
+{
+    return m_area + expansion(1., 1., qpa, std::abs(m_area));
+}
+
 //! Throws if deviation from inversion symmetry is detected. Does not check vertices.
 
 void PolyhedralFace::assert_Ci(const PolyhedralFace& other) const
diff --git a/Sample/HardParticle/PolyhedralComponents.h b/Sample/HardParticle/PolyhedralComponents.h
index 2010db55984..5ea62d689b9 100644
--- a/Sample/HardParticle/PolyhedralComponents.h
+++ b/Sample/HardParticle/PolyhedralComponents.h
@@ -61,6 +61,8 @@ public:
     complex_t ff_n(int m, cvector_t q) const;
     complex_t ff(cvector_t q, bool sym_Ci) const;
     complex_t ff_2D(cvector_t qpa) const;
+    complex_t ff_2D_direct(cvector_t qpa) const; // for TestTriangle
+    complex_t ff_2D_expanded(cvector_t qpa) const; // for TestTriangle
     void assert_Ci(const PolyhedralFace& other) const;
 
 private:
diff --git a/Tests/UnitTests/Numeric/FormFactorTriangleTest.cpp b/Tests/UnitTests/Numeric/FormFactorTriangleTest.cpp
new file mode 100644
index 00000000000..351ba370d77
--- /dev/null
+++ b/Tests/UnitTests/Numeric/FormFactorTriangleTest.cpp
@@ -0,0 +1,41 @@
+#include "Base/Math/Constants.h"
+#include "Sample/HardParticle/PolyhedralComponents.h"
+#include "Tests/GTestWrapper/google_test.h"
+//#include "Tests/UnitTests/Numeric/FormFactorTest.h"
+#include <cstdio>
+
+//! Ad-hoc code for manuscript ffp - JWu dec20
+
+class FFTriangleTest : public ::testing::Test {};
+
+TEST_F(FFTriangleTest, Triangle)
+{
+    const double a = 1.;
+    const double as = a / 2;
+    const double ac = a / sqrt(3) / 2;
+    const double ah = a / sqrt(3);
+    const std::vector<kvector_t> V{{-ac, as, 0.}, {-ac, -as, 0.}, {ah, 0., 0.}};
+
+    const PolyhedralFace T(V, false);
+    EXPECT_NEAR(T.area(), sqrt(3)/4, 1e-15);
+
+    int failures = 0;
+    const int M=43;
+    for (int j=0; j < M; ++j) {
+        const double phi = M_PI_2*j/(M-1);
+        const cvector_t uQ{ sin(phi), cos(phi), 0. };
+        const int N=4000+j;
+        for (int i = 0; i < N; ++i) {
+            const double q = 1e-17*pow(1.7e17,i/(N-1.));
+            const cvector_t Q = uQ * q;
+            const double f1 = std::abs(T.ff_2D_direct(Q));
+            const double f2 = std::abs(T.ff_2D_expanded(Q));
+            const double relerr = std::abs(f1-f2)/f2;
+            if (relerr>7e-16) {
+                printf("%9.6f %16.11e %21.16e %21.16e %10.4e\n", phi, q, f1, f2, relerr);
+                ++failures;
+            }
+        }
+    }
+    EXPECT_EQ(failures, 0);
+}
diff --git a/auto/Wrap/doxygenSample.i b/auto/Wrap/doxygenSample.i
index 0b64464531d..c2e7db6d11c 100644
--- a/auto/Wrap/doxygenSample.i
+++ b/auto/Wrap/doxygenSample.i
@@ -6262,6 +6262,12 @@ Returns the contribution ff(q) of this face to the polyhedral form factor.
 Returns the two-dimensional form factor of this face, for use in a prism. 
 ";
 
+%feature("docstring")  PolyhedralFace::ff_2D_direct "complex_t PolyhedralFace::ff_2D_direct(cvector_t qpa) const
+";
+
+%feature("docstring")  PolyhedralFace::ff_2D_expanded "complex_t PolyhedralFace::ff_2D_expanded(cvector_t qpa) const
+";
+
 %feature("docstring")  PolyhedralFace::assert_Ci "void PolyhedralFace::assert_Ci(const PolyhedralFace &other) const
 
 Throws if deviation from inversion symmetry is detected. Does not check vertices. 
-- 
GitLab