Skip to content
Snippets Groups Projects
Commit 9e76055a authored by Jonathan Lambrechts's avatar Jonathan Lambrechts
Browse files

Solver : support for exact preallocation of linearSystems (only

used in linearSystemPETSc for now)
parent eec9414e
Branches
Tags
No related merge requests found
...@@ -274,6 +274,53 @@ class dofManager{ ...@@ -274,6 +274,53 @@ class dofManager{
{ {
getDofValue(v->getNum(), Dof::createTypeWithTwoInts(iComp, iField), value); getDofValue(v->getNum(), Dof::createTypeWithTwoInts(iComp, iField), value);
} }
inline void insertInSparsityPatternLinConst(const Dof &R, const Dof &C)
{
std::map<Dof, int>::iterator itR = unknown.find(R);
if (itR != unknown.end())
{
typename std::map<Dof,DofAffineConstraint<dataVec> >::iterator itConstraint;
itConstraint = constraints.find(C);
if (itConstraint != constraints.end()){
for (unsigned i = 0; i < (itConstraint->second).linear.size(); i++){
insertInSparsityPattern(R,(itConstraint->second).linear[i].first);
}
}
}
else{ // test function ; (no shift ?)
typename std::map<Dof,DofAffineConstraint<dataVec> >::iterator itConstraint;
itConstraint = constraints.find(R);
if (itConstraint != constraints.end()){
for (unsigned i = 0; i < (itConstraint->second).linear.size(); i++){
insertInSparsityPattern((itConstraint->second).linear[i].first, C);
}
}
}
}
inline void insertInSparsityPattern(const Dof &R, const Dof &C)
{
if (_isParallel && !_parallelFinalized) _parallelFinalize();
if (!_current->isAllocated()) _current->allocate(sizeOfR());
std::map<Dof, int>::iterator itR = unknown.find(R);
if (itR != unknown.end()){
std::map<Dof, int>::iterator itC = unknown.find(C);
if (itC != unknown.end()){
_current->insertInSparsityPattern(itR->second, itC->second);
}
else{
typename std::map<Dof, dataVec>::iterator itFixed = fixed.find(C);
if (itFixed != fixed.end()) {
}else insertInSparsityPatternLinConst(R, C);
}
}
if (itR == unknown.end())
{
insertInSparsityPatternLinConst(R, C);
}
}
inline void assemble(const Dof &R, const Dof &C, const dataMat &value) inline void assemble(const Dof &R, const Dof &C, const dataMat &value)
{ {
if (_isParallel && !_parallelFinalized) _parallelFinalize(); if (_isParallel && !_parallelFinalized) _parallelFinalize();
......
...@@ -22,6 +22,7 @@ class linearSystemBase { ...@@ -22,6 +22,7 @@ class linearSystemBase {
virtual void zeroRightHandSide() = 0; virtual void zeroRightHandSide() = 0;
virtual int systemSolve() = 0; virtual int systemSolve() = 0;
void setParameter (std::string key, std::string value); void setParameter (std::string key, std::string value);
virtual void insertInSparsityPattern(int _row, int _col){};
}; };
template <class scalar> template <class scalar>
......
...@@ -9,6 +9,8 @@ ...@@ -9,6 +9,8 @@
template <> template <>
void linearSystemPETSc<fullMatrix<PetscScalar> >::addToMatrix(int row, int col, const fullMatrix<PetscScalar> &val) void linearSystemPETSc<fullMatrix<PetscScalar> >::addToMatrix(int row, int col, const fullMatrix<PetscScalar> &val)
{ {
if (!_entriesPreAllocated)
preAllocateEntries();
fullMatrix<PetscScalar> &modval = *const_cast<fullMatrix<PetscScalar> *>(&val); fullMatrix<PetscScalar> &modval = *const_cast<fullMatrix<PetscScalar> *>(&val);
for (int ii = 0; ii < val.size1(); ii++) for (int ii = 0; ii < val.size1(); ii++)
for (int jj = 0; jj < ii; jj++) { for (int jj = 0; jj < ii; jj++) {
...@@ -93,13 +95,16 @@ void linearSystemPETSc<fullMatrix<PetscScalar> >::allocate(int nbRows) ...@@ -93,13 +95,16 @@ void linearSystemPETSc<fullMatrix<PetscScalar> >::allocate(int nbRows)
_try(MatSetSizes(_a,nbRows * _blockSize, nbRows * _blockSize, PETSC_DETERMINE, PETSC_DETERMINE)); _try(MatSetSizes(_a,nbRows * _blockSize, nbRows * _blockSize, PETSC_DETERMINE, PETSC_DETERMINE));
if (Msg::GetCommSize() > 1) { if (Msg::GetCommSize() > 1) {
_try(MatSetType(_a, MATMPIBAIJ)); _try(MatSetType(_a, MATMPIBAIJ));
_try(MatSetFromOptions(_a));
_try(MatMPIBAIJSetPreallocation(_a, _blockSize, 5, NULL, 0, NULL));
} else { } else {
_try(MatSetType(_a, MATSEQBAIJ)); _try(MatSetType(_a, MATSEQBAIJ));
_try(MatSetFromOptions(_a));
_try(MatSeqBAIJSetPreallocation(_a, _blockSize, 5, NULL)); //todo preAllocate off-diagonal part
} }
_try(MatSetFromOptions(_a));
_try(MatGetOwnershipRange(_a, &_localRowStart, &_localRowEnd));
_try(MatGetSize(_a, &_globalSize, &_localSize));
_globalSize /= _blockSize;
_localSize /= _blockSize;
_localRowStart /= _blockSize;
_localRowEnd /= _blockSize;
// override the default options with the ones from the option // override the default options with the ones from the option
// database (if any) // database (if any)
_try(VecCreate(PETSC_COMM_WORLD, &_x)); _try(VecCreate(PETSC_COMM_WORLD, &_x));
......
...@@ -37,6 +37,8 @@ ...@@ -37,6 +37,8 @@
#include "GmshConfig.h" #include "GmshConfig.h"
#include "GmshMessage.h" #include "GmshMessage.h"
#include "linearSystem.h" #include "linearSystem.h"
#include "sparsityPattern.h"
#include <vector>
#if defined(HAVE_PETSC) #if defined(HAVE_PETSC)
#include <petsc.h> #include <petsc.h>
...@@ -46,17 +48,19 @@ template <class scalar> ...@@ -46,17 +48,19 @@ template <class scalar>
class linearSystemPETSc : public linearSystem<scalar> { class linearSystemPETSc : public linearSystem<scalar> {
protected: protected:
int _blockSize; // for block Matrix int _blockSize; // for block Matrix
bool _isAllocated, _kspAllocated; bool _isAllocated, _kspAllocated, _entriesPreAllocated;
Mat _a; Mat _a;
Vec _b, _x; Vec _b, _x;
KSP _ksp; KSP _ksp;
int _localRowStart, _localRowEnd, _localSize, _globalSize;
sparsityPattern _sparsity;
static void _try(int ierr) { CHKERRABORT(PETSC_COMM_WORLD, ierr); } static void _try(int ierr) { CHKERRABORT(PETSC_COMM_WORLD, ierr); }
void _kspCreate() { void _kspCreate() {
_try(KSPCreate(PETSC_COMM_WORLD, &_ksp)); _try(KSPCreate(PETSC_COMM_WORLD, &_ksp));
PC pc; PC pc;
_try(KSPGetPC(_ksp, &pc)); _try(KSPGetPC(_ksp, &pc));
// set some default options // set some default options
_try(PCSetType(pc, PCLU));//LU for direct solver and PCILU for indirect solver //_try(PCSetType(pc, PCLU));//LU for direct solver and PCILU for indirect solver
_try(PCFactorSetMatOrderingType(pc, MATORDERING_RCM)); _try(PCFactorSetMatOrderingType(pc, MATORDERING_RCM));
_try(PCFactorSetLevels(pc, 1)); _try(PCFactorSetLevels(pc, 1));
_try(KSPSetTolerances(_ksp, 1.e-8, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT)); _try(KSPSetTolerances(_ksp, 1.e-8, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT));
...@@ -72,7 +76,47 @@ class linearSystemPETSc : public linearSystem<scalar> { ...@@ -72,7 +76,47 @@ class linearSystemPETSc : public linearSystem<scalar> {
if (_kspAllocated) if (_kspAllocated)
_try (KSPDestroy (_ksp)); _try (KSPDestroy (_ksp));
} }
void insertInSparsityPattern (int i, int j) {
i -= _localRowStart;
if (i<0 || i>= _localSize) return;
_sparsity.insertEntry (i,j);
}
virtual bool isAllocated() const { return _isAllocated; } virtual bool isAllocated() const { return _isAllocated; }
virtual void preAllocateEntries() {
if (_entriesPreAllocated) return;
if (!_isAllocated) Msg::Fatal("system must be allocated first");
if (_sparsity.getNbRows() == 0) {
PetscInt prealloc = 300;
PetscTruth set;
PetscOptionsGetInt(PETSC_NULL, "-petsc_prealloc", &prealloc, &set);
if (_blockSize == 0) {
_try(MatSeqAIJSetPreallocation(_a, prealloc, PETSC_NULL));
} else {
_try(MatSeqBAIJSetPreallocation(_a, _blockSize, 5, PETSC_NULL));
}
} else {
std::vector<int> nByRowDiag (_localSize), nByRowOffDiag (_localSize);
for (int i = 0; i < _localSize; i++) {
int n;
const int *r = _sparsity.getRow(i, n);
for (int j = 0; j < n; j++) {
if (r[j] >= _localRowStart && r[j] < _localRowEnd)
nByRowDiag[i] ++;
else
nByRowOffDiag[i] ++;
}
}
if (_blockSize == 0) {
_try(MatSeqAIJSetPreallocation(_a, 0, &nByRowDiag[0]));
_try(MatMPIAIJSetPreallocation(_a, 0, &nByRowDiag[0], 0, &nByRowOffDiag[0]));
} else {
_try(MatSeqBAIJSetPreallocation(_a, _blockSize, 0, &nByRowDiag[0]));
_try(MatMPIBAIJSetPreallocation(_a, _blockSize, 0, &nByRowDiag[0], 0, &nByRowOffDiag[0]));
}
_sparsity.clear();
}
_entriesPreAllocated = true;
}
virtual void allocate(int nbRows) virtual void allocate(int nbRows)
{ {
clear(); clear();
...@@ -81,11 +125,9 @@ class linearSystemPETSc : public linearSystem<scalar> { ...@@ -81,11 +125,9 @@ class linearSystemPETSc : public linearSystem<scalar> {
// override the default options with the ones from the option // override the default options with the ones from the option
// database (if any) // database (if any)
_try(MatSetFromOptions(_a)); _try(MatSetFromOptions(_a));
_try(MatGetOwnershipRange(_a, &_localRowStart, &_localRowEnd));
_try(MatGetSize(_a, &_globalSize, &_localSize));
// preallocation option must be set after other options // preallocation option must be set after other options
PetscInt prealloc = 300;
PetscTruth set;
PetscOptionsGetInt(PETSC_NULL, "-petsc_prealloc", &prealloc, &set);
_try(MatSeqAIJSetPreallocation(_a, prealloc, PETSC_NULL));
_try(VecCreate(PETSC_COMM_WORLD, &_x)); _try(VecCreate(PETSC_COMM_WORLD, &_x));
_try(VecSetSizes(_x, nbRows, PETSC_DETERMINE)); _try(VecSetSizes(_x, nbRows, PETSC_DETERMINE));
// override the default options with the ones from the option // override the default options with the ones from the option
...@@ -93,6 +135,7 @@ class linearSystemPETSc : public linearSystem<scalar> { ...@@ -93,6 +135,7 @@ class linearSystemPETSc : public linearSystem<scalar> {
_try(VecSetFromOptions(_x)); _try(VecSetFromOptions(_x));
_try(VecDuplicate(_x, &_b)); _try(VecDuplicate(_x, &_b));
_isAllocated = true; _isAllocated = true;
_entriesPreAllocated = false;
} }
void print() { void print() {
_try(MatAssemblyBegin(_a, MAT_FINAL_ASSEMBLY)); _try(MatAssemblyBegin(_a, MAT_FINAL_ASSEMBLY));
...@@ -149,6 +192,8 @@ class linearSystemPETSc : public linearSystem<scalar> { ...@@ -149,6 +192,8 @@ class linearSystemPETSc : public linearSystem<scalar> {
} }
virtual void addToMatrix(int row, int col, const scalar &val) virtual void addToMatrix(int row, int col, const scalar &val)
{ {
if (!_entriesPreAllocated)
preAllocateEntries();
PetscInt i = row, j = col; PetscInt i = row, j = col;
PetscScalar s = val; PetscScalar s = val;
_try(MatSetValues(_a, 1, &i, 1, &j, &s, ADD_VALUES)); _try(MatSetValues(_a, 1, &i, 1, &j, &s, ADD_VALUES));
...@@ -167,7 +212,7 @@ class linearSystemPETSc : public linearSystem<scalar> { ...@@ -167,7 +212,7 @@ class linearSystemPETSc : public linearSystem<scalar> {
} }
virtual void zeroMatrix() virtual void zeroMatrix()
{ {
if (_isAllocated) { if (_isAllocated && _entriesPreAllocated) {
_try(MatAssemblyBegin(_a, MAT_FINAL_ASSEMBLY)); _try(MatAssemblyBegin(_a, MAT_FINAL_ASSEMBLY));
_try(MatAssemblyEnd(_a, MAT_FINAL_ASSEMBLY)); _try(MatAssemblyEnd(_a, MAT_FINAL_ASSEMBLY));
_try(MatZeroEntries(_a)); _try(MatZeroEntries(_a));
...@@ -193,6 +238,9 @@ class linearSystemPETSc : public linearSystem<scalar> { ...@@ -193,6 +238,9 @@ class linearSystemPETSc : public linearSystem<scalar> {
_try(KSPSetOperators(_ksp, _a, _a, DIFFERENT_NONZERO_PATTERN)); _try(KSPSetOperators(_ksp, _a, _a, DIFFERENT_NONZERO_PATTERN));
_try(MatAssemblyBegin(_a, MAT_FINAL_ASSEMBLY)); _try(MatAssemblyBegin(_a, MAT_FINAL_ASSEMBLY));
_try(MatAssemblyEnd(_a, MAT_FINAL_ASSEMBLY)); _try(MatAssemblyEnd(_a, MAT_FINAL_ASSEMBLY));
/*MatInfo info;
MatGetInfo(_a, MAT_LOCAL, &info);
printf("mallocs %.0f nz_allocated %.0f nz_used %.0f nz_unneeded %.0f\n", info.mallocs, info.nz_allocated, info.nz_used, info.nz_unneeded);*/
_try(VecAssemblyBegin(_b)); _try(VecAssemblyBegin(_b));
_try(VecAssemblyEnd(_b)); _try(VecAssemblyEnd(_b));
_try(KSPSolve(_ksp, _b, _x)); _try(KSPSolve(_ksp, _b, _x));
......
...@@ -17,17 +17,42 @@ ...@@ -17,17 +17,42 @@
// and the impact on the memory usage for this operation // and the impact on the memory usage for this operation
sparsityPattern::~sparsityPattern() sparsityPattern::~sparsityPattern()
{
clear();
}
void sparsityPattern::clear()
{ {
for(int i = 0; i <_nRows; i++) { for(int i = 0; i <_nRows; i++) {
if (_rowsj[i]) free(_rowsj[i]); if (_rowsj[i]) free(_rowsj[i]);
} }
free(_nByRow); if (_nByRow) free(_nByRow);
free(_nAllocByRows); if (_nAllocByRow) free(_nAllocByRow);
free(_rowsj); if (_rowsj) free(_rowsj);
_nByRow = NULL;
_rowsj = NULL;
_nAllocByRow = NULL;
_nRows = 0;
_nRowsAlloc = 0;
} }
void sparsityPattern::addEntry (int i, int j) void sparsityPattern::insertEntry (int i, int j)
{ {
if (i >= _nRows) {
if (i >= _nRowsAlloc) {
_nRowsAlloc = (i+1)*3/2;
_rowsj = (int**)realloc (_rowsj, sizeof(int*)*_nRowsAlloc);
_nByRow = (int*)realloc (_nByRow, sizeof(int)*_nRowsAlloc);
_nAllocByRow = (int*)realloc(_nAllocByRow, sizeof(int)*_nRowsAlloc);
}
for (int k = _nRows; k <= i; k++) {
_nByRow[k] = 0;
_nAllocByRow[k] = 0;
_rowsj[k] = NULL;
}
_nRows = i+1;
}
int n = _nByRow[i]; int n = _nByRow[i];
int *rowj = _rowsj[i]; int *rowj = _rowsj[i];
int k = 0; int k = 0;
...@@ -57,30 +82,30 @@ void sparsityPattern::addEntry (int i, int j) ...@@ -57,30 +82,30 @@ void sparsityPattern::addEntry (int i, int j)
} }
} }
_nByRow[i] = n+1; _nByRow[i] = n+1;
if (_nByRow[i]> _nAllocByRows[i]) { if (_nByRow[i]> _nAllocByRow[i]) {
int na = (n+1)*3/2; int na = (n+1)*3/2;
_rowsj[i] = (int*)realloc(_rowsj[i], (na*sizeof(int))); _rowsj[i] = (int*)realloc(_rowsj[i], (na*sizeof(int)));
_nAllocByRows[i] = na; _nAllocByRow[i] = na;
} }
memmove(&_rowsj[i][k+1], &_rowsj[i][k], (n-k)*sizeof (int)); memmove(&_rowsj[i][k+1], &_rowsj[i][k], (n-k)*sizeof (int));
_rowsj[i][k] = j; _rowsj[i][k] = j;
} }
sparsityPattern::sparsityPattern (int ni) sparsityPattern::sparsityPattern ()
{ {
_nRows = ni; _nRows = 0;
_rowsj = (int**)malloc (sizeof(int*)*ni); _nRowsAlloc = 0;
_nByRow = (int*)malloc(sizeof(int)*ni); _rowsj = NULL;
_nAllocByRows = (int*)malloc(sizeof(int)*ni); _nByRow = NULL;
for (int i = 0; i < ni; i++) { _nAllocByRow = NULL;
_nByRow[i] = 0;
_nAllocByRows[i] = 0;
_rowsj[i] = NULL;
}
} }
const int *sparsityPattern::getRow (int i, int &size) const const int *sparsityPattern::getRow (int i, int &size) const
{ {
if (i >= _nRows){
size = 0;
return NULL;
}
size = _nByRow[i]; size = _nByRow[i];
return _rowsj[i]; return _rowsj[i];
} }
...@@ -11,15 +11,17 @@ ...@@ -11,15 +11,17 @@
// - the impact on the memory for this operation // - the impact on the memory for this operation
class sparsityPattern { class sparsityPattern {
int *_nByRow, *_nAllocByRows; int *_nByRow, *_nAllocByRow;
int **_rowsj; int **_rowsj;
int _nRows; int _nRows, _nRowsAlloc;
public : public :
void addEntry (int i, int j); void insertEntry (int i, int j);
const int* getRow (int line, int &size) const; const int* getRow (int line, int &size) const;
sparsityPattern (int nRows); void clear();
sparsityPattern ();
~sparsityPattern(); ~sparsityPattern();
inline int getNbRows() {return _nRows;}
}; };
#endif #endif
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment