diff --git a/CMakeLists.txt b/CMakeLists.txt index e1729bd2..c07f3fbb 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -229,8 +229,8 @@ if(POLYSOLVE_WITH_HYPRE) include(hypre) target_link_libraries(polysolve_linear PUBLIC HYPRE::HYPRE) target_compile_definitions(polysolve_linear PUBLIC POLYSOLVE_WITH_HYPRE) - if(HYPRE_WITH_MPI) - target_compile_definitions(polysolve_linear PUBLIC HYPRE_WITH_MPI) + if(HYPRE_ENABLE_MPI) + target_compile_definitions(polysolve_linear PUBLIC HYPRE_ENABLE_MPI) endif() endif() diff --git a/cmake/recipes/hypre.cmake b/cmake/recipes/hypre.cmake index 7cfd0c2b..5fde6c2c 100644 --- a/cmake/recipes/hypre.cmake +++ b/cmake/recipes/hypre.cmake @@ -6,18 +6,67 @@ endif() message(STATUS "Third-party: creating target 'HYPRE::HYPRE'") -set(HYPRE_WITH_MPI OFF CACHE INTERNAL "" FORCE) -set(HYPRE_PRINT_ERRORS ON CACHE INTERNAL "" FORCE) -set(HYPRE_BIGINT ON CACHE INTERNAL "" FORCE) -set(HYPRE_USING_FEI OFF CACHE INTERNAL "" FORCE) -set(HYPRE_USING_OPENMP OFF CACHE INTERNAL "" FORCE) -set(HYPRE_SHARED OFF CACHE INTERNAL "" FORCE) +set(HYPRE_ENABLE_MPI OFF CACHE INTERNAL "" FORCE) +set(HYPRE_ENABLE_PRINT_ERRORS ON CACHE INTERNAL "" FORCE) +set(HYPRE_ENABLE_BIGINT OFF CACHE INTERNAL "" FORCE) +set(HYPRE_ENABLE_MIXEDINT OFF CACHE BOOL "" FORCE) +set(HYPRE_ENABLE_FEI OFF CACHE INTERNAL "" FORCE) +set(HYPRE_ENABLE_OPENMP OFF CACHE INTERNAL "" FORCE) +set(HYPRE_ENABLE_UMPIRE OFF CACHE INTERNAL "" FORCE) + +if (POLYSOLVE_WITH_CUDA) + set(HYPRE_USING_GPU ON CACHE INTERNAL "" FORCE) + set(HYPRE_ENABLE_CUDA ON CACHE INTERNAL "" FORCE) +else() + set(HYPRE_USING_GPU OFF CACHE INTERNAL "" FORCE) + set(HYPRE_ENABLE_CUDA OFF CACHE INTERNAL "" FORCE) +endif() + +# HYPRE unconditionally defines an "uninstall" target, which conflicts with other buggy libraries +# as modern cmake requires unique target name. This is a hacky workaround until upstream is fixed. +macro(add_custom_target _target_name) + if("${_target_name}" STREQUAL "uninstall" AND TARGET uninstall) + # skip: HYPRE's uninstall target conflicts with an existing one + else() + _add_custom_target(${_target_name} ${ARGN}) + endif() +endmacro() include(CPM) CPMAddPackage( NAME hypre GITHUB_REPOSITORY hypre-space/hypre - GIT_TAG v2.28.0 + GIT_TAG v3.1.0 SOURCE_SUBDIR src ) -file(REMOVE "${hypre_SOURCE_DIR}/src/utilities/version") + +# HYPRE v3.1.0 relies on transitive Thrust includes that were removed in CCCL 3.2+. +# Patch HYPRE source. +if (POLYSOLVE_WITH_CUDA) + function(polysolve_prepend_hypre_include file_path include_line) + if(NOT EXISTS "${file_path}") + message(FATAL_ERROR "Expected HYPRE source file does not exist: ${file_path}") + endif() + + file(READ "${file_path}" file_contents) + string(FIND "${file_contents}" "${include_line}" include_pos) + if(include_pos EQUAL -1) + file(WRITE "${file_path}" "${include_line}\n${file_contents}") + endif() + endfunction() + + polysolve_prepend_hypre_include( + "${hypre_SOURCE_DIR}/src/utilities/device_utils.c" + "#include ") + polysolve_prepend_hypre_include( + "${hypre_SOURCE_DIR}/src/seq_mv/csr_matop_device.c" + "#include ") + polysolve_prepend_hypre_include( + "${hypre_SOURCE_DIR}/src/IJ_mv/IJMatrix_parcsr_device.c" + "#include ") + polysolve_prepend_hypre_include( + "${hypre_SOURCE_DIR}/src/IJ_mv/IJVector_parcsr_device.c" + "#include ") + + file(REMOVE "${hypre_SOURCE_DIR}/src/utilities/version") +endif() diff --git a/src/polysolve/linear/HypreSolver.cpp b/src/polysolve/linear/HypreSolver.cpp index 804eca1f..0901b880 100644 --- a/src/polysolve/linear/HypreSolver.cpp +++ b/src/polysolve/linear/HypreSolver.cpp @@ -15,7 +15,7 @@ namespace polysolve::linear HypreSolver::HypreSolver() { precond_num_ = 0; -#ifdef HYPRE_WITH_MPI +#ifdef HYPRE_ENABLE_MPI int done_already; MPI_Initialized(&done_already); @@ -32,6 +32,10 @@ namespace polysolve::linear MPI_Comm_size(MPI_COMM_WORLD, &num_procs); } #endif + if (!HYPRE_Initialized()) + { + HYPRE_Initialize(); + } } // Set solver parameters @@ -91,7 +95,7 @@ namespace polysolve::linear has_matrix_ = true; const HYPRE_Int rows = Ain.rows(); const HYPRE_Int cols = Ain.cols(); -#ifdef HYPRE_WITH_MPI +#ifdef HYPRE_ENABLE_MPI HYPRE_IJMatrixCreate(MPI_COMM_WORLD, 0, rows - 1, 0, cols - 1, &A); #else HYPRE_IJMatrixCreate(0, 0, rows - 1, 0, cols - 1, &A); @@ -285,7 +289,7 @@ namespace polysolve::linear /* Create solver */ HYPRE_Solver solver, precond; -#ifdef HYPRE_WITH_MPI +#ifdef HYPRE_ENABLE_MPI HYPRE_ParCSRPCGCreate(MPI_COMM_WORLD, &solver); #else HYPRE_ParCSRPCGCreate(0, &solver);