GpuSparseMatrixWrapper.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#ifndef OPM_GPUSPARSEMATRIXWRAPPER_HPP
20#define OPM_GPUSPARSEMATRIXWRAPPER_HPP
21
22#include <opm/common/ErrorMacros.hpp>
29
30#include <concepts>
31#include <cstddef>
32#include <cuda.h>
33#include <cusparse.h>
34#include <memory>
35#include <stdexcept>
36#include <type_traits>
37
38namespace Opm::gpuistl
39{
40
61template <typename T, bool ForceLegacy = false>
63{
64public:
65 using field_type = T;
66
67 /*
68 Here is the primary function of this class.
69 Since the generic API for CUDA/HIP is primaryly supported on CUDA 13 (and not yet HIP) for blocked
70 matrices, places wanting to use blocked matrices can invoke this class which handles which API to use.
71 Basically we just check if HIP is present, or if we are using cuda and a version prior to 13.
72 If ForceLegacy is true, always use the legacy API (GpuSparseMatrix) regardless of CUDA version.
73 */
74#if USE_HIP || (!USE_HIP && CUDA_VERSION < 13000)
76#else
77 using matrix_type = std::conditional_t<ForceLegacy,
80#endif
81
82 // Arrow operator overloads for direct access to the underlying matrix
84 if (!m_matrix) {
85 throw std::runtime_error("GpuSparseMatrixWrapper: underlying matrix is nullptr.");
86 }
87 return m_matrix.get();
88 }
89 const matrix_type* operator->() const {
90 if (!m_matrix) {
91 throw std::runtime_error("GpuSparseMatrixWrapper: underlying matrix is nullptr.");
92 }
93 return m_matrix.get();
94 }
95
104 static constexpr int max_block_size = 6;
105
119 GpuSparseMatrixWrapper(const T* nonZeroElements,
120 const int* rowIndices,
121 const int* columnIndices,
122 std::size_t numberOfNonzeroBlocks,
123 std::size_t blockSize,
124 std::size_t numberOfRows)
125 {
126 m_matrix = std::make_unique<matrix_type>(nonZeroElements,
127 rowIndices,
128 columnIndices,
129 numberOfNonzeroBlocks,
130 blockSize,
131 numberOfRows);
132 }
133
145 const GpuVector<int>& columnIndices,
146 std::size_t blockSize)
147 {
148 m_matrix = std::make_unique<matrix_type>(rowIndices, columnIndices, blockSize);
149 }
150
152 {
153 if (!other.m_matrix) {
154 throw std::runtime_error("Internal error, other.m_matrix is a nullptr.");
155 }
156 m_matrix = std::make_unique<matrix_type>(*other.m_matrix);
157 }
158
159 // We want to have this as non-mutable as possible, that is we do not want
160 // to deal with changing matrix sizes and sparsity patterns.
162
163 virtual ~GpuSparseMatrixWrapper() = default;
164
166
167 const matrix_type& get() const {
168 if (!m_matrix) {
169 throw std::runtime_error("GpuSparseMatrixWrapper: underlying matrix is nullptr.");
170 }
171 return *m_matrix;
172 }
173
183 template <class MatrixType>
184 static GpuSparseMatrixWrapper<T, ForceLegacy> fromMatrix(const MatrixType& matrix, bool copyNonZeroElementsDirectly = false)
185 {
186 GpuSparseMatrixWrapper<T, ForceLegacy> gpuSparseMatrixWrapper;
187 gpuSparseMatrixWrapper.m_matrix = std::make_unique<matrix_type>(
188 matrix_type::fromMatrix(matrix, copyNonZeroElementsDirectly));
189 return gpuSparseMatrixWrapper;
190 }
191
192 // Only participates in overload resolution when matrix_type == GpuSparseMatrix<T>
194 requires std::same_as<matrix_type, GpuSparseMatrix<T>>
195 {
196 m_matrix->setUpperTriangular();
197 }
198
203 requires std::same_as<matrix_type, GpuSparseMatrix<T>>
204 {
205 m_matrix->setLowerTriangular();
206 }
207
212 requires std::same_as<matrix_type, GpuSparseMatrix<T>>
213 {
214 m_matrix->setUnitDiagonal();
215 }
216
221 requires std::same_as<matrix_type, GpuSparseMatrix<T>>
222 {
223 m_matrix->setNonUnitDiagonal();
224 }
225
229 std::size_t N() const
230 {
231 return m_matrix->N();
232 }
233
238 std::size_t nonzeroes() const
239 {
240 return m_matrix->nonzeroes();
241 }
242
249 {
250 return m_matrix->getNonZeroValues();
251 }
252
259 {
260 return m_matrix->getNonZeroValues();
261 }
262
269 {
270 return m_matrix->getRowIndices();
271 }
272
279 {
280 return m_matrix->getRowIndices();
281 }
282
289 {
290 return m_matrix->getColumnIndices();
291 }
292
299 {
300 return m_matrix->getColumnIndices();
301 }
302
309 std::size_t dim() const
310 {
311 return m_matrix->dim();
312 }
313
317 std::size_t blockSize() const
318 {
319 return m_matrix->blockSize();
320 }
321
328 {
329 return m_matrix->getDescription();
330 }
331
337 virtual void mv(const GpuVector<T>& x, GpuVector<T>& y) const
338 {
339 m_matrix->mv(x, y);
340 }
341
347 virtual void umv(const GpuVector<T>& x, GpuVector<T>& y) const
348 {
349 m_matrix->umv(x, y);
350 }
351
352
359 virtual void usmv(T alpha, const GpuVector<T>& x, GpuVector<T>& y) const
360 {
361 m_matrix->usmv(alpha, x, y);
362 }
363
374 template <class MatrixType>
375 void updateNonzeroValues(const MatrixType& matrix, bool copyNonZeroElementsDirectly = false)
376 {
377 m_matrix->updateNonzeroValues(matrix, copyNonZeroElementsDirectly);
378 }
379
385 template <bool OtherForceLegacy>
387 {
388 m_matrix->updateNonzeroValues(matrix.get());
389 }
390
395 {
396 m_matrix->setToZero();
397 }
398
419 template<class FunctionType>
420 auto dispatchOnBlocksize(FunctionType function) const
421 {
422 return m_matrix->dispatchOnBlocksize(function);
423 }
424
425private:
426 std::unique_ptr<matrix_type> m_matrix{};
427};
428
429} // namespace Opm::gpuistl
430
431#endif
The GpuSparseMatrixGeneric class uses cuSPARSE Generic API for sparse matrix operations.
Definition: GpuSparseMatrixGeneric.hpp:48
The GpuSparseMatrix class simple wrapper class for a CuSparse matrix.
Definition: GpuSparseMatrix.hpp:61
static GpuSparseMatrix< T > fromMatrix(const MatrixType &matrix, bool copyNonZeroElementsDirectly=false)
fromMatrix creates a new matrix with the same block size and values as the given matrix
The GpuSparseMatrixWrapper Checks CUDA/HIP version and dispatches a version either using the old or t...
Definition: GpuSparseMatrixWrapper.hpp:63
void setLowerTriangular()
setLowerTriangular sets the CuSparse flag that this is an lower diagonal (with non-unit diagonal) mat...
Definition: GpuSparseMatrixWrapper.hpp:202
GpuSparseMatrixWrapper(const GpuSparseMatrixWrapper &other)
Definition: GpuSparseMatrixWrapper.hpp:151
void setUnitDiagonal()
setUnitDiagonal sets the CuSparse flag that this has unit diagional.
Definition: GpuSparseMatrixWrapper.hpp:211
GpuVector< int > & getRowIndices()
getRowIndices returns the row indices used to represent the BSR structure.
Definition: GpuSparseMatrixWrapper.hpp:268
void setUpperTriangular()
Definition: GpuSparseMatrixWrapper.hpp:193
void updateNonzeroValues(const GpuSparseMatrixWrapper< T, OtherForceLegacy > &matrix)
updateNonzeroValues updates the non-zero values by using the non-zero values of the supplied matrix
Definition: GpuSparseMatrixWrapper.hpp:386
virtual void mv(const GpuVector< T > &x, GpuVector< T > &y) const
mv performs matrix vector multiply y = Ax
Definition: GpuSparseMatrixWrapper.hpp:337
static constexpr int max_block_size
Maximum block size supported by this implementation.
Definition: GpuSparseMatrixWrapper.hpp:104
GpuVector< T > & getNonZeroValues()
getNonZeroValues returns the GPU vector containing the non-zero values (ordered by block)
Definition: GpuSparseMatrixWrapper.hpp:248
matrix_type * operator->()
Definition: GpuSparseMatrixWrapper.hpp:83
const GpuVector< T > & getNonZeroValues() const
getNonZeroValues returns the GPU vector containing the non-zero values (ordered by block)
Definition: GpuSparseMatrixWrapper.hpp:258
const matrix_type * operator->() const
Definition: GpuSparseMatrixWrapper.hpp:89
std::size_t N() const
N returns the number of rows (which is equal to the number of columns)
Definition: GpuSparseMatrixWrapper.hpp:229
static GpuSparseMatrixWrapper< T, ForceLegacy > fromMatrix(const MatrixType &matrix, bool copyNonZeroElementsDirectly=false)
fromMatrix creates a new matrix with the same block size and values as the given matrix
Definition: GpuSparseMatrixWrapper.hpp:184
GpuSparseMatrixWrapper(const GpuVector< int > &rowIndices, const GpuVector< int > &columnIndices, std::size_t blockSize)
Definition: GpuSparseMatrixWrapper.hpp:144
void updateNonzeroValues(const MatrixType &matrix, bool copyNonZeroElementsDirectly=false)
updateNonzeroValues updates the non-zero values by using the non-zero values of the supplied matrix
Definition: GpuSparseMatrixWrapper.hpp:375
virtual ~GpuSparseMatrixWrapper()=default
detail::GpuSparseMatrixDescription & getDescription()
getDescription the cusparse matrix description.
Definition: GpuSparseMatrixWrapper.hpp:327
std::size_t dim() const
dim returns the dimension of the vector space on which this matrix acts
Definition: GpuSparseMatrixWrapper.hpp:309
T field_type
Definition: GpuSparseMatrixWrapper.hpp:65
std::size_t nonzeroes() const
nonzeroes behaves as the Dune::BCRSMatrix::nonzeros() function and returns the number of non zero blo...
Definition: GpuSparseMatrixWrapper.hpp:238
GpuVector< int > & getColumnIndices()
getColumnIndices returns the column indices used to represent the BSR structure.
Definition: GpuSparseMatrixWrapper.hpp:288
void setNonUnitDiagonal()
setNonUnitDiagonal sets the CuSparse flag that this has non-unit diagional.
Definition: GpuSparseMatrixWrapper.hpp:220
GpuSparseMatrixWrapper(const T *nonZeroElements, const int *rowIndices, const int *columnIndices, std::size_t numberOfNonzeroBlocks, std::size_t blockSize, std::size_t numberOfRows)
Definition: GpuSparseMatrixWrapper.hpp:119
GpuSparseMatrixWrapper & operator=(const GpuSparseMatrixWrapper &)=delete
virtual void usmv(T alpha, const GpuVector< T > &x, GpuVector< T > &y) const
umv computes y=alpha * Ax + y
Definition: GpuSparseMatrixWrapper.hpp:359
void setToZero()
setToZero resets the matrix to zero values.
Definition: GpuSparseMatrixWrapper.hpp:394
const GpuVector< int > & getColumnIndices() const
getColumnIndices returns the column indices used to represent the BSR structure.
Definition: GpuSparseMatrixWrapper.hpp:298
const matrix_type & get() const
Definition: GpuSparseMatrixWrapper.hpp:167
std::size_t blockSize() const
blockSize size of the blocks
Definition: GpuSparseMatrixWrapper.hpp:317
const GpuVector< int > & getRowIndices() const
getRowIndices returns the row indices used to represent the BSR structure.
Definition: GpuSparseMatrixWrapper.hpp:278
auto dispatchOnBlocksize(FunctionType function) const
Dispatches a function based on the block size of the matrix.
Definition: GpuSparseMatrixWrapper.hpp:420
virtual void umv(const GpuVector< T > &x, GpuVector< T > &y) const
umv computes y=Ax+y
Definition: GpuSparseMatrixWrapper.hpp:347
The CuSparseResource class wraps a CuSparse resource in a proper RAII pattern.
Definition: CuSparseResource.hpp:55
A small, fixed‑dimension MiniVector class backed by std::array that can be used in both host and CUDA...
Definition: GpuFlowProblem.hpp:49