2020-07-10 04:13:55 -05:00
/*
Copyright 2020 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/>.
*/
# include <config.h> // CMake
# include <cstdlib>
# include <cstring>
# include <opm/common/OpmLog/OpmLog.hpp>
# include <opm/common/ErrorMacros.hpp>
2020-07-17 15:00:37 -05:00
# include <opm/simulators/linalg/bda/openclKernels.hpp>
2020-07-10 04:13:55 -05:00
# include "opm/simulators/linalg/bda/WellContributions.hpp"
namespace Opm
{
2020-07-17 15:00:37 -05:00
WellContributions : : WellContributions ( std : : string gpu_mode ) {
if ( gpu_mode . compare ( " cusparse " ) = = 0 ) {
cuda_gpu = true ;
}
if ( gpu_mode . compare ( " opencl " ) = = 0 ) {
opencl_gpu = true ;
}
}
2020-07-10 04:13:55 -05:00
WellContributions : : ~ WellContributions ( )
{
// delete MultisegmentWellContributions
for ( auto ms : multisegments ) {
delete ms ;
}
multisegments . clear ( ) ;
2020-07-17 15:00:37 -05:00
# if HAVE_CUDA
if ( cuda_gpu ) {
freeCudaMemory ( ) ; // should come before 'delete[] h_x'
}
# endif
}
void WellContributions : : addMatrix ( [[maybe_unused]] MatrixType type, [[maybe_unused]] int *colIndices, [[maybe_unused]] double *values, [[maybe_unused]] unsigned int val_size )
2020-07-10 04:13:55 -05:00
{
2020-07-17 15:00:37 -05:00
2020-07-10 04:13:55 -05:00
# if HAVE_CUDA
2020-07-17 15:00:37 -05:00
if ( cuda_gpu ) {
2020-09-24 14:34:46 -05:00
if ( ! allocated ) {
OPM_THROW ( std : : logic_error , " Error cannot add wellcontribution before allocating memory in WellContributions " ) ;
}
2020-07-10 04:13:55 -05:00
addMatrixGpu ( type , colIndices , values , val_size ) ;
2020-07-17 15:00:37 -05:00
}
# endif
# if HAVE_OPENCL
if ( opencl_gpu ) {
2020-09-25 09:31:17 -05:00
if ( h_val_pointers_ocl . empty ( ) ) {
h_val_pointers_ocl . push_back ( 0 ) ;
}
2020-07-17 15:00:37 -05:00
switch ( type ) {
2020-09-24 14:34:46 -05:00
case MatrixType : : C :
h_Ccols_ocl . insert ( h_Ccols_ocl . end ( ) , colIndices , colIndices + val_size ) ;
h_Cnnzs_ocl . insert ( h_Cnnzs_ocl . end ( ) , values , values + val_size * dim * dim_wells ) ;
break ;
case MatrixType : : D :
h_Dnnzs_ocl . insert ( h_Dnnzs_ocl . end ( ) , values , values + dim_wells * dim_wells ) ;
break ;
case MatrixType : : B :
h_Bcols_ocl . insert ( h_Bcols_ocl . end ( ) , colIndices , colIndices + val_size ) ;
h_Bnnzs_ocl . insert ( h_Bnnzs_ocl . end ( ) , values , values + val_size * dim * dim_wells ) ;
2020-09-25 09:31:17 -05:00
h_val_pointers_ocl . push_back ( h_val_pointers_ocl . back ( ) + val_size ) ;
2020-09-24 14:34:46 -05:00
break ;
default :
OPM_THROW ( std : : logic_error , " Error unsupported matrix ID for WellContributions::addMatrix() " ) ;
2020-07-17 15:00:37 -05:00
}
}
# endif
# if !HAVE_CUDA && !HAVE_OPENCL
OPM_THROW ( std : : logic_error , " Error cannot add StandardWell matrix on GPU because neither CUDA nor OpenCL were found by cmake " ) ;
2020-07-10 04:13:55 -05:00
# endif
}
void WellContributions : : setBlockSize ( unsigned int dim_ , unsigned int dim_wells_ )
{
dim = dim_ ;
dim_wells = dim_wells_ ;
2020-09-28 16:01:42 -05:00
if ( dim ! = 3 | | dim_wells ! = 4 ) {
std : : ostringstream oss ;
oss < < " WellContributions::setBlockSize error: dim and dim_wells must be equal to 3 and 4, repectivelly, otherwise the add well contributions kernel won't work. \n " ;
OPM_THROW ( std : : logic_error , oss . str ( ) ) ;
}
2020-07-10 04:13:55 -05:00
}
2020-09-24 14:34:46 -05:00
# if HAVE_CUDA
2020-07-17 15:00:37 -05:00
void WellContributions : : addNumBlocks ( unsigned int numBlocks )
2020-07-10 04:13:55 -05:00
{
if ( allocated ) {
OPM_THROW ( std : : logic_error , " Error cannot add more sizes after allocated in WellContributions " ) ;
}
2020-07-17 15:00:37 -05:00
num_blocks + = numBlocks ;
2020-07-10 04:13:55 -05:00
num_std_wells + + ;
}
2020-09-24 14:34:46 -05:00
void WellContributions : : alloc ( )
{
if ( num_std_wells > 0 ) {
allocStandardWells ( ) ;
allocated = true ;
}
}
# endif
2020-09-02 15:46:44 -05:00
void WellContributions : : addMultisegmentWellContribution ( unsigned int dim_ , unsigned int dim_wells_ ,
2020-07-10 04:13:55 -05:00
unsigned int Nb , unsigned int Mb ,
unsigned int BnumBlocks , std : : vector < double > & Bvalues , std : : vector < unsigned int > & BcolIndices , std : : vector < unsigned int > & BrowPointers ,
unsigned int DnumBlocks , double * Dvalues , int * DcolPointers , int * DrowIndices ,
std : : vector < double > & Cvalues )
{
2020-09-02 15:46:44 -05:00
assert ( dim = = dim_ ) ;
this - > N = Nb * dim_ ;
MultisegmentWellContribution * well = new MultisegmentWellContribution ( dim_ , dim_wells_ , Nb , Mb , BnumBlocks , Bvalues , BcolIndices , BrowPointers , DnumBlocks , Dvalues , DcolPointers , DrowIndices , Cvalues ) ;
2020-07-10 04:13:55 -05:00
multisegments . emplace_back ( well ) ;
+ + num_ms_wells ;
}
void WellContributions : : setReordering ( int * toOrder_ , bool reorder_ )
{
this - > toOrder = toOrder_ ;
this - > reorder = reorder_ ;
for ( auto & ms : multisegments ) {
ms - > setReordering ( toOrder_ , reorder_ ) ;
}
}
} //namespace Opm