HypreCpuTransfers.hpp
Go to the documentation of this file.
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
25
26#include <HYPRE.h>
27#include <_hypre_utilities.h>
28
30{
31
35 template <typename VectorType>
36 void
37 setContinuousVectorForHypre(const VectorType& v,
38 std::vector<HYPRE_Real>& continuous_vector_values,
39 const std::vector<int>& local_hypre_to_local_dune)
40 {
41 // Set v values solution vectors
42 for (size_t i = 0; i < local_hypre_to_local_dune.size(); ++i) {
43 continuous_vector_values[i] = v[local_hypre_to_local_dune[i]][0];
44 }
45 }
46
50 template <typename VectorType>
51 void
53 const std::vector<HYPRE_Real>& continuous_vector_values,
54 const std::vector<int>& local_hypre_to_local_dune)
55 {
56 // Place values back in original positions
57 for (size_t i = 0; i < local_hypre_to_local_dune.size(); ++i) {
58 v[local_hypre_to_local_dune[i]][0] = continuous_vector_values[i];
59 }
60 }
61
65template <typename VectorType>
66void
67transferCpuVectorToHypre(const VectorType& cpu_vec,
68 HYPRE_IJVector hypre_vec,
69 HypreHostDataArrays& host_arrays,
70 const HypreDeviceDataArrays& device_arrays,
71 const ParallelInfo& par_info,
72 bool use_gpu_backend)
73{
74 const int N = static_cast<int>(host_arrays.indices.size());
75 using T = typename VectorType::field_type;
76
77 if (use_gpu_backend) {
78#if HYPRE_USING_CUDA || HYPRE_USING_HIP
79 // GPU backend with CPU input: use pre-allocated device arrays
80 if (par_info.owner_first) {
81 // Direct host-to-device transfer for owner-first ordering
82 const T* values = &(cpu_vec[0][0]);
83 hypre_TMemcpy(
84 device_arrays.vector_buffer_device, values, HYPRE_Real, N, HYPRE_MEMORY_DEVICE, HYPRE_MEMORY_HOST);
85 OPM_HYPRE_SAFE_CALL(HYPRE_IJVectorSetValues(
86 hypre_vec, N, device_arrays.indices_device, device_arrays.vector_buffer_device));
87 } else {
88 // Use continuous storage and device buffer for non-owner-first ordering
90 cpu_vec, host_arrays.continuous_vector_values, par_info.local_hypre_to_local_dune);
91 hypre_TMemcpy(device_arrays.vector_buffer_device,
92 host_arrays.continuous_vector_values.data(),
93 HYPRE_Real,
94 N,
95 HYPRE_MEMORY_DEVICE,
96 HYPRE_MEMORY_HOST);
97 OPM_HYPRE_SAFE_CALL(HYPRE_IJVectorSetValues(
98 hypre_vec, N, device_arrays.indices_device, device_arrays.vector_buffer_device));
99 }
100#endif // HYPRE_USING_CUDA || HYPRE_USING_HIP
101 } else {
102 // CPU backend with CPU input: use host arrays directly
103 if (par_info.owner_first) {
104 // Direct transfer for owner-first ordering
105 const T* values = &(cpu_vec[0][0]);
107 HYPRE_IJVectorSetValues(hypre_vec, N, const_cast<HYPRE_BigInt*>(host_arrays.indices.data()), values));
108 } else {
109 // Use continuous storage for non-owner-first ordering
111 cpu_vec, host_arrays.continuous_vector_values, par_info.local_hypre_to_local_dune);
112 OPM_HYPRE_SAFE_CALL(HYPRE_IJVectorSetValues(hypre_vec,
113 N,
114 const_cast<HYPRE_BigInt*>(host_arrays.indices.data()),
115 host_arrays.continuous_vector_values.data()));
116 }
117 }
118
119 OPM_HYPRE_SAFE_CALL(HYPRE_IJVectorAssemble(hypre_vec));
120}
121
125template <typename VectorType>
126void
127transferHypreToCpuVector(HYPRE_IJVector hypre_vec,
128 VectorType& cpu_vec,
129 HypreHostDataArrays& host_arrays,
130 const HypreDeviceDataArrays& device_arrays,
131 const ParallelInfo& par_info,
132 bool use_gpu_backend)
133{
134 const int N = static_cast<int>(host_arrays.indices.size());
135 using T = typename VectorType::field_type;
136
137 if (use_gpu_backend) {
138#if HYPRE_USING_CUDA || HYPRE_USING_HIP
139 // GPU backend with CPU input: use pre-allocated device arrays
140 if (par_info.owner_first) {
141 // Direct device-to-host transfer for owner-first ordering
142 T* values = &(cpu_vec[0][0]);
143 OPM_HYPRE_SAFE_CALL(HYPRE_IJVectorGetValues(
144 hypre_vec, N, device_arrays.indices_device, device_arrays.vector_buffer_device));
145 hypre_TMemcpy(
146 values, device_arrays.vector_buffer_device, HYPRE_Real, N, HYPRE_MEMORY_HOST, HYPRE_MEMORY_DEVICE);
147 } else {
148 // Use device buffer and then remap for non-owner-first ordering
149 OPM_HYPRE_SAFE_CALL(HYPRE_IJVectorGetValues(
150 hypre_vec, N, device_arrays.indices_device, device_arrays.vector_buffer_device));
151 hypre_TMemcpy(host_arrays.continuous_vector_values.data(),
152 device_arrays.vector_buffer_device,
153 HYPRE_Real,
154 N,
155 HYPRE_MEMORY_HOST,
156 HYPRE_MEMORY_DEVICE);
158 cpu_vec, host_arrays.continuous_vector_values, par_info.local_hypre_to_local_dune);
159 }
160#endif // HYPRE_USING_CUDA || HYPRE_USING_HIP
161 } else {
162 // CPU backend with CPU input: use host arrays directly
163 if (par_info.owner_first) {
164 // Direct transfer for owner-first ordering
165 T* values = &(cpu_vec[0][0]);
167 HYPRE_IJVectorGetValues(hypre_vec, N, const_cast<HYPRE_BigInt*>(host_arrays.indices.data()), values));
168 } else {
169 // Use continuous storage for non-owner-first ordering
170 OPM_HYPRE_SAFE_CALL(HYPRE_IJVectorGetValues(hypre_vec,
171 N,
172 const_cast<HYPRE_BigInt*>(host_arrays.indices.data()),
173 host_arrays.continuous_vector_values.data()));
175 cpu_vec, host_arrays.continuous_vector_values, par_info.local_hypre_to_local_dune);
176 }
177 }
178}
179
185template <typename MatrixType>
186void
187updateMatrixFromCpuMatrix(const MatrixType& cpu_matrix,
188 HYPRE_IJMatrix hypre_matrix,
189 const SparsityPattern& sparsity_pattern,
190 const HypreHostDataArrays& host_arrays,
191 const HypreDeviceDataArrays& device_arrays,
192 bool use_gpu_backend)
193{
194 const auto N = sparsity_pattern.rows.size();
195 const auto nnz = cpu_matrix.nonzeroes(); // Total entries including ghost
196
197 using T = typename MatrixType::field_type;
198 const T* values = &(cpu_matrix[0][0][0][0]);
199
200 if (use_gpu_backend) {
201#if HYPRE_USING_CUDA || HYPRE_USING_HIP
202 hypre_TMemcpy(
203 device_arrays.matrix_buffer_device, values, HYPRE_Real, nnz, HYPRE_MEMORY_DEVICE, HYPRE_MEMORY_HOST);
204 OPM_HYPRE_SAFE_CALL(HYPRE_IJMatrixSetValues2(hypre_matrix,
205 N,
206 device_arrays.ncols_device,
207 device_arrays.rows_device,
208 device_arrays.row_indexes_device,
209 device_arrays.cols_device,
210 device_arrays.matrix_buffer_device));
211#endif
212 } else {
213 OPM_HYPRE_SAFE_CALL(HYPRE_IJMatrixSetValues2(hypre_matrix,
214 N,
215 const_cast<HYPRE_Int*>(sparsity_pattern.ncols.data()),
216 const_cast<HYPRE_BigInt*>(sparsity_pattern.rows.data()),
217 const_cast<HYPRE_Int*>(host_arrays.row_indexes.data()),
218 const_cast<HYPRE_BigInt*>(sparsity_pattern.cols.data()),
219 values));
220 }
221
222 OPM_HYPRE_SAFE_CALL(HYPRE_IJMatrixAssemble(hypre_matrix));
223}
224} // namespace Opm::gpuistl::HypreInterface
225
226#endif // OPM_HYPRE_CPU_TRANSFERS_HPP
#define OPM_HYPRE_SAFE_CALL(expr)
Macro to wrap Hypre function calls with error checking.
Definition: HypreErrorHandling.hpp:96
Unified interface for Hypre operations with both CPU and GPU data structures.
Definition: HypreInterface.hpp:61
void transferCpuVectorToHypre(const VectorType &cpu_vec, HYPRE_IJVector hypre_vec, HypreHostDataArrays &host_arrays, const HypreDeviceDataArrays &device_arrays, const ParallelInfo &par_info, bool use_gpu_backend)
Transfer CPU vector to Hypre vector.
Definition: HypreCpuTransfers.hpp:67
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:52
void transferHypreToCpuVector(HYPRE_IJVector hypre_vec, VectorType &cpu_vec, HypreHostDataArrays &host_arrays, const HypreDeviceDataArrays &device_arrays, const ParallelInfo &par_info, bool use_gpu_backend)
Transfer Hypre vector to CPU vector.
Definition: HypreCpuTransfers.hpp:127
void updateMatrixFromCpuMatrix(const MatrixType &cpu_matrix, HYPRE_IJMatrix hypre_matrix, const SparsityPattern &sparsity_pattern, const HypreHostDataArrays &host_arrays, const HypreDeviceDataArrays &device_arrays, bool use_gpu_backend)
Update Hypre matrix from CPU matrix Uses HYPRE_IJMatrixSetValues2 with pre-computed row_indexes,...
Definition: HypreCpuTransfers.hpp:187
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:37
GPU device memory arrays for HYPRE operations with GPU backend.
Definition: HypreDataStructures.hpp:137
HYPRE_BigInt * rows_device
Definition: HypreDataStructures.hpp:140
HYPRE_Real * vector_buffer_device
Device buffer for vector operations Used when input type and backend are different,...
Definition: HypreDataStructures.hpp:149
HYPRE_Int * ncols_device
Mirrors host data arrays.
Definition: HypreDataStructures.hpp:139
HYPRE_Int * row_indexes_device
Definition: HypreDataStructures.hpp:142
HYPRE_BigInt * indices_device
Definition: HypreDataStructures.hpp:143
HYPRE_Real * matrix_buffer_device
Device buffer for matrix values, only needed for CPU input + GPU backend.
Definition: HypreDataStructures.hpp:155
HYPRE_BigInt * cols_device
Definition: HypreDataStructures.hpp:141
Host arrays for HYPRE matrix and vector data transfers.
Definition: HypreDataStructures.hpp:106
std::vector< HYPRE_BigInt > indices
Global DOF indices for owned degrees of freedom.
Definition: HypreDataStructures.hpp:120
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
Parallel domain decomposition information for HYPRE-Dune interface.
Definition: HypreDataStructures.hpp:37
bool owner_first
Whether owned DOFs appear first in local Dune ordering.
Definition: HypreDataStructures.hpp:77
std::vector< int > local_hypre_to_local_dune
Mapping from local HYPRE indices to local Dune indices.
Definition: HypreDataStructures.hpp:59
Compressed Sparse Row (CSR) sparsity pattern for HYPRE matrix assembly.
Definition: HypreDataStructures.hpp:86
std::vector< HYPRE_BigInt > rows
Global row indices for owned rows (size: N_owned)
Definition: HypreDataStructures.hpp:91
std::vector< HYPRE_Int > ncols
Non-zero entries per owned row (size: N_owned)
Definition: HypreDataStructures.hpp:88
std::vector< HYPRE_BigInt > cols
Global column indices in CSR format (size: nnz)
Definition: HypreDataStructures.hpp:94