36 #include "LinearSystem.hpp"
41 #include <boost/scoped_array.hpp>
43 #include "PetscException.hpp"
44 #include "OutputFileHandler.hpp"
46 #include "HeartEventHandler.hpp"
48 #include "Warnings.hpp"
55 :mPrecondMatrix(NULL),
58 mDestroyMatAndVec(true),
61 mMatrixIsConstant(false),
63 mUseAbsoluteTolerance(false),
64 mDirichletBoundaryConditionsVector(NULL),
65 mpBlockDiagonalPC(NULL),
66 mpLDUFactorisationPC(NULL),
67 mpTwoLevelsBlockDiagonalPC(NULL),
68 mpBathNodes( boost::shared_ptr<std::vector<
PetscInt> >() ),
69 mPrecondMatrixIsNotLhs(false),
70 mRowPreallocation(rowPreallocation),
71 mUseFixedNumberIterations(false),
72 mEvaluateNumItsEveryNSolves(UINT_MAX),
73 mpConvergenceTestContext(NULL),
76 mForceSpectrumReevaluation(false)
78 assert(lhsVectorSize > 0);
88 EXCEPTION(
"You must provide a rowPreallocation argument for a large sparse system");
104 mTotalNumIterations = 0;
105 mMaxNumIterations = 0;
110 :mPrecondMatrix(NULL),
111 mSize(lhsVectorSize),
113 mDestroyMatAndVec(true),
116 mMatrixIsConstant(false),
118 mUseAbsoluteTolerance(false),
119 mDirichletBoundaryConditionsVector(NULL),
120 mpBlockDiagonalPC(NULL),
121 mpLDUFactorisationPC(NULL),
122 mpTwoLevelsBlockDiagonalPC(NULL),
123 mpBathNodes( boost::shared_ptr<std::vector<
PetscInt> >() ),
124 mPrecondMatrixIsNotLhs(false),
125 mUseFixedNumberIterations(false),
126 mEvaluateNumItsEveryNSolves(UINT_MAX),
127 mpConvergenceTestContext(NULL),
130 mForceSpectrumReevaluation(false)
132 assert(lhsVectorSize > 0);
141 mTotalNumIterations = 0;
142 mMaxNumIterations = 0;
147 :mPrecondMatrix(NULL),
149 mDestroyMatAndVec(true),
151 mMatrixIsConstant(false),
153 mUseAbsoluteTolerance(false),
154 mDirichletBoundaryConditionsVector(NULL),
155 mpBlockDiagonalPC(NULL),
156 mpLDUFactorisationPC(NULL),
157 mpTwoLevelsBlockDiagonalPC(NULL),
158 mpBathNodes( boost::shared_ptr<std::vector<
PetscInt> >() ),
159 mPrecondMatrixIsNotLhs(false),
160 mRowPreallocation(rowPreallocation),
161 mUseFixedNumberIterations(false),
162 mEvaluateNumItsEveryNSolves(UINT_MAX),
163 mpConvergenceTestContext(NULL),
166 mForceSpectrumReevaluation(false)
182 mTotalNumIterations = 0;
183 mMaxNumIterations = 0;
188 :mPrecondMatrix(NULL),
190 mDestroyMatAndVec(false),
192 mMatrixIsConstant(false),
194 mUseAbsoluteTolerance(false),
195 mDirichletBoundaryConditionsVector(NULL),
196 mpBlockDiagonalPC(NULL),
197 mpLDUFactorisationPC(NULL),
198 mpTwoLevelsBlockDiagonalPC(NULL),
199 mpBathNodes( boost::shared_ptr<std::vector<
PetscInt> >() ),
200 mPrecondMatrixIsNotLhs(false),
201 mRowPreallocation(UINT_MAX),
202 mUseFixedNumberIterations(false),
203 mEvaluateNumItsEveryNSolves(UINT_MAX),
204 mpConvergenceTestContext(NULL),
207 mForceSpectrumReevaluation(false)
209 assert(residualVector || jacobianMatrix);
224 assert(mat_size == mat_cols);
229 MatGetInfo(
mLhsMatrix, MAT_GLOBAL_MAX, &matrix_info);
246 mTotalNumIterations = 0;
247 mMaxNumIterations = 0;
284 #if (PETSC_VERSION_MAJOR == 3) //PETSc 3.x.x
287 #if ( PETSC_VERSION_MINOR >= 5 ) //PETSc 3.5 or later
302 std::cout << std::endl <<
"KSP iterations report:" << std::endl;
303 std::cout <<
"mNumSolves" <<
"\t" <<
"mTotalNumIterations" <<
"\t" <<
"mMaxNumIterations" <<
"\t" <<
"mAveNumIterations" << std::endl;
304 std::cout <<
mNumSolves <<
"\t" << mTotalNumIterations <<
"\t" << mMaxNumIterations <<
"\t" << ave_num_iterations << std::endl;
415 return (
unsigned)
mSize;
422 for (
unsigned vec_index=0; vec_index<numberOfBases; vec_index++)
425 VecNorm(nullBasis[vec_index], NORM_2, &l2_norm);
426 if (fabs(l2_norm-1.0) > 1e-08)
428 EXCEPTION(
"One of the vectors in the null space is not normalised");
433 for (
unsigned vec_index=1; vec_index<numberOfBases; vec_index++)
436 unsigned num_vectors_ahead = numberOfBases-vec_index;
437 boost::scoped_array<PetscScalar> dot_products(
new PetscScalar[num_vectors_ahead]);
438 #if (PETSC_VERSION_MAJOR == 2 && PETSC_VERSION_MINOR == 2) //PETSc 2.2
439 VecMDot(num_vectors_ahead, nullBasis[vec_index-1], &nullBasis[vec_index], dot_products.get());
441 VecMDot(nullBasis[vec_index-1], num_vectors_ahead, &nullBasis[vec_index], dot_products.get());
443 for (
unsigned index=0; index<num_vectors_ahead; index++)
445 if (fabs(dot_products[index]) > 1e-08 )
447 EXCEPTION(
"The null space is not orthogonal.");
454 PETSCEXCEPT( MatNullSpaceCreate(PETSC_COMM_WORLD, PETSC_FALSE, numberOfBases, nullBasis, &
mMatNullSpace) );
463 PETSCEXCEPT( MatNullSpaceCreate(PETSC_COMM_WORLD, PETSC_FALSE, 0, NULL, &
mMatNullSpace) );
464 #if (PETSC_VERSION_MAJOR == 3 && PETSC_VERSION_MINOR >= 3) //PETSc 3.3 or later
504 KSPGetIterationNumber(this->
mKspSolver, &num_its);
506 return (
unsigned) num_its;
533 EXCEPTION(
"LHS matrix used for preconditioner construction");
556 #if (PETSC_VERSION_MAJOR == 3) //PETSc 3.x.x
557 MatSetOption(
mLhsMatrix, MAT_SYMMETRIC, PETSC_FALSE);
558 MatSetOption(
mLhsMatrix, MAT_STRUCTURALLY_SYMMETRIC, PETSC_FALSE);
559 MatSetOption(
mLhsMatrix, MAT_SYMMETRY_ETERNAL, PETSC_FALSE);
562 MatSetOption(
mLhsMatrix, MAT_NOT_STRUCTURALLY_SYMMETRIC);
563 MatSetOption(
mLhsMatrix, MAT_NOT_SYMMETRY_ETERNAL);
570 PetscBool symmetry_flag_is_set;
571 PetscBool symmetry_flag;
573 MatIsSymmetricKnown(
mLhsMatrix, &symmetry_flag_is_set, &symmetry_flag);
576 return symmetry_flag_is_set && symmetry_flag;
621 if (
mPcType ==
"blockdiagonal")
634 else if (
mPcType ==
"ldufactorisation")
647 else if (
mPcType ==
"twolevelsblockdiagonal")
660 TERMINATE(
"You must provide a list of bath nodes when using TwoLevelsBlockDiagonalPC");
668 PCSetType(prec, pcType);
684 MatGetInfo(
mLhsMatrix, MAT_GLOBAL_SUM, &mat_info);
689 Vec chebyshev_lhs_vector = NULL;
698 const bool is_small = (
mSize <= 6);
700 #if ( PETSC_VERSION_MAJOR==3 && PETSC_VERSION_MINOR >= 5 ) //PETSc 3.5 or later
704 KSPSetReusePreconditioner(
mKspSolver, PETSC_TRUE);
711 MatStructure preconditioner_over_successive_calls;
715 preconditioner_over_successive_calls = SAME_PRECONDITIONER;
719 preconditioner_over_successive_calls = SAME_NONZERO_PATTERN;
725 #if (PETSC_VERSION_MAJOR == 3 && PETSC_VERSION_MINOR >= 3) //PETSc 3.3 or later
737 #if ( PETSC_VERSION_MAJOR == 3 && PETSC_VERSION_MINOR >= 5 ) //PETSc 3.5 or later
745 #if ( PETSC_VERSION_MAJOR == 3 && PETSC_VERSION_MINOR >= 5 ) //PETSc 3.5 or later
764 #if (PETSC_VERSION_MAJOR == 3 && PETSC_VERSION_MINOR >= 3) //PETSc 3.3 or later
781 PCSetType(prec, PCNONE);
788 if (
mPcType ==
"blockdiagonal")
798 else if (
mPcType ==
"ldufactorisation")
808 else if (
mPcType ==
"twolevelsblockdiagonal")
812 TERMINATE(
"You must provide a list of bath nodes when using TwoLevelsBlockDiagonalPC");
825 PCSetType(prec,
mPcType.c_str());
834 KSPSetInitialGuessNonzero(
mKspSolver,PETSC_TRUE);
847 KSPSetComputeEigenvalues(
mKspSolver, PETSC_TRUE);
850 VecDuplicate(
mRhsVector, &chebyshev_lhs_vector);
853 VecCopy(lhsGuess, chebyshev_lhs_vector);
859 PetscReal *r_eig =
new PetscReal[
mSize];
860 PetscReal *c_eig =
new PetscReal[
mSize];
862 KSPComputeEigenvalues(
mKspSolver,
mSize, r_eig, c_eig, &eigs_computed);
867 KSPSetTolerances(
mKspSolver, DBL_EPSILON, DBL_EPSILON, PETSC_DEFAULT, PETSC_DEFAULT);
871 VecCopy(lhsGuess, chebyshev_lhs_vector);
875 KSPComputeEigenvalues(
mKspSolver,
mSize, r_eig, c_eig, &eigs_computed);
877 mEigMax = r_eig[eigs_computed-1];
887 std::cout <<
"EIGS: ";
888 for (
int index=0; index<eigs_computed; index++)
890 std::cout << r_eig[index] <<
", ";
892 std::cout << std::endl;
897 double sigma_one = 1 - alpha*
mEigMin;
898 if (
PetscTools::AmMaster()) std::cout <<
"sigma_1 = 1 - alpha*mEigMin = "<< sigma_one <<std::endl;
903 #if (PETSC_VERSION_MAJOR == 3 && PETSC_VERSION_MINOR >= 3) //PETSc 3.3 or later
910 KSPSetComputeEigenvalues(
mKspSolver, PETSC_FALSE);
937 if (chebyshev_lhs_vector)
945 Timer::Print(
"KSPSetUP (contains preconditioner creation for PETSc preconditioners)");
957 WARNING(
"LinearSystem doesn't like the non-zero pattern of a matrix to change. (I think you changed it).");
975 VecCopy(lhsGuess, lhs_vector);
985 double rhs_zero_tol = 1e-15;
987 if (rhs_norm < rhs_zero_tol && rhs_norm > 0.0)
989 WARNING(
"Using zero initial guess due to small right hand side vector");
1045 #if ((PETSC_VERSION_MAJOR == 2 && PETSC_VERSION_MINOR == 2) || (PETSC_VERSION_MAJOR == 2 && PETSC_VERSION_MINOR == 3 && PETSC_VERSION_SUBMINOR <= 2))
1046 KSPSetNormType(
mKspSolver, KSP_PRECONDITIONED_NORM);
1048 KSPSetNormType(
mKspSolver, KSP_NORM_PRECONDITIONED);
1051 #if (PETSC_VERSION_MAJOR == 3) //PETSc 3.x.x
1054 #if ( PETSC_VERSION_MINOR >= 5 ) //PETSc 3.5 or later
1060 #if ( PETSC_VERSION_MINOR >= 5 ) //PETSc 3.5 or later
1068 KSPSetConvergenceTest(
mKspSolver, KSPDefaultConverged, PETSC_NULL);
1081 std::stringstream num_it_str;
1083 PetscOptionsSetValue(
"-ksp_max_it", num_it_str.str().c_str());
1090 KSPSetComputeEigenvalues(
mKspSolver, PETSC_TRUE);
1105 std::cout <<
"++ Solve: " <<
mNumSolves <<
" NumIterations: " << num_it <<
" ";
1109 mTotalNumIterations += num_it;
1110 if ((
unsigned) num_it > mMaxNumIterations)
1112 mMaxNumIterations = num_it;
1117 KSPConvergedReason reason;
1122 WARNING(
"Not explicitly checking convergence reason when using fixed number of iterations and PETSc 2");
1134 PetscReal *r_eig =
new PetscReal[
mSize];
1135 PetscReal *c_eig =
new PetscReal[
mSize];
1137 KSPComputeEigenvalues(
mKspSolver,
mSize, r_eig, c_eig, &eigs_computed);
1151 #if (PETSC_VERSION_MAJOR == 3 && PETSC_VERSION_MINOR >= 3) //PETSc 3.3 or later
1158 KSPSetComputeEigenvalues(
mKspSolver, PETSC_FALSE);
1161 #if ((PETSC_VERSION_MAJOR == 2 && PETSC_VERSION_MINOR == 2) || (PETSC_VERSION_MAJOR == 2 && PETSC_VERSION_MINOR == 3 && PETSC_VERSION_SUBMINOR <= 2))
1165 EXCEPTION(
"Chebyshev with fixed number of iterations is known to be broken in PETSc <= 2.3.2");
1169 #elif (PETSC_VERSION_MAJOR == 3 && PETSC_VERSION_MINOR >= 2) //PETSc 3.2 or later
1175 #if (PETSC_VERSION_MAJOR == 2)
1176 KSPSetConvergenceTest(
mKspSolver, KSPSkipConverged, PETSC_NULL);
1181 std::stringstream num_it_str;
1182 num_it_str << num_it;
1183 PetscOptionsSetValue(
"-ksp_max_it", num_it_str.str().c_str());
1252 std::stringstream num_it_str;
1254 PetscOptionsSetValue(
"-ksp_max_it", num_it_str.str().c_str());
void AssembleFinalLinearSystem()
Mat & rGetPrecondMatrix()
void FinalisePrecondMatrix()
unsigned mRowPreallocation
void AddToRhsVectorElement(PetscInt row, double value)
void GetOwnershipRange(PetscInt &lo, PetscInt &hi)
bool mUseAbsoluteTolerance
void * mpConvergenceTestContext
void SetKspType(const char *kspType)
void ZeroMatrixRowsWithValueOnDiagonal(std::vector< unsigned > &rRows, double diagonalValue)
unsigned mEvaluateNumItsEveryNSolves
#define EXCEPTION(message)
void SetRelativeTolerance(double relativeTolerance)
Vec Solve(Vec lhsGuess=NULL)
static void BeginEvent(unsigned event)
void SetMatrixElement(PetscInt row, PetscInt col, double value)
void AddToMatrixElement(PetscInt row, PetscInt col, double value)
Vec mDirichletBoundaryConditionsVector
Vec & rGetDirichletBoundaryConditionsVector()
PCTwoLevelsBlockDiagonal * mpTwoLevelsBlockDiagonalPC
#define TERMINATE(message)
void ZeroMatrixRowsAndColumnsWithValueOnDiagonal(std::vector< unsigned > &rRowColIndices, double diagonalValue)
double GetRhsVectorElement(PetscInt row)
boost::shared_ptr< std::vector< PetscInt > > mpBathNodes
double GetMatrixElement(PetscInt row, PetscInt col)
void ZeroMatrixColumn(PetscInt col)
void SetPrecondMatrixIsDifferentFromLhs(bool precondIsDifferent=true)
PetscInt mOwnershipRangeHi
static void Print(std::string message)
void SetMatrixIsSymmetric(bool isSymmetric=true)
LinearSystem(PetscInt lhsVectorSize, unsigned rowPreallocation=UINT_MAX)
PCBlockDiagonal * mpBlockDiagonalPC
void SetNullBasis(Vec nullbasis[], unsigned numberOfBases)
MatNullSpace mMatNullSpace
PCLDUFactorisation * mpLDUFactorisationPC
void SetPcType(const char *pcType, boost::shared_ptr< std::vector< PetscInt > > pBathNodes=boost::shared_ptr< std::vector< PetscInt > >())
void SetAbsoluteTolerance(double absoluteTolerance)
bool mForceSpectrumReevaluation
void SetRhsVectorElement(PetscInt row, double value)
void AssembleIntermediateLinearSystem()
#define CHASTE_CLASS_EXPORT(T)
void SwitchWriteModeLhsMatrix()
unsigned GetNumIterations() const
static void EndEvent(unsigned event)
PetscInt mOwnershipRangeLo
void SetUseFixedNumberIterations(bool useFixedNumberIterations=true, unsigned evaluateNumItsEveryNSolves=UINT_MAX)
bool mPrecondMatrixIsNotLhs
void SetMatrixRow(PetscInt row, double value)
Vec GetMatrixRowDistributed(unsigned rowIndex)
void SetMatrixIsConstant(bool matrixIsConstant)
bool mUseFixedNumberIterations