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>
 
   62                              const int pressureVarIndex,
 
   65                              [[maybe_unused]] 
bool enable_thread_parallel)
 
   67        using VectorBlockType = 
typename Vector::block_type;
 
   68        using MatrixBlockType = 
typename Matrix::block_type;
 
   69        const Matrix& A = matrix;
 
   71        VectorBlockType rhs(0.0);
 
   72        rhs[pressureVarIndex] = 1.0;
 
   75        MatrixBlockType diag_block;
 
   76        VectorBlockType bweights;
 
   77        MatrixBlockType diag_block_transpose;
 
   81#pragma omp parallel for private(diag_block, bweights, diag_block_transpose) if(enable_thread_parallel) 
   83        for (
int row_idx = 0; row_idx < static_cast<int>(A.N()); ++row_idx) {
 
   84            diag_block = MatrixBlockType(0.0);
 
   86            const auto row_it = A.begin() + row_idx;
 
   87            const auto endj = (*row_it).end();
 
   88            for (
auto j = (*row_it).begin(); j != endj; ++j) {
 
   89                if (row_it.index() == j.index()) {
 
   95                diag_block.solve(bweights, rhs);
 
   98                diag_block_transpose.solve(bweights, rhs);
 
  101            double abs_max = *std::max_element(
 
  102                bweights.begin(), bweights.end(), [](
double a, 
double b) { return std::fabs(a) < std::fabs(b); });
 
  103            bweights /= std::fabs(abs_max);
 
  104            weights[row_idx] = bweights;
 
  108    template <
class Matrix, 
class Vector>
 
  110                                const int pressureVarIndex,
 
  111                                const bool transpose,
 
  112                                bool enable_thread_parallel)
 
  114        Vector weights(matrix.N());
 
  120    template <
typename T>
 
  122        std::vector<int> diagonalIndices(matrix.
N(), -1);
 
  123        const auto rowIndices = matrix.
getRowIndices().asStdVector();
 
  127            for (
auto i = rowIndices[row]; i < rowIndices[row+1]; ++i) {
 
  128                if (colIndices[i] == row) {
 
  129                    diagonalIndices[row] = i;
 
  134        return diagonalIndices;
 
  138    template <
typename T, 
bool transpose>
 
  140                             const int pressureVarIndex,
 
  141                             gpuistl::GpuVector<T>& weights,
 
  142                             const gpuistl::GpuVector<int>& diagonalIndices)
 
  144        gpuistl::detail::getQuasiImpesWeights<T, transpose>(matrix, pressureVarIndex, weights, diagonalIndices);
 
  147    template <
typename T, 
bool transpose>
 
  149                                              const int pressureVarIndex,
 
  150                                              const gpuistl::GpuVector<int>& diagonalIndices)
 
  152        gpuistl::GpuVector<T> weights(matrix.N() * matrix.blockSize());
 
  153        getQuasiImpesWeights<T, transpose>(matrix, pressureVarIndex, weights, diagonalIndices);
 
  158    template<
class Vector, 
class ElementContext, 
class Model, 
class ElementChunksType>
 
  160                             const ElementContext& elemCtx,
 
  162                             const ElementChunksType& element_chunks,
 
  163                             [[maybe_unused]] 
bool enable_thread_parallel)
 
  165        using VectorBlockType = 
typename Vector::block_type;
 
  166        using Matrix = 
typename std::decay_t<
decltype(model.linearizer().jacobian())>;
 
  167        using MatrixBlockType = 
typename Matrix::MatrixBlock;
 
  168        constexpr int numEq = VectorBlockType::size();
 
  169        using Evaluation = 
typename std::decay_t<
decltype(model.localLinearizer(
ThreadManager::threadId()).localResidual().residual(0))>
 
  172        VectorBlockType rhs(0.0);
 
  173        rhs[pressureVarIndex] = 1.0;
 
  176        MatrixBlockType block;
 
  177        VectorBlockType bweights;
 
  178        MatrixBlockType block_transpose;
 
  179        Dune::FieldVector<Evaluation, numEq> storage;
 
  183#pragma omp parallel for private(block, bweights, block_transpose, storage) if(enable_thread_parallel) 
  185        for (
const auto& chunk : element_chunks) {
 
  187            ElementContext localElemCtx(elemCtx.simulator());
 
  189            for (
const auto& elem : chunk) {
 
  190                localElemCtx.updatePrimaryStencil(elem);
 
  191                localElemCtx.updatePrimaryIntensiveQuantities(0);
 
  193                model.localLinearizer(thread_id).localResidual().computeStorage(storage, localElemCtx, 0, 0);
 
  195                auto extrusionFactor = localElemCtx.intensiveQuantities(0, 0).extrusionFactor();
 
  196                auto scvVolume = localElemCtx.stencil(0).subControlVolume(0).volume() * extrusionFactor;
 
  197                auto storage_scale = scvVolume / localElemCtx.simulator().timeStepSize();
 
  198                const double pressure_scale = 50e5;
 
  201                for (
int ii = 0; ii < numEq; ++ii) {
 
  202                    for (
int jj = 0; jj < numEq; ++jj) {
 
  203                        block_transpose[jj][ii] = storage[ii].derivative(jj)/storage_scale;
 
  204                        if (jj == pressureVarIndex) {
 
  205                            block_transpose[jj][ii] *= pressure_scale;
 
  209                block_transpose.solve(bweights, rhs);
 
  211                double abs_max = *std::max_element(
 
  212                    bweights.begin(), bweights.end(), [](
double a, 
double b) { return std::fabs(a) < std::fabs(b); });
 
  214                bweights /=  std::fabs(abs_max); 
 
  216                const auto index = localElemCtx.globalSpaceIndex(0, 0);
 
  217                weights[index] = bweights;
 
  223    template <
class Vector, 
class ElementContext, 
class Model, 
class ElementChunksType>
 
  226                                     const ElementContext& elemCtx,
 
  228                                     const ElementChunksType& element_chunks,
 
  229                                     [[maybe_unused]] 
bool enable_thread_parallel)
 
  239        using FluidSystem = 
typename Model::FluidSystem;
 
  240        using LhsEval = double;
 
  242        using PrimaryVariables = 
typename Model::PrimaryVariables;
 
  243        using VectorBlockType = 
typename Vector::block_type;
 
  245            typename std::decay_t<
decltype(model.localLinearizer(
ThreadManager::threadId()).localResidual().residual(0))>::block_type;
 
  246        using Toolbox = MathToolbox<Evaluation>;
 
  248        const auto& solution = model.solution( 0);
 
  249        VectorBlockType bweights;
 
  254#pragma omp parallel for private(bweights) if(enable_thread_parallel) 
  256        for (
const auto& chunk : element_chunks) {
 
  259            ElementContext localElemCtx(elemCtx.simulator());
 
  261            for (
const auto& elem : chunk) {
 
  262                localElemCtx.updatePrimaryStencil(elem);
 
  263                localElemCtx.updatePrimaryIntensiveQuantities(0);
 
  265                const auto index = localElemCtx.globalSpaceIndex(0, 0);
 
  266                const auto& intQuants = localElemCtx.intensiveQuantities(0, 0);
 
  267                const auto& fs = intQuants.fluidState();
 
  269                if (FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx)) {
 
  270                    const unsigned activeCompIdx = FluidSystem::canonicalToActiveCompIdx(
 
  271                        FluidSystem::solventComponentIndex(FluidSystem::waterPhaseIdx));
 
  272                    bweights[activeCompIdx]
 
  273                        = Toolbox::template decay<LhsEval>(1 / fs.invB(FluidSystem::waterPhaseIdx));
 
  276                double denominator = 1.0;
 
  277                double rs = Toolbox::template decay<double>(fs.Rs());
 
  278                double rv = Toolbox::template decay<double>(fs.Rv());
 
  279                const auto& priVars = solution[index];
 
  280                if (priVars.primaryVarsMeaningGas() == PrimaryVariables::GasMeaning::Rv) {
 
  283                if (priVars.primaryVarsMeaningGas() == PrimaryVariables::GasMeaning::Rs) {
 
  286                if (FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx)
 
  287                    && FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx)) {
 
  288                    denominator = Toolbox::template decay<LhsEval>(1 - rs * rv);
 
  291                if (FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx)) {
 
  292                    const unsigned activeCompIdx = FluidSystem::canonicalToActiveCompIdx(
 
  293                        FluidSystem::solventComponentIndex(FluidSystem::oilPhaseIdx));
 
  294                    bweights[activeCompIdx] = Toolbox::template decay<LhsEval>(
 
  295                        (1 / fs.invB(FluidSystem::oilPhaseIdx) - rs / fs.invB(FluidSystem::gasPhaseIdx))
 
  298                if (FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx)) {
 
  299                    const unsigned activeCompIdx = FluidSystem::canonicalToActiveCompIdx(
 
  300                        FluidSystem::solventComponentIndex(FluidSystem::gasPhaseIdx));
 
  301                    bweights[activeCompIdx] = Toolbox::template decay<LhsEval>(
 
  302                        (1 / fs.invB(FluidSystem::gasPhaseIdx) - rv / fs.invB(FluidSystem::oilPhaseIdx))
 
  306                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:159
 
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:224
 
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