21 #ifndef OPM_HYPRE_PRECONDITIONER_HEADER_INCLUDED 22 #define OPM_HYPRE_PRECONDITIONER_HEADER_INCLUDED 24 #include <opm/common/ErrorMacros.hpp> 25 #include <opm/common/TimingMacros.hpp> 26 #include <opm/simulators/linalg/PreconditionerWithUpdate.hpp> 27 #include <opm/simulators/linalg/PropertyTree.hpp> 28 #include <opm/simulators/linalg/gpuistl/HypreInterface.hpp> 29 #include <opm/simulators/linalg/gpuistl/detail/gpu_type_detection.hpp> 31 #include <dune/common/fmatrix.hh> 32 #include <dune/istl/bcrsmatrix.hh> 35 #include <HYPRE_krylov.h> 36 #include <HYPRE_parcsr_ls.h> 37 #include <_hypre_utilities.h> 65 template <
class M,
class X,
class Y,
class Comm>
93 OPM_TIMEBLOCK(prec_construct);
97 if constexpr (std::is_same_v<Comm, Dune::Amg::SequentialInformation>) {
98 mpi_comm = MPI_COMM_SELF;
100 mpi_comm = comm.communicator();
102 MPI_Comm_size(mpi_comm, &size);
103 MPI_Comm_rank(mpi_comm, &rank);
105 assert(size == comm.communicator().size());
106 assert(rank == comm.communicator().rank());
112 HypreInterface::initialize(use_gpu_backend_);
115 solver_ = HypreInterface::createAMGSolver();
116 HypreInterface::setSolverParameters(solver_, prm, use_gpu_backend_);
119 par_info_ = HypreInterface::setupHypreParallelInfo(comm_, A_);
122 sparsity_pattern_ = HypreInterface::setupSparsityPattern(A_, par_info_, par_info_.
owner_first);
125 host_arrays_.
row_indexes = HypreInterface::computeRowIndexes(
138 if (use_gpu_backend_) {
139 #if HYPRE_USING_CUDA || HYPRE_USING_HIP 140 device_arrays_.
ncols_device = hypre_CTAlloc(HYPRE_Int, par_info_.
N_owned, HYPRE_MEMORY_DEVICE);
141 device_arrays_.rows_device = hypre_CTAlloc(HYPRE_BigInt, par_info_.
N_owned, HYPRE_MEMORY_DEVICE);
142 device_arrays_.cols_device = hypre_CTAlloc(HYPRE_BigInt, sparsity_pattern_.
nnz, HYPRE_MEMORY_DEVICE);
143 device_arrays_.row_indexes_device = hypre_CTAlloc(HYPRE_Int, par_info_.
N_owned, HYPRE_MEMORY_DEVICE);
144 device_arrays_.indices_device = hypre_CTAlloc(HYPRE_BigInt, par_info_.
N_owned, HYPRE_MEMORY_DEVICE);
150 device_arrays_.
matrix_buffer_device = hypre_CTAlloc(HYPRE_Real, A_.nonzeroes(), HYPRE_MEMORY_DEVICE);
153 hypre_TMemcpy(device_arrays_.
ncols_device, sparsity_pattern_.
ncols.data(), HYPRE_Int, par_info_.
N_owned, HYPRE_MEMORY_DEVICE, HYPRE_MEMORY_HOST);
154 hypre_TMemcpy(device_arrays_.rows_device, sparsity_pattern_.
rows.data(), HYPRE_BigInt, par_info_.
N_owned, HYPRE_MEMORY_DEVICE, HYPRE_MEMORY_HOST);
155 hypre_TMemcpy(device_arrays_.cols_device, sparsity_pattern_.
cols.data(), HYPRE_BigInt, sparsity_pattern_.
nnz, HYPRE_MEMORY_DEVICE, HYPRE_MEMORY_HOST);
156 hypre_TMemcpy(device_arrays_.row_indexes_device, host_arrays_.
row_indexes.data(), HYPRE_Int, par_info_.
N_owned, HYPRE_MEMORY_DEVICE, HYPRE_MEMORY_HOST);
157 hypre_TMemcpy(device_arrays_.indices_device, host_arrays_.
indices.data(), HYPRE_BigInt, par_info_.
N_owned, HYPRE_MEMORY_DEVICE, HYPRE_MEMORY_HOST);
162 A_hypre_ = HypreInterface::createMatrix(par_info_.
N_owned, par_info_.
dof_offset, comm_);
163 x_hypre_ = HypreInterface::createVector(par_info_.
N_owned, par_info_.
dof_offset, comm_);
164 b_hypre_ = HypreInterface::createVector(par_info_.
N_owned, par_info_.
dof_offset, comm_);
178 if (use_gpu_backend_) {
179 #if HYPRE_USING_CUDA || HYPRE_USING_HIP 181 hypre_TFree(device_arrays_.
ncols_device, HYPRE_MEMORY_DEVICE);
183 if (device_arrays_.rows_device) {
184 hypre_TFree(device_arrays_.rows_device, HYPRE_MEMORY_DEVICE);
186 if (device_arrays_.cols_device) {
187 hypre_TFree(device_arrays_.cols_device, HYPRE_MEMORY_DEVICE);
189 if (device_arrays_.row_indexes_device) {
190 hypre_TFree(device_arrays_.row_indexes_device, HYPRE_MEMORY_DEVICE);
192 if (device_arrays_.indices_device) {
193 hypre_TFree(device_arrays_.indices_device, HYPRE_MEMORY_DEVICE);
204 HypreInterface::destroySolver(solver_);
205 HypreInterface::destroyVector(x_hypre_);
206 HypreInterface::destroyVector(b_hypre_);
207 HypreInterface::destroyMatrix(A_hypre_);
217 OPM_TIMEBLOCK(prec_update);
220 HypreInterface::updateMatrixValues(
221 A_, A_hypre_, sparsity_pattern_, host_arrays_, device_arrays_, use_gpu_backend_);
224 HYPRE_ParCSRMatrix parcsr_A;
225 HYPRE_SAFE_CALL(HYPRE_IJMatrixGetObject(A_hypre_, reinterpret_cast<void**>(&parcsr_A)));
228 HYPRE_ParVector par_x, par_b;
229 HYPRE_SAFE_CALL(HYPRE_IJVectorGetObject(x_hypre_, reinterpret_cast<void**>(&par_x)));
230 HYPRE_SAFE_CALL(HYPRE_IJVectorGetObject(b_hypre_, reinterpret_cast<void**>(&par_b)));
233 HYPRE_SAFE_CALL(HYPRE_BoomerAMGSetup(solver_, parcsr_A, par_b, par_x));
244 void pre(X& v, Y& )
override 246 comm_.copyOwnerToAll(v, v);
259 void apply(X& v,
const Y& d)
override 261 OPM_TIMEBLOCK(prec_apply);
264 HypreInterface::transferVectorToHypre(v, x_hypre_, host_arrays_, device_arrays_, par_info_, use_gpu_backend_);
265 HypreInterface::transferVectorToHypre(d, b_hypre_, host_arrays_, device_arrays_, par_info_, use_gpu_backend_);
268 HYPRE_ParCSRMatrix parcsr_A;
269 HYPRE_ParVector par_x, par_b;
270 HYPRE_SAFE_CALL(HYPRE_IJMatrixGetObject(A_hypre_, reinterpret_cast<void**>(&parcsr_A)));
271 HYPRE_SAFE_CALL(HYPRE_IJVectorGetObject(x_hypre_, reinterpret_cast<void**>(&par_x)));
272 HYPRE_SAFE_CALL(HYPRE_IJVectorGetObject(b_hypre_, reinterpret_cast<void**>(&par_b)));
275 HYPRE_SAFE_CALL(HYPRE_BoomerAMGSolve(solver_, parcsr_A, par_b, par_x));
278 HypreInterface::transferVectorFromHypre(x_hypre_, v, host_arrays_, device_arrays_, par_info_, use_gpu_backend_);
281 comm_.copyOwnerToAll(v, v);
300 Dune::SolverCategory::Category
category()
const override 302 return std::is_same_v<Comm, Dune::Amg::SequentialInformation> ? Dune::SolverCategory::sequential
303 : Dune::SolverCategory::overlapping;
331 HYPRE_Solver solver_ =
nullptr;
332 HYPRE_IJMatrix A_hypre_ =
nullptr;
333 HYPRE_IJVector x_hypre_ =
nullptr;
334 HYPRE_IJVector b_hypre_ =
nullptr;
337 bool use_gpu_backend_ =
false;
std::vector< int > local_dune_to_local_hypre
Mapping from local Dune indices to local HYPRE indices.
Definition: HypreDataStructures.hpp:44
Type trait to detect if a type is a GPU type.
Definition: gpu_type_detection.hpp:40
M matrix_type
The matrix type the preconditioner is for.
Definition: HyprePreconditioner.hpp:70
HYPRE_Int * ncols_device
Mirrors host data arrays.
Definition: HypreDataStructures.hpp:139
T get(const std::string &key) const
Retrieve property value given hierarchical property key.
Definition: PropertyTree.cpp:59
std::vector< HYPRE_BigInt > indices
Global DOF indices for owned degrees of freedom.
Definition: HypreDataStructures.hpp:120
void pre(X &v, Y &) override
Pre-processing step before applying the preconditioner.
Definition: HyprePreconditioner.hpp:244
Unified interface for Hypre operations with both CPU and GPU data structures.
Definition: HypreCpuTransfers.hpp:29
std::vector< HYPRE_Real > continuous_vector_values
Temporary buffer for vector values in non-owner-first ordering.
Definition: HypreDataStructures.hpp:128
Definition: HyprePreconditioner.hpp:42
Dune::SolverCategory::Category category() const override
Returns the solver category.
Definition: HyprePreconditioner.hpp:300
Host arrays for HYPRE matrix and vector data transfers.
Definition: HypreDataStructures.hpp:106
GPU device memory arrays for HYPRE operations with GPU backend.
Definition: HypreDataStructures.hpp:137
HYPRE_Int nnz
Number of non-zero entries in matrix.
Definition: HypreDataStructures.hpp:97
HYPRE_Int dof_offset
Global index offset for this process's owned DOFs.
Definition: HypreDataStructures.hpp:69
std::vector< HYPRE_Int > row_indexes
Pre-computed row start indexes for HYPRE_IJMatrixSetValues2.
Definition: HypreDataStructures.hpp:113
bool owner_first
Whether owned DOFs appear first in local Dune ordering.
Definition: HypreDataStructures.hpp:77
HyprePreconditioner(const M &A, const Opm::PropertyTree prm, const Comm &comm)
Constructor for the HyprePreconditioner class.
Definition: HyprePreconditioner.hpp:89
void post(X &) override
Post-processing step after applying the preconditioner.
Definition: HyprePreconditioner.hpp:291
std::vector< HYPRE_BigInt > rows
Global row indices for owned rows (size: N_owned)
Definition: HypreDataStructures.hpp:91
Interface class adding the update() method to the preconditioner interface.
Definition: PreconditionerWithUpdate.hpp:33
HYPRE_Int N_owned
Number of DOFs owned by this MPI process.
Definition: HypreDataStructures.hpp:62
typename M::field_type matrix_field_type
The field type of the matrix.
Definition: HyprePreconditioner.hpp:72
std::vector< HYPRE_Int > ncols
Non-zero entries per owned row (size: N_owned)
Definition: HypreDataStructures.hpp:88
bool hasPerfectUpdate() const override
Checks if the preconditioner has a perfect update.
Definition: HyprePreconditioner.hpp:311
std::vector< HYPRE_BigInt > cols
Global column indices in CSR format (size: nnz)
Definition: HypreDataStructures.hpp:94
Wrapper for Hypre's BoomerAMG preconditioner.
Definition: HyprePreconditioner.hpp:66
void apply(X &v, const Y &d) override
Applies the preconditioner to a vector.
Definition: HyprePreconditioner.hpp:259
typename X::field_type vector_field_type
The field type of the vectors.
Definition: HyprePreconditioner.hpp:78
HYPRE_Real * vector_buffer_device
Device buffer for vector operations Used when input type and backend are different, for transferring values between host and device.
Definition: HypreDataStructures.hpp:149
~HyprePreconditioner()
Destructor for HyprePreconditioner.
Definition: HyprePreconditioner.hpp:175
HYPRE_Real * matrix_buffer_device
Device buffer for matrix values, only needed for CPU input + GPU backend.
Definition: HypreDataStructures.hpp:155
Compressed Sparse Row (CSR) sparsity pattern for HYPRE matrix assembly.
Definition: HypreDataStructures.hpp:86
Hierarchical collection of key/value pairs.
Definition: PropertyTree.hpp:38
Y range_type
The range type of the preconditioner.
Definition: HyprePreconditioner.hpp:76
void update() override
Updates the preconditioner with the current matrix values.
Definition: HyprePreconditioner.hpp:215
X domain_type
The domain type of the preconditioner.
Definition: HyprePreconditioner.hpp:74
Parallel domain decomposition information for HYPRE-Dune interface.
Definition: HypreDataStructures.hpp:37