#include #include #include #include #include #include #include #include #include #include "bernstein.hpp" #include "multiloop.hpp" #include "quadrature_multipoly.hpp" #include "binomial.hpp" #include "real.hpp" #include "sparkstack.hpp" #include "uvector.hpp" #include "vector" #include "xarray.hpp" #include using namespace algoim; // Driver method which takes a functor phi defining a single polynomial in the reference // rectangle [xmin, xmax]^N, of Bernstein degree P, along with an integrand function, // and performances a q-refinement convergence study, comparing the computed integral // with the given exact answers, for 1 <= q <= qMax. template void qConv1(const Phi& phi, real xmin, real xmax, uvector P, const F& integrand, int qMax, real volume_exact, real surf_exact) { // Construct Bernstein polynomial by mapping [0,1] onto bounding box [xmin,xmax] xarray phipoly(nullptr, P); algoim_spark_alloc(real, phipoly); bernstein::bernsteinInterpolate([&](const uvector& x) { return phi(xmin + x * (xmax - xmin)); }, phipoly); // Build quadrature hierarchy ImplicitPolyQuadrature ipquad(phipoly); // Functional to evaluate volume and surface integrals of given integrand real volume, surf; auto compute = [&](int q) { volume = 0.0; surf = 0.0; // compute volume integral over {phi < 0} using AutoMixed strategy ipquad.integrate(AutoMixed, q, [&](const uvector& x, real w) { if (bernstein::evalBernsteinPoly(phipoly, x) < 0) volume += w * integrand(xmin + x * (xmax - xmin)); }); // compute surface integral over {phi == 0} using AutoMixed strategy ipquad.integrate_surf(AutoMixed, q, [&](const uvector& x, real w, const uvector& wn) { surf += w * integrand(xmin + x * (xmax - xmin)); }); // scale appropriately volume *= pow(xmax - xmin, N); surf *= pow(xmax - xmin, N - 1); }; // Compute results for all q and output in a convergence table for (int q = 1; q <= qMax; ++q) { compute(q); std::cout << q << ' ' << volume << ' ' << surf << ' ' << std::abs(volume - volume_exact) / volume_exact << ' ' << std::abs(surf - surf_exact) / surf_exact << std::endl; } } enum BoolOp { Union, Intersection, Difference }; // Driver method which takes two phi functors defining two polynomials in the reference // rectangle [xmin, xmax]^N, each of of Bernstein degree P, builds a quadrature scheme with the // given q, and outputs it for visualisation in a set of VTP XML files template void qConvMultiPloy(const F1& fphi1, const F2& fphi2, real xmin, real xmax, const uvector& P, const F& integrand, int q, BoolOp op) { // Construct phi by mapping [0,1] onto bounding box [xmin,xmax] xarray phi1(nullptr, P), phi2(nullptr, P); algoim_spark_alloc(real, phi1, phi2); bernstein::bernsteinInterpolate([&](const uvector& x) { return fphi1(xmin + x * (xmax - xmin)); }, phi1); bernstein::bernsteinInterpolate([&](const uvector& x) { return fphi2(xmin + x * (xmax - xmin)); }, phi2); // Build quadrature hierarchy auto t = std::chrono::system_clock::now(); ImplicitPolyQuadrature ipquad(phi1, phi2); // ImplicitPolyQuadrature ipquad(phi1); // Functional to evaluate volume and surface integrals of given integrand real volume, surf; auto compute = [&](int q) { volume = 0.0; surf = 0.0; // compute volume integral over {phi < 0} using AutoMixed strategy ipquad.integrate(AutoMixed, q, [&](const uvector& x, real w) { if (op == Union) { if (bernstein::evalBernsteinPoly(phi1, x) < 0 || bernstein::evalBernsteinPoly(phi2, x) < 0) volume += w * integrand(xmin + x * (xmax - xmin)); } else if (op == Intersection) { if (bernstein::evalBernsteinPoly(phi1, x) < 0 && bernstein::evalBernsteinPoly(phi2, x) < 0) volume += w * integrand(xmin + x * (xmax - xmin)); } else if (op == Difference) { if (bernstein::evalBernsteinPoly(phi1, x) < 0 && bernstein::evalBernsteinPoly(phi2, x) > 0) volume += w * integrand(xmin + x * (xmax - xmin)); } // if (bernstein::evalBernsteinPoly(phi1, x) < 0) volume += w * integrand(xmin + x * (xmax - xmin)); }); // compute surface integral over {phi == 0} using AutoMixed strategy ipquad.integrate_surf(AutoMixed, q, [&](const uvector& x, real w, const uvector& wn) { surf += w * integrand(xmin + x * (xmax - xmin)); }); // scale appropriately volume *= pow(xmax - xmin, N); surf *= pow(xmax - xmin, N - 1); }; compute(q); auto tAfter = std::chrono::system_clock::now(); std::chrono::duration elapsed_seconds = tAfter - t; std::cout << "elapsed time: " << elapsed_seconds.count() << "s\n"; std::cout << "q volume: " << volume << std::endl; } template void qConvMultiPloy2(real xmin, real xmax, const std::vector>& phis, const F& integrand, int q) { auto t = std::chrono::system_clock::now(); ImplicitPolyQuadrature ipquad(phis); // Functional to evaluate volume and surface integrals of given integrand real volume, surf; auto compute = [&](int q) { volume = 0.0; surf = 0.0; // compute volume integral over {phi < 0} using AutoMixed strategy ipquad.integrate(AutoMixed, q, [&](const uvector& x, real w) { // if (bernstein::evalBernsteinPoly(phi1, x) < 0 && bernstein::evalBernsteinPoly(phi2, x) < 0) volume += w * // integrand(xmin + x * (xmax - xmin)); if (bernstein::evalBernsteinPoly(phi1, x) < 0) volume += w * integrand(xmin // + x * (xmax - xmin)); bool in = true; for (int i = 0; i < phis.size(); ++i) { if (bernstein::evalBernsteinPoly(phis[i], x) >= 0) { in = false; break; } } if (in) volume += w * integrand(xmin + x * (xmax - xmin)); }); // compute surface integral over {phi == 0} using AutoMixed strategy // ipquad.integrate_surf(AutoMixed, q, [&](const uvector& x, real w, const uvector& wn) { // surf += w * integrand(xmin + x * (xmax - xmin)); // }); // scale appropriately volume *= pow(xmax - xmin, N); surf *= pow(xmax - xmin, N - 1); }; compute(q); auto tAfter = std::chrono::system_clock::now(); std::chrono::duration elapsed_seconds = tAfter - t; std::cout << "elapsed time: " << elapsed_seconds.count() << "s\n"; std::cout << "volume: " << volume << std::endl; } void fromCommon2Bernstein() {} void testMultiPolys() { const int N = 3; const uvector P = 3; real xmin = -1; real xmax = 1; std::vector> phis; // 大量sphere // xarray* phis = new xarray[100]; for (int i = 0; i < 100; i++) { real centerX = 1.0 - rand() % 20 / 10.0, centerY = 1.0 - rand() % 20 / 10.0, centerZ = 1.0 - rand() % 20 / 10.0; real r = 0.01 + rand() % 10 / 100.0; auto fphi = [&](const uvector& xx) { real x = xx(0) - centerX; real y = xx(1) - centerY; real z = xx(2) - centerZ; return x * x + y * y + z * z - r * r; }; xarray phi(nullptr, P); algoim_spark_alloc(real, phi); bernstein::bernsteinInterpolate([&](const uvector& x) { return fphi(xmin + x * (xmax - xmin)); }, phi); phis.emplace_back(phi); } auto integrand = [](const uvector& x) { return 1.0; }; // qConvMultiPloy<3>(phi0, phi1, -1.0, 1.0, 3, integrand, 3, "exampleC"); std::cout << "testMultiPolys" << std::endl; qConvMultiPloy2<3>(-1.0, 1.0, phis, integrand, 10); } template void power2BernsteinTensorProduct(const xarray& phiPower, xarray& phiBernstein) { xarrayInit(phiBernstein); for (auto i = phiPower.loop(); ~i; ++i) { // phi.l(i) = powerFactors.l(i); real factorBase = phiPower.l(i); if (factorBase == 0) continue; auto traverseRange = phiPower.ext() - i(); std::vector> decompFactors(N, std::vector(max(traverseRange), 0.)); for (int dim = 0; dim < N; ++dim) { // Sigma size_t nDim = phiPower.ext()(dim) - 1; const real* binomNDim = Binomial::row(nDim); for (int j = i(dim); j <= nDim; ++j) { const real* binomJ = Binomial::row(j); decompFactors[dim][j - i(dim)] = binomJ[i(dim)] / binomNDim[i(dim)]; } } xarray subgrid(nullptr, traverseRange); algoim_spark_alloc(real, subgrid); for (auto ii = subgrid.loop(); ~ii; ++ii) { real factor = factorBase; for (int dim = 0; dim < N; ++dim) { factor *= decompFactors[dim][ii(dim)]; } phiBernstein.m(i() + ii()) += factor; } } } template real powerEvaluation(const xarray& phi, const uvector& x) { real res = 0; for (auto i = phi.loop(); ~i; ++i) { real item = phi.l(i); auto exps = i(); for (int dim = 0; dim < N; ++dim) { item *= pow(x(dim), i(dim)); } res += item; } return res; } template void qConvBernstein(const xarray& phi, real xmin, real xmax, const F& integrand, int q, const std::vector>& halfFaces) { auto t = std::chrono::system_clock::now(); uvector testX(0., 0.75, 0.); real testEvalBernstein = bernstein::evalBernsteinPoly(phi, testX); auto vec1 = xarray2StdVector(phi); std::cout << "eval bernstein without interpolation:" << testEvalBernstein << std::endl; // Build quadrature hierarchy ImplicitPolyQuadrature ipquad(phi); // ImplicitPolyQuadrature ipquad(phi1); // Functional to evaluate volume and surface integrals of given integrand real volume; auto compute = [&](int q) { volume = 0.0; // compute volume integral over {phi < 0} using AutoMixed strategy if (!halfFaces.empty()) { ipquad.integrate(AutoMixed, q, [&](const uvector& x, real w) { if (bernstein::evalBernsteinPoly(phi, x) >= 0) return; uvector trueX = xmin + x * (xmax - xmin); // uvector trueX = x; // std::cout << "trueX: " << trueX << std::endl; bool in = true; for (int i = 0; i < halfFaces.size(); ++i) { uvector factors(halfFaces[i][0], halfFaces[i][1], halfFaces[i][2]); if (sum(factors * trueX) + halfFaces[i][3] >= 0) { in = false; break; } } if (in) volume += w * integrand(xmin + x * (xmax - xmin)); }); } else ipquad.integrate(AutoMixed, q, [&](const uvector& x, real w) { if (bernstein::evalBernsteinPoly(phi, x) < 0) volume += w * integrand(xmin + x * (xmax - xmin)); }); // scale appropriately volume *= pow(xmax - xmin, N); }; compute(q); auto tAfter = std::chrono::system_clock::now(); std::chrono::duration elapsed_seconds = tAfter - t; std::cout << "elapsed time: " << elapsed_seconds.count() << "s\n"; std::cout << "q volume: " << volume << std::endl; } // template // void xarrayInit(xarray& arr) // { // for (auto i = arr.loop(); ~i; ++i) { arr.l(i) = 0; } // } void testSpherePowerDirectly() { // a_x(x-c_x)^2 + a_y(y-c_y)^2 + a_z(x-c_z)^2 - r^2 uvector xmin = -1, xmax = 1; uvector range = xmax - xmin; assert(all(range != 0)); // uvector k = 1 / range; // uvector bias = -k * xmin; uvector k = range; uvector bias = xmin; real a[3] = {1, 1, 1}; real c[3] = {0, 0, 0}; real r = 1; uvector ext = 3; xarray phiPower(nullptr, ext), phiBernstein(nullptr, ext); algoim_spark_alloc(real, phiPower, phiBernstein); xarrayInit(phiPower); auto v = xarray2StdVector(phiPower); auto vv = xarray2StdVector(phiBernstein); for (int dim = 0; dim < 3; ++dim) { uvector idx = 0; phiPower.m(idx) += a[dim] * (bias(dim) - c[dim]) * (bias(dim) - c[dim]); idx(dim) = 1; phiPower.m(idx) = 2 * a[dim] * k(dim) * (bias(dim) - c[dim]); idx(dim) = 2; phiPower.m(idx) = a[dim] * k(dim) * k(dim); } phiPower.m(0) -= r * r; auto integrand = [](const uvector&) { return 1.0; }; power2BernsteinTensorProduct(phiPower, phiBernstein); v = xarray2StdVector(phiPower); uvector testX(0., 0., 0.5); real testEval = powerEvaluation(phiPower, testX); std::cout << "eval power:" << testEval << std::endl; real testEvalBernstein = bernstein::evalBernsteinPoly(phiBernstein, testX); auto vec = xarray2StdVector(phiBernstein); std::cout << "eval bernstein:" << testEvalBernstein << std::endl; qConvBernstein(phiBernstein, -1, 1, integrand, 10, {}); } void powerTransformation(const uvector& scale, const uvector& bias, xarray& phiPower) { std::vector>> dimOrderExpansion; const auto& ext = phiPower.ext(); for (int dim = 0; dim < 3; ++dim) { dimOrderExpansion.push_back(std::vector>(ext(dim))); for (int degree = 0; degree < ext(dim); ++degree) { const real* binomDegree = Binomial::row(degree); dimOrderExpansion[dim][degree].reserve(degree + 1); // 根据二项定理展开 for (int i = 0; i <= degree; ++i) { dimOrderExpansion[dim][degree].push_back(binomDegree[i] * pow(scale(dim), i) * pow(bias(dim), degree - i)); } } } for (auto i = phiPower.loop(); ~i; ++i) { // 迭代器必须按照坐标的升序进行访问,即,访问ijk时,(i-1)jk,i(j-1)k,ij(k-1)必须已经访问过 real base = phiPower.l(i); phiPower.l(i) = 0; auto exps = i(); for (MultiLoop<3> j(0, exps + 1); ~j; ++j) { real item = base; for (int dim = 0; dim < 3; ++dim) { item *= dimOrderExpansion[dim][exps(dim)][j(dim)]; } phiPower.m(j()) += item; } } } void testSpherePowerDirectlyByTransformation() { // a_x(x-c_x)^2 + a_y(y-c_y)^2 + a_z(x-c_z)^2 - r^2 uvector xmin = -1, xmax = 1; uvector range = xmax - xmin; assert(all(range != 0)); // uvector k = 1 / range; // uvector bias = -k * xmin; real a[3] = {1, 1, 1}; real c[3] = {0, 0, 0}; real r = 0.2; uvector ext = 3; xarray phiPower(nullptr, ext), phiBernstein(nullptr, ext); algoim_spark_alloc(real, phiPower, phiBernstein); xarrayInit(phiPower); auto v = xarray2StdVector(phiPower); auto vv = xarray2StdVector(phiBernstein); for (int dim = 0; dim < 3; ++dim) { uvector idx = 0; phiPower.m(idx) += a[dim] * (c[dim]) * (c[dim]); idx(dim) = 1; phiPower.m(idx) = 2 * a[dim] * (-c[dim]); idx(dim) = 2; phiPower.m(idx) = a[dim]; } phiPower.m(0) -= r * r; powerTransformation(range, xmin, phiPower); auto integrand = [](const uvector& x) { return 1.0; }; power2BernsteinTensorProduct(phiPower, phiBernstein); v = xarray2StdVector(phiPower); uvector testX(0., 0., 0.5); real testEval = powerEvaluation(phiPower, testX); std::cout << "eval power:" << testEval << std::endl; real testEvalBernstein = bernstein::evalBernsteinPoly(phiBernstein, testX); auto vec = xarray2StdVector(phiBernstein); std::cout << "eval bernstein:" << testEvalBernstein << std::endl; qConvBernstein(phiBernstein, -1, 1, integrand, 10, {}); } void testCylinderPowerDirectly() { // a_x(x-c_x)^2 + a_y(y-c_y)^2 + a_z(x-c_z)^2 - r^2 uvector xmin = -1, xmax = 1; uvector range = xmax - xmin; assert(all(range != 0)); uvector k = range; uvector bias = xmin; real c[3] = {0, 0, 0}; real r = 1, h = 0.8; uvector ext = 3; xarray phiPower(nullptr, ext), phiBernstein(nullptr, ext); algoim_spark_alloc(real, phiPower, phiBernstein); xarrayInit(phiPower); auto v = xarray2StdVector(phiPower); auto vv = xarray2StdVector(phiBernstein); real top = c[2] + h * 0.5, bottom = c[2] - h * 0.5; phiPower.m(uvector(2, 0, 2)) = -1; phiPower.m(uvector(0, 2, 2)) = -1; phiPower.m(uvector(2, 0, 1)) = top + bottom; phiPower.m(uvector(0, 2, 1)) = top + bottom; phiPower.m(uvector(2, 0, 0)) = -bottom * top; phiPower.m(uvector(0, 2, 0)) = -bottom * top; phiPower.m(uvector(1, 0, 2)) = 2 * c[0]; phiPower.m(uvector(0, 1, 2)) = 2 * c[1]; phiPower.m(uvector(1, 0, 1)) = -2 * c[0] * (top + bottom); phiPower.m(uvector(0, 1, 1)) = -2 * c[1] * (top + bottom); phiPower.m(uvector(1, 0, 0)) = 2 * c[0] * (top * bottom); phiPower.m(uvector(0, 1, 0)) = 2 * c[0] * (top * bottom); phiPower.m(uvector(0, 0, 2)) = -(c[0] * c[0] + c[1] * c[1] - r * r); phiPower.m(uvector(0, 0, 1)) = (bottom + top) * (c[0] * c[0] + c[1] * c[1] - r * r); phiPower.m(uvector(0, 0, 0)) = -bottom * top * (c[0] * c[0] + c[1] * c[1] - r * r); powerTransformation(range, xmin, phiPower); auto integrand = [](const uvector& x) { return 1.0; }; power2BernsteinTensorProduct(phiPower, phiBernstein); v = xarray2StdVector(phiPower); uvector testX(0., 0., 0.75); real testEval = powerEvaluation(phiPower, testX); std::cout << "eval power:" << testEval << std::endl; real testEvalBernstein = bernstein::evalBernsteinPoly(phiBernstein, testX); auto vec = xarray2StdVector(phiBernstein); std::cout << "eval bernstein:" << testEvalBernstein << std::endl; std::cout << "testCylinderPowerDirectly" << std::endl; qConvBernstein(phiBernstein, -1, 1, integrand, 10, { {0, 0, 1, -top }, {0, 0, -1, bottom} }); } void testCylinderAlgoim() { const int N = 3; const uvector P = 3; real xmin = -1, xmax = 1; std::vector> phis(3, xarray(nullptr, P)); auto fphiCircle = [](const uvector& xx) { real x = xx(0); real y = xx(1); real z = xx(2); return x * x + y * y - 1; }; auto fphiUp = [](const uvector& xx) { real z = xx(2); return z - 0.5; }; auto fphiFloor = [](const uvector& xx) { real z = xx(2); return -z - 0.5; }; algoim_spark_alloc(real, phis[0]); algoim_spark_alloc(real, phis[1]); algoim_spark_alloc(real, phis[2]); bernstein::bernsteinInterpolate([&](const uvector& x) { return fphiCircle(xmin + x * (xmax - xmin)); }, phis[0]); bernstein::bernsteinInterpolate([&](const uvector& x) { return fphiUp(xmin + x * (xmax - xmin)); }, phis[1]); bernstein::bernsteinInterpolate([&](const uvector& x) { return fphiFloor(xmin + x * (xmax - xmin)); }, phis[2]); auto integrand = [](const uvector& x) { return 1.0; }; // // qConvMultiPloy<3>(phi0, phi1, -1.0, 1.0, 3, integrand, 3, "exampleC"); std::cout << "testCylinderAlgoim" << std::endl; qConvMultiPloy2<3>(-1.0, 1.0, phis, integrand, 10); } void test6PlanesAlgoim() { const int N = 3; const uvector P = 3; real xmin = -1, xmax = 1; std::vector> phis(6, xarray(nullptr, P)); // auto fphiPlane1 = [](const uvector& xx) { // real x = xx(0); // real y = xx(1); // real z = xx(2); // return x + y + z - 1; // }; // auto fphiPlane2 = [](const uvector& xx) { // real x = xx(0); // real y = xx(1); // real z = xx(2); // return x - y + z - 1; // }; // auto fphiPlane3 = [](const uvector& xx) { // real x = xx(0); // real y = xx(1); // real z = xx(2); // return -x + y + z - 1; // }; auto fphiPlane1 = [](const uvector& xx) { real x = xx(0); return x - 0.5; }; auto fphiPlane2 = [](const uvector& xx) { real x = xx(0); return -x - 0.5; }; auto fphiPlane3 = [](const uvector& xx) { real y = xx(1); return y - 0.5; }; auto fphiPlane4 = [](const uvector& xx) { real y = xx(1); return -y - 0.5; }; auto fphiPlane5 = [](const uvector& xx) { real z = xx(2); return z - 0.5; }; auto fphiPlane6 = [](const uvector& xx) { real z = xx(2); return -z - 0.5; }; algoim_spark_alloc(real, phis[0]); algoim_spark_alloc(real, phis[1]); algoim_spark_alloc(real, phis[2]); algoim_spark_alloc(real, phis[3]); algoim_spark_alloc(real, phis[4]); algoim_spark_alloc(real, phis[5]); bernstein::bernsteinInterpolate([&](const uvector& x) { return fphiPlane1(xmin + x * (xmax - xmin)); }, phis[0]); bernstein::bernsteinInterpolate([&](const uvector& x) { return fphiPlane2(xmin + x * (xmax - xmin)); }, phis[1]); bernstein::bernsteinInterpolate([&](const uvector& x) { return fphiPlane3(xmin + x * (xmax - xmin)); }, phis[2]); bernstein::bernsteinInterpolate([&](const uvector& x) { return fphiPlane4(xmin + x * (xmax - xmin)); }, phis[3]); bernstein::bernsteinInterpolate([&](const uvector& x) { return fphiPlane5(xmin + x * (xmax - xmin)); }, phis[4]); bernstein::bernsteinInterpolate([&](const uvector& x) { return fphiPlane6(xmin + x * (xmax - xmin)); }, phis[5]); auto integrand = [](const uvector& x) { return 1.0; }; // // qConvMultiPloy<3>(phi0, phi1, -1.0, 1.0, 3, integrand, 3, "exampleC"); std::cout << "testPlanesAlgoim" << std::endl; qConvMultiPloy2<3>(-1.0, 1.0, phis, integrand, 10); } void test8PlanesAlgoim() { const int N = 3; const uvector P = 3; real xmin = -1, xmax = 1; std::vector> phis(8, xarray(nullptr, P)); auto fphiPlane1 = [](const uvector& xx) { real x = xx(0); real y = xx(1); real z = xx(2); return x + y + z - 1; }; auto fphiPlane2 = [](const uvector& xx) { real x = xx(0); real y = xx(1); real z = xx(2); return x - y + z - 1; }; auto fphiPlane3 = [](const uvector& xx) { real x = xx(0); real y = xx(1); real z = xx(2); return -x + y + z - 1; }; auto fphiPlane4 = [](const uvector& xx) { real x = xx(0); real y = xx(1); real z = xx(2); return -x - y + z - 1; }; auto fphiPlane5 = [](const uvector& xx) { real x = xx(0); real y = xx(1); real z = xx(2); return x + y - z - 1; }; auto fphiPlane6 = [](const uvector& xx) { real x = xx(0); real y = xx(1); real z = xx(2); return x - y - z - 1; }; auto fphiPlane7 = [](const uvector& xx) { real x = xx(0); real y = xx(1); real z = xx(2); return -x + y - z - 1; }; auto fphiPlane8 = [](const uvector& xx) { real x = xx(0); real y = xx(1); real z = xx(2); return -x - y - z - 1; }; algoim_spark_alloc(real, phis[0]); algoim_spark_alloc(real, phis[1]); algoim_spark_alloc(real, phis[2]); algoim_spark_alloc(real, phis[3]); algoim_spark_alloc(real, phis[4]); algoim_spark_alloc(real, phis[5]); algoim_spark_alloc(real, phis[6]); algoim_spark_alloc(real, phis[7]); bernstein::bernsteinInterpolate([&](const uvector& x) { return fphiPlane1(xmin + x * (xmax - xmin)); }, phis[0]); bernstein::bernsteinInterpolate([&](const uvector& x) { return fphiPlane2(xmin + x * (xmax - xmin)); }, phis[1]); bernstein::bernsteinInterpolate([&](const uvector& x) { return fphiPlane3(xmin + x * (xmax - xmin)); }, phis[2]); bernstein::bernsteinInterpolate([&](const uvector& x) { return fphiPlane4(xmin + x * (xmax - xmin)); }, phis[3]); bernstein::bernsteinInterpolate([&](const uvector& x) { return fphiPlane5(xmin + x * (xmax - xmin)); }, phis[4]); bernstein::bernsteinInterpolate([&](const uvector& x) { return fphiPlane6(xmin + x * (xmax - xmin)); }, phis[5]); bernstein::bernsteinInterpolate([&](const uvector& x) { return fphiPlane7(xmin + x * (xmax - xmin)); }, phis[6]); bernstein::bernsteinInterpolate([&](const uvector& x) { return fphiPlane8(xmin + x * (xmax - xmin)); }, phis[7]); auto integrand = [](const uvector& x) { return 1.0; }; // // qConvMultiPloy<3>(phi0, phi1, -1.0, 1.0, 3, integrand, 3, "exampleC"); std::cout << "testPlanesAlgoim" << std::endl; qConvMultiPloy2<3>(-1.0, 1.0, phis, integrand, 10); } void compositePower(const std::vector>& powers, int powerIdx, uvector powerSum, real factor, xarray& res) { if (powerIdx == 0) { { uvector3 ext(1, 1, 1); for (auto& t : powers) { ext += t.ext() - 1; } assert(all(ext == res.ext())); } xarrayInit(res); } if (powerIdx == powers.size()) { res.m(powerSum) += factor; return; } auto& power = powers[powerIdx]; for (auto i = power.loop(); ~i; ++i) { if (power.l(i) == 0) { // factor = 0; continue; } compositePower(powers, powerIdx + 1, powerSum + i(), factor * power.l(i), res); } // int a = 1; } void test8PlanesPowerDirectly() { // a_x(x-c_x)^2 + a_y(y-c_y)^2 + a_z(x-c_z)^2 - r^2 uvector xmin = -1, xmax = 1; uvector range = xmax - xmin; assert(all(range != 0)); uvector k = range; uvector bias = xmin; uvector ext = 2; std::vector> phiPowers(8, xarray(nullptr, ext)); algoim_spark_alloc(real, phiPowers[0], phiPowers[1], phiPowers[2], phiPowers[3], phiPowers[4], phiPowers[5], phiPowers[6], phiPowers[7]); for (int i = 0; i < 8; i++) { xarrayInit(phiPowers[i]); if (i & 1) { phiPowers[i].m(uvector(0, 0, 1)) = 1; } else { phiPowers[i].m(uvector(0, 0, 1)) = -1; } if (i & 2) { phiPowers[i].m(uvector(0, 1, 0)) = 1; } else { phiPowers[i].m(uvector(0, 1, 0)) = -1; } if (i & 4) { phiPowers[i].m(uvector(1, 0, 0)) = 1; } else { phiPowers[i].m(uvector(1, 0, 0)) = -1; } phiPowers[i].m(uvector(0, 0, 0)) = -1; } uvector resExt = 1 + phiPowers.size(); xarray phiPowerAll(nullptr, resExt), phiBernstein(nullptr, resExt); algoim_spark_alloc(real, phiPowerAll, phiBernstein); compositePower(phiPowers, 0, 0, 1, phiPowerAll); powerTransformation(range, xmin, phiPowerAll); auto integrand = [](const uvector& x) { return 1.0; }; power2BernsteinTensorProduct(phiPowerAll, phiBernstein); uvector testX(0., 0., 0.75); real testEval = powerEvaluation(phiPowerAll, testX); std::cout << "eval power:" << testEval << std::endl; real testEvalBernstein = bernstein::evalBernsteinPoly(phiBernstein, testX); auto vec = xarray2StdVector(phiBernstein); std::cout << "eval bernstein:" << testEvalBernstein << std::endl; std::cout << "test8PlanesPowerDirectly" << std::endl; qConvBernstein(phiBernstein, -1, 1, integrand, 10, { {1, 1, 1, -1}, {1, 1, -1, -1}, {1, -1, 1, -1}, {1, -1, -1, -1}, {-1, 1, 1, -1}, {-1, 1, -1, -1}, {-1, -1, 1, -1}, {-1, -1, -1, -1} }); } void test3PlanesAlgoim() { const int N = 3; const uvector P = 3; real xmin = -1, xmax = 1; std::vector> phis(3, xarray(nullptr, P)); auto fphiPlane1 = [](const uvector& xx) { real x = xx(0); real y = xx(1); return x + y; }; auto fphiPlane2 = [](const uvector& xx) { real x = xx(0); real y = xx(1); return x - y; }; auto fphiPlane3 = [](const uvector& xx) { real x = xx(0); return -x - 1; }; algoim_spark_alloc(real, phis[0]); algoim_spark_alloc(real, phis[1]); algoim_spark_alloc(real, phis[2]); bernstein::bernsteinInterpolate([&](const uvector& x) { return fphiPlane1(xmin + x * (xmax - xmin)); }, phis[0]); bernstein::bernsteinInterpolate([&](const uvector& x) { return fphiPlane2(xmin + x * (xmax - xmin)); }, phis[1]); bernstein::bernsteinInterpolate([&](const uvector& x) { return fphiPlane3(xmin + x * (xmax - xmin)); }, phis[2]); auto integrand = [](const uvector& x) { return 1.0; }; // // qConvMultiPloy<3>(phi0, phi1, -1.0, 1.0, 3, integrand, 3, "exampleC"); std::cout << "testPlanesAlgoim" << std::endl; qConvMultiPloy2<3>(-1.0, 1.0, phis, integrand, 10); } void test3PlanesPowerDirectly() { // a_x(x-c_x)^2 + a_y(y-c_y)^2 + a_z(x-c_z)^2 - r^2 uvector xmin = -1, xmax = 1; uvector range = xmax - xmin; assert(all(range != 0)); uvector k = range; uvector bias = xmin; uvector ext = 2; std::vector> phiPowers(3, xarray(nullptr, ext)); algoim_spark_alloc(real, phiPowers[0]); algoim_spark_alloc(real, phiPowers[1]); algoim_spark_alloc(real, phiPowers[2]); for (int i = 0; i < 3; i++) { xarrayInit(phiPowers[i]); } phiPowers[0].m(uvector(1, 0, 0)) = 1; phiPowers[0].m(uvector(0, 1, 0)) = 1; phiPowers[1].m(uvector(1, 0, 0)) = 1; phiPowers[1].m(uvector(0, 1, 0)) = -1; phiPowers[2].m(uvector(1, 0, 0)) = -1; phiPowers[2].m(uvector(0, 0, 0)) = -1; uvector resExt = 1 + phiPowers.size(); xarray phiPowerAll(nullptr, resExt), phiBernstein(nullptr, resExt); algoim_spark_alloc(real, phiPowerAll); algoim_spark_alloc(real, phiBernstein); compositePower(phiPowers, 0, 0, 1, phiPowerAll); auto v = xarray2StdVector(phiPowerAll); uvector testX(0., 0.75, 0); real testEval = powerEvaluation(phiPowerAll, testX); std::cout << "eval power before trans:" << testEval << std::endl; powerTransformation(range, xmin, phiPowerAll); auto vAfterTrans = xarray2StdVector(phiPowerAll); auto integrand = [](const uvector& x) { return 1.0; }; power2BernsteinTensorProduct(phiPowerAll, phiBernstein); // bernstein::normalise(phiBernstein); real testEval0 = powerEvaluation(phiPowers[0], testX); std::cout << "eval power0:" << testEval0 << std::endl; real testEval1 = powerEvaluation(phiPowers[1], testX); std::cout << "eval power1:" << testEval1 << std::endl; real testEval2 = powerEvaluation(phiPowers[2], testX); std::cout << "eval power2:" << testEval2 << std::endl; real testEvalBernstein = bernstein::evalBernsteinPoly(phiBernstein, testX); auto vec = xarray2StdVector(phiBernstein); std::cout << "eval bernstein:" << testEvalBernstein << std::endl; std::cout << "test8PlanesPowerDirectly" << std::endl; qConvBernstein(phiBernstein, -1, 1, integrand, 10, { {1, 1, 0, 0 }, {1, -1, 0, 0 }, {-1, 0, 0, -1}, }); } void testConicAlgoim() { const int N = 3; const uvector P = 3; real xmin = -1, xmax = 1; std::vector> phis(3, xarray(nullptr, P)); auto fphiPlane1 = [](const uvector& xx) { real x = xx(0); real y = xx(1); real z = xx(2); return x * x + y * y - z * z; }; auto fphiPlane2 = [](const uvector& xx) { real x = xx(0); real y = xx(1); real z = xx(2); return x * z - y; }; auto fphiPlane3 = [](const uvector& xx) { real x = xx(0); return -x - 1; }; algoim_spark_alloc(real, phis[0]); algoim_spark_alloc(real, phis[1]); algoim_spark_alloc(real, phis[2]); bernstein::bernsteinInterpolate([&](const uvector& x) { return fphiPlane1(xmin + x * (xmax - xmin)); }, phis[0]); bernstein::bernsteinInterpolate([&](const uvector& x) { return fphiPlane2(xmin + x * (xmax - xmin)); }, phis[1]); bernstein::bernsteinInterpolate([&](const uvector& x) { return fphiPlane3(xmin + x * (xmax - xmin)); }, phis[2]); auto integrand = [](const uvector& x) { return 1.0; }; // // qConvMultiPloy<3>(phi0, phi1, -1.0, 1.0, 3, integrand, 3, "exampleC"); std::cout << "testPlanesAlgoim" << std::endl; qConvMultiPloy2<3>(-1.0, 1.0, phis, integrand, 10); } void testQuarterSphere() { uvector xmin = -1, xmax = 1; uvector range = xmax - xmin; assert(all(range != 0)); uvector k = range; uvector bias = xmin; std::vector> phiPowers; phiPowers.push_back(xarray(nullptr, 3)); phiPowers.push_back(xarray(nullptr, 2)); phiPowers.push_back(xarray(nullptr, 2)); algoim_spark_alloc(real, phiPowers[0]); algoim_spark_alloc(real, phiPowers[1]); algoim_spark_alloc(real, phiPowers[2]); for (int i = 0; i < 3; i++) { xarrayInit(phiPowers[i]); } phiPowers[0].m(uvector(2, 0, 0)) = 1; phiPowers[0].m(uvector(0, 2, 0)) = 1; phiPowers[0].m(uvector(0, 0, 2)) = 1; phiPowers[0].m(uvector(0, 0, 0)) = -1; phiPowers[1].m(uvector(1, 0, 0)) = 1; phiPowers[1].m(uvector(0, 1, 0)) = 1; // phiPowers[1].m(uvector(0, 0, 1)) = 1; phiPowers[2].m(uvector(1, 0, 0)) = 1; phiPowers[2].m(uvector(0, 1, 0)) = -1; // phiPowers[2].m(uvector(0, 0, 1)) = -1; uvector resExt = 1 + 2 + 1 + 1; xarray phiPowerAll(nullptr, resExt), phiBernstein(nullptr, resExt); algoim_spark_alloc(real, phiPowerAll); algoim_spark_alloc(real, phiBernstein); compositePower(phiPowers, 0, 0, 1, phiPowerAll); auto v = xarray2StdVector(phiPowerAll); uvector testX(0., 0.75, 0); real testEval = powerEvaluation(phiPowerAll, testX); std::cout << "eval power before trans:" << testEval << std::endl; powerTransformation(range, xmin, phiPowerAll); auto vAfterTrans = xarray2StdVector(phiPowerAll); auto integrand = [](const uvector& x) { return 1.0; }; power2BernsteinTensorProduct(phiPowerAll, phiBernstein); // bernstein::normalise(phiBernstein); real testEval0 = powerEvaluation(phiPowers[0], testX); std::cout << "eval power0:" << testEval0 << std::endl; real testEval1 = powerEvaluation(phiPowers[1], testX); std::cout << "eval power1:" << testEval1 << std::endl; real testEval2 = powerEvaluation(phiPowers[2], testX); std::cout << "eval power2:" << testEval2 << std::endl; real testEvalBernstein = bernstein::evalBernsteinPoly(phiBernstein, testX); auto vec = xarray2StdVector(phiBernstein); std::cout << "eval bernstein:" << testEvalBernstein << std::endl; std::cout << "testSphereQuarterDirectly" << std::endl; qConvBernstein(phiBernstein, -1, 1, integrand, 30, { {1, 1, 0, 0}, {1, -1, 0, 0}, }); } void test4PlanesAlgoim() { const int N = 3; const uvector P = 3; real xmin = -1, xmax = 1; std::vector> phis(4, xarray(nullptr, P)); auto fphiPlane1 = [](const uvector& xx) { real x = xx(0); real y = xx(1); return x + y; }; auto fphiPlane2 = [](const uvector& xx) { real x = xx(0); real y = xx(1); return x - y; }; auto fphiPlane3 = [](const uvector& xx) { real x = xx(0); return -x - 1; }; auto fphiPlane4 = [](const uvector& xx) { real x = xx(0); real y = xx(1); real z = xx(2); // return x + y - z; return y - 1; }; algoim_spark_alloc(real, phis[0]); algoim_spark_alloc(real, phis[1]); algoim_spark_alloc(real, phis[2]); algoim_spark_alloc(real, phis[3]); bernstein::bernsteinInterpolate([&](const uvector& x) { return fphiPlane1(xmin + x * (xmax - xmin)); }, phis[0]); bernstein::bernsteinInterpolate([&](const uvector& x) { return fphiPlane2(xmin + x * (xmax - xmin)); }, phis[1]); bernstein::bernsteinInterpolate([&](const uvector& x) { return fphiPlane3(xmin + x * (xmax - xmin)); }, phis[2]); bernstein::bernsteinInterpolate([&](const uvector& x) { return fphiPlane4(xmin + x * (xmax - xmin)); }, phis[3]); auto integrand = [](const uvector& x) { return 1.0; }; // // qConvMultiPloy<3>(phi0, phi1, -1.0, 1.0, 3, integrand, 3, "exampleC"); std::cout << "test4PlanesAlgoim" << std::endl; qConvMultiPloy2<3>(-1.0, 1.0, phis, integrand, 10); } void test4PlanesPowerDirectly() { // a_x(x-c_x)^2 + a_y(y-c_y)^2 + a_z(x-c_z)^2 - r^2 uvector xmin = -1, xmax = 1; uvector range = xmax - xmin; assert(all(range != 0)); uvector k = range; uvector bias = xmin; uvector ext = 2; std::vector> phiPowers(4, xarray(nullptr, ext)); algoim_spark_alloc(real, phiPowers[0]); algoim_spark_alloc(real, phiPowers[1]); algoim_spark_alloc(real, phiPowers[2]); algoim_spark_alloc(real, phiPowers[3]); for (int i = 0; i < 4; i++) { xarrayInit(phiPowers[i]); } phiPowers[0].m(uvector(1, 0, 0)) = 1; phiPowers[0].m(uvector(0, 1, 0)) = 1; phiPowers[1].m(uvector(1, 0, 0)) = 1; phiPowers[1].m(uvector(0, 1, 0)) = -1; phiPowers[2].m(uvector(1, 0, 0)) = -1; phiPowers[2].m(uvector(0, 0, 0)) = -1; phiPowers[3].m(uvector(1, 0, 0)) = 1; phiPowers[3].m(uvector(0, 1, 0)) = 1; phiPowers[3].m(uvector(0, 0, 1)) = -1; uvector resExt = 1 + phiPowers.size(); xarray phiPowerAll(nullptr, resExt), phiBernstein(nullptr, resExt); algoim_spark_alloc(real, phiPowerAll); algoim_spark_alloc(real, phiBernstein); compositePower(phiPowers, 0, 0, 1, phiPowerAll); auto v = xarray2StdVector(phiPowerAll); uvector testX(0., 0.75, 0.2); real testEval = powerEvaluation(phiPowerAll, testX); std::cout << "eval power before trans:" << testEval << std::endl; powerTransformation(range, xmin, phiPowerAll); real testEvalAfterTrans = powerEvaluation(phiPowerAll, testX); std::cout << "eval power after trans:" << testEvalAfterTrans << std::endl; auto vAfterTrans = xarray2StdVector(phiPowerAll); auto integrand = [](const uvector& x) { return 1.0; }; power2BernsteinTensorProduct(phiPowerAll, phiBernstein); // bernstein::normalise(phiBernstein); real testEval0 = powerEvaluation(phiPowers[0], testX); std::cout << "eval power0:" << testEval0 << std::endl; real testEval1 = powerEvaluation(phiPowers[1], testX); std::cout << "eval power1:" << testEval1 << std::endl; real testEval2 = powerEvaluation(phiPowers[2], testX); std::cout << "eval power2:" << testEval2 << std::endl; real testEvalBernstein = bernstein::evalBernsteinPoly(phiBernstein, testX); auto vec = xarray2StdVector(phiBernstein); std::cout << "eval bernstein:" << testEvalBernstein << std::endl; std::cout << "test4PlanesPowerDirectly" << std::endl; qConvBernstein(phiBernstein, -1, 1, integrand, 10, { {1, 1, 0, 0 }, {1, -1, 0, 0 }, {-1, 0, 0, -1}, {1, 1, -1, 0 }, }); } void testMultiScale() { auto phi0 = [](const uvector& xx) { real x = xx(0) + 100000.; real y = xx(1); real z = xx(2) - 100000.; real r = 800000.; return x * x + y * y + z * z - r * r; }; auto phi1 = [](const uvector& xx) { // real x = xx(0); // real y = xx(1); // real z = xx(2); // return x * x + y * y + z * z - 1; real x = xx(0) + 100000.; real y = xx(1) - 800000.; real z = xx(2) - 100000.; real r = 1000.; return x * x + y * y + z * z - r * r; }; auto phi2 = [](const uvector& xx) { real z = xx(2); return -z - 100000.; }; auto integrand = [](const uvector& x) { return 1.0; }; qConvMultiPloy<3>(phi0, phi2, -1000000., 1000000., 3, integrand, 20, Difference); } void testBitSet() { std::bitset<10> set(128); set.set(); std::cout << set << std::endl; } void testBooluarray() { algoim::booluarray<2, 3> tmp; tmp(0) = true; tmp(1) = true; tmp(2) = true; std::cout << tmp.bits << std::endl; } void testPower2Bernstein() { uvector ext(3, 3, 3); xarray power(nullptr, ext), bernstein(nullptr, ext); algoim_spark_alloc(real, power, bernstein); xarrayInit(power); power.m(uvector(1, 2, 0)) = 3; power.m(uvector(0, 1, 2)) = 4; power.m(uvector(1, 2, 2)) = 5; power.m(uvector(0, 0, 0)) = 3; uvector3 X(0.8, 0.7, 0.6); auto evalPower = powerEvaluation(power, X); power2BernsteinTensorProduct(power, bernstein); auto evalBernstein = bernstein::evalBernsteinPoly(bernstein, X); std::cout << "eval power: " << evalPower << std::endl; std::cout << "eval bernstein: " << evalBernstein << std::endl; } void testMain() { // testBooluarray(); // testMultiPolys(); // testMultiScale(); // testSpherePowerDirectly(); // testSpherePowerDirectlyByTransformation(); // testCylinderPowerDirectly(); // testCylinderAlgoim(); // test8PlanesAlgoim(); // test8PlanesPowerDirectly(); // test4PlanesPowerDirectly(); // test4PlanesAlgoim(); // testQuarterSphere(); // testPower2Bernstein(); }