99#include < limits>
1010
1111#include " rxmesh/geometry_util.cuh"
12- #include " rxmesh/matrix/cudss_cholesky_solver.h"
1312#include " rxmesh/reduce_handle.h"
1413#include " rxmesh/rxmesh_static.h"
1514#include " rxmesh/util/timer.h"
1615
16+ #include " rxmesh/matrix/cg_solver.h"
17+ #include " rxmesh/matrix/cudss_cholesky_solver.h"
18+ #include " rxmesh/matrix/pcg_solver.h"
19+
1720using namespace rxmesh ;
1821
1922int main (int argc, char ** argv)
@@ -22,10 +25,13 @@ int main(int argc, char** argv)
2225
2326 CLI ::App app{" Heat geodesics (Crane et al. 2017)" };
2427
25- std::string mesh_path = STRINGIFY (INPUT_DIR ) " sphere3.obj" ;
26- uint32_t device_id = 0 ;
27- uint32_t source_vid = 0 ;
28- T t_factor = 1 .0f ;
28+ std::string mesh_path = STRINGIFY (INPUT_DIR ) " sphere3.obj" ;
29+ uint32_t device_id = 0 ;
30+ uint32_t source_vid = 0 ;
31+ T t_factor = 1 .0f ;
32+ int cg_max_iter = 10000 ;
33+ std::string solver = " cudss" ;
34+
2935
3036 app.add_option (" -i,--input" , mesh_path, " Input OBJ mesh file" )
3137 ->default_val (mesh_path);
@@ -37,17 +43,37 @@ int main(int argc, char** argv)
3743 t_factor,
3844 " Heat time-step multiplier on h^2 (default 1)" )
3945 ->default_val (1 .0f );
46+ app.add_option (" -c,--cg_max_iter" , cg_max_iter, " Max #iter for CG solver" )
47+ ->default_val (cg_max_iter);
48+ app.add_option (" -l,--solver" ,
49+ solver,
50+ " Solver. Only cudss, cg, and pcg are supported" )
51+ ->default_val (solver);
4052
4153 try {
4254 app.parse (argc, argv);
4355 } catch (const CLI ::ParseError& e) {
4456 return app.exit (e);
4557 }
46-
4758 rx_init (device_id);
4859
49- RXMeshStatic rx (mesh_path);
60+ RXMESH_INFO (" input = {}" , mesh_path);
61+ RXMESH_INFO (" device_id = {}" , device_id);
62+ RXMESH_INFO (" source_vid = {}" , source_vid);
63+ RXMESH_INFO (" solver = {}" , solver);
64+ RXMESH_INFO (" cg_max_iter = {}" , cg_max_iter);
65+
66+ if (solver != " pcg" && solver != " cg" && solver != " cudss" ) {
67+ RXMESH_ERROR (
68+ " Unuspported solver option {}. Supported options are cudss, cg, "
69+ " and pcg" ,
70+ solver);
71+ return EXIT_FAILURE ;
72+ }
5073
74+
75+ RXMeshStatic rx (mesh_path);
76+
5177 auto coords = *rx.get_input_vertex_coordinates ();
5278
5379 const uint32_t num_vertices = rx.get_num_vertices ();
@@ -164,10 +190,21 @@ int main(int argc, char** argv)
164190
165191
166192 // 4) solve A_heat*u = rhs
167- cuDSSCholeskySolver<SparseMatrix<T>> heat_solver (&A_heat);
168- heat_solver.pre_solve (rx, rhs, phi_or_u);
169- heat_solver.solve (rhs, phi_or_u);
170-
193+ if (solver == " cudss" ) {
194+ cuDSSCholeskySolver<SparseMatrix<T>> heat_solver (&A_heat);
195+ heat_solver.pre_solve (rx, rhs, phi_or_u);
196+ heat_solver.solve (rhs, phi_or_u);
197+ }
198+ if (solver == " pcg" ) {
199+ PCGSolver<T> heat_solver (A_heat, 1 , cg_max_iter);
200+ heat_solver.pre_solve (rhs, phi_or_u);
201+ heat_solver.solve (rhs, phi_or_u);
202+ }
203+ if (solver == " cg" ) {
204+ CGSolver<T> heat_solver (A_heat, 1 , cg_max_iter);
205+ heat_solver.pre_solve (rhs, phi_or_u);
206+ heat_solver.solve (rhs, phi_or_u);
207+ }
171208
172209 // 5) Per-face X = -grad(u) / |grad(u)|.
173210 // For a triangle (p0, p1, p2) with face normal N:
@@ -250,26 +287,39 @@ int main(int argc, char** argv)
250287
251288
252289 // 7) Solve L phi = div(X)
253- cuDSSCholeskySolver<SparseMatrix<T>> poisson_solver (&L);
254290 phi_or_u.reset (0 , DEVICE );
255- poisson_solver.pre_solve (rx, rhs, phi_or_u);
256- poisson_solver.solve (rhs, phi_or_u);
291+ if (solver == " cudss" ) {
292+ cuDSSCholeskySolver<SparseMatrix<T>> poisson_solver (&L);
293+ poisson_solver.pre_solve (rx, rhs, phi_or_u);
294+ poisson_solver.solve (rhs, phi_or_u);
295+ }
296+ if (solver == " pcg" ) {
297+ PCGSolver<T> poisson_solver (L, 1 , cg_max_iter);
298+ poisson_solver.pre_solve (rhs, phi_or_u);
299+ poisson_solver.solve (rhs, phi_or_u);
300+ }
301+ if (solver == " cg" ) {
302+ CGSolver<T> poisson_solver (L, 1 , cg_max_iter);
303+ poisson_solver.pre_solve (rhs, phi_or_u);
304+ poisson_solver.solve (rhs, phi_or_u);
305+ }
257306
258307
259308 // Distance = phi - phi(source)
260309 rx.for_each_vertex (DEVICE , [=] __device__ (const VertexHandle vh) mutable {
261310 dist (vh, 0 ) = phi_or_u (vh, 0 ) - phi_or_u (source_handle, 0 );
262311 });
263- dist.move (DEVICE , HOST );
312+ dist.move (DEVICE , HOST );
264313
265314 timer.stop ();
266315
267316 RXMESH_INFO (" Heat Geodesics took {} (ms)" , timer.elapsed_millis ());
268317#if USE_POLYSCOPE
318+ auto ps_geo =
319+ rx.get_polyscope_mesh ()->addVertexScalarQuantity (" geodesic" , dist);
320+ ps_geo->setEnabled (true );
269321
270- rx.get_polyscope_mesh ()
271- ->addVertexScalarQuantity (" geodesic" , dist)
272- ->setEnabled (true );
322+ ps_geo->setIsolinesEnabled (true );
273323 polyscope::show ();
274324#endif
275325
0 commit comments