17#ifndef OPM_ISTLSOLVERGPUISTL_HEADER_INCLUDED
18#define OPM_ISTLSOLVERGPUISTL_HEADER_INCLUDED
20#include <dune/istl/operators.hh>
23#include <opm/grid/utility/ElementChunks.hpp>
24#include <opm/simulators/linalg/AbstractISTLSolver.hpp>
25#include <opm/simulators/linalg/getQuasiImpesWeights.hpp>
26#include <opm/simulators/linalg/ISTLSolver.hpp>
29#include <opm/simulators/linalg/gpuistl_hip/GpuSparseMatrixWrapper.hpp>
30#include <opm/simulators/linalg/gpuistl_hip/GpuVector.hpp>
31#include <opm/simulators/linalg/gpuistl_hip/PinnedMemoryHolder.hpp>
33#include <opm/simulators/linalg/gpuistl/GpuSparseMatrixWrapper.hpp>
34#include <opm/simulators/linalg/gpuistl/GpuVector.hpp>
35#include <opm/simulators/linalg/gpuistl/PinnedMemoryHolder.hpp>
38#include <opm/simulators/linalg/ExtractParallelGridInformationToISTL.hpp>
39#include <opm/simulators/linalg/ParallelIstlInformation.hpp>
40#include <opm/simulators/linalg/findOverlapRowsAndColumns.hpp>
41#include <opm/simulators/linalg/gpuistl/detail/FlexibleSolverWrapper.hpp>
42#include <opm/simulators/linalg/printlinearsolverparameter.hpp>
59template <
class TypeTag>
67 using Matrix =
typename SparseMatrixAdapter::IstlMatrix;
71 using ElementChunksType = Opm::ElementChunks<GridView, Dune::Partitions::All>;
73 using real_type =
typename Vector::field_type;
83 using CommunicationType = Dune::OwnerOverlapCopyCommunication<int, int>;
85 using CommunicationType = Dune::Communication<int>;
99 bool forceSerial =
false)
100 : m_parameters(parameters)
101 , m_simulator(simulator)
102 , m_forceSerial(forceSerial)
103 , m_element_chunks(simulator.vanguard().gridView(), Dune::Partitions::all, ThreadManager::maxThreads())
106 m_comm = std::make_shared<CommunicationType>(simulator.vanguard().grid().comm());
110 ElementMapper elemMapper(simulator.vanguard().gridView(), Dune::mcmgElementLayout());
112 Opm::detail::findOverlapAndInterior(simulator.vanguard().grid(), elemMapper, m_overlapRows, m_interiorRows);
114 const std::size_t size = simulator.vanguard().grid().leafGridView().size(0);
116 Opm::detail::copyParValues(m_parallelInformation, size, *m_comm);
120 m_comm = std::make_shared<CommunicationType>(simulator.gridView().comm());
122 m_parameters.init(simulator.vanguard().eclState().getSimulationConfig().useCPR());
127 OPM_THROW(std::logic_error,
"Well operators are currently not supported for the GPU backend. "
128 "Use --matrix-add-well-contributions=true to add well contributions to the matrix instead.");
131 Opm::detail::printLinearSolverParameters(m_parameters, m_propertyTree, simulator.gridView().comm());
160 OPM_THROW(std::logic_error,
"Only one solver available for the GPU backend.");
183 void prepare(
const SparseMatrixAdapter& M, Vector& b)
override
197 void prepare(
const Matrix& M, Vector& b)
override
201 Opm::detail::makeOverlapRowsInvalid(
const_cast<Matrix&
>(M), m_overlapRows);
206 OPM_CATCH_AND_RETHROW_AS_CRITICAL_ERROR(
"This is likely due to a faulty linear solver JSON specification. "
207 "Check for errors related to missing nodes.");
231 OPM_THROW(std::runtime_error,
"m_rhs not initialized, prepare(matrix, rhs); needs to be called");
233 m_rhs->copyToHost(b);
260 Dune::InverseOperatorResult result;
262 OPM_THROW(std::runtime_error,
"m_matrix not initialized, prepare(matrix, rhs); needs to be called");
265 OPM_THROW(std::runtime_error,
"m_rhs not initialized, prepare(matrix, rhs); needs to be called");
268 OPM_THROW(std::runtime_error,
269 "m_gpuFlexibleSolver not initialized, prepare(matrix, rhs); needs to be called");
273 m_x = std::make_unique<GPUVector>(x);
274 m_pinnedXMemory = std::make_unique<PinnedMemoryHolder<real_type>>(
275 const_cast<real_type*
>(&x[0][0]),
280 m_x->copyFromHostAsync(x);
282 m_gpuSolver->apply(*m_x, *m_rhs, result);
288 m_lastSeenIterations = result.iterations;
289 return checkConvergence(result);
299 return m_lastSeenIterations;
305 const CommunicationType*
comm()
const override
318 return !m_forceSerial && m_comm->communicator().size() > 1;
333 bool checkConvergence(
const Dune::InverseOperatorResult& result)
const
339 std::function<GPUVector&()> getWeightsCalculator()
341 std::function<GPUVector&()> weightsCalculator;
343 using namespace std::string_literals;
345 auto preconditionerType = m_propertyTree.
get(
"preconditioner.type"s,
"cpr"s);
347 std::transform(preconditionerType.begin(), preconditionerType.end(), preconditionerType.begin(), ::tolower);
348 if (preconditionerType ==
"cpr" || preconditionerType ==
"cprt"
349 || preconditionerType ==
"cprw" || preconditionerType ==
"cprwt") {
350 const bool transpose = preconditionerType ==
"cprt" || preconditionerType ==
"cprwt";
351 const auto weightsType = m_propertyTree.
get(
"preconditioner.weight_type"s,
"quasiimpes"s);
352 if (weightsType ==
"quasiimpes") {
353 m_weights.emplace(m_matrix->N() * m_matrix->blockSize());
355 auto diagonalIndices = Amg::precomputeDiagonalIndices(*m_matrix);
356 m_diagonalIndices.emplace(diagonalIndices);
359 weightsCalculator = [
this]() -> GPUVector& {
360 Amg::getQuasiImpesWeights<real_type, true>(
361 *m_matrix, pressureIndex, *m_weights, *m_diagonalIndices);
365 weightsCalculator = [
this]() -> GPUVector& {
366 Amg::getQuasiImpesWeights<real_type, false>(
367 *m_matrix, pressureIndex, *m_weights, *m_diagonalIndices);
371 }
else if (weightsType ==
"trueimpes") {
373 m_cpuWeights.resize(m_matrix->N());
374 m_pinnedWeightsMemory = std::make_unique<PinnedMemoryHolder<real_type>>(
375 const_cast<real_type*
>(&m_cpuWeights[0][0]), m_cpuWeights.dim());
376 m_weights.emplace(m_cpuWeights);
378 const bool enableThreadParallel = m_parameters.cpr_weights_thread_parallel_;
380 weightsCalculator = [
this, enableThreadParallel]() -> GPUVector& {
382 ElementContext elemCtx(m_simulator);
383 Amg::getTrueImpesWeights(pressureIndex,
385 elemCtx, m_simulator.model(),
387 enableThreadParallel);
390 m_weights->copyFromHostAsync(m_cpuWeights);
393 }
else if (weightsType ==
"trueimpesanalytic") {
395 m_cpuWeights.resize(m_matrix->N());
396 m_pinnedWeightsMemory = std::make_unique<PinnedMemoryHolder<real_type>>(
397 const_cast<real_type*
>(&m_cpuWeights[0][0]), m_cpuWeights.dim());
398 m_weights.emplace(m_cpuWeights);
399 const bool enableThreadParallel = m_parameters.cpr_weights_thread_parallel_;
401 weightsCalculator = [
this, enableThreadParallel]() -> GPUVector& {
403 ElementContext elemCtx(m_simulator);
404 Amg::getTrueImpesWeightsAnalytic(pressureIndex,
406 elemCtx, m_simulator.model(),
408 enableThreadParallel);
411 m_weights->copyFromHostAsync(m_cpuWeights);
415 OPM_THROW(std::invalid_argument,
416 "Weights type " + weightsType
417 +
" not implemented for cpr."
418 " Please use quasiimpes, trueimpes or trueimpesanalytic.");
421 return weightsCalculator;
424 void updateMatrix(
const Matrix& M)
428 m_pinnedMatrixMemory = std::make_unique<PinnedMemoryHolder<real_type>>(
429 const_cast<real_type*
>(&M[0][0][0][0]),
430 M.nonzeroes() * M[0][0].N() * M[0][0].M()
432 std::function<GPUVector&()> weightsCalculator = getWeightsCalculator();
433 m_gpuSolver = std::make_unique<SolverType>(
434 *m_matrix,
isParallel(), m_propertyTree, pressureIndex, weightsCalculator, m_forceSerial, m_comm.get());
436 m_matrix->updateNonzeroValues(M,
true);
437 m_gpuSolver->update();
441 void updateRhs(
const Vector& b)
444 m_rhs = std::make_unique<GPUVector>(b);
445 m_pinnedRhsMemory = std::make_unique<PinnedMemoryHolder<real_type>>(
446 const_cast<real_type*
>(&b[0][0]),
451 m_rhs->copyFromHostAsync(b);
455 FlowLinearSolverParameters m_parameters;
456 const Simulator& m_simulator;
457 const bool m_forceSerial;
458 PropertyTree m_propertyTree;
459 ElementChunksType m_element_chunks;
461 int m_lastSeenIterations = 0;
462 int m_solveCount = 0;
464 std::unique_ptr<GPUMatrix> m_matrix;
466 std::unique_ptr<SolverType> m_gpuSolver;
468 std::unique_ptr<GPUVector> m_rhs;
469 std::unique_ptr<GPUVector> m_x;
471 std::unique_ptr<PinnedMemoryHolder<real_type>> m_pinnedMatrixMemory;
472 std::unique_ptr<PinnedMemoryHolder<real_type>> m_pinnedRhsMemory;
473 std::unique_ptr<PinnedMemoryHolder<real_type>> m_pinnedXMemory;
474 std::unique_ptr<PinnedMemoryHolder<real_type>> m_pinnedWeightsMemory;
477 std::optional<GPUVector> m_weights;
478 std::optional<GPUVectorInt> m_diagonalIndices;
480 std::shared_ptr<CommunicationType> m_comm;
481 std::vector<int> m_interiorRows;
482 std::vector<int> m_overlapRows;
483 std::any m_parallelInformation;
Abstract interface for ISTL solvers.
Definition AbstractISTLSolver.hpp:45
static bool checkConvergence(const Dune::InverseOperatorResult &result, const FlowLinearSolverParameters ¶meters)
Check the convergence of the linear solver.
Definition AbstractISTLSolver.hpp:194
T get(const std::string &key) const
Retrieve property value given hierarchical property key.
Definition PropertyTree.cpp:59
The GpuSparseMatrixWrapper Checks CUDA/HIP version and dispatches a version either using the old or t...
Definition GpuSparseMatrixWrapper.hpp:62
static GpuSparseMatrixWrapper< real_type, false > fromMatrix(const MatrixType &matrix, bool copyNonZeroElementsDirectly=false)
Definition GpuSparseMatrixWrapper.hpp:183
Definition gpu_type_detection.hpp:30
bool isParallel() const
Check if we are running in parallel mode.
Definition ISTLSolverGPUISTL.hpp:315
ISTLSolverGPUISTL(const Simulator &simulator, const FlowLinearSolverParameters ¶meters, bool forceSerial=false)
Construct a system solver.
Definition ISTLSolverGPUISTL.hpp:97
void setMatrix(const SparseMatrixAdapter &) override
Set the matrix for the solver.
Definition ISTLSolverGPUISTL.hpp:241
void prepare(const SparseMatrixAdapter &M, Vector &b) override
Prepare the solver with the given matrix and right-hand side vector.
Definition ISTLSolverGPUISTL.hpp:183
const CommunicationType * comm() const override
Get the communication object used by the solver.
Definition ISTLSolverGPUISTL.hpp:305
int getSolveCount() const override
Get the count of how many times the solver has been called.
Definition ISTLSolverGPUISTL.hpp:327
void setResidual(Vector &) override
Set the residual vector.
Definition ISTLSolverGPUISTL.hpp:215
void getResidual(Vector &b) const override
Get the residual vector.
Definition ISTLSolverGPUISTL.hpp:228
bool solve(Vector &x) override
Solve the system of linear equations Ax = b.
Definition ISTLSolverGPUISTL.hpp:257
ISTLSolverGPUISTL(const Simulator &simulator)
Construct a system solver.
Definition ISTLSolverGPUISTL.hpp:136
int iterations() const override
Definition ISTLSolverGPUISTL.hpp:297
void eraseMatrix() override
Signals that the memory for the matrix internally in the solver could be erased.
Definition ISTLSolverGPUISTL.hpp:146
int numAvailableSolvers() const override
Get the number of available solvers.
Definition ISTLSolverGPUISTL.hpp:169
void setActiveSolver(int num) override
Set the active solver by its index.
Definition ISTLSolverGPUISTL.hpp:157
void prepare(const Matrix &M, Vector &b) override
Prepare the solver with the given matrix and right-hand side vector.
Definition ISTLSolverGPUISTL.hpp:197
FlexibleSolverWrapper is compilational trick to reduce compile time overhead.
Definition FlexibleSolverWrapper.hpp:45
A small, fixed‑dimension MiniVector class backed by std::array that can be used in both host and CUDA...
Definition AmgxInterface.hpp:38
typename Properties::Detail::GetPropImpl< TypeTag, Property >::type::type GetPropType
get the type alias defined in the property (equivalent to old macro GET_PROP_TYPE(....
Definition propertysystem.hh:233
void extractParallelGridInformationToISTL(const Dune::CpGrid &, std::any &)
Extracts the information about the data decomposition from the grid for dune-istl.
Definition ExtractParallelGridInformationToISTL.cpp:46
PropertyTree setupPropertyTree(FlowLinearSolverParameters p, bool linearSolverMaxIterSet, bool linearSolverReductionSet)
Set up a property tree intended for FlexibleSolver by either reading the tree from a JSON file or cre...
Definition setupPropertyTree.cpp:181
bool IsSet(bool errorIfNotRegistered=true)
Returns true if a parameter has been specified at runtime, false otherwise.
Definition parametersystem.hpp:270
auto Get(bool errorIfNotRegistered=true)
Retrieve a runtime parameter.
Definition parametersystem.hpp:187
This class carries all parameters for the NewtonIterationBlackoilInterleaved class.
Definition FlowLinearSolverParameters.hpp:98