opm-simulators
ISTLSolverRuntimeOptionProxy.hpp
1 /*
2  Copyright 2025 Equinor ASA
3 
4  This file is part of the Open Porous Media project (OPM).
5  OPM is free software: you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation, either version 3 of the License, or
8  (at your option) any later version.
9  OPM is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13  You should have received a copy of the GNU General Public License
14  along with OPM. If not, see <http://www.gnu.org/licenses/>.
15 */
16 
17 #ifndef OPM_ISTLSOLVERRUNTIMEOPTIONPROXY_HEADER_INCLUDED
18 #define OPM_ISTLSOLVERRUNTIMEOPTIONPROXY_HEADER_INCLUDED
19 
20 #include "opm/simulators/linalg/FlowLinearSolverParameters.hpp"
21 #include <opm/simulators/linalg/setupPropertyTree.hpp>
22 #include <opm/simulators/linalg/AbstractISTLSolver.hpp>
23 #include <opm/simulators/linalg/ISTLSolver.hpp>
25 #if COMPILE_GPU_BRIDGE
26 #include <opm/simulators/linalg/ISTLSolverGpuBridge.hpp>
27 #endif
28 
29 #if USE_HIP
30 #include <opm/simulators/linalg/gpuistl_hip/ISTLSolverGPUISTL.hpp>
31 #elif HAVE_CUDA
32 #include <opm/simulators/linalg/gpuistl/ISTLSolverGPUISTL.hpp>
33 #endif
34 
35 #include <opm/simulators/linalg/system/ISTLSolverSystem.hpp>
36 
37 #include <filesystem>
38 #include <fmt/format.h>
39 
40 namespace Opm
41 {
42 
46 template <class TypeTag>
47 class ISTLSolverRuntimeOptionProxy : public AbstractISTLSolver<GetPropType<TypeTag, Properties::SparseMatrixAdapter>,
48  GetPropType<TypeTag, Properties::GlobalEqVector>>
49 {
50 public:
51  using SparseMatrixAdapter = GetPropType<TypeTag, Properties::SparseMatrixAdapter>;
52  using Vector = GetPropType<TypeTag, Properties::GlobalEqVector>;
53  using Simulator = GetPropType<TypeTag, Properties::Simulator>;
54  using Matrix = typename SparseMatrixAdapter::IstlMatrix;
55 
56 #if HAVE_MPI
57  using CommunicationType = Dune::OwnerOverlapCopyCommunication<int, int>;
58 #else
59  using CommunicationType = Dune::Communication<int>;
60 #endif
61 
62 
63  static void registerParameters()
64  {
65  FlowLinearSolverParameters::registerParameters();
66  }
67 
75  ISTLSolverRuntimeOptionProxy(const Simulator& simulator,
76  const FlowLinearSolverParameters& parameters,
77  bool forceSerial = false)
78  {
79  createSolver(simulator, parameters, forceSerial);
80  }
81 
84  explicit ISTLSolverRuntimeOptionProxy(const Simulator& simulator)
85  {
86  createSolver(simulator);
87  }
88 
89 
90  void eraseMatrix() override
91  {
92  istlSolver_->eraseMatrix();
93  }
94 
95  void setActiveSolver(int num) override
96  {
97  istlSolver_->setActiveSolver(num);
98  }
99 
100  int numAvailableSolvers() const override
101  {
102  return istlSolver_->numAvailableSolvers();
103  }
104 
105  void prepare(const SparseMatrixAdapter& M, Vector& b) override
106  {
107  istlSolver_->prepare(M, b);
108  }
109 
110  void prepare(const Matrix& M, Vector& b) override
111  {
112  istlSolver_->prepare(M, b);
113  }
114 
115  void setResidual(Vector& b) override
116  {
117  istlSolver_->setResidual(b);
118  }
119 
120  void getResidual(Vector& b) const override
121  {
122  istlSolver_->getResidual(b);
123  }
124 
125  void setMatrix(const SparseMatrixAdapter& M) override
126  {
127  istlSolver_->setMatrix(M);
128  }
129 
130  bool solve(Vector& x) override
131  {
132  return istlSolver_->solve(x);
133  }
134 
135  int iterations() const override
136  {
137  return istlSolver_->iterations();
138  }
139 
140  const CommunicationType* comm() const override
141  {
142  return istlSolver_->comm();
143  }
144 
145  int getSolveCount() const override
146  {
147  return istlSolver_->getSolveCount();
148  }
149 
150 private:
151  std::unique_ptr<AbstractISTLSolver<SparseMatrixAdapter, Vector>> istlSolver_;
152 
153 
154  template <class... Args>
155  void createSolver(const Simulator& simulator, Args&&... args)
156  {
157  auto linSolverConf = Parameters::Get<Parameters::LinearSolver>();
158  bool useSystemCpr = (linSolverConf == "system_cpr");
159  if (!useSystemCpr && linSolverConf.size() > 5
160  && linSolverConf.ends_with(".json")
161  && std::filesystem::exists(linSolverConf)) {
162  try {
163  PropertyTree prm(linSolverConf);
164  useSystemCpr = (prm.get<std::string>("preconditioner.type", "") == "system_cpr");
165  } catch (...) {}
166  }
167  if (useSystemCpr) {
168  using Indices = GetPropType<TypeTag, Properties::Indices>;
169  const auto backend = Parameters::linearSolverAcceleratorTypeFromCLI();
170  if (backend != Parameters::LinearSolverAcceleratorType::CPU) {
171  OPM_THROW(std::invalid_argument,
172  "The system_cpr preconditioner currently only "
173  "supports --linear-solver-accelerator=cpu");
174  }
175  // System solver types are hardcoded for 3-equation blackoil (see SystemTypes.hpp).
176  if constexpr (Indices::numEq == 3) {
177  istlSolver_ = std::make_unique<ISTLSolverSystem<TypeTag>>(
178  simulator, std::forward<Args>(args)...);
179  } else {
180  OPM_THROW(std::invalid_argument,
181  "The system_cpr preconditioner is only supported for "
182  "standard 3-phase blackoil (3 equations). This model has " +
183  std::to_string(Indices::numEq) + " equations.");
184  }
185  checkSystemCPRMatrixAddWell(Parameters::Get<Parameters::MatrixAddWellContributions>());
186  return;
187  }
188 
189  const auto backend = Parameters::linearSolverAcceleratorTypeFromCLI();
190  if (backend == Parameters::LinearSolverAcceleratorType::CPU) {
191  // Note that for now we keep the old behavior of using the bridge solver if it is available.
192 #if COMPILE_GPU_BRIDGE
193  istlSolver_ = std::make_unique<ISTLSolverGpuBridge<TypeTag>>(simulator, std::forward<Args>(args)...);
194 #else
195  istlSolver_ = std::make_unique<ISTLSolver<TypeTag>>(simulator, std::forward<Args>(args)...);
196 #endif
197  }
198 #if HAVE_CUDA
199  else if (backend == Parameters::LinearSolverAcceleratorType::GPU) {
200  istlSolver_ = std::make_unique<gpuistl::ISTLSolverGPUISTL<TypeTag>>(simulator, std::forward<Args>(args)...);
201  }
202 #endif
203  else {
204  // If we reach here, it means the backend is not supported. This could be because we have added a third backend
205  // that we need to handle. A user error would be handled in the linearSolverAcceleratorTypeFromString function called above.
206  OPM_THROW(std::invalid_argument, fmt::format(fmt::runtime("Unknown backend: {}"), Parameters::toString(backend)));
207  }
208  }
209 };
210 } // namespace Opm
211 
212 #endif
ISTLSolverRuntimeOptionProxy(const Simulator &simulator, const FlowLinearSolverParameters &parameters, bool forceSerial=false)
Construct a system solver.
Definition: ISTLSolverRuntimeOptionProxy.hpp:75
Structs needed for tpfalinearizer and its gpuparams struct extracted to be defined in one place that ...
Definition: blackoilbioeffectsmodules.hh:45
ISTLSolverRuntimeOptionProxy(const Simulator &simulator)
Construct a system solver.
Definition: ISTLSolverRuntimeOptionProxy.hpp:84
const CommunicationType * comm() const override
Get the communication object used by the solver.
Definition: ISTLSolverRuntimeOptionProxy.hpp:140
The Opm property system, traits with inheritance.
void eraseMatrix() override
Signals that the memory for the matrix internally in the solver could be erased.
Definition: ISTLSolverRuntimeOptionProxy.hpp:90
This class carries all parameters for the NewtonIterationBlackoilInterleaved class.
Definition: FlowLinearSolverParameters.hpp:97
int numAvailableSolvers() const override
Get the number of available solvers.
Definition: ISTLSolverRuntimeOptionProxy.hpp:100
Manages the initializing and running of time dependent problems.
Definition: simulator.hh:83
Hierarchical collection of key/value pairs.
Definition: PropertyTree.hpp:38
int getSolveCount() const override
Get the count of how many times the solver has been called.
Definition: ISTLSolverRuntimeOptionProxy.hpp:145
int iterations() const override
Get the number of iterations used in the last solve.
Definition: ISTLSolverRuntimeOptionProxy.hpp:135
void setActiveSolver(int num) override
Set the active solver by its index.
Definition: ISTLSolverRuntimeOptionProxy.hpp:95