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

same multi-q test is used everywhere

parent 01c62a9d
No related branches found
No related tags found
1 merge request!1185MultiQTest: detailed report for worst case only
Pipeline #82882 passed
#include "Base/Const/Units.h"
#include "Sample/HardParticle/HardParticles.h"
#include "Sample/Scattering/Rotations.h"
#include "Tests/Unit/Numeric/MultiQTest.h"
class FormFactorOtherTest : public MultiQTest {};
class FormFactorOtherTest : public testing::Test {};
//*********** cylinders ***************
TEST_F(FormFactorOtherTest, HorizontalCylinderAsCylinder)
{
const double R = .3, L = 3;
Cylinder p0(R, L);
HorizontalCylinder p1(R, L);
test_absEq_at_realQ([&](C3 q) { return p0.formfactor(q); },
[&](C3 q) { return p1.formfactor(q.rotatedY(M_PI / 2)); }, 2e-15, 1e-99,
100);
Cylinder f0(R, L);
HorizontalCylinder f1(R, L);
int failures = formfactorTest::run_test3_for_many_q(
[&](C3 q) -> complex_t { return f0.formfactor(q); },
[&](C3 q) -> complex_t { return f1.formfactor(q.rotatedY(M_PI / 2)); },
1e-99, 100, 2e-15, true);
EXPECT_EQ(failures, 0);
}
TEST_F(FormFactorOtherTest, HorizontalCylinderSlices)
{
const double R = .3, L = 3;
HorizontalCylinder p0(R, L);
HorizontalCylinder p1a(R, L, -R, -0.3 * R);
HorizontalCylinder p1b(R, L, -0.3 * R, +R);
test_complexEq_at_realQ(
[&](C3 q) { return p0.formfactor(q); },
[&](C3 q) { return p1a.formfactor(q) + exp_I(q.z() * 0.7 * R) * p1b.formfactor(q); },
1.2e-3, 1e-99, 100);
HorizontalCylinder f0(R, L);
HorizontalCylinder f1a(R, L, -R, -0.3 * R);
HorizontalCylinder f1b(R, L, -0.3 * R, +R);
int failures = formfactorTest::run_test3_for_many_q(
[&](C3 q) -> complex_t { return f0.formfactor(q); },
[&](C3 q) -> complex_t { return f1a.formfactor(q)
+ exp_I(q.z() * 0.7 * R) * f1b.formfactor(q); },
1e-99, 100, 1.2e-3, true);
EXPECT_EQ(failures, 0);
}
......@@ -16,29 +16,6 @@ const auto qlist = testing::Combine(
testing::Values(-1e-15, +1e-14, -1e-11, 1e-7, -1e-3, .1, 1, sqrt(2), sqrt(3)),
testing::Values(0, -4e-16, +8e-16, -5e-11, 3e-7, -2e-3, .01, .1));
void run_test_for_many_q(std::function<void(C3)> run_one_test, double qmag_min, double qmag_max,
bool real_only)
{
ParamGenerator<std::tuple<C3, C3, double, double, double>> gen = qlist;
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();
run_one_test(q); // callback passed as argument
}
}
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)
{
......
......@@ -10,10 +10,6 @@
namespace formfactorTest {
//! Runs callback function "run_one_test(q)" for a huge number of different vectors q.
void run_test_for_many_q(std::function<void(C3)> run_one_test, double qmag_min, double qmag_max,
bool real_only = false);
//! Runs tests of fff0(q) vs fff1(q) for a huge number of different vectors q.
//! The callback functions fff0/1 may compute ff0(q) vs ff1(q), or ff(q) vs ff(q').
int run_test3_for_many_q(std::function<complex_t(C3)> fff0, std::function<complex_t(C3)> fff1,
......@@ -21,42 +17,4 @@ int run_test3_for_many_q(std::function<complex_t(C3)> fff0, std::function<comple
} // namespace formfactorTest
class MultiQTest : public testing::Test {
protected:
//! Tests whether form factors are almost equal for various real q
void test_complexEq_at_realQ(std::function<complex_t(const C3&)> f0,
std::function<complex_t(const C3&)> f1, double eps, double qmag1,
double qmag2)
{
formfactorTest::run_test_for_many_q([&](C3 q) { complexEq(q, f0(q), f1(q), eps); }, qmag1,
qmag2, true);
}
//! Tests whether absolute values of form factors are almost equal for various real q
void test_absEq_at_realQ(std::function<complex_t(const C3&)> f0,
std::function<complex_t(const C3&)> f1, double eps, double qmag1,
double qmag2)
{
formfactorTest::run_test_for_many_q([&](C3 q) { absEq(q, f0(q), f1(q), eps); }, qmag1,
qmag2, true);
}
private:
//! Tests whether c0 and c1 are almost equal.
//! Parameter q is transmitted for use in error message only.
void complexEq(C3 q, complex_t c0, complex_t c1, double eps)
{
const double avge = (std::abs(c0) + std::abs(c1)) / 2;
const double precision = std::max(1e-16, eps * avge);
EXPECT_NEAR(real(c0), real(c1), precision) << "q=" << q << "\n";
EXPECT_NEAR(imag(c0), imag(c1), precision) << "q=" << q << "\n";
}
void absEq(C3 q, complex_t c0, complex_t c1, double eps)
{
const double avge = (std::abs(c0) + std::abs(c1)) / 2;
const double precision = std::max(1e-16, eps * avge);
EXPECT_NEAR(abs(c0), abs(c1), precision) << "q=" << q << "\n";
}
};
#endif // BORNAGAIN_TESTS_UNIT_NUMERIC_MULTIQTEST_H
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