opm-simulators
HypreUtils.hpp
1 /*
2  Copyright 2025 Equinor ASA
3 
4  This file is part of the Open Porous Media project (OPM).
5 
6  OPM is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  OPM is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with OPM. If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #ifndef OPM_HYPRE_MATRIX_UTILS_HPP
21 #define OPM_HYPRE_MATRIX_UTILS_HPP
22 
23 // Fix conflict with Dune's matrixmarket.hh header - HYPRE defines MM_MAX_LINE_LENGTH as macro
24 // but Dune expects it as enum value
25 #ifdef MM_MAX_LINE_LENGTH
26 #undef MM_MAX_LINE_LENGTH
27 #endif
28 
29 #include <opm/simulators/linalg/gpuistl/hypreinterface/HypreErrorHandling.hpp>
30 
31 #include <HYPRE.h>
32 #include <_hypre_utilities.h>
33 
34 #include <algorithm>
35 #include <vector>
36 
38 {
53 inline std::vector<HYPRE_Real>
54 getMatrixValues(HYPRE_IJMatrix hypre_matrix,
55  const std::vector<HYPRE_Int>& ncols,
56  const std::vector<HYPRE_BigInt>& rows,
57  const std::vector<HYPRE_BigInt>& cols,
58  bool use_gpu_backend = false)
59 {
60  const auto N = rows.size();
61  std::vector<HYPRE_Real> values(cols.size());
62 
63  if (use_gpu_backend) {
64  // HYPRE_IJMatrixGetValues not supported on GPU, use HYPRE_ParCSRMatrixGetRow instead
65  void* object;
66  OPM_HYPRE_SAFE_CALL(HYPRE_IJMatrixGetObject(hypre_matrix, &object));
67  auto par_csr_matrix = static_cast<HYPRE_ParCSRMatrix>(object);
68  HYPRE_Int max_row_size = *std::max_element(ncols.begin(), ncols.end());
69  HYPRE_Complex* row_values_host = hypre_CTAlloc(HYPRE_Complex, max_row_size, HYPRE_MEMORY_HOST);
70 
71  size_t value_idx = 0;
72  for (size_t row_idx = 0; row_idx < N; ++row_idx) {
73  HYPRE_Int row_ncols;
74  HYPRE_BigInt* row_cols_device;
75  HYPRE_Complex* row_values_device;
76  OPM_HYPRE_SAFE_CALL(HYPRE_ParCSRMatrixGetRow(
77  par_csr_matrix, rows[row_idx], &row_ncols, &row_cols_device, &row_values_device));
78  if (row_ncols > 0) {
79  hypre_TMemcpy(row_values_host,
80  row_values_device,
81  HYPRE_Complex,
82  row_ncols,
83  HYPRE_MEMORY_HOST,
84  HYPRE_MEMORY_DEVICE);
85  for (HYPRE_Int j = 0; j < row_ncols; ++j, ++value_idx) {
86  values[value_idx] = static_cast<HYPRE_Real>(row_values_host[j]);
87  }
88  }
89  OPM_HYPRE_SAFE_CALL(HYPRE_ParCSRMatrixRestoreRow(
90  par_csr_matrix, rows[row_idx], &row_ncols, &row_cols_device, &row_values_device));
91  }
92  hypre_TFree(row_values_host, HYPRE_MEMORY_HOST);
93  } else {
94  OPM_HYPRE_SAFE_CALL(HYPRE_IJMatrixGetValues(hypre_matrix,
95  N,
96  const_cast<HYPRE_Int*>(ncols.data()),
97  const_cast<HYPRE_BigInt*>(rows.data()),
98  const_cast<HYPRE_BigInt*>(cols.data()),
99  values.data()));
100  }
101  return values;
102 }
103 } // namespace Opm::gpuistl::HypreInterface
104 
105 #endif // OPM_HYPRE_MATRIX_UTILS_HPP
Unified interface for Hypre operations with both CPU and GPU data structures.
Definition: HypreCpuTransfers.hpp:29
std::vector< HYPRE_Real > getMatrixValues(HYPRE_IJMatrix hypre_matrix, const std::vector< HYPRE_Int > &ncols, const std::vector< HYPRE_BigInt > &rows, const std::vector< HYPRE_BigInt > &cols, bool use_gpu_backend=false)
Get matrix values from Hypre matrix.
Definition: HypreUtils.hpp:54