#include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; namespace { const double nano = 1.0e-9; // Time a region of code template auto xtime(double& time, const F& f) -> typename enable_if::value, void>::type { const ticks tb = getticks(); f(); const ticks te = getticks(); time += seconds_per_tick() * elapsed(te, tb); } template auto xtime(double& time, const F& f) -> typename enable_if::value, decltype(f())>::type { const ticks tb = getticks(); const decltype(f()) ret = f(); const ticks te = getticks(); time += seconds_per_tick() * elapsed(te, tb); return ret; } // Convert to string // (Would like to use to_string instead, but this doesn't seem to // compile on Stampede) template string to_str(const T& x) { ostringstream buf; buf << x; return buf.str(); } template void check_equal(const string descr, const A1& x1, const A2& x2, const bboxset1::bboxset& bset1, const bboxset2::bboxset& bset2) { DECLARE_CCTK_PARAMETERS; if (verbose) { cout << " <" << D << "> " << descr << "..."; cout.flush(); } set> v1, v2; bset1.serialise(v1); bset2.serialise(v2); bool eq = v1 == v2; if (not eq) { eq = (bset1 == bboxset1::bboxset(v2) and bset2 == bboxset2::bboxset(v1)); } if (eq) { if (verbose) cout << " [success]\n"; } else { if (verbose) cout << " [failure]\n"; cout.flush(); cerr.flush(); fflush(stdout); fflush(stderr); CCTK_VParamWarn(CCTK_THORNSTRING, "Found difference in operation \"%s\":", descr.c_str()); fflush(stdout); fflush(stderr); cout << "\n" << "input1=" << x1 << "\n" << "input2=" << x2 << "\n" << "bset1=" << bset1 << "\n" << "bset2=" << bset2 << "\n" << "bset1.serialised=" << v1 << "\n" << "bset2.serialised=" << v2 << "\n"; cout.flush(); cerr.flush(); const bboxset1::bboxset bs(v2); cout << "bset1-bset2=" << bset1-bs << "\n" << "bset2-bset1=" << bs-bset1 << "\n"; } } template void check_equal(const string descr, const bboxset1::bboxset& bset1, const bboxset2::bboxset& bset2) { check_equal(descr, "", "", bset1, bset2); } #define bvect bvect_ #define b2vect b2vect_ #define ivect ivect_ #define i2vect i2vect_ #define ibbox ibbox_ template struct full_boxes_t { typedef ::vect bvect; typedef ::vect b2vect; typedef ::vect ivect; typedef ::vect i2vect; typedef ::bbox ibbox; typedef bboxset1::bboxset ibset1; typedef bboxset2::bboxset ibset2; ibbox interior; b2vect is_outer_boundary; ibbox exterior; ibset1 ghosts1; ibset2 ghosts2; ibbox communicated; ibset1 outer_boundaries1; ibset2 outer_boundaries2; ibbox owned; ibset1 boundaries1; ibset2 boundaries2; ibset1 buffers1; ibset2 buffers2; ibset1 overlaps1; ibset2 overlaps2; ibset1 active1; ibset2 active2; }; template struct level_boxes_t { typedef ::vect bvect; typedef ::vect b2vect; typedef ::vect ivect; typedef ::vect i2vect; typedef ::bbox ibbox; typedef bboxset1::bboxset ibset1; typedef bboxset2::bboxset ibset2; ibset1 buffers1; ibset2 buffers2; ibset1 active1; ibset2 active2; }; template void test() { DECLARE_CCTK_PARAMETERS; CCTK_VInfo(CCTK_THORNSTRING, "Testing bboxset2<%d>...", D); // Prevent warnings about shadowing declarations typedef ::vect bvect; typedef ::vect b2vect; typedef ::vect ivect; typedef ::vect i2vect; typedef ::bbox ibbox; typedef bboxset1::bboxset ibset1; typedef bboxset2::bboxset ibset2; const int str = 3; // a non-trivial stride double time1, time2, time1a, time2a, time_check; // Some warm-up gymnastics with emtpy sets ibset1 bs1; ibset2 bs2; xtime(time_check, [&]() { check_equal("create ibset", bs1, bs2); }); assert(bs1.empty()); assert(bs2.empty()); ibbox b; bs1 |= b; bs2 |= b; xtime(time_check, [&]() { check_equal("union with empty ibbox", bs1, bs2); }); assert(bs1.empty()); assert(bs2.empty()); bs1 &= b; bs2 &= b; xtime(time_check, [&]() { check_equal("intersection with empty ibbox", bs1, bs2); }); assert(bs1.empty()); assert(bs2.empty()); bs1 += b; bs2 += b; xtime(time_check, [&]() { check_equal("symmetric union with empty ibbox", bs1, bs2); }); assert(bs1.empty()); assert(bs2.empty()); bs1 -= b; bs2 -= b; xtime(time_check, [&]() { check_equal("difference with empty ibbox", bs1, bs2); }); assert(bs1.empty()); assert(bs2.empty()); // Some basic tests b = ibbox(ivect(0*str), ivect(9*str), ivect(str)); bs1 += b; bs2 += b; xtime(time_check, [&]() { check_equal("add ibbox", bs1, bs2); }); bs1 -= b; bs2 -= b; xtime(time_check, [&]() { check_equal("subtract ibbox", bs1, bs2); }); bs1 |= b; bs2 |= b; xtime(time_check, [&]() { check_equal("union", bs1, bs2); }); bs1 &= b; bs2 &= b; xtime(time_check, [&]() { check_equal("intersection", bs1, bs2); }); ibset1 bs1a = bs1.shift(ivect(1)); ibset2 bs2a = bs2.shift(ivect(1)); xtime(time_check, [&]() { check_equal("shift", bs1a, bs2a); }); ibset1 bs1b = bs1.expand(ivect(1), ivect(1)); ibset2 bs2b = bs2.expand(ivect(1), ivect(1)); xtime(time_check, [&]() { check_equal("expand", bs1b, bs2b); }); ibset1 bs1c = bs1 & bs1a; ibset2 bs2c = bs2 & bs2a; xtime(time_check, [&]() { check_equal("non-trivial intersection", bs1c, bs2c); }); ibset1 bs1d = bs1b - bs1; ibset2 bs2d = bs2b - bs2; xtime(time_check, [&]() { check_equal("non-trivial difference", bs1d, bs2d); }); // Many tests with random sets bs1 = ibset1(); bs2 = ibset2(); xtime(time_check, [&]() { check_equal("many dense bboxes (init)", bs1, bs2); }); time1 = time2 = time_check = 0.0; for (int n=0; n<40; ++n) { ivect lo, up; for (int d=0; d> full_boxes(components); level_boxes_t level_boxes; for (int c=0; c::owned); }); xtime(time2, [&]() { allowned2 = ibset2(full_boxes, &full_boxes_t::owned); }); xtime(time_check, [&]() { check_equal("allowned", allowned1, allowned2); }); xtime(time1a, [&]() { assert(allowned1 <= domain_active); }); xtime(time2a, [&]() { assert(allowned2 <= domain_active); }); // All not-owned regions ibset1 notowned1; ibset2 notowned2; xtime(time1, [&]() { notowned1 = domain_active - allowned1; }); xtime(time2, [&]() { notowned2 = domain_active - allowned2; }); xtime(time_check, [&]() { check_equal("notowned", notowned1, notowned2); }); // All not-active points ibset1 notactive1; ibset2 notactive2; xtime(time1, [&]() { notactive1 = notowned1.expand(buffer_width + overlap_width); }); xtime(time2, [&]() { notactive2 = notowned2.expand(buffer_width + overlap_width); }); xtime(time_check, [&]() { check_equal("notactive", notactive1, notactive2); }); // All not-active points, in stages int const num_substeps = any(any(ghost_width == 0)) ? 0 : minval(minval(buffer_width / ghost_width)); assert(all(all(buffer_width == num_substeps * ghost_width))); vector notactive_stepped1(num_substeps+1); vector notactive_stepped2(num_substeps+1); notactive_stepped1.AT(0) = notowned1; notactive_stepped2.AT(0) = notowned2; for (int substep=1; substep<=num_substeps; ++substep) { xtime(time1, [&]() { notactive_stepped1.AT(substep) = notactive_stepped1.AT(substep-1).expand(ghost_width); }); xtime(time2, [&]() { notactive_stepped2.AT(substep) = notactive_stepped2.AT(substep-1).expand(ghost_width); }); xtime(time_check, [&]() { check_equal("notactive_stepped[" + to_str(substep) + "]", notactive_stepped1.AT(substep), notactive_stepped2.AT(substep)); }); } ibset1 notactive_overlaps1; ibset2 notactive_overlaps2; xtime(time1a, [&]() { notactive_overlaps1 = notactive_stepped1.AT(num_substeps).expand(overlap_width); }); xtime(time2a, [&]() { notactive_overlaps2 = notactive_stepped2.AT(num_substeps).expand(overlap_width); }); xtime(time_check, [&]() { check_equal("notactive_overlaps", notactive_overlaps1, notactive_overlaps2); }); if (all(all(buffer_width == num_substeps * ghost_width))) { xtime(time1a, [&]() { assert(notactive_overlaps1 == notactive1); }); xtime(time2a, [&]() { assert(notactive_overlaps2 == notactive2); }); } // All buffer zones ibset1& allbuffers1 = level_boxes.buffers1; ibset2& allbuffers2 = level_boxes.buffers2; xtime(time1, [&]() { allbuffers1 = allowned1 & notowned1.expand(buffer_width); }); xtime(time2, [&]() { allbuffers2 = allowned2 & notowned2.expand(buffer_width); }); xtime(time_check, [&]() { check_equal("allbuffers", allbuffers1, allbuffers2); }); // All overlap zones ibset1 alloverlaps1; ibset2 alloverlaps2; xtime(time1, [&]() { alloverlaps1 = (allowned1 & notactive1) - allbuffers1; }); xtime(time2, [&]() { alloverlaps2 = (allowned2 & notactive2) - allbuffers2; }); xtime(time_check, [&]() { check_equal("alloverlaps", alloverlaps1, alloverlaps2); }); // All active points ibset1& allactive1 = level_boxes.active1; ibset2& allactive2 = level_boxes.active2; xtime(time1, [&]() { allactive1 = allowned1 - notactive1; }); xtime(time2, [&]() { allactive2 = allowned2 - notactive2; }); xtime(time_check, [&]() { check_equal("allactive", allactive1, allactive2); }); // All stepped buffer zones vector allbuffers_stepped1(num_substeps); vector allbuffers_stepped2(num_substeps); ibset1 allbuffers_stepped_combined1; ibset2 allbuffers_stepped_combined2; for (int substep=0; substep.", D); } } // namespace extern "C" void TestBBoxSet2_test(CCTK_ARGUMENTS) { DECLARE_CCTK_ARGUMENTS; test<1>(); test<2>(); test<3>(); }