Skip to content

Commit 326df40

Browse files
committed
Add tests
1 parent d01ff4d commit 326df40

3 files changed

Lines changed: 121 additions & 3 deletions

File tree

src/surface/embedded_geometry_interface.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -827,13 +827,14 @@ void EmbeddedGeometryInterface::computePolygonDECOperators() {
827827
size_t V = mesh.nVertices();
828828
size_t E = mesh.nEdges();
829829
size_t F = mesh.nFaces();
830-
size_t H = mesh.nInteriorHalfedges();
830+
size_t H = mesh.nHalfedges(); // technically only needs to be nInteriorHalfedges(), but interior halfedges aren't
831+
// indexed densely
831832
std::vector<Eigen::Triplet<double>> tripletsD0, tripletsD1, tripletsH1;
832833

833834
// exterior derivatives
834835
polygonD0 = Eigen::SparseMatrix<double>(H, V);
835-
for (Edge e : mesh.edges()) {
836-
for (Halfedge he : e.adjacentHalfedges()) {
836+
for (Face f : mesh.faces()) {
837+
for (Halfedge he : f.adjacentHalfedges()) {
837838
size_t hIdx = halfedgeIndices[he];
838839
size_t vA = vertexIndices[he.tailVertex()];
839840
size_t vB = vertexIndices[he.tipVertex()];

test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ set(TEST_SRCS
106106
src/load_test_meshes.cpp
107107
src/point_cloud_test.cpp
108108
src/poisson_disk_sampler_test.cpp
109+
src/polygon_operators_test.cpp
109110
src/stl_reader_test.cpp
110111
src/surface_misc_test.cpp
111112
)
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
#include "geometrycentral/surface/embedded_geometry_interface.h"
2+
#include "geometrycentral/surface/meshio.h"
3+
#include "geometrycentral/surface/vertex_position_geometry.h"
4+
5+
#include "load_test_meshes.h"
6+
7+
#include "gtest/gtest.h"
8+
9+
#include <iostream>
10+
#include <string>
11+
12+
using namespace geometrycentral;
13+
using namespace geometrycentral::surface;
14+
15+
class PolygonMeshSuite : public MeshAssetSuite {};
16+
17+
/* Test that the lumped mass matrices correspond with their unlumped versions. */
18+
TEST_F(PolygonMeshSuite, MassLumpingTest) {
19+
20+
double epsilon = 1e-8;
21+
for (MeshAsset& a : allMeshes()) {
22+
a.printThyName();
23+
SurfaceMesh& mesh = *a.mesh;
24+
VertexPositionGeometry& geometry = *a.geometry;
25+
26+
geometry.requireSimplePolygonVertexLumpedMassMatrix();
27+
geometry.requireSimplePolygonVertexGalerkinMassMatrix();
28+
29+
SparseMatrix<double> Mt = geometry.simplePolygonVertexGalerkinMassMatrix.transpose();
30+
SparseMatrix<double>& M = geometry.simplePolygonVertexLumpedMassMatrix;
31+
for (size_t i = 0; i < mesh.nVertices(); i++) {
32+
double rowSum = 0.;
33+
for (SparseMatrix<double>::InnerIterator it(Mt, i); it; ++it) {
34+
rowSum += it.value();
35+
}
36+
EXPECT_LT(std::abs(rowSum - M.coeffRef(i, i)), epsilon);
37+
}
38+
39+
geometry.unrequireSimplePolygonVertexLumpedMassMatrix();
40+
geometry.unrequireSimplePolygonVertexGalerkinMassMatrix();
41+
}
42+
}
43+
44+
/* Check that polygon Laplacians and mass matrices coincide with simplicial versions on a triangle mesh. */
45+
TEST_F(PolygonMeshSuite, TriangularTest) {
46+
47+
double epsilon = 1e-8;
48+
for (MeshAsset& a : triangularMeshes()) {
49+
a.printThyName();
50+
SurfaceMesh& mesh = *a.mesh;
51+
VertexPositionGeometry& geometry = *a.geometry;
52+
53+
geometry.requireVertexGalerkinMassMatrix();
54+
geometry.requireVertexLumpedMassMatrix();
55+
geometry.requireCotanLaplacian();
56+
geometry.requireSimplePolygonLaplacian();
57+
geometry.requireSimplePolygonVertexLumpedMassMatrix();
58+
geometry.requireSimplePolygonVertexGalerkinMassMatrix();
59+
geometry.requirePolygonLaplacian();
60+
geometry.requirePolygonVertexLumpedMassMatrix();
61+
62+
double L = geometry.cotanLaplacian.norm();
63+
double Mg = geometry.vertexGalerkinMassMatrix.norm();
64+
double Ml = geometry.vertexLumpedMassMatrix.norm();
65+
66+
EXPECT_LT((geometry.simplePolygonLaplacian - geometry.cotanLaplacian).norm() / L, epsilon);
67+
EXPECT_LT((geometry.polygonLaplacian - geometry.cotanLaplacian).norm() / L, epsilon);
68+
EXPECT_LT((geometry.simplePolygonVertexGalerkinMassMatrix - geometry.vertexGalerkinMassMatrix).norm() / Mg,
69+
epsilon);
70+
EXPECT_LT((geometry.simplePolygonVertexLumpedMassMatrix - geometry.vertexLumpedMassMatrix).norm() / Ml, epsilon);
71+
EXPECT_LT((geometry.polygonVertexLumpedMassMatrix - geometry.vertexLumpedMassMatrix).norm() / Ml, epsilon);
72+
73+
geometry.unrequireVertexGalerkinMassMatrix();
74+
geometry.unrequireVertexLumpedMassMatrix();
75+
geometry.unrequireCotanLaplacian();
76+
geometry.unrequireSimplePolygonLaplacian();
77+
geometry.unrequireSimplePolygonVertexLumpedMassMatrix();
78+
geometry.unrequireSimplePolygonVertexGalerkinMassMatrix();
79+
geometry.unrequirePolygonLaplacian();
80+
geometry.unrequirePolygonVertexLumpedMassMatrix();
81+
}
82+
}
83+
84+
/* Check that Laplacian can be assembled as expected from DEC operators. */
85+
TEST_F(PolygonMeshSuite, DECTest) {
86+
87+
double epsilon = 1e-8;
88+
for (MeshAsset& a : allMeshes()) {
89+
a.printThyName();
90+
SurfaceMesh& mesh = *a.mesh;
91+
VertexPositionGeometry& geometry = *a.geometry;
92+
93+
geometry.requirePolygonDECOperators();
94+
geometry.requirePolygonLaplacian();
95+
96+
SparseMatrix<double>& L = geometry.polygonLaplacian;
97+
SparseMatrix<double>& h0 = geometry.polygonHodge0;
98+
SparseMatrix<double>& h0Inv = geometry.polygonHodge0Inverse;
99+
SparseMatrix<double>& h1 = geometry.polygonHodge1;
100+
SparseMatrix<double>& h2 = geometry.polygonHodge2;
101+
SparseMatrix<double>& h2Inv = geometry.polygonHodge2Inverse;
102+
SparseMatrix<double>& d0 = geometry.polygonD0;
103+
SparseMatrix<double>& d1 = geometry.polygonD1;
104+
EXPECT_LT((L - d0.transpose() * h1 * d0).norm(), epsilon);
105+
106+
if (mesh.isTriangular()) {
107+
geometry.requireDECOperators();
108+
EXPECT_LT((h0 - geometry.hodge0).norm(), epsilon);
109+
EXPECT_LT((h2 - geometry.hodge2).norm(), epsilon);
110+
geometry.unrequireDECOperators();
111+
}
112+
113+
geometry.unrequirePolygonDECOperators();
114+
geometry.unrequirePolygonLaplacian();
115+
}
116+
}

0 commit comments

Comments
 (0)