opm-simulators/opm/simulators/linalg/bda/opencl/CPR.hpp

144 lines
6.0 KiB
C++
Raw Normal View History

/*
Copyright 2021 Equinor ASA
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
2021-11-22 09:42:18 -06:00
#ifndef OPM_CPR_HPP
#define OPM_CPR_HPP
#include <mutex>
#include <dune/istl/paamg/matrixhierarchy.hh>
2021-12-01 04:47:29 -06:00
#include <dune/istl/umfpack.hh>
2022-02-01 09:51:32 -06:00
#include <opm/simulators/linalg/bda/opencl/opencl.hpp>
#include <opm/simulators/linalg/bda/opencl/BILU0.hpp>
#include <opm/simulators/linalg/bda/Matrix.hpp>
2022-02-01 09:51:32 -06:00
#include <opm/simulators/linalg/bda/opencl/OpenclMatrix.hpp>
#include <opm/simulators/linalg/bda/opencl/Preconditioner.hpp>
2022-02-01 09:51:32 -06:00
#include <opm/simulators/linalg/bda/opencl/openclSolverBackend.hpp>
2024-04-15 15:38:04 -05:00
namespace Opm::Accelerator {
2024-04-15 09:13:22 -05:00
template<class Scalar> class BlockedMatrix;
2021-11-23 02:44:18 -06:00
/// This class implements a Constrained Pressure Residual (CPR) preconditioner
2024-04-15 15:38:04 -05:00
template<class Scalar, unsigned int block_size>
class CPR : public Preconditioner<Scalar,block_size>
{
2024-04-15 15:38:04 -05:00
using Base = Preconditioner<Scalar,block_size>;
using Base::N;
using Base::Nb;
using Base::nnz;
using Base::nnzb;
using Base::verbosity;
using Base::context;
using Base::queue;
using Base::events;
using Base::err;
private:
int num_levels;
2024-04-15 15:38:04 -05:00
std::vector<Scalar> weights, coarse_vals, coarse_x, coarse_y;
std::vector<Matrix<Scalar>> Amatrices, Rmatrices; // scalar matrices that represent the AMG hierarchy
std::vector<OpenclMatrix<Scalar>> d_Amatrices, d_Rmatrices; // scalar matrices that represent the AMG hierarchy
std::vector<std::vector<int> > PcolIndices; // prolongation does not need a full matrix, only store colIndices
std::vector<cl::Buffer> d_PcolIndices;
2024-04-15 15:38:04 -05:00
std::vector<std::vector<Scalar>> invDiags; // inverse of diagonal of Amatrices
std::vector<cl::Buffer> d_invDiags;
std::vector<cl::Buffer> d_t, d_f, d_u; // intermediate vectors used during amg cycle
std::unique_ptr<cl::Buffer> d_rs; // use before extracting the pressure
std::unique_ptr<cl::Buffer> d_weights; // the quasiimpes weights, used to extract pressure
2024-04-15 15:38:04 -05:00
std::unique_ptr<OpenclMatrix<Scalar>> d_mat; // stores blocked matrix
std::unique_ptr<cl::Buffer> d_coarse_y, d_coarse_x; // stores the scalar vectors
std::once_flag opencl_buffers_allocated; // only allocate OpenCL Buffers once
2024-04-15 15:38:04 -05:00
std::unique_ptr<BILU0<Scalar,block_size>> bilu0; // Blocked ILU0 preconditioner
BlockedMatrix<Scalar>* mat = nullptr; // input matrix, blocked
2021-11-25 06:40:30 -06:00
2024-04-15 15:38:04 -05:00
using DuneMat = Dune::BCRSMatrix<Dune::FieldMatrix<Scalar, 1, 1> >;
using DuneVec = Dune::BlockVector<Dune::FieldVector<Scalar, 1> >;
using MatrixOperator = Dune::MatrixAdapter<DuneMat, DuneVec, DuneVec>;
using DuneAmg = Dune::Amg::MatrixHierarchy<MatrixOperator, Dune::Amg::SequentialInformation>;
std::unique_ptr<DuneAmg> dune_amg;
std::unique_ptr<DuneMat> dune_coarse; // extracted pressure matrix, finest level in AMG hierarchy
std::shared_ptr<MatrixOperator> dune_op; // operator, input to Dune AMG
std::vector<int> level_sizes; // size of each level in the AMG hierarchy
std::vector<std::vector<int> > diagIndices; // index of diagonal value for each level
2021-12-01 04:47:29 -06:00
Dune::UMFPack<DuneMat> umfpack; // dune/istl/umfpack object used to solve the coarsest level of AMG
bool always_recalculate_aggregates = false; // OPM always reuses the aggregates by default
bool recalculate_aggregates = true; // only rerecalculate if true
const int pressure_idx = 1; // hardcoded to mimic OPM
unsigned num_pre_smooth_steps; // number of Jacobi smooth steps before restriction
unsigned num_post_smooth_steps; // number of Jacobi smooth steps after prolongation
std::unique_ptr<openclSolverBackend<1> > coarse_solver; // coarse solver is scalar
bool opencl_ilu_parallel; // whether ILU0 operation should be parallelized
// Analyze the AMG hierarchy build by Dune
void analyzeHierarchy();
// Analyze the aggregateMaps from the AMG hierarchy
// These can be reused, so only use when recalculate_aggregates is true
void analyzeAggregateMaps();
2021-11-23 10:12:31 -06:00
// Initialize and allocate matrices and vectors
void init_opencl_buffers();
// Copy matrices and vectors to GPU
void opencl_upload();
2021-11-25 06:40:30 -06:00
// apply pressure correction to vector
void apply_amg(const cl::Buffer& y, cl::Buffer& x);
void amg_cycle_gpu(const int level, cl::Buffer &y, cl::Buffer &x);
2024-04-15 15:38:04 -05:00
void create_preconditioner_amg(BlockedMatrix<Scalar>* mat);
2021-11-25 06:40:30 -06:00
public:
CPR(bool opencl_ilu_parallel, int verbosity);
2024-04-15 15:38:04 -05:00
bool analyze_matrix(BlockedMatrix<Scalar>* mat) override;
bool analyze_matrix(BlockedMatrix<Scalar>* mat,
BlockedMatrix<Scalar>* jacMat) override;
2022-02-25 06:33:24 -06:00
// set own Opencl variables, but also that of the bilu0 preconditioner
2024-04-15 15:38:04 -05:00
void setOpencl(std::shared_ptr<cl::Context>& context,
std::shared_ptr<cl::CommandQueue>& queue) override;
// applies blocked ilu0
// also applies amg for pressure component
void apply(const cl::Buffer& y, cl::Buffer& x) override;
2024-04-15 15:38:04 -05:00
bool create_preconditioner(BlockedMatrix<Scalar>* mat) override;
bool create_preconditioner(BlockedMatrix<Scalar>* mat,
BlockedMatrix<Scalar>* jacMat) override;
};
2021-11-26 09:49:47 -06:00
// solve A^T * x = b
// A should represent a 3x3 matrix
// x and b are vectors with 3 elements
2024-04-15 15:38:04 -05:00
template<class Scalar>
void solve_transposed_3x3(const Scalar* A, const Scalar* b, Scalar* x);
2021-11-26 09:49:47 -06:00
2024-04-15 15:38:04 -05:00
} // namespace Opm::Accelerator
#endif