#include "Eigen/SparseCore"
#include "Eigen/SparseLU"
#include "gtest/gtest.h"
class PoissonImplicitTest : public ::testing::Test {
public:
int N;
protected:
void SetUp() override {
size = {1, 1};
shift = {0, 0};
}
template <class BasisType, class WeightType>
double solve(const BasisType& basis, int support_size,
int num_nodes_x, const WeightType& weight) {
std::function<double(
Vec2d)> analytical = [=](
const Vec2d& p) {
return std::sin(
PI*(p[0]-shift[0])/size[0])*std::sin(
PI*(p[1]-shift[1])/size[1]);
};
Vec2d low = shift, high = shift+size;
BoxShape<Vec2d> box(low, high);
DomainDiscretization<Vec2d> domain = box.discretizeWithStep(size[0] / num_nodes_x);
N = domain.size();
domain.findSupport(FindClosest(support_size));
WLS<BasisType, WeightType, ScaleToFarthest> approx(basis, weight);
auto storage = domain.computeShapes<
sh::lap>(approx, domain.interior());
Eigen::SparseMatrix<double, Eigen::RowMajor> M(N, N);
M.reserve(storage.supportSizes());
Eigen::VectorXd rhs(N); rhs.setZero();
auto op = storage.implicitOperators(M, rhs);
for (int i : domain.interior()) {
auto p = domain.pos(i);
op.lap(i) = -
PI*
PI*(size.squaredNorm())/size[0]/size[0]/size[1]/size[1]*
std::sin(
PI*(p[0]-shift[0])/size[0])*std::sin(
PI*(p[1]-shift[1])/size[1]);
}
for (int i : domain.boundary()) {
op.value(i) = 0;
}
M.makeCompressed();
Eigen::SparseMatrix<double> M2 = M;
Eigen::SparseLU<decltype(M2)> solver;
solver.compute(M2);
Eigen::VectorXd sol = solver.solve(rhs);
Range<double> error(N);
double maxan = 0;
for (int i = 0; i < N; ++i) {
double an = analytical(domain.pos(i));
if (an > maxan) maxan = an;
error[i] = std::abs(an - sol[i]);
}
double L_inf_error = *std::max_element(error.begin(), error.end());
return L_inf_error / maxan;
}
};
TEST_F(PoissonImplicitTest, Monomials5NoWeight) {
Monomials<Vec2d> mon5({{0, 0}, {0, 1}, {1, 0}, {2, 0}, {0, 2}});
int ss = 5;
EXPECT_LT(solve(mon5, ss, 29, NoWeight<Vec2d>()), 1e-3);
EXPECT_LT(solve(mon5, ss, 93, NoWeight<Vec2d>()), 1e-4);
}
TEST_F(PoissonImplicitTest, Monomials5NoWeightShifted) {
shift = {-123.234, 234.98713};
Monomials<Vec2d> mon5({{0, 0}, {0, 1}, {1, 0}, {2, 0}, {0, 2}});
int ss = 5;
EXPECT_LT(solve(mon5, ss, 29, NoWeight<Vec2d>()), 1e-3);
}
TEST_F(PoissonImplicitTest, Monomials5NoWeightScaledUp) {
size = 1000.2345;
Monomials<Vec2d> mon5({{0, 0}, {0, 1}, {1, 0}, {2, 0}, {0, 2}});
int ss = 5;
EXPECT_LT(solve(mon5, ss, 29, NoWeight<Vec2d>()), 1e-3);
}
TEST_F(PoissonImplicitTest, Monomials5NoWeightScaledDown) {
size = 0.00112;
Monomials<Vec2d> mon5({{0, 0}, {0, 1}, {1, 0}, {2, 0}, {0, 2}});
int ss = 5;
EXPECT_LT(solve(mon5, ss, 29, NoWeight<Vec2d>()), 1e-3);
}
TEST_F(PoissonImplicitTest, Gaussians5NoWeight) {
double sigmaB = 100;
Gaussians<Vec2d> g5(5, sigmaB);
int ss = 5;
EXPECT_LT(solve(g5, ss, 29, NoWeight<Vec2d>()), 1e-3);
EXPECT_LT(solve(g5, ss, 93, NoWeight<Vec2d>()), 1e-5);
double err = solve(g5, ss, 167, NoWeight<Vec2d>());
EXPECT_LT(err, 1e-4);
EXPECT_GT(err, 1e-5);
}
TEST_F(PoissonImplicitTest, Gaussians5Weight) {
double sigmaB = 100;
int ss = 5;
Gaussians<Vec2d> g5(ss, sigmaB);
GaussianWeight<Vec2d> w(1000.0);
EXPECT_LT(solve(g5, ss, 29, NoWeight<Vec2d>()), 1e-3);
}
TEST_F(PoissonImplicitTest, Monomials9NoWeight) {
int ss = 9;
EXPECT_LT(solve(mon9, ss, 29, NoWeight<Vec2d>()), 1e-3);
EXPECT_LT(solve(mon9, ss, 93, NoWeight<Vec2d>()), 1e-4);
}
TEST_F(PoissonImplicitTest, Monomials9Weight) {
GaussianWeight<Vec2d> w(1000.0);
int ss = 9;
EXPECT_LT(solve(mon9, ss, 29, w), 1e-3);
EXPECT_LT(solve(mon9, ss, 93, w), 1e-4);
}
TEST_F(PoissonImplicitTest, Gaussians9NoWeight) {
double sigmaB = 100;
Gaussians<Vec2d> g9(9, sigmaB);
int ss = 9;
EXPECT_LT(solve(g9, ss, 22, NoWeight<Vec2d>()), 1e-2);
EXPECT_LT(solve(g9, ss, 66, NoWeight<Vec2d>()), 1e-3);
EXPECT_LT(solve(g9, ss, 149, NoWeight<Vec2d>()), 1e-4);
}
TEST_F(PoissonImplicitTest, Monomials6Weight) {
GaussianWeight<Vec2d> w(1.0);
Monomials<Vec2d> mon6(2);
int ss = 9;
EXPECT_LT(solve(mon6, ss, 18, w), 1e-2);
EXPECT_LT(solve(mon6, ss, 59, w), 1e-3);
}
}