From b51f691ef1c5e40ea3a2261f4cf23c3a56bfe35d Mon Sep 17 00:00:00 2001 From: "Victor A. P. Magri" <50467563+victorapm@users.noreply.github.com> Date: Thu, 1 Feb 2024 13:36:43 -0500 Subject: [PATCH] Add MGR restriction helper (#1037) Add hypre_MGRBuildRFromW for building classical restriction operators R = [-Wr I] from an input matrix Wr --- src/parcsr_ls/_hypre_parcsr_ls.h | 5 +- src/parcsr_ls/par_mgr.c | 11 --- src/parcsr_ls/par_mgr_interp.c | 136 +++++++++++++++++++++++++++++++ src/parcsr_ls/protos.h | 5 +- 4 files changed, 144 insertions(+), 13 deletions(-) diff --git a/src/parcsr_ls/_hypre_parcsr_ls.h b/src/parcsr_ls/_hypre_parcsr_ls.h index ee0fdc1968..220f272efa 100644 --- a/src/parcsr_ls/_hypre_parcsr_ls.h +++ b/src/parcsr_ls/_hypre_parcsr_ls.h @@ -3701,7 +3701,7 @@ HYPRE_Int hypre_MGRGetNumIterations( void *mgr_vdata, HYPRE_Int *num_iterations HYPRE_Int hypre_MGRGetFinalRelativeResidualNorm( void *mgr_vdata, HYPRE_Real *res_norm ); HYPRE_Int hypre_MGRGetCoarseGridConvergenceFactor( void *mgr_data, HYPRE_Real *conv_factor ); -/* par_mgr.c */ +/* par_mgr_interp.c */ HYPRE_Int hypre_MGRBuildInterp( hypre_ParCSRMatrix *A, hypre_ParCSRMatrix *A_FF, hypre_ParCSRMatrix *A_FC, HYPRE_Int *CF_marker, hypre_ParCSRMatrix *S, HYPRE_BigInt *num_cpts_global, @@ -3740,6 +3740,9 @@ HYPRE_Int hypre_MGRGetAcfCPR( hypre_ParCSRMatrix *A, HYPRE_Int blk_size, HYPRE_Int *c_marker, HYPRE_Int *f_marker, hypre_ParCSRMatrix **A_CF_ptr ); HYPRE_Int hypre_MGRTruncateAcfCPR( hypre_ParCSRMatrix *A_CF, hypre_ParCSRMatrix **A_CF_new_ptr ); +HYPRE_Int hypre_MGRBuildRFromW( HYPRE_Int *C_map, HYPRE_Int *F_map, HYPRE_BigInt *row_starts_R, + HYPRE_BigInt *col_starts_R, hypre_ParCSRMatrix *W, + hypre_ParCSRMatrix **R_ptr ); /* par_mgr_coarsen.c */ HYPRE_Int hypre_MGRCoarseParms( MPI_Comm comm, HYPRE_Int num_rows, hypre_IntArray *CF_marker, diff --git a/src/parcsr_ls/par_mgr.c b/src/parcsr_ls/par_mgr.c index 264338385a..f4dce4a01c 100644 --- a/src/parcsr_ls/par_mgr.c +++ b/src/parcsr_ls/par_mgr.c @@ -21,17 +21,6 @@ //#include "dsuperlu.h" //#endif -#if defined(HYPRE_USING_GPU) -void hypre_NoGPUSupport(char *option) -{ - char msg[256]; - hypre_sprintf(msg, "Error: Chosen %s option is not currently supported on GPU\n\n", option); - hypre_printf("%s ", msg); - // hypre_error_w_msg(1, msg); - hypre_MPI_Abort(hypre_MPI_COMM_WORLD, -1); -} -#endif - /* Need to define these hypre_lapack protos here instead of including _hypre_lapack.h to avoid conflicts with * dsuperlu.h on some lapack functions. Alternative is to move superLU related functions to a separate file. */ diff --git a/src/parcsr_ls/par_mgr_interp.c b/src/parcsr_ls/par_mgr_interp.c index a227244736..5e7b2a94d5 100644 --- a/src/parcsr_ls/par_mgr_interp.c +++ b/src/parcsr_ls/par_mgr_interp.c @@ -2375,3 +2375,139 @@ hypre_MGRTruncateAcfCPR(hypre_ParCSRMatrix *A_CF, return hypre_error_flag; } + +/*-------------------------------------------------------------------------- + * hypre_MGRBuildRFromWHost + * + * Constructs a classical restriction operator as R = [-W I]. + *--------------------------------------------------------------------------*/ + +HYPRE_Int +hypre_MGRBuildRFromWHost(HYPRE_Int *C_map, + HYPRE_Int *F_map, + hypre_ParCSRMatrix *W, + hypre_ParCSRMatrix *R) +{ + /* Input matrix variables */ + hypre_CSRMatrix *W_diag = hypre_ParCSRMatrixDiag(W); + HYPRE_Int *W_diag_i = hypre_CSRMatrixI(W_diag); + HYPRE_Int *W_diag_j = hypre_CSRMatrixJ(W_diag); + HYPRE_Complex *W_diag_a = hypre_CSRMatrixData(W_diag); + HYPRE_Int W_diag_num_rows = hypre_CSRMatrixNumRows(W_diag); + + /* Output matrix */ + hypre_CSRMatrix *R_diag = hypre_ParCSRMatrixDiag(R); + HYPRE_Int *R_diag_i = hypre_CSRMatrixI(R_diag); + HYPRE_Int *R_diag_j = hypre_CSRMatrixJ(R_diag); + HYPRE_Complex *R_diag_a = hypre_CSRMatrixData(R_diag); + + /* Local variables */ + HYPRE_Int i, j, nnz_diag; + HYPRE_Real one = 1.0; + + R_diag_i[0] = nnz_diag = 0; + for (i = 0; i < W_diag_num_rows; i++) + { + /* Set CF connections */ + for (j = W_diag_i[i]; j < W_diag_i[i + 1]; j++) + { + R_diag_j[nnz_diag] = F_map[W_diag_j[j]]; + R_diag_a[nnz_diag] = - W_diag_a[j]; + nnz_diag++; + } + + /* Set CC connection */ + R_diag_j[nnz_diag] = C_map[i]; + R_diag_a[nnz_diag] = one; + nnz_diag++; + + /* Update row pointer */ + R_diag_i[i + 1] = nnz_diag; + } + + return hypre_error_flag; +} + +/*-------------------------------------------------------------------------- + * hypre_MGRBuildRFromW + * + * Constructs a classical restriction operator as R = [-W I]. + *--------------------------------------------------------------------------*/ + +HYPRE_Int +hypre_MGRBuildRFromW(HYPRE_Int *C_map, + HYPRE_Int *F_map, + HYPRE_BigInt *row_starts_R, + HYPRE_BigInt *col_starts_R, + hypre_ParCSRMatrix *W, + hypre_ParCSRMatrix **R_ptr) +{ + /* Input matrix variables */ + MPI_Comm comm = hypre_ParCSRMatrixComm(W); + HYPRE_BigInt num_rows_W = hypre_ParCSRMatrixGlobalNumRows(W); + HYPRE_BigInt num_cols_W = hypre_ParCSRMatrixGlobalNumCols(W); + HYPRE_MemoryLocation memory_location_W = hypre_ParCSRMatrixMemoryLocation(W); + + hypre_CSRMatrix *W_diag = hypre_ParCSRMatrixDiag(W); + HYPRE_Int W_diag_num_rows = hypre_CSRMatrixNumRows(W_diag); + HYPRE_Int W_diag_nnz = hypre_CSRMatrixNumNonzeros(W_diag); + + hypre_CSRMatrix *W_offd = hypre_ParCSRMatrixOffd(W); + HYPRE_Int W_offd_num_cols = hypre_CSRMatrixNumCols(W_offd); + HYPRE_Int W_offd_nnz = hypre_CSRMatrixNumNonzeros(W_offd); + + /* Output matrix */ + hypre_ParCSRMatrix *R; + HYPRE_BigInt num_rows_R = num_rows_W; + HYPRE_BigInt num_cols_R = num_cols_W + num_rows_W; + HYPRE_Int num_nonzeros_diag = W_diag_nnz + W_diag_num_rows; + HYPRE_Int num_nonzeros_offd = W_offd_nnz; + + /* Sanity checks */ + if (W_offd_nnz > 0 || W_offd_num_cols > 0) + { + *R_ptr = NULL; + + hypre_error_w_msg(HYPRE_ERROR_GENERIC, "Not implemented for matrices with nonzero offd"); + return hypre_error_flag; + } + + /*----------------------------------------------------------------------- + * Create and initialize output matrix + *-----------------------------------------------------------------------*/ + + R = hypre_ParCSRMatrixCreate(comm, num_rows_R, num_cols_R, + row_starts_R, col_starts_R, W_offd_num_cols, + num_nonzeros_diag, num_nonzeros_offd); + hypre_ParCSRMatrixInitialize_v2(R, memory_location_W); + + /*----------------------------------------------------------------------- + * Fill matrix entries + *-----------------------------------------------------------------------*/ + +#if defined (HYPRE_USING_GPU) + HYPRE_ExecutionPolicy exec = hypre_GetExecPolicy1(memory_location_W); + + if (exec == HYPRE_EXEC_DEVICE) + { + /* TODO (VPM): Implement hypre_MGRBuildRFromWDevice */ + hypre_ParCSRMatrixMigrate(W, HYPRE_MEMORY_HOST); + hypre_ParCSRMatrixMigrate(R, HYPRE_MEMORY_HOST); + hypre_MGRBuildRFromWHost(C_map, F_map, W, R); + hypre_ParCSRMatrixMigrate(W, HYPRE_MEMORY_DEVICE); + hypre_ParCSRMatrixMigrate(R, HYPRE_MEMORY_DEVICE); + } + else +#endif + { + hypre_MGRBuildRFromWHost(C_map, F_map, W, R); + } + + /* Setup communication package */ + hypre_MatvecCommPkgCreate(R); + + /* Set output pointer */ + *R_ptr = R; + + return hypre_error_flag; +} diff --git a/src/parcsr_ls/protos.h b/src/parcsr_ls/protos.h index a71ea61182..162cdf6c7b 100644 --- a/src/parcsr_ls/protos.h +++ b/src/parcsr_ls/protos.h @@ -2248,7 +2248,7 @@ HYPRE_Int hypre_MGRGetNumIterations( void *mgr_vdata, HYPRE_Int *num_iterations HYPRE_Int hypre_MGRGetFinalRelativeResidualNorm( void *mgr_vdata, HYPRE_Real *res_norm ); HYPRE_Int hypre_MGRGetCoarseGridConvergenceFactor( void *mgr_data, HYPRE_Real *conv_factor ); -/* par_mgr.c */ +/* par_mgr_interp.c */ HYPRE_Int hypre_MGRBuildInterp( hypre_ParCSRMatrix *A, hypre_ParCSRMatrix *A_FF, hypre_ParCSRMatrix *A_FC, HYPRE_Int *CF_marker, hypre_ParCSRMatrix *S, HYPRE_BigInt *num_cpts_global, @@ -2287,6 +2287,9 @@ HYPRE_Int hypre_MGRGetAcfCPR( hypre_ParCSRMatrix *A, HYPRE_Int blk_size, HYPRE_Int *c_marker, HYPRE_Int *f_marker, hypre_ParCSRMatrix **A_CF_ptr ); HYPRE_Int hypre_MGRTruncateAcfCPR( hypre_ParCSRMatrix *A_CF, hypre_ParCSRMatrix **A_CF_new_ptr ); +HYPRE_Int hypre_MGRBuildRFromW( HYPRE_Int *C_map, HYPRE_Int *F_map, HYPRE_BigInt *row_starts_R, + HYPRE_BigInt *col_starts_R, hypre_ParCSRMatrix *W, + hypre_ParCSRMatrix **R_ptr ); /* par_mgr_coarsen.c */ HYPRE_Int hypre_MGRCoarseParms( MPI_Comm comm, HYPRE_Int num_rows, hypre_IntArray *CF_marker,