Skip to content

Commit 30fd34d

Browse files
committed
workaround for numerical non-SPD operator on some inputs
1 parent fdd6497 commit 30fd34d

File tree

1 file changed

+11
-1
lines changed

1 file changed

+11
-1
lines changed

src/surface/vector_heat_method.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "geometrycentral/surface/vector_heat_method.h"
2+
#include "geometrycentral/numerical/linear_algebra_utilities.h"
23
#include "geometrycentral/utilities/vector2.h"
34

45
namespace geometrycentral {
@@ -55,7 +56,9 @@ void VectorHeatMethodSolver::ensureHaveVectorHeatSolver() {
5556
// PositiveDefiniteSolver. Otherwise, we must use a SquareSolver
5657
geom.requireEdgeCotanWeights();
5758
bool isDelaunay = true;
59+
double minCotanWeight = std::numeric_limits<double>::max();
5860
for (Edge e : mesh.edges()) {
61+
minCotanWeight = std::min(minCotanWeight, geom.edgeCotanWeights[e]);
5962
if (geom.edgeCotanWeights[e] < -1e-6) {
6063
isDelaunay = false;
6164
break;
@@ -64,7 +67,14 @@ void VectorHeatMethodSolver::ensureHaveVectorHeatSolver() {
6467
geom.unrequireEdgeCotanWeights();
6568

6669
if (isDelaunay) {
67-
vectorHeatSolver.reset(new PositiveDefiniteSolver<std::complex<double>>(vectorOp));
70+
// TODO we said the matrix should be SPD if Delaunay, but SuiteSparse is failing with non-SPD error
71+
// (observed by nsharp on intrinsic delaunay RamSkull100k.obj)
72+
// workaround with a try-catch for now
73+
try {
74+
vectorHeatSolver.reset(new PositiveDefiniteSolver<std::complex<double>>(vectorOp));
75+
} catch (const std::runtime_error&) {
76+
vectorHeatSolver.reset(new SquareSolver<std::complex<double>>(vectorOp));
77+
}
6878
} else {
6979
vectorHeatSolver.reset(new SquareSolver<std::complex<double>>(vectorOp)); // not necessarily SPD without Delaunay
7080
}

0 commit comments

Comments
 (0)