opm-simulators
HypreCpuTransfers.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_CPU_TRANSFERS_HPP
21 #define OPM_HYPRE_CPU_TRANSFERS_HPP
22 
23 #include <opm/simulators/linalg/hypreinterface/HypreDataStructures.hpp>
24 #include <opm/simulators/linalg/hypreinterface/HypreErrorHandling.hpp>
25 
26 #if HYPRE_USING_CUDA
27 #include <opm/simulators/linalg/gpuistl/hypreinterface/HypreCpuTransfers.hpp>
28 #elif HYPRE_USING_HIP
29 #include <opm/simulators/linalg/gpuistl_hip/hypreinterface/HypreCpuTransfers.hpp>
30 #endif
31 
32 #include <HYPRE.h>
33 #include <_hypre_utilities.h>
34 
36 {
37 
41  template <typename VectorType>
42  void
43  setContinuousVectorForHypre(const VectorType& v,
44  std::vector<HYPRE_Real>& continuous_vector_values,
45  const std::vector<int>& local_hypre_to_local_dune)
46  {
47  // Set v values solution vectors
48  for (size_t i = 0; i < local_hypre_to_local_dune.size(); ++i) {
49  continuous_vector_values[i] = v[local_hypre_to_local_dune[i]][0];
50  }
51  }
52 
56  template <typename VectorType>
57  void
59  const std::vector<HYPRE_Real>& continuous_vector_values,
60  const std::vector<int>& local_hypre_to_local_dune)
61  {
62  // Place values back in original positions
63  for (size_t i = 0; i < local_hypre_to_local_dune.size(); ++i) {
64  v[local_hypre_to_local_dune[i]][0] = continuous_vector_values[i];
65  }
66  }
67 
71 template <typename VectorType>
72 void
73 transferCpuVectorToHypre(const VectorType& cpu_vec,
74  HYPRE_IJVector hypre_vec,
76  [[maybe_unused]] const linalg::HypreInterface::DeviceDataArrays& device_arrays,
78  bool use_gpu_backend)
79 {
80  const int N = static_cast<int>(host_arrays.indices.size());
81  using T = typename VectorType::field_type;
82 
83  if (use_gpu_backend) {
84 #if HYPRE_USING_CUDA || HYPRE_USING_HIP
85  gpuistl::HypreInterface::transferCpuVectorToHypre(cpu_vec, hypre_vec, host_arrays,
86  device_arrays, par_info);
87 #endif // HYPRE_USING_CUDA || HYPRE_USING_HIP
88  } else {
89  // CPU backend with CPU input: use host arrays directly
90  if (par_info.owner_first) {
91  // Direct transfer for owner-first ordering
92  const T* values = &(cpu_vec[0][0]);
93  OPM_HYPRE_SAFE_CALL(
94  HYPRE_IJVectorSetValues(hypre_vec, N, const_cast<HYPRE_BigInt*>(host_arrays.indices.data()), values));
95  } else {
96  // Use continuous storage for non-owner-first ordering
98  cpu_vec, host_arrays.continuous_vector_values, par_info.local_hypre_to_local_dune);
99  OPM_HYPRE_SAFE_CALL(HYPRE_IJVectorSetValues(hypre_vec,
100  N,
101  const_cast<HYPRE_BigInt*>(host_arrays.indices.data()),
102  host_arrays.continuous_vector_values.data()));
103  }
104  }
105 
106  OPM_HYPRE_SAFE_CALL(HYPRE_IJVectorAssemble(hypre_vec));
107 }
108 
112 template <typename VectorType>
113 void
114 transferHypreToCpuVector(HYPRE_IJVector hypre_vec,
115  VectorType& cpu_vec,
117  [[maybe_unused]] const linalg::HypreInterface::DeviceDataArrays& device_arrays,
118  const linalg::HypreInterface::ParallelInfo& par_info,
119  bool use_gpu_backend)
120 {
121  const int N = static_cast<int>(host_arrays.indices.size());
122  using T = typename VectorType::field_type;
123 
124  if (use_gpu_backend) {
125 #if HYPRE_USING_CUDA || HYPRE_USING_HIP
126  gpuistl::HypreInterface::transferHypreToCpuVector(hypre_vec, cpu_vec, host_arrays,
127  device_arrays, par_info);
128 #endif // HYPRE_USING_CUDA || HYPRE_USING_HIP
129  } else {
130  // CPU backend with CPU input: use host arrays directly
131  if (par_info.owner_first) {
132  // Direct transfer for owner-first ordering
133  T* values = &(cpu_vec[0][0]);
134  OPM_HYPRE_SAFE_CALL(
135  HYPRE_IJVectorGetValues(hypre_vec, N, const_cast<HYPRE_BigInt*>(host_arrays.indices.data()), values));
136  } else {
137  // Use continuous storage for non-owner-first ordering
138  OPM_HYPRE_SAFE_CALL(HYPRE_IJVectorGetValues(hypre_vec,
139  N,
140  const_cast<HYPRE_BigInt*>(host_arrays.indices.data()),
141  host_arrays.continuous_vector_values.data()));
143  cpu_vec, host_arrays.continuous_vector_values, par_info.local_hypre_to_local_dune);
144  }
145  }
146 }
147 
153 template <typename MatrixType>
154 void
155 updateMatrixFromCpuMatrix(const MatrixType& cpu_matrix,
156  HYPRE_IJMatrix hypre_matrix,
157  const linalg::HypreInterface::SparsityPattern& sparsity_pattern,
158  const linalg::HypreInterface::HostDataArrays& host_arrays,
159  [[maybe_unused]] const linalg::HypreInterface::DeviceDataArrays& device_arrays,
160  bool use_gpu_backend)
161 {
162  const auto N = sparsity_pattern.rows.size();
163 
164  using T = typename MatrixType::field_type;
165  const T* values = &(cpu_matrix[0][0][0][0]);
166 
167  if (use_gpu_backend) {
168 #if HYPRE_USING_CUDA || HYPRE_USING_HIP
169  gpuistl::HypreInterface::updateMatrixFromCpuMatrix(cpu_matrix, hypre_matrix, sparsity_pattern, device_arrays);
170 #endif
171  } else {
172  OPM_HYPRE_SAFE_CALL(HYPRE_IJMatrixSetValues2(hypre_matrix,
173  N,
174  const_cast<HYPRE_Int*>(sparsity_pattern.ncols.data()),
175  const_cast<HYPRE_BigInt*>(sparsity_pattern.rows.data()),
176  const_cast<HYPRE_Int*>(host_arrays.row_indexes.data()),
177  const_cast<HYPRE_BigInt*>(sparsity_pattern.cols.data()),
178  values));
179  }
180 
181  OPM_HYPRE_SAFE_CALL(HYPRE_IJMatrixAssemble(hypre_matrix));
182 }
183 
184 } // namespace Opm::linalg::HypreInterface
185 
186 #endif // OPM_HYPRE_CPU_TRANSFERS_HPP
std::vector< HYPRE_BigInt > rows
Global row indices for owned rows (size: N_owned)
Definition: HypreDataStructures.hpp:91
Parallel domain decomposition information for HYPRE-Dune interface.
Definition: HypreDataStructures.hpp:37
void transferHypreToCpuVector(HYPRE_IJVector hypre_vec, VectorType &cpu_vec, linalg::HypreInterface::HostDataArrays &host_arrays, [[maybe_unused]] const linalg::HypreInterface::DeviceDataArrays &device_arrays, const linalg::HypreInterface::ParallelInfo &par_info, bool use_gpu_backend)
Transfer Hypre vector to CPU vector.
Definition: HypreCpuTransfers.hpp:114
std::vector< HYPRE_BigInt > cols
Global column indices in CSR format (size: nnz)
Definition: HypreDataStructures.hpp:94
Compressed Sparse Row (CSR) sparsity pattern for HYPRE matrix assembly.
Definition: HypreDataStructures.hpp:86
std::vector< int > local_hypre_to_local_dune
Mapping from local HYPRE indices to local Dune indices.
Definition: HypreDataStructures.hpp:59
std::vector< HYPRE_Int > ncols
Non-zero entries per owned row (size: N_owned)
Definition: HypreDataStructures.hpp:88
Host arrays for HYPRE matrix and vector data transfers.
Definition: HypreDataStructures.hpp:106
void updateMatrixFromCpuMatrix(const MatrixType &cpu_matrix, HYPRE_IJMatrix hypre_matrix, const linalg::HypreInterface::SparsityPattern &sparsity_pattern, const linalg::HypreInterface::HostDataArrays &host_arrays, [[maybe_unused]] const linalg::HypreInterface::DeviceDataArrays &device_arrays, bool use_gpu_backend)
Update Hypre matrix from CPU matrix Uses HYPRE_IJMatrixSetValues2 with pre-computed row_indexes...
Definition: HypreCpuTransfers.hpp:155
void setContinuousVectorForHypre(const VectorType &v, std::vector< HYPRE_Real > &continuous_vector_values, const std::vector< int > &local_hypre_to_local_dune)
Extract owned vector values in the order expected by HYPRE.
Definition: HypreCpuTransfers.hpp:43
void transferCpuVectorToHypre(const VectorType &cpu_vec, HYPRE_IJVector hypre_vec, linalg::HypreInterface::HostDataArrays &host_arrays, [[maybe_unused]] const linalg::HypreInterface::DeviceDataArrays &device_arrays, const linalg::HypreInterface::ParallelInfo &par_info, bool use_gpu_backend)
Transfer CPU vector to Hypre vector.
Definition: HypreCpuTransfers.hpp:73
void setDuneVectorFromContinuousVector(VectorType &v, const std::vector< HYPRE_Real > &continuous_vector_values, const std::vector< int > &local_hypre_to_local_dune)
Distribute HYPRE vector values back to original vector positions.
Definition: HypreCpuTransfers.hpp:58
Unified interface for Hypre operations with both CPU and GPU data structures.
Definition: HypreCpuTransfers.hpp:35
bool owner_first
Whether owned DOFs appear first in local Dune ordering.
Definition: HypreDataStructures.hpp:77
GPU device memory arrays for HYPRE operations with GPU backend.
Definition: HypreDataStructures.hpp:137
std::vector< HYPRE_Real > continuous_vector_values
Temporary buffer for vector values in non-owner-first ordering.
Definition: HypreDataStructures.hpp:128
std::vector< HYPRE_Int > row_indexes
Pre-computed row start indexes for HYPRE_IJMatrixSetValues2.
Definition: HypreDataStructures.hpp:113
std::vector< HYPRE_BigInt > indices
Global DOF indices for owned degrees of freedom.
Definition: HypreDataStructures.hpp:120