add umfpack solver to SparseMatrix

This commit is contained in:
Arne Morten Kvarving 2017-09-26 20:40:48 +02:00
parent 5c9bac9cf9
commit 9329ac73f6
8 changed files with 84 additions and 15 deletions

View File

@ -212,7 +212,17 @@ IF(IFEM_USE_OPENMP)
ENDIF(OPENMP_FOUND) ENDIF(OPENMP_FOUND)
ENDIF(IFEM_USE_OPENMP) ENDIF(IFEM_USE_OPENMP)
# ISTL # UMFPack
if(IFEM_USE_UMFPACK)
find_package(SuiteSparse COMPONENTS umfpack)
if(SuiteSparse_UMFPACK_FOUND)
list(APPEND IFEM_DEFINITIONS -DHAS_UMFPACK=1)
list(APPEND IFEM_DEPINCLUDES ${UMFPACK_INCLUDE_DIR})
list(APPEND IFEM_DEPLIBS ${UMFPACK_LIBRARY})
endif()
endif()
# ISTL - need to be after UMFPack and SuperLU
if(IFEM_USE_ISTL) if(IFEM_USE_ISTL)
find_package(ISTL) find_package(ISTL)
if(ISTL_FOUND) if(ISTL_FOUND)

View File

@ -20,17 +20,12 @@ if(SUPERLU_FOUND)
list(APPEND ISTL_DEFINITIONS -DHAVE_SUPERLU=1 -DSUPERLU_POST_2005_VERSION=1 -DSUPERLU_NTYPE=1 -DSUPERLU_MIN_VERSION_4_3=1) list(APPEND ISTL_DEFINITIONS -DHAVE_SUPERLU=1 -DSUPERLU_POST_2005_VERSION=1 -DSUPERLU_NTYPE=1 -DSUPERLU_MIN_VERSION_4_3=1)
endif() endif()
if(IFEM_USE_UMFPACK) if(SuiteSparse_UMFPACK_FOUND AND ISTL_FOUND)
find_package(SuiteSparse COMPONENTS umfpack)
endif()
if(SuiteSparse_UMFPACK_FOUND)
list(APPEND ISTL_DEFINITIONS -DHAVE_UMFPACK=1) list(APPEND ISTL_DEFINITIONS -DHAVE_UMFPACK=1)
list(APPEND ISTL_INCLUDE_DIRS ${UMFPACK_INCLUDE_DIR}) list(APPEND ISTL_INCLUDE_DIRS ${UMFPACK_INCLUDE_DIR})
list(APPEND ISTL_LIBRARIES ${UMFPACK_LIBRARY}) list(APPEND ISTL_LIBRARIES ${UMFPACK_LIBRARY})
endif() endif()
list(APPEND ISTL_INCLUDE_DIRS ${ISTL_INCLUDEDIR}) list(APPEND ISTL_INCLUDE_DIRS ${ISTL_INCLUDEDIR})
include(FindPackageHandleStandardArgs) include(FindPackageHandleStandardArgs)

View File

@ -24,6 +24,9 @@
#elif defined(HAVE_MPI) #elif defined(HAVE_MPI)
#include <mpi.h> #include <mpi.h>
#endif #endif
#ifdef HAS_UMFPACK
#include <umfpack.h>
#endif
int IFEM::argc; int IFEM::argc;
char** IFEM::argv; char** IFEM::argv;
@ -113,6 +116,14 @@ int IFEM::Init (int arg_c, char** arg_v, const char* title)
#else #else
std::cout <<"disabled"; std::cout <<"disabled";
#endif #endif
std::cout <<"\n UMFPack support: ";
#if HAS_UMFPACK
std::cout <<"enabled (v" << UMFPACK_MAIN_VERSION <<"."
<< UMFPACK_SUB_VERSION <<"."
<< UMFPACK_SUBSUB_VERSION << ")";
#else
std::cout <<"disabled";
#endif
std::cout <<"\n ISTL support: "; std::cout <<"\n ISTL support: ";
#if HAS_ISTL #if HAS_ISTL

View File

