2020-03-13 08:21:59 -05:00
/*
2020-03-16 06:57:35 -05:00
Copyright 2020 Equinor ASA
2020-03-13 08:21:59 -05:00
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/>.
*/
2020-03-18 11:48:28 -05:00
# ifndef WELLCONTRIBUTIONS_HEADER_INCLUDED
# define WELLCONTRIBUTIONS_HEADER_INCLUDED
2020-03-13 08:21:59 -05:00
2021-11-11 05:17:24 -06:00
# include <memory>
2020-03-18 11:48:28 -05:00
# include <vector>
2020-05-15 09:00:09 -05:00
# include <opm/simulators/linalg/bda/MultisegmentWellContribution.hpp>
2020-10-14 12:23:57 -05:00
# if HAVE_SUITESPARSE_UMFPACK
# include<umfpack.h>
# endif
2020-09-30 13:10:21 -05:00
# include <dune/common/version.hh>
2020-03-13 08:21:59 -05:00
namespace Opm
{
2020-06-22 11:26:49 -05:00
/// This class serves to eliminate the need to include the WellContributions into the matrix (with --matrix-add-well-contributions=true) for the cusparseSolver
/// If the --matrix-add-well-contributions commandline parameter is true, this class should not be used
/// So far, StandardWell and MultisegmentWell are supported
2020-07-10 04:13:55 -05:00
/// StandardWells are only supported for cusparseSolver (CUDA), MultisegmentWells are supported for both cusparseSolver and openclSolver
/// A single instance (or pointer) of this class is passed to the BdaSolver.
2020-06-22 11:26:49 -05:00
/// For StandardWell, this class contains all the data and handles the computation. For MultisegmentWell, the vector 'multisegments' contains all the data. For more information, check the MultisegmentWellContribution class.
/// A StandardWell uses C, D and B and performs y -= (C^T * (D^-1 * (B*x)))
/// B and C are vectors, disguised as matrices and contain blocks of StandardWell::numEq by StandardWell::numStaticWellEq
/// D is a block, disguised as matrix, the square block has size StandardWell::numStaticWellEq. D is actually stored as D^-1
/// B*x and D*B*x are a vector with numStaticWellEq doubles
/// C*D*B*x is a blocked matrix with a symmetric sparsity pattern, contains square blocks with size numEq. For every columnindex i, j in StandardWell::duneB_, there is a block on (i, j) in C*D*B*x.
///
/// This class is used in 3 phases:
/// - get total size of all wellcontributions that must be stored here
/// - allocate memory
/// - copy data of wellcontributions
class WellContributions
{
2020-07-10 04:13:55 -05:00
public :
2021-11-11 07:45:12 -06:00
static std : : unique_ptr < WellContributions > create ( const std : : string & accelerator_mode , bool useWellConn ) ;
2020-09-30 13:10:21 -05:00
# if DUNE_VERSION_NEWER(DUNE_ISTL, 2, 7)
2020-10-14 12:23:57 -05:00
using UMFPackIndex = SuiteSparse_long ;
2020-09-30 13:10:21 -05:00
# else
using UMFPackIndex = int ;
# endif
2020-07-10 04:13:55 -05:00
/// StandardWell has C, D and B matrices that need to be copied
enum class MatrixType {
C ,
D ,
B
} ;
2021-11-11 07:45:12 -06:00
protected :
2020-11-11 11:34:10 -06:00
bool allocated = false ;
2020-06-22 11:26:49 -05:00
2020-09-25 14:56:27 -05:00
unsigned int N ; // number of rows (not blockrows) in vectors x and y
2020-11-11 11:34:10 -06:00
unsigned int dim ; // number of columns in blocks in B and C, equal to StandardWell::numEq
unsigned int dim_wells ; // number of rows in blocks in B and C, equal to StandardWell::numStaticWellEq
2020-09-24 14:34:46 -05:00
unsigned int num_blocks = 0 ; // total number of blocks in all wells
unsigned int num_std_wells = 0 ; // number of StandardWells in this object
2020-11-11 11:34:10 -06:00
unsigned int num_ms_wells = 0 ; // number of MultisegmentWells in this object, must equal multisegments.size()
2020-09-24 14:34:46 -05:00
unsigned int num_blocks_so_far = 0 ; // keep track of where next data is written
unsigned int num_std_wells_so_far = 0 ; // keep track of where next data is written
2021-11-11 05:23:16 -06:00
std : : vector < unsigned int > val_pointers ; // val_pointers[wellID] == index of first block for this well in Ccols and Bcols
2020-11-11 11:34:10 -06:00
2021-11-11 05:17:24 -06:00
std : : vector < std : : unique_ptr < MultisegmentWellContribution > > multisegments ;
2020-11-11 11:34:10 -06:00
2020-07-17 15:00:37 -05:00
public :
unsigned int getNumWells ( ) {
return num_std_wells + num_ms_wells ;
}
2020-09-24 14:34:46 -05:00
/// Indicate how large the next StandardWell is, this function cannot be called after alloc() is called
/// \param[in] numBlocks number of blocks in C and B of next StandardWell
void addNumBlocks ( unsigned int numBlocks ) ;
/// Allocate memory for the StandardWells
void alloc ( ) ;
2020-07-17 15:00:37 -05:00
2021-11-11 07:45:12 -06:00
/// Empty destructor.
virtual ~ WellContributions ( ) = default ;
2020-07-17 15:00:37 -05:00
2020-06-22 11:26:49 -05:00
/// Indicate how large the blocks of the StandardWell (C and B) are
/// \param[in] dim number of columns
/// \param[in] dim_wells number of rows
void setBlockSize ( unsigned int dim , unsigned int dim_wells ) ;
/// Store a matrix in this object, in blocked csr format, can only be called after alloc() is called
/// \param[in] type indicate if C, D or B is sent
/// \param[in] colIndices columnindices of blocks in C or B, ignored for D
/// \param[in] values array of nonzeroes
/// \param[in] val_size number of blocks in C or B, ignored for D
void addMatrix ( MatrixType type , int * colIndices , double * values , unsigned int val_size ) ;
/// Add a MultisegmentWellContribution, actually creates an object on heap that is destroyed in the destructor
/// Matrices C and B are passed in Blocked CSR, matrix D in CSC
/// \param[in] dim size of blocks in vectors x and y, equal to MultisegmentWell::numEq
/// \param[in] dim_wells size of blocks of C, B and D, equal to MultisegmentWell::numWellEq
/// \param[in] Mb number of blockrows in C, B and D
/// \param[in] Bvalues nonzero values of matrix B
/// \param[in] BcolIndices columnindices of blocks of matrix B
/// \param[in] BrowPointers rowpointers of matrix B
/// \param[in] DnumBlocks number of blocks in D
/// \param[in] Dvalues nonzero values of matrix D
/// \param[in] DcolPointers columnpointers of matrix D
/// \param[in] DrowIndices rowindices of matrix D
/// \param[in] Cvalues nonzero values of matrix C
void addMultisegmentWellContribution ( unsigned int dim , unsigned int dim_wells ,
2021-04-30 05:23:46 -05:00
unsigned int Mb ,
std : : vector < double > & Bvalues , std : : vector < unsigned int > & BcolIndices , std : : vector < unsigned int > & BrowPointers ,
2020-09-30 13:10:21 -05:00
unsigned int DnumBlocks , double * Dvalues ,
UMFPackIndex * DcolPointers , UMFPackIndex * DrowIndices ,
2020-06-22 11:26:49 -05:00
std : : vector < double > & Cvalues ) ;
2021-11-11 07:45:12 -06:00
protected :
//! \brief API specific allocation.
virtual void APIalloc ( ) { }
/// Api specific upload of matrix.
virtual void APIaddMatrix ( MatrixType , int * , double * , unsigned int ) { }
2020-06-22 11:26:49 -05:00
} ;
2020-03-13 08:21:59 -05:00
} //namespace Opm
# endif