From 7d035ec0589121d12a49d09e1e382137a0a9359d Mon Sep 17 00:00:00 2001 From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de> Date: Sun, 11 Dec 2022 19:26:37 +0100 Subject: [PATCH] further generalization of test function pass functions q->ff instead of q's or ff's --- Tests/Unit/Numeric/FormFactorSymmetryTest.cpp | 29 +--------- Tests/Unit/Numeric/MultiQTest.cpp | 58 +++++++++++++++++++ Tests/Unit/Numeric/MultiQTest.h | 3 + 3 files changed, 64 insertions(+), 26 deletions(-) diff --git a/Tests/Unit/Numeric/FormFactorSymmetryTest.cpp b/Tests/Unit/Numeric/FormFactorSymmetryTest.cpp index c5f5f861af1..5b2f86905f7 100644 --- a/Tests/Unit/Numeric/FormFactorSymmetryTest.cpp +++ b/Tests/Unit/Numeric/FormFactorSymmetryTest.cpp @@ -11,35 +11,12 @@ protected: void run_test(IFormFactor* ff, std::function<C3(const C3&)> trafo, double eps, double qmag1, double qmag2) { - int failures = formfactorTest::run_test2_for_many_q( - [&](C3 q, bool report) -> double { return test_qq_eq(ff, q, trafo(q), eps, report); }, + int failures = formfactorTest::run_test3_for_many_q( + [&](C3 q) -> complex_t { return ff->formfactor(q); }, + [&](C3 q) -> complex_t { return ff->formfactor(trafo(q)); }, qmag1, qmag2, eps); EXPECT_EQ(failures, 0); } - -private: - double test_qq_eq(IFormFactor* ff, C3 q, C3 p, double eps, bool report) - { - complex_t f0 = ff->formfactor(q); -#ifdef ALGORITHM_DIAGNOSTIC - std::string msg0 = polyhedralDiagnosis.message(); -#endif - const complex_t f1 = ff->formfactor(p); - const double avge = (std::abs(f0) + std::abs(f1)) / 2; - const double abserr = std::max(fabs(real(f0) - real(f1)), fabs(imag(f0) - imag(f1))); - const double result = abserr / avge * std::min(1., eps * avge / 1e-16); - if (report) { - std::cout << "Deviation of q0 = " << q << "\n"; - std::cout << " and q1 = " << p << ":\n"; - std::cout << " Re(f0) = " << std::setprecision(16) << real(f0) - << ", Im(f0) = " << imag(f0) << "\n"; - std::cout << " Re(f1) = " << real(f1) << ", Im(f1) = " << imag(f1) << "\n"; - std::cout << " abs dev = " << std::setprecision(8) << abserr - << ", rel dev = " << abserr / avge << ", score = " << result - << ", limit = " << eps << "\n"; - } - return result; - } }; //*********** polyhedra *************** diff --git a/Tests/Unit/Numeric/MultiQTest.cpp b/Tests/Unit/Numeric/MultiQTest.cpp index 61cc6aa0769..05c0a411a15 100644 --- a/Tests/Unit/Numeric/MultiQTest.cpp +++ b/Tests/Unit/Numeric/MultiQTest.cpp @@ -75,4 +75,62 @@ int run_test2_for_many_q(std::function<double(C3, bool)> run_one_test, double qm return failures; } +int run_test3_for_many_q(std::function<complex_t(C3)> fff0, std::function<complex_t(C3)> fff1, + double qmag_min, double qmag_max, double eps, bool real_only) +{ + auto evaluate = [&](C3 q) -> std::tuple<complex_t, complex_t, double, double, double> { + const complex_t f0 = fff0(q); + const complex_t f1 = fff1(q); + const double avge = (std::abs(f0) + std::abs(f1)) / 2; + const double abserr = real_only ? + std::abs(f0) - std::abs(f1) + : std::max(fabs(real(f0) - real(f1)), fabs(imag(f0) - imag(f1))); + const double deviation = abserr / avge * std::min(1., eps * avge / 1e-16); + return { f0, f1, avge, abserr, deviation }; + }; + + ParamGenerator<std::tuple<C3, C3, double, double, double>> gen = qlist; + double max_deviation = 0; + C3 q_at_max; + int failures = 0; + for (auto it : gen) { + const C3 q_maindir = std::get<0>(it); + const C3 q_sidedir = std::get<1>(it); + const double qrealmag = std::get<2>(it); + const double qsidemag = std::get<3>(it); + const double qimagrel = std::get<4>(it); + if (real_only && qimagrel) + continue; + const complex_t qmag(qrealmag, qrealmag * qimagrel); + if (std::abs(qmag) <= qmag_min || std::abs(qmag) >= qmag_max) + continue; + if (q_maindir == q_sidedir) + continue; + const C3 q = qmag * (q_maindir + qsidemag * q_sidedir).unit(); + + const auto [f0, f1, avge, abserr, deviation] = evaluate(q); + + if (deviation > eps) { + ++failures; + if (deviation > max_deviation) { + max_deviation = deviation; + q_at_max = q; + } + } + } + + if (failures) { + const auto [f0, f1, avge, abserr, deviation] = evaluate(q_at_max); + std::cout << "Deviation at q = " << q_at_max << ":\n"; + std::cout << " Re(f0) = " << std::setprecision(16) << real(f0) + << ", Im(f0) = " << imag(f0) << "\n"; + std::cout << " Re(f1) = " << real(f1) << ", Im(f1) = " << imag(f1) << "\n"; + std::cout << " abs dev = " << std::setprecision(8) << abserr + << ", rel dev = " << abserr / avge << ", score = " << deviation + << ", limit = " << eps << "\n"; + } + + return failures; +} + } // namespace formfactorTest diff --git a/Tests/Unit/Numeric/MultiQTest.h b/Tests/Unit/Numeric/MultiQTest.h index 152d2999a87..d22a3e24f72 100644 --- a/Tests/Unit/Numeric/MultiQTest.h +++ b/Tests/Unit/Numeric/MultiQTest.h @@ -18,6 +18,9 @@ void run_test_for_many_q(std::function<void(C3)> run_one_test, double qmag_min, int run_test2_for_many_q(std::function<double(C3, bool)> run_one_test, double qmag_min, double qmag_max, double eps, bool real_only = false); +int run_test3_for_many_q(std::function<complex_t(C3)> fff0, std::function<complex_t(C3)> fff1, + double qmag_min, double qmag_max, double eps, bool real_only = false); + } // namespace formfactorTest -- GitLab