tpfalinearizergpuparams.hh
Go to the documentation of this file.
1// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2// vi: set et ts=4 sw=4 sts=4:
3/*
4
5 Copyright 2026 Equinor ASA
6
7 This file is part of the Open Porous Media project (OPM).
8 OPM is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 OPM is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with OPM. If not, see <http://www.gnu.org/licenses/>.
20*/
30#ifndef TPFA_LINEARIZER_GPU_PARAMS_HH
31#define TPFA_LINEARIZER_GPU_PARAMS_HH
32
33#if HAVE_CUDA && OPM_IS_COMPILING_WITH_GPU_COMPILER
34
35#include <memory>
36#include <string>
37#include <vector>
38
39#include <opm/common/utility/gpuistl_if_available.hpp>
40
41#if USE_HIP
42#include <opm/simulators/linalg/gpuistl_hip/GpuSparseMatrixWrapper.hpp>
43#include <opm/simulators/linalg/gpuistl_hip/MiniMatrix.hpp>
44#include <opm/simulators/linalg/gpuistl_hip/MiniVector.hpp>
45#else
49#endif
50
51#include <opm/common/utility/SparseTable.hpp>
56
58
59namespace Opm {
60
73template <class TypeTag>
74class TpfaLinearizerGpuParams
75{
76 using Scalar = GetPropType<TypeTag, Properties::Scalar>;
77 using GlobalEqVector = GetPropType<TypeTag, Properties::GlobalEqVector>;
78 using SparseMatrixAdapter = GetPropType<TypeTag, Properties::SparseMatrixAdapter>;
79 using LocalResidual = GetPropType<TypeTag, Properties::LocalResidual>;
80 using IntensiveQuantities = GetPropType<TypeTag, Properties::IntensiveQuantities>;
81 using FluidSystem = GetPropType<TypeTag, Properties::FluidSystem>;
82 using Model = GetPropType<TypeTag, Properties::Model>;
83 using Problem = GetPropType<TypeTag, Properties::Problem>;
84
85 enum { numEq = getPropValue<TypeTag, Properties::NumEq>() };
86
87 using MatrixBlockCPU = typename SparseMatrixAdapter::MatrixBlock;
88 using VectorBlockCPU = Dune::FieldVector<Scalar, numEq>;
89 using MatrixBlockGPU = gpuistl::MiniMatrix<Scalar, numEq>;
90 using VectorBlockGPU = gpuistl::MiniVector<Scalar, numEq>;
91
92 using ResidualNBInfo = typename LocalResidual::ResidualNBInfo;
93 using NeighborInfoCPU = NeighborInfoStruct<ResidualNBInfo, MatrixBlockCPU>;
94 using NeighborInfoGPU = NeighborInfoStruct<ResidualNBInfo, MatrixBlockGPU>;
95
96 using ScalarFluidState = typename IntensiveQuantities::ScalarFluidState;
97 using BoundaryConditionDataCPU = BoundaryConditionData<VectorBlockCPU, ScalarFluidState>;
98 using BoundaryInfoCPU = BoundaryInfo<BoundaryConditionDataCPU>;
99
100 // Fluid system buffer/view/ptr types derived without spelling out the fluid-system
101 // template parameters explicitly.
102 using NonStaticFluidSystem = std::decay_t<decltype(FluidSystem::getNonStaticInstance())>;
103 using GpuFluidSystemBuffer = std::decay_t<decltype(::Opm::gpuistl::copy_to_gpu(
104 std::declval<NonStaticFluidSystem&>()))>;
105 using GpuFluidSystemView
106 = std::decay_t<decltype(::Opm::gpuistl::make_view(std::declval<GpuFluidSystemBuffer&>()))>;
107 using GpuFluidSystemPtr = std::shared_ptr<GpuFluidSystemView>;
108
109public:
110 // Type aliases required by callers to instantiate the GPU kernel templates.
111 using CorrectTypeTagView =
112 typename ::Opm::Properties::TTag::to_gpu_type_t<TypeTag, gpuistl::GpuView>;
113
114 // GPUBOIQ and LocalResidualGPU are not taken from typetag as we need the
115 // outer class to template correctly here
116 using GPUBOIQ = BlackOilIntensiveQuantities<CorrectTypeTagView>;
117 using LocalResidualGPU = BlackOilLocalResidualTPFA<CorrectTypeTagView>;
118
119private:
120 using GpuScalarFluidState = typename GPUBOIQ::ScalarFluidState;
121 using BoundaryConditionDataGPU = BoundaryConditionData<VectorBlockGPU, GpuScalarFluidState>;
122 using BoundaryInfoGPU = BoundaryInfo<BoundaryConditionDataGPU>;
123
124 using GpuModelBufferType = SimpleFIBlackOilModel<CorrectTypeTagView, gpuistl::GpuBuffer>;
125 using GpuFlowProblemBufferType = ThermalGasWaterFlowProblem<Scalar, gpuistl::GpuBuffer>;
126
127 using GpuModel = GetPropType<TypeTag, Properties::GpuFIBlackOilModel>;
128
129 FullDomain<gpuistl::GpuBuffer<int>> domainBuffer_;
130 SparseTable<NeighborInfoGPU, gpuistl::GpuBuffer> neighborInfoBuffer_;
131 // diagMatAddressView_ is non-owning: the underlying buffer lives in TpfaLinearizer.
132 gpuistl::GpuView<MatrixBlockGPU*> diagMatAddressView_;
133 gpuistl::GpuBuffer<VectorBlockGPU> residualBuffer_;
134 gpuistl::GpuView<VectorBlockGPU>
135 residualView_; // stored as lvalue because mutable ref must be provided
136 // dynamicGpuFluidSystemBuffer_ must be declared before dynamicGpuFluidSystemPtr_
137 // because the ptr holds a GpuView into the buffer's GPU memory.
138 GpuFluidSystemBuffer dynamicGpuFluidSystemBuffer_;
139 // The fluid-system ptr is kept alive because gpuModelBuffer_ and
140 // boundaryInfoBuffer_ store raw GPU pointers into it.
141 GpuFluidSystemPtr dynamicGpuFluidSystemPtr_;
142 GpuModelBufferType gpuModelBuffer_;
143 GpuFlowProblemBufferType gpuFlowProblemBuffer_;
144 gpuistl::GpuBuffer<BoundaryInfoGPU> boundaryInfoBuffer_;
145
146public:
167 TpfaLinearizerGpuParams(const FullDomain<>& domain,
168 const SparseTable<NeighborInfoCPU>& neighborInfo,
169 gpuistl::GpuSparseMatrixWrapper<Scalar>& gpuJacobian,
170 gpuistl::GpuBuffer<MatrixBlockGPU*>& gpuBufferDiagMatAddress,
171 typename SparseMatrixAdapter::IstlMatrix& cpuJacobian,
172 GlobalEqVector& residual,
173 const std::vector<BoundaryInfoCPU>& boundaryInfo,
174 Model& model,
175 const Problem& problem,
176 unsigned int numCells)
177 : domainBuffer_(copy_to_gpu(domain))
178 , neighborInfoBuffer_(
179 gpuistl::copy_to_gpu<MatrixBlockGPU>(neighborInfo, gpuJacobian, cpuJacobian))
180 , diagMatAddressView_(gpuistl::make_view(gpuBufferDiagMatAddress))
181 , residualBuffer_(gpuistl::copy_to_gpu_residual<GlobalEqVector, VectorBlockGPU>(residual))
182 , residualView_(gpuistl::make_view(residualBuffer_))
183 , dynamicGpuFluidSystemBuffer_(
184 ::Opm::gpuistl::copy_to_gpu(FluidSystem::getNonStaticInstance()))
185 , dynamicGpuFluidSystemPtr_(
186 gpuistl::make_gpu_shared_ptr(::Opm::gpuistl::make_view(dynamicGpuFluidSystemBuffer_)))
187 , gpuModelBuffer_([&]() -> GpuModelBufferType {
188 std::vector<Scalar> volumes(numCells);
189 for (unsigned i = 0; i < numCells; ++i) {
190 volumes[domain.cells[i]] = model.dofTotalVolume(domain.cells[i]);
191 }
192 GpuModel gpuModel(
193 model.intensiveQuantityCache()[0], model.intensiveQuantityCache()[1], volumes);
194 return gpuistl::copy_to_gpu(gpuModel, *dynamicGpuFluidSystemPtr_.get());
195 }())
196 , gpuFlowProblemBuffer_([&]() -> GpuFlowProblemBufferType {
197 std::vector<Scalar> alpha0(numCells);
198 std::vector<Scalar> alpha1(numCells);
199 std::vector<Scalar> alpha2(numCells);
200 std::vector<Scalar> alpha3(numCells);
201 std::vector<Scalar> alpha4(numCells);
202 std::vector<Scalar> alpha5(numCells);
203 const auto& thermalHalfTransBoundary
204 = problem.eclTransmissibilities().getThermalHalfTransBoundary();
205 for (const auto& [key, value] : thermalHalfTransBoundary) {
206 const unsigned cell = key.first;
207 const unsigned dir = key.second;
208 if (dir == 0) {
209 alpha0[cell] = value;
210 } else if (dir == 1) {
211 alpha1[cell] = value;
212 } else if (dir == 2) {
213 alpha2[cell] = value;
214 } else if (dir == 3) {
215 alpha3[cell] = value;
216 } else if (dir == 4) {
217 alpha4[cell] = value;
218 } else if (dir == 5) {
219 alpha5[cell] = value;
220 } else {
221 OPM_THROW(std::logic_error,
222 "Invalid direction for thermal half transmissibility: "
223 + std::to_string(dir));
224 }
225 }
226 ThermalGasWaterFlowProblem<Scalar> gpuFlowProblem(
227 alpha0, alpha1, alpha2, alpha3, alpha4, alpha5, problem.moduleParams());
228 return gpuistl::copy_to_gpu(gpuFlowProblem);
229 }())
230 , boundaryInfoBuffer_(
231 gpuistl::copy_to_gpu<VectorBlockGPU, GpuScalarFluidState, BoundaryInfoGPU>(
232 boundaryInfo, *dynamicGpuFluidSystemPtr_.get()))
233 {
234 }
235
236 auto domainView()
237 {
238 return make_view(domainBuffer_);
239 }
240
241 auto neighborInfoView()
242 {
243 return gpuistl::make_view(neighborInfoBuffer_);
244 }
245
246 auto& diagMatAddressView()
247 {
248 return diagMatAddressView_;
249 }
250
251 auto& residualView()
252 {
253 return residualView_;
254 }
255
256 auto modelView()
257 {
258 return gpuistl::make_view(gpuModelBuffer_);
259 }
260
261 auto flowProblemView()
262 {
263 return gpuistl::make_view(gpuFlowProblemBuffer_);
264 }
265
266 auto boundaryInfoView()
267 {
268 return gpuistl::make_view(boundaryInfoBuffer_);
269 }
270
271 std::size_t boundaryInfoSize() const
272 {
273 return boundaryInfoBuffer_.size();
274 }
275
282 void copyResidualToHost(GlobalEqVector& residual, unsigned numCells)
283 {
284 auto cpuResidualFromGpu = residualBuffer_.asStdVector();
285 std::memcpy(residual.data(), cpuResidualFromGpu.data(), numCells * numEq * sizeof(Scalar));
286 }
287
293 void copyJacobianToHost(SparseMatrixAdapter& jacobian,
294 gpuistl::GpuSparseMatrixWrapper<Scalar>& gpuJacobian)
295 {
296 auto gpuJacobianNonZeroes = gpuJacobian.getNonZeroValues().asStdVector();
297 auto& cpuJacobian = jacobian.istlMatrix();
298 const std::size_t totalMatrixSize = cpuJacobian.nonzeroes() * numEq * numEq;
299 std::memcpy(&(cpuJacobian[0][0][0][0]),
300 gpuJacobianNonZeroes.data(),
301 totalMatrixSize * sizeof(Scalar));
302 }
303};
304
305} // namespace Opm
306
307#endif // HAVE_CUDA && OPM_IS_COMPILING_WITH_GPU_COMPILER
308
309#endif // TPFA_LINEARIZER_GPU_PARAMS_HH
inline ::Opm::NoThermalLawManager make_view(::Opm::NoThermalLawManager &)
make_view overload for the no-op thermal manager.
Definition: GpuFlowProblem.hpp:102
std::shared_ptr< T > make_gpu_shared_ptr()
Creates a shared pointer managing GPU-allocated memory of the specified element type.
Definition: gpu_smart_pointer.hpp:49
inline ::Opm::NoThermalLawManager copy_to_gpu(const ::Opm::NoThermalLawManager &)
copy_to_gpu overload for the no-op thermal manager.
Definition: GpuFlowProblem.hpp:95
Definition: blackoilbioeffectsmodules.hh:45
std::string to_string(const ConvergenceReport::ReservoirFailure::Type t)