Addressed some comments of PR#2209

This commit is contained in:
T.D. (Tongdong) Qiu 2019-12-18 15:47:35 +01:00
parent 8e7eddb3ea
commit b543947e66
4 changed files with 41 additions and 39 deletions

View File

@ -22,6 +22,7 @@
#include <sstream> #include <sstream>
#include <opm/common/OpmLog/OpmLog.hpp> #include <opm/common/OpmLog/OpmLog.hpp>
#include <opm/common/ErrorMacros.hpp>
#include <opm/material/common/Unused.hpp> #include <opm/material/common/Unused.hpp>
#include <opm/simulators/linalg/bda/BdaBridge.hpp> #include <opm/simulators/linalg/bda/BdaBridge.hpp>
@ -43,49 +44,51 @@ BdaBridge::BdaBridge(bool use_gpu_, int linear_solver_verbosity OPM_UNUSED, int
} }
#if HAVE_CUDA #if HAVE_CUDA
template <class BridgeMatrix> template <class BridgeMatrix>
int checkZeroDiagonal(BridgeMatrix& mat) { int checkZeroDiagonal(BridgeMatrix& mat) {
static std::vector<int> diag_indices; // contains offsets of the diagonal nnzs static std::vector<typename BridgeMatrix::size_type> diag_indices; // contains offsets of the diagonal nnzs
int numZeros = 0; int numZeros = 0;
const int dim = 3; const int dim = 3;
const double zero_replace = 1e-15; const double zero_replace = 1e-15;
double *nnzs = &(mat[0][0][0][0]);
if(diag_indices.size() == 0){ if(diag_indices.size() == 0){
int N = mat.N()*dim; int N = mat.N();
diag_indices.reserve(N); diag_indices.reserve(N);
for(typename BridgeMatrix::const_iterator r = mat.begin(); r != mat.end(); ++r){ int roff = 0;
for(auto c = r->begin(); c != r->end(); ++c){ for(typename BridgeMatrix::iterator r = mat.begin(); r != mat.end(); ++r){
if(r.index() == c.index()){ auto diag = r->find(r.index()); // diag is an iterator
assert(diag.index() == r.index());
for(int rr = 0; rr < dim; ++rr){ for(int rr = 0; rr < dim; ++rr){
// pointer arithmetic auto& val = (*diag)[rr][rr]; // reference to easily change the value
int offset = (int)((long unsigned)&(mat[r.index()][c.index()][rr][rr]) - (long unsigned)nnzs); // in bytes
offset /= sizeof(double); // convert offset to doubles
diag_indices.emplace_back(offset);
double val = nnzs[offset];
if (val == 0.0){ // could be replaced by '< 1e-30' or similar if (val == 0.0){ // could be replaced by '< 1e-30' or similar
nnzs[offset] = zero_replace; val = zero_replace;
++numZeros; ++numZeros;
} }
} }
break; diag_indices.emplace_back(diag.offset());
}
}
} }
}else{ }else{
for(int offset : diag_indices){ for(typename BridgeMatrix::iterator r = mat.begin(); r != mat.end(); ++r){
if(nnzs[offset] == 0.0){ // could be replaced by '< 1e-30' or similar typename BridgeMatrix::size_type offset = diag_indices[r.index()];
nnzs[offset] = zero_replace; auto& diag_block = r->getptr()[offset]; // diag_block is a reference to MatrixBlock, located on column r of row r
for(int rr = 0; rr < dim; ++rr){
auto& val = diag_block[rr][rr];
if(val == 0.0){ // could be replaced by '< 1e-30' or similar
val = zero_replace;
++numZeros; ++numZeros;
} }
} }
} }
}
return numZeros; return numZeros;
} }
// iterate sparsity pattern from Matrix and put colIndices and rowPointers in arrays // iterate sparsity pattern from Matrix and put colIndices and rowPointers in arrays
// sparsity pattern should stay the same due to matrix-add-well-contributions // sparsity pattern should stay the same due to matrix-add-well-contributions
// this could be removed if Dune::BCRSMatrix features an API call that returns colIndices and rowPointers
template <class BridgeMatrix> template <class BridgeMatrix>
void getSparsityPattern(BridgeMatrix& mat, std::vector<int> &h_rows, std::vector<int> &h_cols) { void getSparsityPattern(BridgeMatrix& mat, std::vector<int> &h_rows, std::vector<int> &h_cols) {
int sum_nnzs = 0; int sum_nnzs = 0;
@ -102,8 +105,9 @@ void getSparsityPattern(BridgeMatrix& mat, std::vector<int> &h_rows, std::vector
sum_nnzs += size_row; sum_nnzs += size_row;
h_rows.emplace_back(sum_nnzs); h_rows.emplace_back(sum_nnzs);
} }
// set last rowpointer if(h_rows[mat.N()] != mat.nonzeroes()){
h_rows[mat.N()] = mat.nonzeroes(); OPM_THROW(std::logic_error, "Error size of rows do not sum to number of nonzeroes in BdaBridge::getSparsityPattern()");
}
} }
} // end getSparsityPattern() } // end getSparsityPattern()
@ -121,10 +125,10 @@ void BdaBridge::solve_system(BridgeMatrix *mat OPM_UNUSED, BridgeVector &b OPM_U
static std::vector<int> h_cols; static std::vector<int> h_cols;
int dim = (*mat)[0][0].N(); int dim = (*mat)[0][0].N();
int N = mat->N()*dim; int N = mat->N()*dim;
int nnz = mat->nonzeroes()*dim*dim; int nnz = (h_rows.empty()) ? mat->nonzeroes()*dim*dim : h_rows.back()*dim*dim;
if(dim != 3){ if(dim != 3){
OpmLog::error("cusparseSolver only accepts blocksize = 3 at this time"); OpmLog::warning("cusparseSolver only accepts blocksize = 3 at this time, will use Dune for the remainder of the program");
use_gpu = false; use_gpu = false;
} }
@ -157,7 +161,7 @@ void BdaBridge::solve_system(BridgeMatrix *mat OPM_UNUSED, BridgeVector &b OPM_U
// actually solve // actually solve
typedef cusparseSolverBackend::cusparseSolverStatus cusparseSolverStatus; typedef cusparseSolverBackend::cusparseSolverStatus cusparseSolverStatus;
// assume that underlying data (nonzeroes) from mat (Dune::BCRSMatrix) are contiguous, if this is not the case, cusparseSolver is expected to produce garbage // assume that underlying data (nonzeroes) from mat (Dune::BCRSMatrix) are contiguous, if this is not the case, cusparseSolver is expected to perform undefined behaviour
cusparseSolverStatus status = backend->solve_system(N, nnz, dim, static_cast<double*>(&(((*mat)[0][0][0][0]))), h_rows.data(), h_cols.data(), static_cast<double*>(&(b[0][0])), result); cusparseSolverStatus status = backend->solve_system(N, nnz, dim, static_cast<double*>(&(((*mat)[0][0][0][0]))), h_rows.data(), h_cols.data(), static_cast<double*>(&(b[0][0])), result);
switch(status){ switch(status){
case cusparseSolverStatus::CUSPARSE_SOLVER_SUCCESS: case cusparseSolverStatus::CUSPARSE_SOLVER_SUCCESS:
@ -189,7 +193,7 @@ template <class BridgeVector>
void BdaBridge::get_result(BridgeVector &x OPM_UNUSED){ void BdaBridge::get_result(BridgeVector &x OPM_UNUSED){
#if HAVE_CUDA #if HAVE_CUDA
if(use_gpu){ if(use_gpu){
backend->post_process(&(x[0][0])); backend->post_process(static_cast<double*>(&(x[0][0])));
} }
#endif #endif
} }

View File

@ -17,13 +17,11 @@
along with OPM. If not, see <http://www.gnu.org/licenses/>. along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef CUDA_HEADER_H #ifndef CUDA_HEADER_HEADER_INCLUDED
#define CUDA_HEADER_H #define CUDA_HEADER_HEADER_INCLUDED
#include <iostream> #include <iostream>
typedef double Block[9];
#define cudaCheckLastError(msg) __cudaCheckError( __FILE__, __LINE__, #msg ) #define cudaCheckLastError(msg) __cudaCheckError( __FILE__, __LINE__, #msg )
inline void __cudaCheckError(const char *file, const int line, const char *msg){ inline void __cudaCheckError(const char *file, const int line, const char *msg){

View File

@ -32,7 +32,7 @@
#include <opm/simulators/linalg/bda/cusparseSolverBackend.hpp> #include <opm/simulators/linalg/bda/cusparseSolverBackend.hpp>
#include <opm/simulators/linalg/bda/BdaResult.hpp> #include <opm/simulators/linalg/bda/BdaResult.hpp>
#include <opm/simulators/linalg/bda/cuda_header.h> #include <opm/simulators/linalg/bda/cuda_header.hpp>
#include "cublas_v2.h" #include "cublas_v2.h"
#include "cusparse_v2.h" #include "cusparse_v2.h"

View File

@ -17,8 +17,8 @@
along with OPM. If not, see <http://www.gnu.org/licenses/>. along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef OPM_cuSPARSESOLVER_BACKEND_HEADER_INCLUDED #ifndef OPM_CUSPARSESOLVER_BACKEND_HEADER_INCLUDED
#define OPM_cuSPARSESOLVER_BACKEND_HEADER_INCLUDED #define OPM_CUSPARSESOLVER_BACKEND_HEADER_INCLUDED
#include "cublas_v2.h" #include "cublas_v2.h"