20#ifndef OPM_GET_QUASI_IMPES_WEIGHTS_HEADER_INCLUDED
21#define OPM_GET_QUASI_IMPES_WEIGHTS_HEADER_INCLUDED
23#include <dune/common/fvector.hh>
25#include <opm/grid/utility/ElementChunks.hpp>
27#include <opm/material/common/MathToolbox.hpp>
34#include <opm/simulators/linalg/gpuistl_hip/detail/cpr_amg_operations.hpp>
46 template <
class DenseMatrix>
50 for (
int i = 0; i < M.rows; ++i)
51 for (
int j = 0; j < M.cols; ++j)
60 template <
class Matrix,
class Vector>
61 void getQuasiImpesWeights(
const Matrix& matrix,
const int pressureVarIndex,
const bool transpose, Vector& weights,
bool enable_thread_parallel)
63 using VectorBlockType =
typename Vector::block_type;
64 using MatrixBlockType =
typename Matrix::block_type;
65 const Matrix& A = matrix;
67 VectorBlockType rhs(0.0);
68 rhs[pressureVarIndex] = 1.0;
71 MatrixBlockType diag_block;
72 VectorBlockType bweights;
73 MatrixBlockType diag_block_transpose;
77#pragma omp parallel for private(diag_block, bweights, diag_block_transpose) if(enable_thread_parallel)
79 for (
int row_idx = 0; row_idx < static_cast<int>(A.N()); ++row_idx) {
80 diag_block = MatrixBlockType(0.0);
82 const auto row_it = A.begin() + row_idx;
83 const auto endj = (*row_it).end();
84 for (
auto j = (*row_it).begin(); j != endj; ++j) {
85 if (row_it.index() == j.index()) {
91 diag_block.solve(bweights, rhs);
94 diag_block_transpose.solve(bweights, rhs);
97 double abs_max = *std::max_element(
98 bweights.begin(), bweights.end(), [](
double a,
double b) { return std::fabs(a) < std::fabs(b); });
99 bweights /= std::fabs(abs_max);
100 weights[row_idx] = bweights;
104 template <
class Matrix,
class Vector>
105 Vector
getQuasiImpesWeights(
const Matrix& matrix,
const int pressureVarIndex,
const bool transpose,
bool enable_thread_parallel)
107 Vector weights(matrix.N());
113 template <
typename T>
115 std::vector<int> diagonalIndices(matrix.
N(), -1);
116 const auto rowIndices = matrix.
getRowIndices().asStdVector();
120 for (
auto i = rowIndices[row]; i < rowIndices[row+1]; ++i) {
121 if (colIndices[i] == row) {
122 diagonalIndices[row] = i;
127 return diagonalIndices;
131 template <
typename T,
bool transpose>
133 const int pressureVarIndex,
134 gpuistl::GpuVector<T>& weights,
135 const gpuistl::GpuVector<int>& diagonalIndices)
137 gpuistl::detail::getQuasiImpesWeights<T, transpose>(matrix, pressureVarIndex, weights, diagonalIndices);
140 template <
typename T,
bool transpose>
142 const int pressureVarIndex,
143 const gpuistl::GpuVector<int>& diagonalIndices)
145 gpuistl::GpuVector<T> weights(matrix.N() * matrix.blockSize());
146 getQuasiImpesWeights<T, transpose>(matrix, pressureVarIndex, weights, diagonalIndices);
151 template<
class Vector,
class ElementContext,
class Model,
class ElementChunksType>
153 const ElementContext& elemCtx,
155 const ElementChunksType& element_chunks,
156 bool enable_thread_parallel)
158 using VectorBlockType =
typename Vector::block_type;
159 using Matrix =
typename std::decay_t<
decltype(model.linearizer().jacobian())>;
160 using MatrixBlockType =
typename Matrix::MatrixBlock;
161 constexpr int numEq = VectorBlockType::size();
162 using Evaluation =
typename std::decay_t<
decltype(model.localLinearizer(
ThreadManager::threadId()).localResidual().residual(0))>
165 VectorBlockType rhs(0.0);
166 rhs[pressureVarIndex] = 1.0;
169 MatrixBlockType block;
170 VectorBlockType bweights;
171 MatrixBlockType block_transpose;
172 Dune::FieldVector<Evaluation, numEq> storage;
176#pragma omp parallel for private(block, bweights, block_transpose, storage) if(enable_thread_parallel)
178 for (
const auto& chunk : element_chunks) {
180 ElementContext localElemCtx(elemCtx.simulator());
182 for (
const auto& elem : chunk) {
183 localElemCtx.updatePrimaryStencil(elem);
184 localElemCtx.updatePrimaryIntensiveQuantities(0);
186 model.localLinearizer(thread_id).localResidual().computeStorage(storage, localElemCtx, 0, 0);
188 auto extrusionFactor = localElemCtx.intensiveQuantities(0, 0).extrusionFactor();
189 auto scvVolume = localElemCtx.stencil(0).subControlVolume(0).volume() * extrusionFactor;
190 auto storage_scale = scvVolume / localElemCtx.simulator().timeStepSize();
191 const double pressure_scale = 50e5;
194 for (
int ii = 0; ii < numEq; ++ii) {
195 for (
int jj = 0; jj < numEq; ++jj) {
196 block_transpose[jj][ii] = storage[ii].derivative(jj)/storage_scale;
197 if (jj == pressureVarIndex) {
198 block_transpose[jj][ii] *= pressure_scale;
202 block_transpose.solve(bweights, rhs);
204 double abs_max = *std::max_element(
205 bweights.begin(), bweights.end(), [](
double a,
double b) { return std::fabs(a) < std::fabs(b); });
207 bweights /= std::fabs(abs_max);
209 const auto index = localElemCtx.globalSpaceIndex(0, 0);
210 weights[index] = bweights;
216 template <
class Vector,
class ElementContext,
class Model,
class ElementChunksType>
219 const ElementContext& elemCtx,
221 const ElementChunksType& element_chunks,
222 bool enable_thread_parallel)
232 using FluidSystem =
typename Model::FluidSystem;
233 using LhsEval = double;
235 using PrimaryVariables =
typename Model::PrimaryVariables;
236 using VectorBlockType =
typename Vector::block_type;
238 typename std::decay_t<
decltype(model.localLinearizer(
ThreadManager::threadId()).localResidual().residual(0))>::block_type;
239 using Toolbox = MathToolbox<Evaluation>;
241 const auto& solution = model.solution( 0);
242 VectorBlockType bweights;
247#pragma omp parallel for private(bweights) if(enable_thread_parallel)
249 for (
const auto& chunk : element_chunks) {
252 ElementContext localElemCtx(elemCtx.simulator());
254 for (
const auto& elem : chunk) {
255 localElemCtx.updatePrimaryStencil(elem);
256 localElemCtx.updatePrimaryIntensiveQuantities(0);
258 const auto index = localElemCtx.globalSpaceIndex(0, 0);
259 const auto& intQuants = localElemCtx.intensiveQuantities(0, 0);
260 const auto& fs = intQuants.fluidState();
262 if (FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx)) {
263 const unsigned activeCompIdx = FluidSystem::canonicalToActiveCompIdx(
264 FluidSystem::solventComponentIndex(FluidSystem::waterPhaseIdx));
265 bweights[activeCompIdx]
266 = Toolbox::template decay<LhsEval>(1 / fs.invB(FluidSystem::waterPhaseIdx));
269 double denominator = 1.0;
270 double rs = Toolbox::template decay<double>(fs.Rs());
271 double rv = Toolbox::template decay<double>(fs.Rv());
272 const auto& priVars = solution[index];
273 if (priVars.primaryVarsMeaningGas() == PrimaryVariables::GasMeaning::Rv) {
276 if (priVars.primaryVarsMeaningGas() == PrimaryVariables::GasMeaning::Rs) {
279 if (FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx)
280 && FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx)) {
281 denominator = Toolbox::template decay<LhsEval>(1 - rs * rv);
284 if (FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx)) {
285 const unsigned activeCompIdx = FluidSystem::canonicalToActiveCompIdx(
286 FluidSystem::solventComponentIndex(FluidSystem::oilPhaseIdx));
287 bweights[activeCompIdx] = Toolbox::template decay<LhsEval>(
288 (1 / fs.invB(FluidSystem::oilPhaseIdx) - rs / fs.invB(FluidSystem::gasPhaseIdx))
291 if (FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx)) {
292 const unsigned activeCompIdx = FluidSystem::canonicalToActiveCompIdx(
293 FluidSystem::solventComponentIndex(FluidSystem::gasPhaseIdx));
294 bweights[activeCompIdx] = Toolbox::template decay<LhsEval>(
295 (1 / fs.invB(FluidSystem::gasPhaseIdx) - rv / fs.invB(FluidSystem::oilPhaseIdx))
299 weights[index] = bweights;
#define OPM_END_PARALLEL_TRY_CATCH(prefix, comm)
Catch exception and throw in a parallel try-catch clause.
Definition: DeferredLoggingErrorHelpers.hpp:192
#define OPM_BEGIN_PARALLEL_TRY_CATCH()
Macro to setup the try of a parallel try-catch.
Definition: DeferredLoggingErrorHelpers.hpp:158
static unsigned threadId()
Return the index of the current OpenMP thread.
The GpuSparseMatrixWrapper Checks CUDA/HIP version and dispatches a version either using the old or t...
Definition: GpuSparseMatrixWrapper.hpp:61
GpuVector< int > & getRowIndices()
getRowIndices returns the row indices used to represent the BSR structure.
Definition: GpuSparseMatrixWrapper.hpp:267
GpuVector< int > & getColumnIndices()
getColumnIndices returns the column indices used to represent the BSR structure.
Definition: GpuSparseMatrixWrapper.hpp:287
size_t N() const
N returns the number of rows (which is equal to the number of columns)
Definition: GpuSparseMatrixWrapper.hpp:228
void getTrueImpesWeights(int pressureVarIndex, Vector &weights, const ElementContext &elemCtx, const Model &model, const ElementChunksType &element_chunks, bool enable_thread_parallel)
Definition: getQuasiImpesWeights.hpp:152
void getQuasiImpesWeights(const Matrix &matrix, const int pressureVarIndex, const bool transpose, Vector &weights, bool enable_thread_parallel)
Definition: getQuasiImpesWeights.hpp:61
void getTrueImpesWeightsAnalytic(int, Vector &weights, const ElementContext &elemCtx, const Model &model, const ElementChunksType &element_chunks, bool enable_thread_parallel)
Definition: getQuasiImpesWeights.hpp:217
DenseMatrix transposeDenseMatrix(const DenseMatrix &M)
Definition: getQuasiImpesWeights.hpp:47
int to_int(std::size_t s)
to_int converts a (on most relevant platforms) 64 bits unsigned size_t to a signed 32 bits signed int
Definition: safe_conversion.hpp:52
Definition: blackoilbioeffectsmodules.hh:43