Added support for element-by-element preconditioner using option pc = mat
git-svn-id: http://svn.sintef.no/trondheim/IFEM/trunk@1457 e10b68d5-8a6e-419e-a041-bce267b0401d
This commit is contained in:
parent
cf3443a3c6
commit
1eab860d79
@ -15,6 +15,8 @@
|
|||||||
#ifdef HAS_PETSC
|
#ifdef HAS_PETSC
|
||||||
#include "SAM.h"
|
#include "SAM.h"
|
||||||
#include "petscversion.h"
|
#include "petscversion.h"
|
||||||
|
#include "petscis.h"
|
||||||
|
#include "petscsys.h"
|
||||||
|
|
||||||
#if PETSC_VERSION_MAJOR == 3 && PETSC_VERSION_MINOR >= 2
|
#if PETSC_VERSION_MAJOR == 3 && PETSC_VERSION_MINOR >= 2
|
||||||
#include "petscpcmg.h"
|
#include "petscpcmg.h"
|
||||||
@ -186,6 +188,9 @@ PETScMatrix::PETScMatrix(const LinSolParams& spar) : solParams(spar)
|
|||||||
KSPSetNullSpace(ksp,nsp);
|
KSPSetNullSpace(ksp,nsp);
|
||||||
}
|
}
|
||||||
LinAlgInit::increfs();
|
LinAlgInit::increfs();
|
||||||
|
|
||||||
|
elmIS = 0;
|
||||||
|
ISsize = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -204,6 +209,9 @@ PETScMatrix::PETScMatrix (const PETScMatrix& B) : solParams(B.solParams)
|
|||||||
KSPSetNullSpace(ksp,nsp);
|
KSPSetNullSpace(ksp,nsp);
|
||||||
}
|
}
|
||||||
LinAlgInit::increfs();
|
LinAlgInit::increfs();
|
||||||
|
|
||||||
|
elmIS = 0;
|
||||||
|
ISsize = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -219,6 +227,10 @@ PETScMatrix::~PETScMatrix ()
|
|||||||
// Deallocation of matrix object.
|
// Deallocation of matrix object.
|
||||||
MatDestroy(PETSCMANGLE(A));
|
MatDestroy(PETSCMANGLE(A));
|
||||||
LinAlgInit::decrefs();
|
LinAlgInit::decrefs();
|
||||||
|
|
||||||
|
for (int i = 0;i < ISsize;i++)
|
||||||
|
ISDestroy(elmIS[i]);
|
||||||
|
delete elmIS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -445,6 +457,10 @@ void PETScMatrix::initAssembly (const SAM& sam)
|
|||||||
// Get number of equations in linear system
|
// Get number of equations in linear system
|
||||||
const PetscInt neq = sam.getNoEquations();
|
const PetscInt neq = sam.getNoEquations();
|
||||||
|
|
||||||
|
// RUNAR
|
||||||
|
if (!strncasecmp(solParams.getPreconditioner(),"mat",3))
|
||||||
|
std::cout << "EBE = " << this->makeElementIS(sam) << std::endl;
|
||||||
|
|
||||||
// Set correct number of rows and columns for matrix.
|
// Set correct number of rows and columns for matrix.
|
||||||
MatSetSizes(A,neq,neq,PETSC_DECIDE,PETSC_DECIDE);
|
MatSetSizes(A,neq,neq,PETSC_DECIDE,PETSC_DECIDE);
|
||||||
MPI_Barrier(PETSC_COMM_WORLD);
|
MPI_Barrier(PETSC_COMM_WORLD);
|
||||||
@ -577,6 +593,8 @@ bool PETScMatrix::multiply (const SystemVector& B, SystemVector& C)
|
|||||||
|
|
||||||
bool PETScMatrix::solve (SystemVector& B, bool newLHS)
|
bool PETScMatrix::solve (SystemVector& B, bool newLHS)
|
||||||
{
|
{
|
||||||
|
Mat AebeI;
|
||||||
|
|
||||||
const PETScVector* Bptr = dynamic_cast<PETScVector*>(&B);
|
const PETScVector* Bptr = dynamic_cast<PETScVector*>(&B);
|
||||||
if (!Bptr)
|
if (!Bptr)
|
||||||
return false;
|
return false;
|
||||||
@ -586,7 +604,12 @@ bool PETScMatrix::solve (SystemVector& B, bool newLHS)
|
|||||||
VecCopy(Bptr->getVector(),x);
|
VecCopy(Bptr->getVector(),x);
|
||||||
|
|
||||||
// Has lefthand side changed?
|
// Has lefthand side changed?
|
||||||
if (newLHS)
|
if (!strncasecmp(solParams.getPreconditioner(),"mat",3)) {
|
||||||
|
if (!this->makeEBEpreconditioner(A,&AebeI))
|
||||||
|
return false;
|
||||||
|
KSPSetOperators(ksp,A,AebeI,SAME_NONZERO_PATTERN);
|
||||||
|
}
|
||||||
|
else if (newLHS)
|
||||||
KSPSetOperators(ksp,A,A,SAME_NONZERO_PATTERN);
|
KSPSetOperators(ksp,A,A,SAME_NONZERO_PATTERN);
|
||||||
else
|
else
|
||||||
KSPSetOperators(ksp,A,A,SAME_PRECONDITIONER);
|
KSPSetOperators(ksp,A,A,SAME_PRECONDITIONER);
|
||||||
@ -600,6 +623,9 @@ bool PETScMatrix::solve (SystemVector& B, bool newLHS)
|
|||||||
PetscPrintf(PETSC_COMM_WORLD,"\n Iterations for %s = %D\n",solParams.getMethod(),its);
|
PetscPrintf(PETSC_COMM_WORLD,"\n Iterations for %s = %D\n",solParams.getMethod(),its);
|
||||||
VecDestroy(PETSCMANGLE(x));
|
VecDestroy(PETSCMANGLE(x));
|
||||||
|
|
||||||
|
if (ISsize > 0)
|
||||||
|
MatDestroy(AebeI);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -731,4 +757,87 @@ real PETScMatrix::Linfnorm () const
|
|||||||
return norm;
|
return norm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool PETScMatrix::makeElementIS(const SAM& sam)
|
||||||
|
{
|
||||||
|
std::vector<PetscInt> meen;
|
||||||
|
|
||||||
|
ISsize = sam.getNoElms();
|
||||||
|
|
||||||
|
elmIS = new IS[ISsize];
|
||||||
|
for (int e = 1;e <= ISsize;e++) {
|
||||||
|
if (!sam.getElmEqns(meen,e))
|
||||||
|
return false;
|
||||||
|
std::sort(meen.begin(),meen.end());
|
||||||
|
|
||||||
|
for (size_t i = 0;i < meen.size();i++)
|
||||||
|
meen[i]--;
|
||||||
|
|
||||||
|
int ndof = 0;
|
||||||
|
for (size_t i = 0;i < meen.size();i++)
|
||||||
|
if (meen[i] >= 0)
|
||||||
|
ndof++;
|
||||||
|
|
||||||
|
PetscInt l2g[ndof];
|
||||||
|
ndof = 0;
|
||||||
|
for (size_t i = 0;i < meen.size();i++)
|
||||||
|
if (meen[i] >= 0)
|
||||||
|
l2g[ndof++] = meen[i];
|
||||||
|
|
||||||
|
ISCreateGeneral(PETSC_COMM_SELF,ndof,l2g,&(elmIS[e-1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool PETScMatrix::makeEBEpreconditioner(const Mat A, Mat* AeI)
|
||||||
|
{
|
||||||
|
PetscInt nedof;
|
||||||
|
const PetscInt* indx;
|
||||||
|
Vector vals;
|
||||||
|
std::vector<int> locidx;
|
||||||
|
|
||||||
|
if (!elmIS)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Mat* subMats;
|
||||||
|
MatGetSubMatrices(A,ISsize,elmIS,elmIS,MAT_INITIAL_MATRIX,&subMats);
|
||||||
|
|
||||||
|
MatDuplicate(A,MAT_DO_NOT_COPY_VALUES,AeI);
|
||||||
|
MatZeroEntries(*AeI);
|
||||||
|
|
||||||
|
Matrix elmMat;
|
||||||
|
for (PetscInt e = 0;e < ISsize;e++) {
|
||||||
|
ISGetSize(elmIS[e],&nedof);
|
||||||
|
|
||||||
|
locidx.resize(nedof);
|
||||||
|
for (int i = 0;i < nedof;i++)
|
||||||
|
locidx[i] = i;
|
||||||
|
|
||||||
|
vals.resize(nedof*nedof,true);
|
||||||
|
MatGetValues(subMats[e],nedof,&(locidx.front()),nedof,&(locidx.front()),&(vals.front()));
|
||||||
|
|
||||||
|
int dof = 0;
|
||||||
|
elmMat.resize(nedof,nedof);
|
||||||
|
for (int i = 1;i <= nedof;i++)
|
||||||
|
for (int j = 1;j <= nedof;j++)
|
||||||
|
elmMat(i,j) = vals[dof++];
|
||||||
|
|
||||||
|
utl::invert(elmMat);
|
||||||
|
elmMat.transpose();
|
||||||
|
|
||||||
|
ISGetIndices(elmIS[e],&indx);
|
||||||
|
MatSetValues(*AeI,nedof,indx,nedof,indx,elmMat.ptr(),ADD_VALUES);
|
||||||
|
ISRestoreIndices(elmIS[e],&indx);
|
||||||
|
}
|
||||||
|
|
||||||
|
MatDestroyMatrices(ISsize,&subMats);
|
||||||
|
|
||||||
|
MatAssemblyBegin(*AeI,MAT_FINAL_ASSEMBLY);
|
||||||
|
MatAssemblyEnd(*AeI,MAT_FINAL_ASSEMBLY);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
#endif // HAS_PETSC
|
#endif // HAS_PETSC
|
||||||
|
@ -227,6 +227,14 @@ private:
|
|||||||
KSP ksp; //!< Linear solver
|
KSP ksp; //!< Linear solver
|
||||||
MatNullSpace nsp; //!< Null-space of linear operator
|
MatNullSpace nsp; //!< Null-space of linear operator
|
||||||
const LinSolParams& solParams; //!< Linear solver parameters
|
const LinSolParams& solParams; //!< Linear solver parameters
|
||||||
|
IS* elmIS; //!< Element index sets
|
||||||
|
PetscInt ISsize; //!< Number of index sets/elements
|
||||||
|
|
||||||
|
//! \brief Constructs index set needed for element-by-element preconditioner
|
||||||
|
bool makeElementIS(const SAM& sam);
|
||||||
|
|
||||||
|
//! \brief Constructs the EBE preconditioner of the given matrix
|
||||||
|
bool makeEBEpreconditioner(const Mat A, Mat* AeI);
|
||||||
|
|
||||||
#else // dummy implementation when PETSc is not included
|
#else // dummy implementation when PETSc is not included
|
||||||
virtual SystemMatrix* copy() const { return 0; }
|
virtual SystemMatrix* copy() const { return 0; }
|
||||||
|
Loading…
Reference in New Issue
Block a user