@ -22,6 +22,9 @@
#ifdef HAS_SAMG #ifdef HAS_SAMG
#include "samg.h" #include "samg.h"
#endif #endif
#ifdef HAS_UMFPACK
#include <umfpack.h>
#endif
#ifdef USE_OPENMP #ifdef USE_OPENMP
#include <omp.h> #include <omp.h>
#endif #endif
@ -252,7 +255,7 @@ Real& SparseMatrix::operator () (size_t r, size_t c)
return value; return value;
} }
} }
else if (solver == SUPERLU) { else if (solver == SUPERLU || solver == UMFPACK) {
// Column-oriented format with 0-based indices // Column-oriented format with 0-based indices
IntVec::const_iterator begin = JA.begin() + IA[c-1]; IntVec::const_iterator begin = JA.begin() + IA[c-1];
IntVec::const_iterator end = JA.begin() + IA[c]; IntVec::const_iterator end = JA.begin() + IA[c];
@ -289,7 +292,7 @@ const Real& SparseMatrix::operator () (size_t r, size_t c) const
ValueIter vit = elem.find(IJPair(r,c)); ValueIter vit = elem.find(IJPair(r,c));
if (vit != elem.end()) return vit->second; if (vit != elem.end()) return vit->second;
} }
else if (solver == SUPERLU) { else if (solver == SUPERLU || solver == UMFPACK) {
// Column-oriented format with 0-based indices // Column-oriented format with 0-based indices
IntVec::const_iterator begin = JA.begin() + IA[c-1]; IntVec::const_iterator begin = JA.begin() + IA[c-1];
IntVec::const_iterator end = JA.begin() + IA[c]; IntVec::const_iterator end = JA.begin() + IA[c];
@ -321,7 +324,7 @@ void SparseMatrix::dump (std::ostream& os, char format, const char* label)
for (ValueIter it = elem.begin(); it != elem.end(); it++) for (ValueIter it = elem.begin(); it != elem.end(); it++)
os << it->first.first <<' '<< it->first.second <<" "<< it->second os << it->first.first <<' '<< it->first.second <<" "<< it->second
<<";\n"; <<";\n";
else if (solver == SUPERLU) { else if (solver == SUPERLU || solver == UMFPACK) {
// Column-oriented format with 0-based indices // Column-oriented format with 0-based indices
os << JA[0]+1 <<" 1 "<< A[0]; os << JA[0]+1 <<" 1 "<< A[0];
for (size_t j = 1; j <= ncol; j++) for (size_t j = 1; j <= ncol; j++)
@ -383,7 +386,7 @@ void SparseMatrix::printSparsity (std::ostream& os) const
for (c = 1; c <= ncol; c++) for (c = 1; c <= ncol; c++)
if (editable) if (editable)
os << (elem.find(IJPair(r,c)) == elem.end() ? '.' : 'X'); os << (elem.find(IJPair(r,c)) == elem.end() ? '.' : 'X');
else if (solver == SUPERLU) { else if (solver == SUPERLU || solver == UMFPACK) {
// Column-oriented format with 0-based indices // Column-oriented format with 0-based indices
IntVec::const_iterator begin = JA.begin() + IA[c-1]; IntVec::const_iterator begin = JA.begin() + IA[c-1];
IntVec::const_iterator end = JA.begin() + IA[c]; IntVec::const_iterator end = JA.begin() + IA[c];
@ -488,7 +491,7 @@ bool SparseMatrix::add (const SystemMatrix& B, Real alpha)
} }
else if (editable == 'P') else if (editable == 'P')
{ {
if (solver == SUPERLU) if (solver == SUPERLU || solver == UMFPACK)
// Column-oriented format with 0-based indices // Column-oriented format with 0-based indices
for (size_t j = 1; j <= Bptr->ncol; j++) for (size_t j = 1; j <= Bptr->ncol; j++)
for (int i = Bptr->IA[j-1]; i < Bptr->IA[j]; i++) for (int i = Bptr->IA[j-1]; i < Bptr->IA[j]; i++)
@ -704,6 +707,7 @@ void SparseMatrix::preAssemble (const SAM& sam, bool delayLocking)
<< nrow <<"x"<< ncol <<"): "<< std::flush; << nrow <<"x"<< ncol <<"): "<< std::flush;
switch (solver) { switch (solver) {
case UMFPACK:
case SUPERLU: this->optimiseSLU(dofc); break; case SUPERLU: this->optimiseSLU(dofc); break;
case S_A_M_G: this->optimiseSAMG(); break; case S_A_M_G: this->optimiseSAMG(); break;
default: break; default: break;
@ -733,6 +737,7 @@ void SparseMatrix::preAssemble (const std::vector<IntVec>& MMNPC, size_t nel)
} }
switch (solver) { switch (solver) {
case UMFPACK:
case SUPERLU: this->optimiseSLU(); break; case SUPERLU: this->optimiseSLU(); break;
case S_A_M_G: this->optimiseSAMG(); break; case S_A_M_G: this->optimiseSAMG(); break;
default: break; default: break;
@ -962,6 +967,7 @@ bool SparseMatrix::solve (SystemVector& B, bool, Real* rc)
{ {
case SUPERLU: return this->solveSLUx(*Bptr,rc); case SUPERLU: return this->solveSLUx(*Bptr,rc);
case S_A_M_G: return this->solveSAMG(*Bptr); case S_A_M_G: return this->solveSAMG(*Bptr);
case UMFPACK: return this->solveUMF(*Bptr,rc);
default: std::cerr <<"SparseMatrix::solve: No equation solver"<< std::endl; default: std::cerr <<"SparseMatrix::solve: No equation solver"<< std::endl;
} }
@ -1219,6 +1225,43 @@ bool SparseMatrix::solveSLUx (Vector& B, Real* rcond)
} }
bool SparseMatrix::solveUMF (Vector& B, Real* rcond)
{
if (!factored) this->optimiseSLU();
#ifdef HAS_UMFPACK
double info[UMFPACK_INFO];
Vector X(B.size());
void* symbolic;
umfpack_di_symbolic(nrow, ncol, IA.data(), JA.data(),
A.data(), &symbolic, nullptr, info);
if (info[UMFPACK_STATUS] != UMFPACK_OK)
return false;
void* numeric;
umfpack_di_numeric(IA.data(), JA.data(), A.data(), symbolic,
&numeric, nullptr, info);
if (info[UMFPACK_STATUS] != UMFPACK_OK)
{
umfpack_di_free_symbolic(&symbolic);
return false;
}
if (rcond)
*rcond = info[UMFPACK_RCOND];
umfpack_di_solve(UMFPACK_A,
IA.data(), JA.data(), A.data(),
&X[0], &B[0], numeric, nullptr, info);
if (info[UMFPACK_STATUS] == UMFPACK_OK)
B = X;
umfpack_di_free_symbolic(&symbolic);
umfpack_di_free_numeric(&numeric);
return info[UMFPACK_STATUS] == UMFPACK_OK;
#else
std::cerr <<"SparseMatrix::solve: UMFPACK solver not available"<< std::endl;
return false;
#endif
}
bool SparseMatrix::solveSAMG (Vector& B) bool SparseMatrix::solveSAMG (Vector& B)
{ {
int ierr = 1; int ierr = 1;
@ -1290,7 +1333,7 @@ Real SparseMatrix::Linfnorm () const
if (editable) if (editable)
for (ValueIter it = elem.begin(); it != elem.end(); ++it) for (ValueIter it = elem.begin(); it != elem.end(); ++it)
sums[it->first.first-1] += fabs(it->second); sums[it->first.first-1] += fabs(it->second);
else if (solver == SUPERLU) else if (solver == SUPERLU || solver == UMFPACK)
// Column-oriented format with 0-based row-indices // Column-oriented format with 0-based row-indices
for (size_t j = 1; j <= ncol; j++) for (size_t j = 1; j <= ncol; j++)
for (int i = IA[j-1]; i < IA[j]; i++) for (int i = IA[j-1]; i < IA[j]; i++)

View File

@ -39,7 +39,7 @@ class SparseMatrix : public SystemMatrix
{ {
public: public:
//! \brief Available equation solvers for this matrix type. //! \brief Available equation solvers for this matrix type.
enum SparseSolver { NONE, SUPERLU, S_A_M_G }; enum SparseSolver { NONE, SUPERLU, S_A_M_G, UMFPACK };
//! \brief Default constructor creating an empty matrix. //! \brief Default constructor creating an empty matrix.
SparseMatrix(SparseSolver eqSolver = NONE, int nt = 1); SparseMatrix(SparseSolver eqSolver = NONE, int nt = 1);
@ -236,6 +236,11 @@ protected:
//! \param[out] rcond Reciprocal condition number of the LHS-matrix (optional) //! \param[out] rcond Reciprocal condition number of the LHS-matrix (optional)
bool solveSLUx(Vector& B, Real* rcond); bool solveSLUx(Vector& B, Real* rcond);
//! \brief Invokes the UMFPACK equation solver for a given right-hand-side.
//! \param B Right-hand-side vector on input, solution vector on output
//! \param[out] rcond Reciprocal condition number of the LHS-matrix (optional)
bool solveUMF(Vector& B, Real* rcond);
//! \brief Writes the system matrix to the given output stream. //! \brief Writes the system matrix to the given output stream.
virtual std::ostream& write(std::ostream& os) const; virtual std::ostream& write(std::ostream& os) const;

View File

@ -118,6 +118,7 @@ SystemMatrix* SystemMatrix::create (const ProcessAdm& padm, Type matrixType,
case SPR : return new SPRMatrix(); case SPR : return new SPRMatrix();
case SPARSE: return new SparseMatrix(SparseMatrix::SUPERLU,num_thread_SLU); case SPARSE: return new SparseMatrix(SparseMatrix::SUPERLU,num_thread_SLU);
case SAMG : return new SparseMatrix(SparseMatrix::S_A_M_G); case SAMG : return new SparseMatrix(SparseMatrix::S_A_M_G);
case UMFPACK: return new SparseMatrix(SparseMatrix::UMFPACK);
#ifdef HAS_ISTL #ifdef HAS_ISTL
case ISTL : return new ISTLMatrix(padm,defaultPar,ltype); case ISTL : return new ISTLMatrix(padm,defaultPar,ltype);
#endif #endif

View File

@ -203,7 +203,7 @@ class SystemMatrix
public: public:
//! \brief The available system matrix formats. //! \brief The available system matrix formats.
enum Type { DENSE = 0, SPR = 1, SPARSE = 2, SAMG = 3, enum Type { DENSE = 0, SPR = 1, SPARSE = 2, SAMG = 3,
PETSC = 4, ISTL = 5 }; PETSC = 4, ISTL = 5, UMFPACK = 6 };
//! \brief Static method creating a matrix of the given type. //! \brief Static method creating a matrix of the given type.
static SystemMatrix* create(const ProcessAdm& padm, Type matrixType, static SystemMatrix* create(const ProcessAdm& padm, Type matrixType,

View File

@ -66,6 +66,8 @@ void SIMoptions::setLinearSolver (const std::string& eqsolver)
solver = SystemMatrix::SPR; solver = SystemMatrix::SPR;
else if (eqsolver == "superlu") else if (eqsolver == "superlu")
solver = SystemMatrix::SPARSE; solver = SystemMatrix::SPARSE;
else if (eqsolver == "umfpack")
solver = SystemMatrix::UMFPACK;
else if (eqsolver == "samg") else if (eqsolver == "samg")
solver = SystemMatrix::SAMG; solver = SystemMatrix::SAMG;
else if (eqsolver == "petsc") else if (eqsolver == "petsc")
@ -259,6 +261,8 @@ bool SIMoptions::parseOldOptions (int argc, char** argv, int& i)
} }
else if (!strcmp(argv[i],"-samg")) else if (!strcmp(argv[i],"-samg"))
solver = SystemMatrix::SAMG; solver = SystemMatrix::SAMG;
else if (!strcmp(argv[i],"-umfpack"))
solver = SystemMatrix::UMFPACK;
else if (!strcmp(argv[i],"-petsc")) else if (!strcmp(argv[i],"-petsc"))
solver = SystemMatrix::PETSC; solver = SystemMatrix::PETSC;
else if (!strcmp(argv[i],"-istl")) else if (!strcmp(argv[i],"-istl"))