00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "LinearSystem.hpp"
00030 #include "PetscException.hpp"
00031 #include <iostream>
00032 #include "OutputFileHandler.hpp"
00033 #include "PetscTools.hpp"
00034 #include <cassert>
00035 #include "HeartEventHandler.hpp"
00036 #include "Timer.hpp"
00037
00038
00040
00042
00043 LinearSystem::LinearSystem(PetscInt lhsVectorSize, MatType matType)
00044 :mSize(lhsVectorSize),
00045 mMatNullSpace(NULL),
00046 mDestroyMatAndVec(true),
00047 mKspIsSetup(false),
00048 mNonZerosUsed(0.0),
00049 mMatrixIsConstant(false),
00050 mTolerance(1e-6),
00051 mUseAbsoluteTolerance(false),
00052 mDirichletBoundaryConditionsVector(NULL),
00053 mpBlockDiagonalPC(NULL),
00054 mpLDUFactorisationPC(NULL)
00055 {
00056 SetupVectorAndMatrix(matType);
00057
00060 mKspType = "gmres";
00061 mPcType = "jacobi";
00062
00063 #ifdef TRACE_KSP
00064 mNumSolves = 0;
00065 mTotalNumIterations = 0;
00066 mMaxNumIterations = 0;
00067 #endif
00068 }
00069
00070 LinearSystem::LinearSystem(PetscInt lhsVectorSize, Mat lhsMatrix, Vec rhsVector, MatType matType)
00071 :mSize(lhsVectorSize),
00072 mMatNullSpace(NULL),
00073 mDestroyMatAndVec(true),
00074 mKspIsSetup(false),
00075 mNonZerosUsed(0.0),
00076 mMatrixIsConstant(false),
00077 mTolerance(1e-6),
00078 mUseAbsoluteTolerance(false),
00079 mDirichletBoundaryConditionsVector(NULL),
00080 mpBlockDiagonalPC(NULL),
00081 mpLDUFactorisationPC(NULL)
00082 {
00083
00084 mLhsMatrix = lhsMatrix;
00085 mRhsVector = rhsVector;
00086
00087 VecGetOwnershipRange(mRhsVector, &mOwnershipRangeLo, &mOwnershipRangeHi);
00088
00089 #ifdef TRACE_KSP
00090 mNumSolves = 0;
00091 mTotalNumIterations = 0;
00092 mMaxNumIterations = 0;
00093 #endif
00094 }
00095
00096 LinearSystem::LinearSystem(Vec templateVector)
00097 :mMatNullSpace(NULL),
00098 mDestroyMatAndVec(true),
00099 mKspIsSetup(false),
00100 mMatrixIsConstant(false),
00101 mTolerance(1e-6),
00102 mUseAbsoluteTolerance(false),
00103 mDirichletBoundaryConditionsVector(NULL),
00104 mpBlockDiagonalPC(NULL),
00105 mpLDUFactorisationPC(NULL)
00106 {
00107 VecDuplicate(templateVector, &mRhsVector);
00108 VecGetSize(mRhsVector, &mSize);
00109 VecGetOwnershipRange(mRhsVector, &mOwnershipRangeLo, &mOwnershipRangeHi);
00110 PetscInt local_size = mOwnershipRangeHi - mOwnershipRangeLo;
00111
00112 PetscTools::SetupMat(mLhsMatrix, mSize, mSize, (MatType) MATMPIAIJ, local_size, local_size);
00113
00116 mKspType = "gmres";
00117 mPcType = "jacobi";
00118
00119 #ifdef TRACE_KSP
00120 mNumSolves = 0;
00121 mTotalNumIterations = 0;
00122 mMaxNumIterations = 0;
00123 #endif
00124 }
00125
00126 LinearSystem::LinearSystem(Vec residualVector, Mat jacobianMatrix)
00127 :mMatNullSpace(NULL),
00128 mDestroyMatAndVec(false),
00129 mKspIsSetup(false),
00130 mMatrixIsConstant(false),
00131 mTolerance(1e-6),
00132 mUseAbsoluteTolerance(false),
00133 mDirichletBoundaryConditionsVector(NULL),
00134 mpBlockDiagonalPC(NULL),
00135 mpLDUFactorisationPC(NULL)
00136 {
00137 assert(residualVector || jacobianMatrix);
00138 mRhsVector = residualVector;
00139 mLhsMatrix = jacobianMatrix;
00140
00141 PetscInt mat_size=0, vec_size=0;
00142 if (mRhsVector)
00143 {
00144 VecGetSize(mRhsVector, &vec_size);
00145 mSize = (unsigned)vec_size;
00146 VecGetOwnershipRange(mRhsVector, &mOwnershipRangeLo, &mOwnershipRangeHi);
00147 }
00148 if (mLhsMatrix)
00149 {
00150 PetscInt mat_cols;
00151 MatGetSize(mLhsMatrix, &mat_size, &mat_cols);
00152 assert(mat_size == mat_cols);
00153 mSize = (unsigned)mat_size;
00154 MatGetOwnershipRange(mLhsMatrix, &mOwnershipRangeLo, &mOwnershipRangeHi);
00155 }
00156 assert(!mRhsVector || !mLhsMatrix || vec_size == mat_size);
00157
00160 mKspType = "gmres";
00161 mPcType = "jacobi";
00162
00163 #ifdef TRACE_KSP
00164 mNumSolves = 0;
00165 mTotalNumIterations = 0;
00166 mMaxNumIterations = 0;
00167 #endif
00168 }
00169
00170 LinearSystem::~LinearSystem()
00171 {
00172 if (mpBlockDiagonalPC)
00173 {
00174 delete mpBlockDiagonalPC;
00175 }
00176
00177 if (mpLDUFactorisationPC)
00178 {
00179 delete mpLDUFactorisationPC;
00180 }
00181
00182 if (mDestroyMatAndVec)
00183 {
00184 VecDestroy(mRhsVector);
00185 MatDestroy(mLhsMatrix);
00186 }
00187
00188 if (mMatNullSpace)
00189 {
00190 MatNullSpaceDestroy(mMatNullSpace);
00191 }
00192
00193 if (mKspIsSetup)
00194 {
00195 KSPDestroy(mKspSolver);
00196 }
00197
00198 if (mDirichletBoundaryConditionsVector)
00199 {
00201 VecDestroy(mDirichletBoundaryConditionsVector);
00202 }
00203
00204 #ifdef TRACE_KSP
00205 if (mNumSolves > 0)
00206 {
00207 double ave_num_iterations = mTotalNumIterations/(double)mNumSolves;
00208
00209 std::cout << std::endl << "KSP iterations report:" << std::endl;
00210 std::cout << "mNumSolves" << "\t" << "mTotalNumIterations" << "\t" << "mMaxNumIterations" << "\t" << "mAveNumIterations" << std::endl;
00211 std::cout << mNumSolves << "\t" << mTotalNumIterations << "\t" << mMaxNumIterations << "\t" << ave_num_iterations << std::endl;
00212 }
00213 #endif
00214
00215 }
00216
00217 void LinearSystem::SetupVectorAndMatrix(MatType matType)
00218 {
00219 VecCreate(PETSC_COMM_WORLD, &mRhsVector);
00220 VecSetSizes(mRhsVector, PETSC_DECIDE, mSize);
00221 VecSetFromOptions(mRhsVector);
00222
00223 PetscTools::SetupMat(mLhsMatrix, mSize, mSize, matType);
00224
00225 VecGetOwnershipRange(mRhsVector, &mOwnershipRangeLo, &mOwnershipRangeHi);
00226 }
00227
00228 void LinearSystem::SetMatrixElement(PetscInt row, PetscInt col, double value)
00229 {
00230 if (row >= mOwnershipRangeLo && row < mOwnershipRangeHi)
00231 {
00232 MatSetValue(mLhsMatrix, row, col, value, INSERT_VALUES);
00233 }
00234 }
00235
00236 void LinearSystem::AddToMatrixElement(PetscInt row, PetscInt col, double value)
00237 {
00238 if (row >= mOwnershipRangeLo && row < mOwnershipRangeHi)
00239 {
00240 MatSetValue(mLhsMatrix, row, col, value, ADD_VALUES);
00241 }
00242 }
00243
00244 void LinearSystem::AssembleFinalLinearSystem()
00245 {
00246 AssembleFinalLhsMatrix();
00247 AssembleRhsVector();
00248 }
00249
00250 void LinearSystem::AssembleIntermediateLinearSystem()
00251 {
00252 AssembleIntermediateLhsMatrix();
00253 AssembleRhsVector();
00254 }
00255
00256 void LinearSystem::AssembleFinalLhsMatrix()
00257 {
00258 MatAssemblyBegin(mLhsMatrix, MAT_FINAL_ASSEMBLY);
00259 MatAssemblyEnd(mLhsMatrix, MAT_FINAL_ASSEMBLY);
00260 }
00261
00262 void LinearSystem::AssembleIntermediateLhsMatrix()
00263 {
00264 MatAssemblyBegin(mLhsMatrix, MAT_FLUSH_ASSEMBLY);
00265 MatAssemblyEnd(mLhsMatrix, MAT_FLUSH_ASSEMBLY);
00266 }
00267
00268 void LinearSystem::AssembleRhsVector()
00269 {
00270 VecAssemblyBegin(mRhsVector);
00271 VecAssemblyEnd(mRhsVector);
00272 }
00273
00274 void LinearSystem::SetRhsVectorElement(PetscInt row, double value)
00275 {
00276 if (row >= mOwnershipRangeLo && row < mOwnershipRangeHi)
00277 {
00278 VecSetValues(mRhsVector, 1, &row, &value, INSERT_VALUES);
00279 }
00280 }
00281
00282 void LinearSystem::AddToRhsVectorElement(PetscInt row, double value)
00283 {
00284 if (row >= mOwnershipRangeLo && row < mOwnershipRangeHi)
00285 {
00286 VecSetValues(mRhsVector, 1, &row, &value, ADD_VALUES);
00287 }
00288 }
00289
00290 void LinearSystem::DisplayMatrix()
00291 {
00292 MatView(mLhsMatrix,PETSC_VIEWER_STDOUT_WORLD);
00293 }
00294
00295 void LinearSystem::DisplayRhs()
00296 {
00297 VecView(mRhsVector,PETSC_VIEWER_STDOUT_WORLD);
00298 }
00299
00300 void LinearSystem::SetMatrixRow(PetscInt row, double value)
00301 {
00302 if (row >= mOwnershipRangeLo && row < mOwnershipRangeHi)
00303 {
00304 PetscInt rows, cols;
00305 MatGetSize(mLhsMatrix, &rows, &cols);
00306 for (PetscInt i=0; i<cols; i++)
00307 {
00308 this->SetMatrixElement(row, i, value);
00309 }
00310 }
00311 }
00312
00313 Vec LinearSystem::GetMatrixRowDistributed(unsigned row_index)
00314 {
00315 Vec lhs_ith_row;
00316 VecDuplicate(mRhsVector, &lhs_ith_row);
00317
00318 PetscInt num_entries;
00319 const PetscInt *column_indices;
00320 const PetscScalar *values;
00321
00322 bool am_row_owner = (PetscInt)row_index >= mOwnershipRangeLo && (PetscInt)row_index < mOwnershipRangeHi;
00323
00324
00325
00326 if (am_row_owner)
00327 {
00328 MatGetRow(mLhsMatrix, row_index, &num_entries, &column_indices, &values);
00329 VecSetValues(lhs_ith_row, num_entries, column_indices, values, INSERT_VALUES);
00330 }
00331
00332 VecAssemblyBegin(lhs_ith_row);
00333 VecAssemblyEnd(lhs_ith_row);
00334
00335 if (am_row_owner)
00336 {
00337 MatRestoreRow(mLhsMatrix, row_index, &num_entries, &column_indices, &values);
00338 }
00339
00340 return lhs_ith_row;
00341 }
00342
00343 void LinearSystem::ZeroMatrixRowsWithValueOnDiagonal(std::vector<unsigned>& rRows, double diagonalValue)
00344 {
00345 MatAssemblyBegin(mLhsMatrix, MAT_FINAL_ASSEMBLY);
00346 MatAssemblyEnd(mLhsMatrix, MAT_FINAL_ASSEMBLY);
00347
00348
00349
00350
00351
00352 #if PETSC_VERSION_MAJOR == 3
00353 MatSetOption(mLhsMatrix, MAT_KEEP_ZEROED_ROWS, PETSC_TRUE);
00354 #else
00355 MatSetOption(mLhsMatrix, MAT_KEEP_ZEROED_ROWS);
00356 #endif
00357
00358 PetscInt* rows = new PetscInt[rRows.size()];
00359 for(unsigned i=0; i<rRows.size(); i++)
00360 {
00361 rows[i] = rRows[i];
00362 }
00363 #if (PETSC_VERSION_MAJOR == 2 && PETSC_VERSION_MINOR == 2) //PETSc 2.2
00364 IS is;
00365 ISCreateGeneral(PETSC_COMM_WORLD, rRows.size(), rows, &is);
00366 MatZeroRows(mLhsMatrix, is, &diagonalValue);
00367 ISDestroy(is);
00368 #else
00369 MatZeroRows(mLhsMatrix, rRows.size(), rows, diagonalValue);
00370 #endif
00371 delete [] rows;
00372 }
00373
00374
00375 void LinearSystem::ZeroMatrixRowsAndColumnsWithValueOnDiagonal(std::vector<unsigned>& rRowColIndices, double diagonalValue)
00376 {
00377 MatAssemblyBegin(mLhsMatrix, MAT_FINAL_ASSEMBLY);
00378 MatAssemblyEnd(mLhsMatrix, MAT_FINAL_ASSEMBLY);
00379
00380 std::vector<unsigned> nonzero_rows_per_column[rRowColIndices.size()];
00381
00382
00383
00384
00385
00386 for(unsigned index=0; index<rRowColIndices.size(); index++)
00387 {
00388 unsigned column = rRowColIndices[index];
00389
00390
00391
00392 for (PetscInt row = mOwnershipRangeLo; row < mOwnershipRangeHi; row++)
00393 {
00394 if (GetMatrixElement(row, column) != 0.0)
00395 {
00396 nonzero_rows_per_column[index].push_back(row);
00397 }
00398 }
00399 }
00400
00401
00402 for(unsigned index=0; index<rRowColIndices.size(); index++)
00403 {
00404
00405 unsigned size = nonzero_rows_per_column[index].size();
00406 PetscInt* rows = new PetscInt[size];
00407 PetscInt cols[1];
00408 double* zeros = new double[size];
00409
00410 cols[0] = rRowColIndices[index];
00411
00412 for (unsigned i=0; i<size; i++)
00413 {
00414 rows[i] = nonzero_rows_per_column[index][i];
00415 zeros[i] = 0.0;
00416 }
00417
00418 MatSetValues(mLhsMatrix, size, rows, 1, cols, zeros, INSERT_VALUES);
00419 delete [] rows;
00420 delete [] zeros;
00421 }
00422
00423
00424 ZeroMatrixRowsWithValueOnDiagonal(rRowColIndices, diagonalValue);
00425 }
00426
00427
00428
00429
00430 void LinearSystem::ZeroMatrixColumn(PetscInt col)
00431 {
00432 MatAssemblyBegin(mLhsMatrix, MAT_FINAL_ASSEMBLY);
00433 MatAssemblyEnd(mLhsMatrix, MAT_FINAL_ASSEMBLY);
00434
00435
00436
00437 std::vector<unsigned> nonzero_rows;
00438 for (PetscInt row = mOwnershipRangeLo; row < mOwnershipRangeHi; row++)
00439 {
00440 if (GetMatrixElement(row, col) != 0.0)
00441 {
00442 nonzero_rows.push_back(row);
00443 }
00444 }
00445
00446
00447 unsigned size = nonzero_rows.size();
00448 PetscInt* rows = new PetscInt[size];
00449 PetscInt cols[1];
00450 double* zeros = new double[size];
00451
00452 cols[0] = col;
00453
00454 for (unsigned i=0; i<size; i++)
00455 {
00456 rows[i] = nonzero_rows[i];
00457 zeros[i] = 0.0;
00458 }
00459
00460 MatSetValues(mLhsMatrix, size, rows, 1, cols, zeros, INSERT_VALUES);
00461 delete [] rows;
00462 delete [] zeros;
00463 }
00464
00465 void LinearSystem::ZeroRhsVector()
00466 {
00467 double* p_rhs_vector_array;
00468 VecGetArray(mRhsVector, &p_rhs_vector_array);
00469 for (PetscInt local_index=0; local_index<mOwnershipRangeHi - mOwnershipRangeLo; local_index++)
00470 {
00471 p_rhs_vector_array[local_index]=0.0;
00472 }
00473 VecRestoreArray(mRhsVector, &p_rhs_vector_array);
00474 }
00475
00476 void LinearSystem::ZeroLhsMatrix()
00477 {
00478 MatZeroEntries(mLhsMatrix);
00479 }
00480
00481 void LinearSystem::ZeroLinearSystem()
00482 {
00483 ZeroRhsVector();
00484 ZeroLhsMatrix();
00485 }
00486
00487 unsigned LinearSystem::GetSize() const
00488 {
00489 return (unsigned) mSize;
00490 }
00491
00492 void LinearSystem::SetNullBasis(Vec nullBasis[], unsigned numberOfBases)
00493 {
00494 #ifndef NDEBUG
00495
00496 for (unsigned vec_index=0; vec_index<numberOfBases; vec_index++)
00497 {
00498 PetscReal l2_norm;
00499 VecNorm(nullBasis[vec_index], NORM_2, &l2_norm);
00500 if (fabs(l2_norm-1.0) > 1e-08)
00501 {
00502 EXCEPTION("One of the vectors in the null space is not normalised");
00503 }
00504 }
00505
00506
00507 for (unsigned vec_index=1; vec_index<numberOfBases; vec_index++)
00508 {
00509
00510 unsigned num_vectors_ahead = numberOfBases-vec_index;
00511 PetscScalar dot_products[num_vectors_ahead];
00512 #if (PETSC_VERSION_MAJOR == 2 && PETSC_VERSION_MINOR == 2) //PETSc 2.2
00513 VecMDot(num_vectors_ahead, nullBasis[vec_index-1], &nullBasis[vec_index], dot_products);
00514 #else
00515 VecMDot(nullBasis[vec_index-1], num_vectors_ahead, &nullBasis[vec_index], dot_products);
00516 #endif
00517 for (unsigned index=0; index<num_vectors_ahead; index++)
00518 {
00519 if (fabs(dot_products[index]) > 1e-08 )
00520 {
00521 EXCEPTION("The null space is not orthogonal.");
00522 }
00523 }
00524
00525 }
00526
00527 #endif
00528
00529 PETSCEXCEPT( MatNullSpaceCreate(PETSC_COMM_WORLD, PETSC_FALSE, numberOfBases, nullBasis, &mMatNullSpace) );
00530 }
00531
00532 void LinearSystem::RemoveNullSpace()
00533 {
00534
00535 if (mMatNullSpace)
00536 {
00537 PETSCEXCEPT( MatNullSpaceDestroy(mMatNullSpace) );
00538 PETSCEXCEPT( MatNullSpaceCreate(PETSC_COMM_WORLD, PETSC_FALSE, 0, NULL, &mMatNullSpace) );
00539 if (mKspIsSetup)
00540 {
00541 PETSCEXCEPT( KSPSetNullSpace(mKspSolver, mMatNullSpace) );
00542 }
00543
00544 }
00545 }
00546
00547
00548 void LinearSystem::GetOwnershipRange(PetscInt& lo, PetscInt& hi)
00549 {
00550 lo = mOwnershipRangeLo;
00551 hi = mOwnershipRangeHi;
00552 }
00553
00554 double LinearSystem::GetMatrixElement(PetscInt row, PetscInt col)
00555 {
00556 assert(mOwnershipRangeLo <= row && row < mOwnershipRangeHi);
00557 PetscInt row_as_array[1];
00558 row_as_array[0] = row;
00559 PetscInt col_as_array[1];
00560 col_as_array[0] = col;
00561
00562 double ret_array[1];
00563
00564 MatGetValues(mLhsMatrix, 1, row_as_array, 1, col_as_array, ret_array);
00565
00566 return ret_array[0];
00567 }
00568
00569 double LinearSystem::GetRhsVectorElement(PetscInt row)
00570 {
00571 assert(mOwnershipRangeLo <= row && row < mOwnershipRangeHi);
00572
00573 double* p_rhs_vector;
00574 PetscInt local_index=row-mOwnershipRangeLo;
00575 VecGetArray(mRhsVector, &p_rhs_vector);
00576 double answer=p_rhs_vector[local_index];
00577 VecRestoreArray(mRhsVector, &p_rhs_vector);
00578
00579 return answer;
00580 }
00581
00582 unsigned LinearSystem::GetNumIterations() const
00583 {
00584 assert(this->mKspIsSetup);
00585
00586 PetscInt num_its;
00587 KSPGetIterationNumber(this->mKspSolver, &num_its);
00588
00589 return (unsigned) num_its;
00590 }
00591
00592
00593 Vec& LinearSystem::rGetRhsVector()
00594 {
00595 return mRhsVector;
00596 }
00597
00598 Vec LinearSystem::GetRhsVector() const
00599 {
00600 return mRhsVector;
00601 }
00602
00603 Mat& LinearSystem::rGetLhsMatrix()
00604 {
00605 return mLhsMatrix;
00606 }
00607
00608 Mat LinearSystem::GetLhsMatrix() const
00609 {
00610 return mLhsMatrix;
00611 }
00612
00613 Vec& LinearSystem::rGetDirichletBoundaryConditionsVector()
00614 {
00615 return mDirichletBoundaryConditionsVector;
00616 }
00617
00618 void LinearSystem::SetMatrixIsSymmetric(bool isSymmetric)
00619 {
00621
00622 if (isSymmetric)
00623 {
00624 #if (PETSC_VERSION_MAJOR == 3) //PETSc 3.x.x
00625 MatSetOption(mLhsMatrix, MAT_SYMMETRIC, PETSC_TRUE);
00626 MatSetOption(mLhsMatrix, MAT_SYMMETRY_ETERNAL, PETSC_TRUE);
00627 #else
00628 MatSetOption(mLhsMatrix, MAT_SYMMETRIC);
00629 MatSetOption(mLhsMatrix, MAT_SYMMETRY_ETERNAL);
00630 #endif
00631 }
00632 else
00633 {
00634 #if (PETSC_VERSION_MAJOR == 3) //PETSc 3.x.x
00635 MatSetOption(mLhsMatrix, MAT_SYMMETRIC, PETSC_FALSE);
00636 MatSetOption(mLhsMatrix, MAT_STRUCTURALLY_SYMMETRIC, PETSC_FALSE);
00637 MatSetOption(mLhsMatrix, MAT_SYMMETRY_ETERNAL, PETSC_FALSE);
00638 #else
00639 MatSetOption(mLhsMatrix, MAT_NOT_SYMMETRIC);
00640 MatSetOption(mLhsMatrix, MAT_NOT_STRUCTURALLY_SYMMETRIC);
00641 MatSetOption(mLhsMatrix, MAT_NOT_SYMMETRY_ETERNAL);
00642 #endif
00643 }
00644 }
00645
00646 bool LinearSystem::IsMatrixSymmetric()
00647 {
00648 PetscTruth symmetry_flag_is_set;
00649 PetscTruth symmetry_flag;
00650
00651 MatIsSymmetricKnown(mLhsMatrix, &symmetry_flag_is_set, &symmetry_flag);
00652
00653
00654 return symmetry_flag_is_set && symmetry_flag;
00655 }
00656
00657 void LinearSystem::SetMatrixIsConstant(bool matrixIsConstant)
00658 {
00659 mMatrixIsConstant=matrixIsConstant;
00660 }
00661
00662 void LinearSystem::SetRelativeTolerance(double relativeTolerance)
00663 {
00664 mTolerance=relativeTolerance;
00665 mUseAbsoluteTolerance=false;
00666 if (mKspIsSetup)
00667 {
00668 KSPSetTolerances(mKspSolver, mTolerance, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT);
00669 }
00670 }
00671
00672 void LinearSystem::SetAbsoluteTolerance(double absoluteTolerance)
00673 {
00674 mTolerance=absoluteTolerance;
00675 mUseAbsoluteTolerance=true;
00676 if (mKspIsSetup)
00677 {
00678 KSPSetTolerances(mKspSolver, DBL_EPSILON, mTolerance, PETSC_DEFAULT, PETSC_DEFAULT);
00679 }
00680 }
00681
00682 void LinearSystem::SetKspType(const char *kspType)
00683 {
00684 mKspType = kspType;
00685 if (mKspIsSetup)
00686 {
00687 KSPSetType(mKspSolver, kspType);
00688 KSPSetFromOptions(mKspSolver);
00689 }
00690 }
00691
00692 void LinearSystem::SetPcType(const char* pcType)
00693 {
00694 mPcType=pcType;
00695 if (mKspIsSetup)
00696 {
00697 if (mPcType == "blockdiagonal")
00698 {
00699 if (mpBlockDiagonalPC)
00700 {
00701
00702 delete mpBlockDiagonalPC;
00703 }
00704 mpBlockDiagonalPC = new PCBlockDiagonal(mKspSolver);
00705 }
00706 else if (mPcType == "ldufactorisation")
00707 {
00708 if (mpLDUFactorisationPC)
00709 {
00710
00711 delete mpLDUFactorisationPC;
00712 }
00713 mpLDUFactorisationPC = new PCLDUFactorisation(mKspSolver);
00714 }
00715 else
00716 {
00717 PC prec;
00718 KSPGetPC(mKspSolver, &prec);
00719 PCSetType(prec, pcType);
00720 }
00721 KSPSetFromOptions(mKspSolver);
00722 }
00723 }
00724
00725 Vec LinearSystem::Solve(Vec lhsGuess)
00726 {
00727
00728
00729
00730
00731
00732 MatInfo mat_info;
00733 MatGetInfo(mLhsMatrix, MAT_GLOBAL_SUM, &mat_info);
00734
00735 if (!mKspIsSetup)
00736 {
00737 HeartEventHandler::BeginEvent(HeartEventHandler::COMMUNICATION);
00738 mNonZerosUsed=mat_info.nz_used;
00739
00740 PC prec;
00741
00742 KSPCreate(PETSC_COMM_WORLD, &mKspSolver);
00743
00744
00745
00746
00747 if (mMatrixIsConstant)
00748 {
00749 KSPSetOperators(mKspSolver, mLhsMatrix, mLhsMatrix, SAME_PRECONDITIONER);
00750 }
00751 else
00752 {
00753 KSPSetOperators(mKspSolver, mLhsMatrix, mLhsMatrix, SAME_NONZERO_PATTERN);
00754 }
00755
00756
00757
00758 if (mUseAbsoluteTolerance)
00759 {
00760 KSPSetTolerances(mKspSolver, DBL_EPSILON, mTolerance, PETSC_DEFAULT, PETSC_DEFAULT);
00761 }
00762 else
00763 {
00764 KSPSetTolerances(mKspSolver, mTolerance, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT);
00765 }
00766
00767
00768 KSPSetType(mKspSolver, mKspType.c_str());
00769 KSPGetPC(mKspSolver, &prec);
00770
00771
00772
00773 if (mSize <= 4)
00774 {
00775 PCSetType(prec, PCNONE);
00776 }
00777 else
00778 {
00779 #ifdef TRACE_KSP
00780 Timer::Reset();
00781 #endif
00782 if (mPcType == "blockdiagonal")
00783 {
00784 mpBlockDiagonalPC = new PCBlockDiagonal(mKspSolver);
00785 #ifdef TRACE_KSP
00786 Timer::Print("Purpose-build preconditioner creation");
00787 #endif
00788
00789 }
00790 else if (mPcType == "ldufactorisation")
00791 {
00792 mpLDUFactorisationPC = new PCLDUFactorisation(mKspSolver);
00793 #ifdef TRACE_KSP
00794 Timer::Print("Purpose-build preconditioner creation");
00795 #endif
00796 }
00797 else
00798 {
00799 PCSetType(prec, mPcType.c_str());
00800 }
00801 }
00802
00803 if (mMatNullSpace)
00804 {
00806 PETSCEXCEPT( KSPSetNullSpace(mKspSolver, mMatNullSpace) );
00807 }
00808
00809 if (lhsGuess)
00810 {
00811
00812
00813 KSPSetInitialGuessNonzero(mKspSolver,PETSC_TRUE);
00814 }
00815
00816 KSPSetFromOptions(mKspSolver);
00817
00818 #ifdef TRACE_KSP
00819 Timer::Reset();
00820 #endif
00821 KSPSetUp(mKspSolver);
00822 #ifdef TRACE_KSP
00823 Timer::Print("KSPSetUP (contains preconditioner creation for PETSc preconditioners)");
00824 #endif
00825
00826 mKspIsSetup = true;
00827
00828 HeartEventHandler::EndEvent(HeartEventHandler::COMMUNICATION);
00829 }
00830 else
00831 {
00832 #define COVERAGE_IGNORE
00833 if (mNonZerosUsed!=mat_info.nz_used)
00834 {
00835 EXCEPTION("LinearSystem doesn't allow the non-zero pattern of a matrix to change. (I think you changed it).");
00836 }
00837
00838
00839
00840
00841
00842
00843 #undef COVERAGE_IGNORE
00844 }
00845
00846
00848 HeartEventHandler::BeginEvent(HeartEventHandler::COMMUNICATION);
00849 Vec lhs_vector;
00850 VecDuplicate(mRhsVector, &lhs_vector);
00851 if (lhsGuess)
00852 {
00853 VecCopy(lhsGuess, lhs_vector);
00854 }
00855 HeartEventHandler::EndEvent(HeartEventHandler::COMMUNICATION);
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896 try
00897 {
00898 HeartEventHandler::BeginEvent(HeartEventHandler::SOLVE_LINEAR_SYSTEM);
00899
00900 #ifdef TRACE_KSP
00901 Timer::Reset();
00902 #endif
00903
00904 PETSCEXCEPT(KSPSolve(mKspSolver, mRhsVector, lhs_vector));
00905 HeartEventHandler::EndEvent(HeartEventHandler::SOLVE_LINEAR_SYSTEM);
00906
00907 #ifdef TRACE_KSP
00908 PetscInt num_it;
00909 KSPGetIterationNumber(mKspSolver, &num_it);
00910 std::cout << "++ Solve: " << mNumSolves << " NumIterations: " << num_it << " ";
00911 Timer::Print("Solve");
00912
00913 mNumSolves++;
00914 mTotalNumIterations += num_it;
00915 if ((unsigned) num_it > mMaxNumIterations)
00916 {
00917 mMaxNumIterations = num_it;
00918 }
00919 #endif
00920
00921
00922
00923 KSPConvergedReason reason;
00924 KSPGetConvergedReason(mKspSolver, &reason);
00925 KSPEXCEPT(reason);
00926
00927
00928 }
00929 catch (const Exception& e)
00930 {
00931
00932 VecDestroy(lhs_vector);
00933 throw e;
00934 }
00935
00936 return lhs_vector;
00937 }
00938
00939
00940
00941 #include "SerializationExportWrapperForCpp.hpp"
00942 CHASTE_CLASS_EXPORT(LinearSystem);