void evalTest(const std::size_t p_size, const std::size_t p_samples) { Polynomial<T,Dim> P; Index<Dim> polyIdx; { typename Shape<Dim>::type polyShape; polyShape.fill(p_size); P.reshape(polyShape).applyToCoefficients([](T& ak, const Index<Dim>& idx){ ak = T(idx())/T(idx.maxId()); }); } std::array<T,Dim> X; T dX; { const T a = T(0); const T b = T(1); dX = (b-a)/(p_samples-1); } typename Shape<Dim>::type sampleShape; sampleShape.fill(p_samples); Index<Dim> sampleIdx(sampleShape); while(!sampleIdx.atMaxId()) { for (std::size_t d=0; d < Dim; d++) X[d] = sampleIdx[d]*dX; T lhs, rhs; lhs = P(X); rhs = T(0); polyIdx.reset(P.shape()); while(!polyIdx.atMaxId()) { T val = T(1); for (std::size_t d=0; d<Dim; d++) val *= std::pow(X[d],polyIdx[d]); rhs += T(polyIdx())/T(polyIdx.maxId())*val; ++polyIdx; } ASSERT_LE(std::abs(rhs-lhs),std::pow(10,Dim)*std::numeric_limits<T>::epsilon()); ++sampleIdx; } }
void test(std::size_t p_maxOrder, bool includePeriodicBds=false) { typename Shape<Dim>::type shape; typename Domain<T,Dim>::DomainSize domainSize; Domain<T,Dim> ref, inBuffer, outBuffer; Domain<T,Dim>& in = inBuffer; Domain<T,Dim>& out = outBuffer; std::array<int,Dim> order; shape.fill(8); domainSize.fill(2*hysop::constants::pi); T eps = std::numeric_limits<T>::epsilon(); const std::size_t N = std::accumulate(shape.begin(), shape.end(), 1, std::multiplies<std::size_t>()); ref.resize(domainSize).reshape(shape); in = ref; out = ref; typename Shape<Dim>::type maxOrder, testCases; maxOrder.fill(p_maxOrder+1); testCases.fill(nExtensionsPair); Index<Dim> orderId(maxOrder); Index<Dim> testCaseId; std::size_t testCaseCount; while(!(++orderId).atMaxId()) { std::cout << " ::Order::" << orderId.ids() << (verbose ? "\n" : ""); std::array<T,3> meanDists; meanDists.fill(0); testCaseId.reset(testCases); testCaseCount = testCaseId.maxId(); while(!testCaseId.atMaxId()) { std::copy(orderId.ids().begin(),orderId.ids().end(), order.begin()); /* generate transform configuration */ std::array<std::pair<fft::Extension,fft::Extension>, Dim> extConfig; for (std::size_t k=0; k<Dim; k++) { std::size_t id = testCaseId[k]; extConfig[k] = pext[id]; if(pext[id].first==fft::Extension::NONE) order[k] = 0; } fft::FftDomainConfiguration<Dim> domainConfig(extConfig, includePeriodicBds); const std::size_t orderSum = std::accumulate(order.begin(), order.end(), 0); if(orderSum == 0) { testCaseCount--; ++testCaseId; continue; } T orderPow = std::pow(T(10),T(orderSum)); if(std::is_same<T,long double>::value) /* just in case long doubles are not hardware supported... */ orderPow *= 1e3; const auto criteria = std::make_tuple(orderPow*eps*N,orderPow*eps*sqrt(N),2*orderPow*eps); const auto f = [&](const typename Domain<T,Dim>::SpaceVariable &x) { T val = func<T>(testCaseId[0])(x[0]); for (std::size_t d=1; d < Dim; d++) val *= func<T>(testCaseId[d])(x[d]); return val; }; const auto d = [&](const typename Domain<T,Dim>::SpaceVariable &x) { T val = derivative<T>(testCaseId[0],order[0])(x[0]); for (std::size_t d=1; d < Dim; d++) val *= derivative<T>(testCaseId[d],order[d])(x[d]); return val; }; { ref.resetDomainConfiguration(domainConfig.boundariesConfiguration()); in = ref; out = ref; in.apply(f); ref.apply(d); out.data().apply([](T& v){ v=T(0);}); } solver::FftDiffSolver<T,Dim> solver(domainSize, domainConfig, FFTW_MEASURE, includePeriodicBds, includePeriodicBds); solver.apply(in.data(), out.data(), order); std::stringstream ss; ss << "["; for (std::size_t k=0; k<Dim-1; k++) ss << extConfig[k].first << "/" << extConfig[k].second << ","; ss << extConfig[Dim-1].first << "/" << extConfig[Dim-1].second; ss << "]"; const auto dist = out.distance(ref); const bool pass = (std::get<0>(dist) < std::get<0>(criteria)) && (std::get<1>(dist) < std::get<1>(criteria)) && (std::get<2>(dist) < std::get<2>(criteria)); if((pass && verbose) || !pass) { std::cout << (pass ? GREEN : RED); std::cout << "\t" << std::setw(Dim*15) << ss.str() << " => " << (pass ? "OK" : "KO") << " " << RESET << std::scientific << std::setprecision(2) << dist << std::endl; } if(!pass) { //in.print("IN"); //ref.print("REF"); //out.print("OUT"); std::cout << "Test failed => Criteria was: " << criteria << std::endl; } meanDists[0] += std::get<0>(dist); meanDists[1] += std::get<1>(dist); meanDists[2] += std::get<2>(dist); EXPECT_TRUE(pass); ++testCaseId; } for (std::size_t k = 0; k < 3; k++) meanDists[k] /= T(testCaseCount); std::cout << "=> mean distances over " << std::scientific << std::setprecision(1) << std::setw(4) << testCaseCount << " testcases: " << meanDists; for (std::size_t k = 0; k < 3; k++) meanDists[k] = std::round(meanDists[k]/eps); std::cout << " ~= " << std::fixed << std::setprecision(0) << meanDists << " eps" << std::endl; } }