Skip to content
Snippets Groups Projects
Commit 7d035ec0 authored by Wuttke, Joachim's avatar Wuttke, Joachim
Browse files

further generalization of test function

pass functions q->ff instead of q's or ff's
parent 81ba1bf0
No related branches found
No related tags found
1 merge request!1185MultiQTest: detailed report for worst case only
......@@ -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 ***************
......
......@@ -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
......@@ -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
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment