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>
29#include <dune/common/fmatrix.hh>
30#include <dune/istl/bcrsmatrix.hh>
33#include <HYPRE_parcsr_ls.h>
34#include <HYPRE_krylov.h>
35#include <_hypre_utilities.h>
52template<
class M,
class X,
class Y>
67 OPM_TIMEBLOCK(prec_construct);
70 MPI_Comm_size(MPI_COMM_WORLD, &size);
72 OPM_THROW(std::runtime_error,
"HyprePreconditioner is currently only implemented for sequential runs");
75 use_gpu_ = prm.
get<
bool>(
"use_gpu",
false);
78#if HYPRE_USING_CUDA || HYPRE_USING_HIP
80 HYPRE_SetMemoryLocation(HYPRE_MEMORY_DEVICE);
81 HYPRE_SetExecutionPolicy(HYPRE_EXEC_DEVICE);
83 HYPRE_SetSpGemmUseVendor(
false);
85 HYPRE_SetUseGpuRand(1);
86 HYPRE_DeviceInitialize();
87 HYPRE_PrintDeviceInfo();
92 HYPRE_SetMemoryLocation(HYPRE_MEMORY_HOST);
93 HYPRE_SetExecutionPolicy(HYPRE_EXEC_HOST);
97 HYPRE_BoomerAMGCreate(&solver_);
100 HYPRE_BoomerAMGSetPrintLevel(solver_, prm.
get<
int>(
"print_level", 0));
101 HYPRE_BoomerAMGSetMaxIter(solver_, prm.
get<
int>(
"max_iter", 1));
102 HYPRE_BoomerAMGSetStrongThreshold(solver_, prm.
get<
double>(
"strong_threshold", 0.5));
103 HYPRE_BoomerAMGSetAggTruncFactor(solver_, prm.
get<
double>(
"agg_trunc_factor", 0.3));
104 HYPRE_BoomerAMGSetInterpType(solver_, prm.
get<
int>(
"interp_type", 6));
105 HYPRE_BoomerAMGSetMaxLevels(solver_, prm.
get<
int>(
"max_levels", 15));
106 HYPRE_BoomerAMGSetTol(solver_, prm.
get<
double>(
"tolerance", 0.0));
109 HYPRE_BoomerAMGSetRelaxType(solver_, 16);
110 HYPRE_BoomerAMGSetCoarsenType(solver_, 8);
111 HYPRE_BoomerAMGSetAggNumLevels(solver_, 0);
112 HYPRE_BoomerAMGSetAggInterpType(solver_, 6);
114 HYPRE_BoomerAMGSetKeepTranspose(solver_,
true);
117 HYPRE_BoomerAMGSetRelaxType(solver_, prm.
get<
int>(
"relax_type", 13));
118 HYPRE_BoomerAMGSetCoarsenType(solver_, prm.
get<
int>(
"coarsen_type", 10));
119 HYPRE_BoomerAMGSetAggNumLevels(solver_, prm.
get<
int>(
"agg_num_levels", 1));
120 HYPRE_BoomerAMGSetAggInterpType(solver_, prm.
get<
int>(
"agg_interp_type", 4));
125 nnz_ = A_.nonzeroes();
126 HYPRE_IJVectorCreate(MPI_COMM_SELF, 0, N_-1, &x_hypre_);
127 HYPRE_IJVectorCreate(MPI_COMM_SELF, 0, N_-1, &b_hypre_);
128 HYPRE_IJVectorSetObjectType(x_hypre_, HYPRE_PARCSR);
129 HYPRE_IJVectorSetObjectType(b_hypre_, HYPRE_PARCSR);
130 HYPRE_IJVectorInitialize(x_hypre_);
131 HYPRE_IJVectorInitialize(b_hypre_);
134 std::iota(indices_.begin(), indices_.end(), 0);
136 indices_device_ = hypre_CTAlloc(HYPRE_BigInt, N_, HYPRE_MEMORY_DEVICE);
137 hypre_TMemcpy(indices_device_, indices_.data(), HYPRE_BigInt, N_, HYPRE_MEMORY_DEVICE, HYPRE_MEMORY_HOST);
139 x_values_device_ = hypre_CTAlloc(HYPRE_Real, N_, HYPRE_MEMORY_DEVICE);
140 b_values_device_ = hypre_CTAlloc(HYPRE_Real, N_, HYPRE_MEMORY_DEVICE);
144 HYPRE_IJMatrixCreate(MPI_COMM_SELF, 0, N_-1, 0, N_-1, &A_hypre_);
145 HYPRE_IJMatrixSetObjectType(A_hypre_, HYPRE_PARCSR);
146 HYPRE_IJMatrixInitialize(A_hypre_);
148 setupSparsityPattern();
159 HYPRE_BoomerAMGDestroy(solver_);
162 HYPRE_IJMatrixDestroy(A_hypre_);
165 HYPRE_IJVectorDestroy(x_hypre_);
168 HYPRE_IJVectorDestroy(b_hypre_);
170 if (values_device_) {
171 hypre_TFree(values_device_, HYPRE_MEMORY_DEVICE);
173 if (x_values_device_) {
174 hypre_TFree(x_values_device_, HYPRE_MEMORY_DEVICE);
176 if (b_values_device_) {
177 hypre_TFree(b_values_device_, HYPRE_MEMORY_DEVICE);
179 if (indices_device_) {
180 hypre_TFree(indices_device_, HYPRE_MEMORY_DEVICE);
190 OPM_TIMEBLOCK(prec_update);
192 HYPRE_BoomerAMGSetup(solver_, parcsr_A_, par_b_, par_x_);
203 void pre(X& , Y& )
override {
214 void apply(X& v,
const Y& d)
override {
215 OPM_TIMEBLOCK(prec_apply);
218 copyVectorsToHypre(v, d);
221 HYPRE_BoomerAMGSolve(solver_, parcsr_A_, par_b_, par_x_);
224 copyVectorFromHypre(v);
242 Dune::SolverCategory::Category
category()
const override {
243 return Dune::SolverCategory::sequential;
265 void setupSparsityPattern() {
273 for (
auto row = A_.begin(); row != A_.end(); ++row) {
274 const int rowIdx = row.index();
275 rows_[rowIdx] = rowIdx;
276 ncols_[rowIdx] = row->size();
278 for (
auto col = row->begin(); col != row->end(); ++col) {
279 cols_[pos++] = col.index();
284 ncols_device_ = hypre_CTAlloc(HYPRE_Int, N_, HYPRE_MEMORY_DEVICE);
285 rows_device_ = hypre_CTAlloc(HYPRE_BigInt, N_, HYPRE_MEMORY_DEVICE);
286 cols_device_ = hypre_CTAlloc(HYPRE_BigInt, nnz_, HYPRE_MEMORY_DEVICE);
287 values_device_ = hypre_CTAlloc(HYPRE_Real, nnz_, HYPRE_MEMORY_DEVICE);
290 hypre_TMemcpy(ncols_device_, ncols_.data(), HYPRE_Int, N_, HYPRE_MEMORY_DEVICE, HYPRE_MEMORY_HOST);
291 hypre_TMemcpy(rows_device_, rows_.data(), HYPRE_BigInt, N_, HYPRE_MEMORY_DEVICE, HYPRE_MEMORY_HOST);
292 hypre_TMemcpy(cols_device_, cols_.data(), HYPRE_BigInt, nnz_, HYPRE_MEMORY_DEVICE, HYPRE_MEMORY_HOST);
303 void copyMatrixToHypre() {
304 OPM_TIMEBLOCK(prec_copy_matrix);
306 const HYPRE_Real* values = &(A_[0][0][0][0]);
314 hypre_TMemcpy(values_device_, values, HYPRE_Real, nnz_, HYPRE_MEMORY_DEVICE, HYPRE_MEMORY_HOST);
315 HYPRE_IJMatrixSetValues(A_hypre_, N_, ncols_device_, rows_device_, cols_device_, values_device_);
318 HYPRE_IJMatrixSetValues(A_hypre_, N_, ncols_.data(), rows_.data(), cols_.data(), values);
321 HYPRE_IJMatrixAssemble(A_hypre_);
322 HYPRE_IJMatrixGetObject(A_hypre_,
reinterpret_cast<void**
>(&parcsr_A_));
334 void copyVectorsToHypre(
const X& v,
const Y& d) {
335 OPM_TIMEBLOCK(prec_copy_vectors_to_hypre);
336 const HYPRE_Real* x_vals = &(v[0][0]);
337 const HYPRE_Real* b_vals = &(d[0][0]);
340 hypre_TMemcpy(x_values_device_, x_vals, HYPRE_Real, N_, HYPRE_MEMORY_DEVICE, HYPRE_MEMORY_HOST);
341 hypre_TMemcpy(b_values_device_, b_vals, HYPRE_Real, N_, HYPRE_MEMORY_DEVICE, HYPRE_MEMORY_HOST);
343 HYPRE_IJVectorSetValues(x_hypre_, N_, indices_device_, x_values_device_);
344 HYPRE_IJVectorSetValues(b_hypre_, N_, indices_device_, b_values_device_);
347 HYPRE_IJVectorSetValues(x_hypre_, N_, indices_.data(), x_vals);
348 HYPRE_IJVectorSetValues(b_hypre_, N_, indices_.data(), b_vals);
351 HYPRE_IJVectorAssemble(x_hypre_);
352 HYPRE_IJVectorAssemble(b_hypre_);
353 HYPRE_IJVectorGetObject(x_hypre_,
reinterpret_cast<void**
>(&par_x_));
354 HYPRE_IJVectorGetObject(b_hypre_,
reinterpret_cast<void**
>(&par_b_));
365 void copyVectorFromHypre(X& v) {
366 OPM_TIMEBLOCK(prec_copy_vector_from_hypre);
367 HYPRE_Real* values = &(v[0][0]);
369 HYPRE_IJVectorGetValues(x_hypre_, N_, indices_device_, x_values_device_);
370 hypre_TMemcpy(values, x_values_device_, HYPRE_Real, N_, HYPRE_MEMORY_HOST, HYPRE_MEMORY_DEVICE);
373 HYPRE_IJVectorGetValues(x_hypre_, N_, indices_.data(), values);
378 bool use_gpu_ =
false;
380 HYPRE_Solver solver_ =
nullptr;
381 HYPRE_IJMatrix A_hypre_ =
nullptr;
382 HYPRE_ParCSRMatrix parcsr_A_ =
nullptr;
383 HYPRE_IJVector x_hypre_ =
nullptr;
384 HYPRE_IJVector b_hypre_ =
nullptr;
385 HYPRE_ParVector par_x_ =
nullptr;
386 HYPRE_ParVector par_b_ =
nullptr;
388 std::vector<HYPRE_Int> ncols_;
389 std::vector<HYPRE_BigInt> rows_;
390 std::vector<HYPRE_BigInt> cols_;
391 HYPRE_Int* ncols_device_ =
nullptr;
392 HYPRE_BigInt* rows_device_ =
nullptr;
393 HYPRE_BigInt* cols_device_ =
nullptr;
394 HYPRE_Real* values_device_ =
nullptr;
396 std::vector<HYPRE_BigInt> indices_;
397 HYPRE_BigInt* indices_device_ =
nullptr;
401 HYPRE_Real* x_values_device_ =
nullptr;
402 HYPRE_Real* b_values_device_ =
nullptr;
Interface class adding the update() method to the preconditioner interface.
Definition: PreconditionerWithUpdate.hpp:32
Wrapper for Hypre's BoomerAMG preconditioner.
Definition: HyprePreconditioner.hpp:53
HyprePreconditioner(const M &A, const Opm::PropertyTree prm)
Constructor for the HyprePreconditioner class.
Definition: HyprePreconditioner.hpp:64
void pre(X &, Y &) override
Pre-processing step before applying the preconditioner.
Definition: HyprePreconditioner.hpp:203
Dune::SolverCategory::Category category() const override
Returns the solver category.
Definition: HyprePreconditioner.hpp:242
void post(X &) override
Post-processing step after applying the preconditioner.
Definition: HyprePreconditioner.hpp:234
bool hasPerfectUpdate() const override
Checks if the preconditioner has a perfect update.
Definition: HyprePreconditioner.hpp:251
void update() override
Updates the preconditioner with the current matrix values.
Definition: HyprePreconditioner.hpp:189
void apply(X &v, const Y &d) override
Applies the preconditioner to a vector.
Definition: HyprePreconditioner.hpp:214
~HyprePreconditioner()
Destructor for the HyprePreconditioner class.
Definition: HyprePreconditioner.hpp:157
Hierarchical collection of key/value pairs.
Definition: PropertyTree.hpp:39
T get(const std::string &key) const
Definition: HyprePreconditioner.hpp:40