21#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
37TEST_CASE(
"PolynomialSquaredNorm<2> with 2 rows (P1)")
39 Eigen::ArrayXXd theta(2, 3);
40 theta << 1.0, 2.0, 3.0,
44 auto result = PolynomialSquaredNorm<2>(theta);
51TEST_CASE(
"PolynomialSquaredNorm<2> with 3 rows (P2)")
53 Eigen::ArrayXXd theta(3, 2);
58 auto result = PolynomialSquaredNorm<2>(theta);
60 CHECK(
result(0) == doctest::Approx(4.0 + 9.0 * 0.5 + 25.0));
64TEST_CASE(
"PolynomialSquaredNorm<2> with 4 rows (P3)")
66 Eigen::ArrayXXd theta(4, 1);
67 theta << 1.0, 2.0, 3.0, 4.0;
69 auto result = PolynomialSquaredNorm<2>(theta);
71 CHECK(
result(0) == doctest::Approx(1.0 + 4.0 / 3.0 + 9.0 / 3.0 + 16.0));
74TEST_CASE(
"PolynomialSquaredNorm<3> with 3 rows (P1)")
76 Eigen::ArrayXXd theta(3, 2);
81 auto result = PolynomialSquaredNorm<3>(theta);
83 CHECK(
result(0) == doctest::Approx(1.0 + 9.0 + 25.0));
84 CHECK(
result(1) == doctest::Approx(4.0 + 16.0 + 36.0));
87TEST_CASE(
"PolynomialSquaredNorm<3> with 6 rows (P2)")
89 Eigen::ArrayXXd theta(6, 1);
90 theta << 1.0, 2.0, 3.0, 4.0, 5.0, 6.0;
92 auto result = PolynomialSquaredNorm<3>(theta);
95 1.0 + 4.0 + 9.0 + 16.0 * 0.5 + 25.0 * 0.5 + 36.0 * 0.5));
98TEST_CASE(
"PolynomialSquaredNorm<3> with 10 rows (P3)")
100 Eigen::ArrayXXd theta(10, 1);
101 for (
int i = 0; i < 10; i++)
102 theta(i, 0) =
static_cast<real>(i + 1);
105 for (
int i = 0; i < 3; i++)
106 expected += theta(i, 0) * theta(i, 0);
107 for (
int i = 3; i < 9; i++)
108 expected += theta(i, 0) * theta(i, 0) / 3.0;
109 expected += theta(9, 0) * theta(9, 0) / 6.0;
110 auto result = PolynomialSquaredNorm<3>(theta);
118TEST_CASE(
"PolynomialDotProduct<2> self-product equals PolynomialSquaredNorm")
120 for (
int nRows : {2, 3, 4})
123 Eigen::ArrayXXd theta(nRows, 3);
125 auto normResult = PolynomialSquaredNorm<2>(theta);
126 auto dotResult = PolynomialDotProduct<2>(theta, theta);
127 for (
int j = 0; j < 3; j++)
130 CHECK(dotResult(j) == doctest::Approx(normResult(j)).epsilon(1e-14));
138 Eigen::ArrayXXd a(nRows, 2),
b(nRows, 2);
147 Eigen::ArrayXXd alphaA =
alpha * a;
148 Eigen::ArrayXd left = PolynomialDotProduct<2>(alphaA,
b);
149 Eigen::ArrayXd right =
alpha * PolynomialDotProduct<2>(a,
b);
150 for (
int j = 0; j < 2; j++)
153 CHECK(left(j) == doctest::Approx(right(j)).epsilon(1e-13));
163 Eigen::ArrayXXd u1(2, 3), u2(2, 3), out(2, 3);
166 u2 << 2.0, 1.0, 10.0,
170 CHECK(out(0, 0) == doctest::Approx(1.0));
171 CHECK(out(0, 1) == doctest::Approx(1.0));
172 CHECK(out(0, 2) == doctest::Approx(5.0));
173 CHECK(out(1, 0) == doctest::Approx(3.0));
174 CHECK(out(1, 1) == doctest::Approx(2.0));
175 CHECK(out(1, 2) == doctest::Approx(3.0));
178TEST_CASE(
"FMINMOD_Biway: opposite-sign inputs produce zero")
180 Eigen::ArrayXXd u1(1, 4), u2(1, 4), out(1, 4);
181 u1 << 1.0, -1.0, 3.0, -5.0;
182 u2 << -2.0, 2.0, -0.5, 7.0;
184 for (
int j = 0; j < 4; j++)
187 CHECK(out(0, j) == doctest::Approx(0.0));
193 Eigen::ArrayXXd u1(1, 2), u2(1, 2), out(1, 2);
197 CHECK(out(0, 0) == doctest::Approx(0.0));
198 CHECK(out(0, 1) == doctest::Approx(0.0));
207 Eigen::ArrayXXd u1(1, 2), u2(1, 2), out(1, 2);
214 CHECK(out(0, 0) == doctest::Approx(8.0 / 3.0).epsilon(1e-10));
216 CHECK(out(0, 1) == doctest::Approx(-4.0).epsilon(1e-10));
221 Eigen::ArrayXXd u1(1, 2), u2(1, 2), out(1, 2);
225 CHECK(out(0, 0) == doctest::Approx(0.0).epsilon(1e-10));
226 CHECK(out(0, 1) == doctest::Approx(0.0).epsilon(1e-10));
229TEST_CASE(
"FVanLeer_Biway: equal inputs return same value")
231 Eigen::ArrayXXd u1(1, 2), u2(1, 2), out(1, 2);
236 CHECK(out(0, 0) == doctest::Approx(5.0).epsilon(1e-10));
237 CHECK(out(0, 1) == doctest::Approx(-3.0).epsilon(1e-10));
244TEST_CASE(
"FWBAP_L2_Biway: identical inputs pass through")
246 Eigen::ArrayXXd u1(2, 3), u2(2, 3), out(2, 3);
250 for (
int i = 0; i < 2; i++)
251 for (
int j = 0; j < 3; j++)
255 CHECK(out(i, j) == doctest::Approx(u1(i, j)).epsilon(1e-10));
261 Eigen::ArrayXXd u1(3, 5), u2(3, 5), out(3, 5);
265 CHECK_FALSE(out.hasNaN());
268TEST_CASE(
"FWBAP_L2_Biway: output bounded by inputs for same-sign")
271 Eigen::ArrayXXd u1(1, 100), u2(1, 100), out(1, 100);
277 for (
int j = 0; j < 100; j++)
281 CHECK(out(0, j) >= -1e-10);
289TEST_CASE(
"FWBAP_L2_Cut_Biway: opposite-sign cut to zero")
291 Eigen::ArrayXXd u1(1, 3), u2(1, 3), out(1, 3);
292 u1 << 1.0, -2.0, 3.0;
293 u2 << -1.0, 2.0, -3.0;
295 for (
int j = 0; j < 3; j++)
298 CHECK(out(0, j) == doctest::Approx(0.0).epsilon(1e-10));
304 Eigen::ArrayXXd u1(2, 4), u2(2, 4), out(2, 4);
308 CHECK_FALSE(out.hasNaN());
315TEST_CASE(
"FWBAP_L2_Multiway: all identical inputs pass through")
317 Eigen::ArrayXXd u0(2, 3);
319 std::vector<Eigen::ArrayXXd> uOthers = {u0, u0, u0, u0};
323 for (
int i = 0; i < 2; i++)
324 for (
int j = 0; j < 3; j++)
328 CHECK(out(i, j) == doctest::Approx(u0(i, j)).epsilon(1e-8));
334 std::vector<Eigen::ArrayXXd> uOthers(5);
335 for (
auto &u : uOthers)
341 out.resizeLike(uOthers[0]);
343 CHECK_FALSE(out.hasNaN());
350TEST_CASE(
"FWBAP_L2_Multiway_Polynomial2D: all identical pass through")
352 Eigen::ArrayXXd u0(2, 3);
354 std::vector<Eigen::ArrayXXd> uOthers = {u0, u0, u0};
357 FWBAP_L2_Multiway_Polynomial2D(uOthers, 3, out, 1.0);
358 for (
int i = 0; i < 2; i++)
359 for (
int j = 0; j < 3; j++)
363 CHECK(out(i, j) == doctest::Approx(u0(i, j)).epsilon(1e-8));
367TEST_CASE(
"FWBAP_L2_Multiway_Polynomial2D: no NaN for random inputs (nRows=2,3,4)")
369 for (
int nRows : {2, 3, 4})
372 std::vector<Eigen::ArrayXXd> uOthers(4);
373 for (
auto &u : uOthers)
379 out.resizeLike(uOthers[0]);
380 FWBAP_L2_Multiway_Polynomial2D(uOthers, 4, out, 1.0);
381 CHECK_FALSE(out.hasNaN());
389TEST_CASE(
"FMEMM_Multiway_Polynomial2D: center input unchanged when smallest")
392 Eigen::ArrayXXd center(2, 2);
395 std::vector<Eigen::ArrayXXd> uOthers(3);
396 for (
auto &u : uOthers)
403 out.resizeLike(center);
404 FMEMM_Multiway_Polynomial2D(center, uOthers, 3, out, 1.0);
405 CHECK_FALSE(out.hasNaN());
407 for (
int i = 0; i < 2; i++)
408 for (
int j = 0; j < 2; j++)
412 CHECK(out(i, j) == doctest::Approx(center(i, j)).epsilon(1e-8));
416TEST_CASE(
"FMEMM_Multiway_Polynomial2D: no NaN for random inputs")
418 Eigen::ArrayXXd center(3, 4);
420 std::vector<Eigen::ArrayXXd> uOthers(3);
421 for (
auto &u : uOthers)
427 out.resizeLike(center);
428 FMEMM_Multiway_Polynomial2D(center, uOthers, 3, out, 1.0);
429 CHECK_FALSE(out.hasNaN());
436TEST_CASE(
"FWBAP_L2_Multiway_PolynomialOrth: all identical pass through")
438 Eigen::ArrayXXd u0(3, 2);
440 std::vector<Eigen::ArrayXXd> uOthers = {u0, u0, u0};
443 FWBAP_L2_Multiway_PolynomialOrth(uOthers, 3, out, 1.0);
444 for (
int i = 0; i < 3; i++)
445 for (
int j = 0; j < 2; j++)
449 CHECK(out(i, j) == doctest::Approx(u0(i, j)).epsilon(1e-8));
453TEST_CASE(
"FWBAP_L2_Multiway_PolynomialOrth: no NaN")
455 std::vector<Eigen::ArrayXXd> uOthers(4);
456 for (
auto &u : uOthers)
462 out.resizeLike(uOthers[0]);
463 FWBAP_L2_Multiway_PolynomialOrth(uOthers, 4, out, 1.0);
464 CHECK_FALSE(out.hasNaN());
471TEST_CASE(
"FWBAP_L2_Biway_PolynomialNorm<2,1>: identical inputs pass through")
473 using ArrT = Eigen::Array<real, Eigen::Dynamic, 1>;
474 ArrT u1(2, 1), u2(2, 1), out(2, 1);
477 FWBAP_L2_Biway_PolynomialNorm<2, 1>(u1, u2, out, 1.0);
478 CHECK(out(0) == doctest::Approx(u1(0)).epsilon(1e-8));
479 CHECK(out(1) == doctest::Approx(u1(1)).epsilon(1e-8));
482TEST_CASE(
"FWBAP_L2_Biway_PolynomialNorm<2,Eigen::Dynamic>: no NaN")
484 Eigen::ArrayXXd u1(3, 4), u2(3, 4), out(3, 4);
487 FWBAP_L2_Biway_PolynomialNorm<2, Eigen::Dynamic>(u1, u2, out, 1.0);
488 CHECK_FALSE(out.hasNaN());
491TEST_CASE(
"FWBAP_L2_Biway_PolynomialNorm<3,Eigen::Dynamic>: no NaN for 3D dims")
493 for (
int nRows : {3, 6, 10})
496 Eigen::ArrayXXd u1(nRows, 2), u2(nRows, 2), out(nRows, 2);
499 FWBAP_L2_Biway_PolynomialNorm<3, Eigen::Dynamic>(u1, u2, out, 1.0);
500 CHECK_FALSE(out.hasNaN());
508TEST_CASE(
"FMEMM_Biway_PolynomialNorm<2,Eigen::Dynamic>: u2 smaller returns u2")
511 Eigen::ArrayXXd u1(2, 2), u2(2, 2), out(2, 2);
516 FMEMM_Biway_PolynomialNorm<2, Eigen::Dynamic>(u1, u2, out, 1.0);
517 CHECK_FALSE(out.hasNaN());
520 real dist_to_u2 = (out - u2).matrix().norm();
521 real dist_to_u1 = (out - u1).matrix().norm();
522 CHECK(dist_to_u2 < dist_to_u1);
525TEST_CASE(
"FMEMM_Biway_PolynomialNorm<2,Eigen::Dynamic>: no NaN")
527 Eigen::ArrayXXd u1(4, 3), u2(4, 3), out(4, 3);
530 FMEMM_Biway_PolynomialNorm<2, Eigen::Dynamic>(u1, u2, out, 1.0);
531 CHECK_FALSE(out.hasNaN());
538TEST_CASE(
"FWBAP_L2_Biway_PolynomialOrth: identical inputs pass through")
540 Eigen::ArrayXXd u1(3, 2), u2(3, 2), out(3, 2);
544 for (
int i = 0; i < 3; i++)
545 for (
int j = 0; j < 2; j++)
549 CHECK(out(i, j) == doctest::Approx(u1(i, j)).epsilon(1e-8));
553TEST_CASE(
"FWBAP_L2_Biway_PolynomialOrth: no NaN")
555 Eigen::ArrayXXd u1(4, 5), u2(4, 5), out(4, 5);
559 CHECK_FALSE(out.hasNaN());
566TEST_CASE(
"Limiter ordering: FMINMOD output <= FWBAP output for same-sign")
568 Eigen::ArrayXXd u1(1, 100), u2(1, 100), outMM(1, 100), outWBAP(1, 100);
570 u1 = u1.abs() + 0.01;
572 u2 = u2.abs() + 0.01;
576 for (
int j = 0; j < 100; j++)
579 CHECK(outMM(0, j) <= outWBAP(0, j) + 1e-12);
587TEST_CASE(
"All limiters handle near-zero inputs without NaN")
589 Eigen::ArrayXXd u1(2, 3), u2(2, 3);
590 u1.setConstant(1e-300);
591 u2.setConstant(1e-300);
593 Eigen::ArrayXXd out(2, 3);
598 CHECK_FALSE(out.hasNaN());
603 CHECK_FALSE(out.hasNaN());
605 SUBCASE(
"FWBAP_L2_Biway")
608 CHECK_FALSE(out.hasNaN());
610 SUBCASE(
"FWBAP_L2_Cut_Biway")
613 CHECK_FALSE(out.hasNaN());
615 SUBCASE(
"FWBAP_L2_Biway_PolynomialNorm<2>")
617 FWBAP_L2_Biway_PolynomialNorm<2, Eigen::Dynamic>(u1, u2, out, 1.0);
618 CHECK_FALSE(out.hasNaN());
620 SUBCASE(
"FWBAP_L2_Biway_PolynomialOrth")
623 CHECK_FALSE(out.hasNaN());
void FWBAP_L2_Cut_Biway(const Tin1 &u1, const Tin2 &u2, Tout &uOut, real n)
void FWBAP_L2_Multiway(const TinOthers &uOthers, int Nother, Tout &uOut, real n1=1.0)
input vector<Eigen::Array-like>
void FMINMOD_Biway(const Tin1 &u1, const Tin2 &u2, Tout &uOut, real n)
input eigen arrays
void FWBAP_L2_Biway_PolynomialOrth(const Tin1 &u1, const Tin2 &u2, Tout &uOut, real n)
void FVanLeer_Biway(const Tin1 &u1, const Tin2 &u2, Tout &uOut, real n)
input eigen arrays
void FWBAP_L2_Biway(const Tin1 &u1, const Tin2 &u2, Tout &uOut, real n)
input eigen arrays
the host side operators are provided as implemented
double real
Canonical floating-point scalar used throughout DNDSR (double precision).
TEST_CASE("3D: VFV P2 HQM error < P1 on sinCos3D")