LinearSystem.cpp

00001 /*
00002 
00003 Copyright (C) University of Oxford, 2005-2009
00004 
00005 University of Oxford means the Chancellor, Masters and Scholars of the
00006 University of Oxford, having an administrative office at Wellington
00007 Square, Oxford OX1 2JD, UK.
00008 
00009 This file is part of Chaste.
00010 
00011 Chaste is free software: you can redistribute it and/or modify it
00012 under the terms of the GNU Lesser General Public License as published
00013 by the Free Software Foundation, either version 2.1 of the License, or
00014 (at your option) any later version.
00015 
00016 Chaste is distributed in the hope that it will be useful, but WITHOUT
00017 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
00019 License for more details. The offer of Chaste under the terms of the
00020 License is subject to the License being interpreted in accordance with
00021 English Law and subject to any action against the University of Oxford
00022 being under the jurisdiction of the English Courts.
00023 
00024 You should have received a copy of the GNU Lesser General Public License
00025 along with Chaste. If not, see <http://www.gnu.org/licenses/>.
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 
00037 
00039 // Implementation
00041 
00042 LinearSystem::LinearSystem(PetscInt lhsVectorSize, MatType matType)
00043    :mSize(lhsVectorSize),
00044     mMatNullSpace(NULL),
00045     mDestroyMatAndVec(true),
00046     mKspIsSetup(false),
00047     mNonZerosUsed(0.0),
00048     mMatrixIsConstant(false),
00049     mTolerance(1e-6),
00050     mUseAbsoluteTolerance(false),
00051     mDirichletBoundaryConditionsVector(NULL),
00052     mpBlockDiagonalPC(NULL)
00053 {
00054     SetupVectorAndMatrix(matType);
00055     
00058     mKspType = "gmres";
00059     mPcType = "jacobi";
00060     
00061 #ifdef TRACE_KSP
00062     mNumSolves = 0;
00063     mTotalNumIterations = 0;
00064     mMaxNumIterations = 0;
00065 #endif        
00066 }
00067 
00068 LinearSystem::LinearSystem(PetscInt lhsVectorSize, Mat lhsMatrix, Vec rhsVector, MatType matType)
00069    :mSize(lhsVectorSize),
00070     mMatNullSpace(NULL),
00071     mDestroyMatAndVec(true),
00072     mKspIsSetup(false),
00073     mNonZerosUsed(0.0),
00074     mMatrixIsConstant(false),
00075     mTolerance(1e-6),
00076     mUseAbsoluteTolerance(false),
00077     mDirichletBoundaryConditionsVector(NULL),
00078     mpBlockDiagonalPC(NULL)
00079 {
00080     // Conveniently, PETSc Mats and Vecs are actually pointers
00081     mLhsMatrix = lhsMatrix;
00082     mRhsVector = rhsVector;
00083     
00084     VecGetOwnershipRange(mRhsVector, &mOwnershipRangeLo, &mOwnershipRangeHi);
00085     
00086 #ifdef TRACE_KSP
00087     mNumSolves = 0;
00088     mTotalNumIterations = 0;
00089     mMaxNumIterations = 0;
00090 #endif        
00091 }
00092 
00093 LinearSystem::LinearSystem(Vec templateVector)
00094    :mMatNullSpace(NULL),
00095     mDestroyMatAndVec(true),
00096     mKspIsSetup(false),
00097     mMatrixIsConstant(false),
00098     mTolerance(1e-6),
00099     mUseAbsoluteTolerance(false),
00100     mDirichletBoundaryConditionsVector(NULL),
00101     mpBlockDiagonalPC(NULL)
00102 {
00103     VecDuplicate(templateVector, &mRhsVector);
00104     VecGetSize(mRhsVector, &mSize);
00105     VecGetOwnershipRange(mRhsVector, &mOwnershipRangeLo, &mOwnershipRangeHi);
00106     PetscInt local_size = mOwnershipRangeHi - mOwnershipRangeLo;
00107 
00108     PetscTools::SetupMat(mLhsMatrix, mSize, mSize, (MatType) MATMPIAIJ, local_size, local_size);
00109 
00112     mKspType = "gmres";
00113     mPcType = "jacobi";
00114 
00115 #ifdef TRACE_KSP
00116     mNumSolves = 0;
00117     mTotalNumIterations = 0;
00118     mMaxNumIterations = 0;
00119 #endif        
00120 }
00121 
00122 LinearSystem::LinearSystem(Vec residualVector, Mat jacobianMatrix)
00123     :mMatNullSpace(NULL),
00124     mDestroyMatAndVec(false),
00125     mKspIsSetup(false),
00126     mMatrixIsConstant(false),
00127     mTolerance(1e-6),
00128     mUseAbsoluteTolerance(false),
00129     mDirichletBoundaryConditionsVector(NULL),
00130     mpBlockDiagonalPC(NULL)
00131 {
00132     assert(residualVector || jacobianMatrix);
00133     mRhsVector = residualVector;
00134     mLhsMatrix = jacobianMatrix;
00135 
00136     PetscInt mat_size=0, vec_size=0;
00137     if (mRhsVector)
00138     {
00139         VecGetSize(mRhsVector, &vec_size);
00140         mSize = (unsigned)vec_size;
00141         VecGetOwnershipRange(mRhsVector, &mOwnershipRangeLo, &mOwnershipRangeHi);
00142     }
00143     if (mLhsMatrix)
00144     {
00145         PetscInt mat_cols;
00146         MatGetSize(mLhsMatrix, &mat_size, &mat_cols);
00147         assert(mat_size == mat_cols);
00148         mSize = (unsigned)mat_size;
00149         MatGetOwnershipRange(mLhsMatrix, &mOwnershipRangeLo, &mOwnershipRangeHi);
00150     }
00151     assert(!mRhsVector || !mLhsMatrix || vec_size == mat_size);
00152 
00155     mKspType = "gmres";
00156     mPcType = "jacobi";
00157 
00158 #ifdef TRACE_KSP
00159     mNumSolves = 0;
00160     mTotalNumIterations = 0;
00161     mMaxNumIterations = 0;
00162 #endif
00163 }
00164 
00165 LinearSystem::~LinearSystem()
00166 {
00167     if (mpBlockDiagonalPC)
00168     {
00169         delete mpBlockDiagonalPC;
00170     }
00171     
00172     if (mDestroyMatAndVec)
00173     {
00174         VecDestroy(mRhsVector);
00175         MatDestroy(mLhsMatrix);
00176     }
00177 
00178     if (mMatNullSpace)
00179     {
00180         MatNullSpaceDestroy(mMatNullSpace);
00181     }
00182 
00183     if (mKspIsSetup)
00184     {
00185         KSPDestroy(mKspSolver);
00186     }
00187 
00188     if (mDirichletBoundaryConditionsVector)
00189     {
00191         VecDestroy(mDirichletBoundaryConditionsVector);
00192     }
00193     
00194 #ifdef TRACE_KSP
00195     if (mNumSolves > 0)
00196     {
00197         double ave_num_iterations = mTotalNumIterations/(double)mNumSolves;
00198     
00199         std::cout << std::endl << "KSP iterations report:" << std::endl;
00200         std::cout << "mNumSolves" << "\t" << "mTotalNumIterations" << "\t" << "mMaxNumIterations" << "\t" << "mAveNumIterations" << std::endl;
00201         std::cout << mNumSolves << "\t" << mTotalNumIterations << "\t" << mMaxNumIterations << "\t" << ave_num_iterations << std::endl;
00202     }
00203 #endif    
00204     
00205 }
00206 
00207 void LinearSystem::SetupVectorAndMatrix(MatType matType)
00208 {
00209     VecCreate(PETSC_COMM_WORLD, &mRhsVector);
00210     VecSetSizes(mRhsVector, PETSC_DECIDE, mSize);
00211     VecSetFromOptions(mRhsVector);
00212 
00213     PetscTools::SetupMat(mLhsMatrix, mSize, mSize, matType);
00214 
00215     VecGetOwnershipRange(mRhsVector, &mOwnershipRangeLo, &mOwnershipRangeHi);
00216 }
00217 
00218 void LinearSystem::SetMatrixElement(PetscInt row, PetscInt col, double value)
00219 {
00220     if (row >= mOwnershipRangeLo && row < mOwnershipRangeHi)
00221     {
00222         MatSetValue(mLhsMatrix, row, col, value, INSERT_VALUES);
00223     }
00224 }
00225 
00226 void LinearSystem::AddToMatrixElement(PetscInt row, PetscInt col, double value)
00227 {
00228     if (row >= mOwnershipRangeLo && row < mOwnershipRangeHi)
00229     {
00230         MatSetValue(mLhsMatrix, row, col, value, ADD_VALUES);
00231     }
00232 }
00233 
00234 void LinearSystem::AssembleFinalLinearSystem()
00235 {
00236     AssembleFinalLhsMatrix();
00237     AssembleRhsVector();
00238 }
00239 
00240 void LinearSystem::AssembleIntermediateLinearSystem()
00241 {
00242     AssembleIntermediateLhsMatrix();
00243     AssembleRhsVector();
00244 }
00245 
00246 void LinearSystem::AssembleFinalLhsMatrix()
00247 {
00248     MatAssemblyBegin(mLhsMatrix, MAT_FINAL_ASSEMBLY);
00249     MatAssemblyEnd(mLhsMatrix, MAT_FINAL_ASSEMBLY);
00250 }
00251 
00252 void LinearSystem::AssembleIntermediateLhsMatrix()
00253 {
00254     MatAssemblyBegin(mLhsMatrix, MAT_FLUSH_ASSEMBLY);
00255     MatAssemblyEnd(mLhsMatrix, MAT_FLUSH_ASSEMBLY);
00256 }
00257 
00258 void LinearSystem::AssembleRhsVector()
00259 {
00260     VecAssemblyBegin(mRhsVector);
00261     VecAssemblyEnd(mRhsVector);
00262 }
00263 
00264 void LinearSystem::SetRhsVectorElement(PetscInt row, double value)
00265 {
00266     if (row >= mOwnershipRangeLo && row < mOwnershipRangeHi)
00267     {
00268         VecSetValues(mRhsVector, 1, &row, &value, INSERT_VALUES);
00269     }
00270 }
00271 
00272 void LinearSystem::AddToRhsVectorElement(PetscInt row, double value)
00273 {
00274     if (row >= mOwnershipRangeLo && row < mOwnershipRangeHi)
00275     {
00276         VecSetValues(mRhsVector, 1, &row, &value, ADD_VALUES);
00277     }
00278 }
00279 
00280 void LinearSystem::DisplayMatrix()
00281 {
00282     MatView(mLhsMatrix,PETSC_VIEWER_STDOUT_WORLD);
00283 }
00284 
00285 void LinearSystem::DisplayRhs()
00286 {
00287     VecView(mRhsVector,PETSC_VIEWER_STDOUT_WORLD);
00288 }
00289 
00290 void LinearSystem::SetMatrixRow(PetscInt row, double value)
00291 {
00292     if (row >= mOwnershipRangeLo && row < mOwnershipRangeHi)
00293     {
00294         PetscInt rows, cols;
00295         MatGetSize(mLhsMatrix, &rows, &cols);
00296         for (PetscInt i=0; i<cols; i++)
00297         {
00298             this->SetMatrixElement(row, i, value);
00299         }
00300     }
00301 }
00302 
00303 void LinearSystem::ZeroMatrixRow(PetscInt row)
00304 {
00305     MatAssemblyBegin(mLhsMatrix, MAT_FINAL_ASSEMBLY);
00306     MatAssemblyEnd(mLhsMatrix, MAT_FINAL_ASSEMBLY);
00307     double diag_zero=0.0;
00308     // MatZeroRows allows a non-zero value to be placed on the diagonal
00309     // diag_zero is the value to put in the diagonal
00310 
00311 #if (PETSC_VERSION_MINOR == 2) //Old API
00312     IS is;
00313     ISCreateGeneral(PETSC_COMM_WORLD,1,&row,&is);
00314     MatZeroRows(mLhsMatrix, is, &diag_zero);
00315     ISDestroy(is);
00316 #else
00317 
00318     MatZeroRows(mLhsMatrix, 1, &row, diag_zero);
00319 #endif
00320 
00321 }
00322 
00323 void LinearSystem::ZeroMatrixColumn(PetscInt col)
00324 {
00325     MatAssemblyBegin(mLhsMatrix, MAT_FINAL_ASSEMBLY);
00326     MatAssemblyEnd(mLhsMatrix, MAT_FINAL_ASSEMBLY);
00327 
00328 //#if (PETSC_VERSION_MINOR == 2) //Old API
00329    // hello Joe.
00330    // Hello
00331 //#else
00332     // determine which rows in this column are non-zero (and
00333     // therefore need to be zeroed)
00334     std::vector<unsigned> nonzero_rows;
00335     for (PetscInt row = mOwnershipRangeLo; row < mOwnershipRangeHi; row++)
00336     {
00337         if (GetMatrixElement(row, col) != 0.0)
00338         {
00339             nonzero_rows.push_back(row);
00340         }
00341     }
00342 
00343     // set those rows to be zero by calling MatSetValues
00344     unsigned size = nonzero_rows.size();
00345     PetscInt* rows = new PetscInt[size];
00346     PetscInt cols[1];
00347     double* zeros = new double[size];
00348 
00349     cols[0] = col;
00350 
00351     for (unsigned i=0; i<size; i++)
00352     {
00353         rows[i] = nonzero_rows[i];
00354         zeros[i] = 0.0;
00355     }
00356 
00357     MatSetValues(mLhsMatrix, size, rows, 1, cols, zeros, INSERT_VALUES);
00358     delete [] rows;
00359     delete [] zeros;
00360 //#endif
00361 }
00362 
00363 void LinearSystem::ZeroRhsVector()
00364 {
00365     double *p_rhs_vector_array;
00366     VecGetArray(mRhsVector, &p_rhs_vector_array);
00367     for (PetscInt local_index=0; local_index<mOwnershipRangeHi - mOwnershipRangeLo; local_index++)
00368     {
00369         p_rhs_vector_array[local_index]=0.0;
00370     }
00371     VecRestoreArray(mRhsVector, &p_rhs_vector_array);
00372 }
00373 
00374 void LinearSystem::ZeroLhsMatrix()
00375 {
00376     MatZeroEntries(mLhsMatrix);
00377 }
00378 
00379 void LinearSystem::ZeroLinearSystem()
00380 {
00381     ZeroRhsVector();
00382     ZeroLhsMatrix();
00383 }
00384 
00385 unsigned LinearSystem::GetSize() const
00386 {
00387     return (unsigned) mSize;
00388 }
00389 
00390 void LinearSystem::SetNullBasis(Vec nullBasis[], unsigned numberOfBases)
00391 {
00392     PETSCEXCEPT( MatNullSpaceCreate(PETSC_COMM_WORLD, PETSC_FALSE, numberOfBases, nullBasis, &mMatNullSpace) );
00393 }
00394 
00395 void LinearSystem::GetOwnershipRange(PetscInt& lo, PetscInt& hi)
00396 {
00397     lo = mOwnershipRangeLo;
00398     hi = mOwnershipRangeHi;
00399 }
00400 
00401 double LinearSystem::GetMatrixElement(PetscInt row, PetscInt col)
00402 {
00403     assert(mOwnershipRangeLo <= row && row < mOwnershipRangeHi);
00404     PetscInt row_as_array[1];
00405     row_as_array[0] = row;
00406     PetscInt col_as_array[1];
00407     col_as_array[0] = col;
00408 
00409     double ret_array[1];
00410 
00411     MatGetValues(mLhsMatrix, 1, row_as_array, 1, col_as_array, ret_array);
00412 
00413     return ret_array[0];
00414 }
00415 
00416 double LinearSystem::GetRhsVectorElement(PetscInt row)
00417 {
00418     assert(mOwnershipRangeLo <= row && row < mOwnershipRangeHi);
00419 
00420     double *p_rhs_vector;
00421     PetscInt local_index=row-mOwnershipRangeLo;
00422     VecGetArray(mRhsVector, &p_rhs_vector);
00423     double answer=p_rhs_vector[local_index];
00424     VecRestoreArray(mRhsVector, &p_rhs_vector);
00425 
00426     return answer;
00427 }
00428 
00429 unsigned LinearSystem::GetNumIterations() const
00430 {
00431     assert(this->mKspIsSetup);
00432     
00433     PetscInt num_its;
00434     KSPGetIterationNumber(this->mKspSolver, &num_its);
00435     
00436     return (unsigned) num_its;
00437 }
00438 
00439 
00440 Vec& LinearSystem::rGetRhsVector()
00441 {
00442     return mRhsVector;
00443 }
00444 
00445 Vec LinearSystem::GetRhsVector() const
00446 {
00447     return mRhsVector;
00448 }
00449 
00450 Mat& LinearSystem::rGetLhsMatrix()
00451 {
00452     return mLhsMatrix;
00453 }
00454 
00455 Mat LinearSystem::GetLhsMatrix() const
00456 {
00457     return mLhsMatrix;
00458 }
00459 
00460 Vec& LinearSystem::rGetDirichletBoundaryConditionsVector()
00461 {
00462     return mDirichletBoundaryConditionsVector;
00463 }
00464 
00465 void LinearSystem::SetMatrixIsSymmetric(bool isSymmetric)
00466 {
00467     if (isSymmetric)
00468     {
00469         MatSetOption(mLhsMatrix, MAT_SYMMETRIC);
00470         MatSetOption(mLhsMatrix, MAT_SYMMETRY_ETERNAL);
00471     }
00472     else
00473     {
00474         MatSetOption(mLhsMatrix, MAT_NOT_SYMMETRIC);
00475         MatSetOption(mLhsMatrix, MAT_NOT_STRUCTURALLY_SYMMETRIC);
00476         MatSetOption(mLhsMatrix, MAT_NOT_SYMMETRY_ETERNAL);
00477     }        
00478 }
00479 
00480 void LinearSystem::SetMatrixIsConstant(bool matrixIsConstant)
00481 {
00482     mMatrixIsConstant=matrixIsConstant;
00483 }
00484 
00485 void LinearSystem::SetRelativeTolerance(double relativeTolerance)
00486 {
00487     mTolerance=relativeTolerance;
00488     mUseAbsoluteTolerance=false;
00489     if (mKspIsSetup)
00490     {
00491         KSPSetTolerances(mKspSolver, mTolerance, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT);
00492     }
00493 }
00494 
00495 void LinearSystem::SetAbsoluteTolerance(double absoluteTolerance)
00496 {
00497     mTolerance=absoluteTolerance;
00498     mUseAbsoluteTolerance=true;
00499     if (mKspIsSetup)
00500     {
00501         KSPSetTolerances(mKspSolver, DBL_EPSILON, mTolerance, PETSC_DEFAULT, PETSC_DEFAULT);
00502     }
00503 }
00504 
00505 void LinearSystem::SetKspType(const char *kspType)
00506 {
00507     mKspType = kspType;
00508     if (mKspIsSetup)
00509     {
00510         KSPSetType(mKspSolver, kspType);
00511         KSPSetFromOptions(mKspSolver);
00512     }
00513 }
00514 
00515 void LinearSystem::SetPcType(const char *pcType)
00516 {
00517     mPcType=pcType;
00518     if (mKspIsSetup)
00519     {
00520         if (mPcType == "blockdiagonal")
00521         {
00522             if (mpBlockDiagonalPC)
00523             {
00524                 // If the preconditioner has been set to "blockdiagonal" before, we need to free the pointer.
00525                 delete mpBlockDiagonalPC;
00526             }
00527             mpBlockDiagonalPC = new PCBlockDiagonal(mKspSolver);
00528         }
00529         else
00530         {        
00531             PC prec;
00532             KSPGetPC(mKspSolver, &prec);
00533             PCSetType(prec, pcType);
00534         }
00535         KSPSetFromOptions(mKspSolver);
00536     }
00537 }
00538 
00539 Vec LinearSystem::Solve(Vec lhsGuess)
00540 {
00541     /* The following lines are very useful for debugging
00542      *    MatView(mLhsMatrix,    PETSC_VIEWER_STDOUT_WORLD);
00543      *    VecView(mRhsVector,    PETSC_VIEWER_STDOUT_WORLD);
00544      */
00545     //Double check that the non-zero pattern hasn't changed
00546     MatInfo mat_info;
00547     MatGetInfo(mLhsMatrix, MAT_GLOBAL_SUM, &mat_info);
00548 
00549     if (!mKspIsSetup)
00550     {
00551         HeartEventHandler::BeginEvent(HeartEventHandler::COMMUNICATION);
00552         mNonZerosUsed=mat_info.nz_used;
00553         //MatNorm(mLhsMatrix, NORM_FROBENIUS, &mMatrixNorm);
00554         PC prec; //Type of pre-conditioner
00555 
00556         KSPCreate(PETSC_COMM_WORLD, &mKspSolver);
00557         //See
00558         //http://www-unix.mcs.anl.gov/petsc/petsc-2/snapshots/petsc-current/docs/manualpages/KSP/KSPSetOperators.html
00559         //The preconditioner flag (last argument) in the following calls says
00560         //how to reuse the preconditioner on subsequent iterations
00561         if (mMatrixIsConstant)
00562         {
00563             KSPSetOperators(mKspSolver, mLhsMatrix, mLhsMatrix, SAME_PRECONDITIONER);
00564         }
00565         else
00566         {
00567             KSPSetOperators(mKspSolver, mLhsMatrix, mLhsMatrix, SAME_NONZERO_PATTERN);
00568         }
00569 
00570         // Set either absolute or relative tolerance of the KSP solver.
00571         // The default is to use relative tolerance (1e-6)
00572         if (mUseAbsoluteTolerance)
00573         {
00574             KSPSetTolerances(mKspSolver, DBL_EPSILON, mTolerance, PETSC_DEFAULT, PETSC_DEFAULT);
00575         }
00576         else
00577         {
00578             KSPSetTolerances(mKspSolver, mTolerance, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT);
00579         }
00580 
00581         // set ksp and pc types
00582         KSPSetType(mKspSolver, mKspType.c_str());
00583         KSPGetPC(mKspSolver, &prec);
00584 
00585 
00586         // Turn off pre-conditioning if the system size is very small
00587         if (mSize <= 4)
00588         {
00589             PCSetType(prec, PCNONE);
00590         }
00591         else
00592         {
00593             if (mPcType == "blockdiagonal")
00594             {
00595                 mpBlockDiagonalPC = new PCBlockDiagonal(mKspSolver);
00596             }
00597             else
00598             {            
00599                 PCSetType(prec, mPcType.c_str());
00600             }
00601         }
00602 
00603         if (mMatNullSpace)
00604         {
00606             PETSCEXCEPT( KSPSetNullSpace(mKspSolver, mMatNullSpace) );
00607         }
00608 
00609         if (lhsGuess)
00610         {
00611             //Assume that the user of this method will always be kind enough
00612             //to give us a reasonable guess.
00613             KSPSetInitialGuessNonzero(mKspSolver,PETSC_TRUE);
00614         }
00615 
00616         KSPSetFromOptions(mKspSolver);
00617         KSPSetUp(mKspSolver);
00618 
00619         mKspIsSetup = true;
00620                 
00621         HeartEventHandler::EndEvent(HeartEventHandler::COMMUNICATION);
00622     }
00623     else
00624     {
00625         #define COVERAGE_IGNORE
00626         if (mNonZerosUsed!=mat_info.nz_used)
00627         {
00628             EXCEPTION("LinearSystem doesn't allow the non-zero pattern of a matrix to change. (I think you changed it).");
00629         }
00630 //        PetscScalar norm;
00631 //        MatNorm(mLhsMatrix, NORM_FROBENIUS, &norm);
00632 //        if (fabs(norm - mMatrixNorm) > 0)
00633 //        {
00634 //            EXCEPTION("LinearSystem doesn't allow the matrix norm to change");
00635 //        }
00636         #undef COVERAGE_IGNORE
00637     }
00638 
00639     // Create solution vector
00641     HeartEventHandler::BeginEvent(HeartEventHandler::COMMUNICATION);
00642     Vec lhs_vector;
00643     VecDuplicate(mRhsVector, &lhs_vector);//Sets the same size (doesn't copy)
00644     if (lhsGuess)
00645     {
00646         VecCopy(lhsGuess, lhs_vector);
00647         //VecZeroEntries(lhs_vector);
00648     }
00649     HeartEventHandler::EndEvent(HeartEventHandler::COMMUNICATION);
00650 //    //Double check that the mRhsVector contains sensible values
00651 //    double *p_rhs, *p_guess;
00652 //    VecGetArray(mRhsVector, &p_rhs);
00653 //    VecGetArray(lhsGuess, &p_guess);
00654 //    for (int global_index=mOwnershipRangeLo; global_index<mOwnershipRangeHi; global_index++)
00655 //    {
00656 //        int local_index = global_index - mOwnershipRangeLo;
00657 //        assert(!std::isnan(p_rhs[local_index]));
00658 //        assert(!std::isnan(p_guess[local_index]));
00659 //        if (p_rhs[local_index] != p_rhs[local_index])
00660 //        {
00661 //            std::cout << "********* PETSc nan\n";
00662 //            assert(0);
00663 //        }
00664 //    }
00665 //    std::cout << "b[0] = " << p_rhs[0] << ", guess[0] = " << p_guess[0] << "\n";
00666 //    VecRestoreArray(mRhsVector, &p_rhs);
00667 //    VecRestoreArray(lhsGuess, &p_guess);
00668 //    // Test A*guess
00669 //    Vec temp;
00670 //    VecDuplicate(mRhsVector, &temp);
00671 //    MatMult(mLhsMatrix, lhs_vector, temp);
00672 //    double *p_temp;
00673 //    VecGetArray(temp, &p_temp);
00674 //    std::cout << "temp[0] = " << p_temp[0] << "\n";
00675 //    VecRestoreArray(temp, &p_temp);
00676 //    VecDestroy(temp);
00677 //    // Dump the matrix to file
00678 //    PetscViewer viewer;
00679 //    PetscViewerASCIIOpen(PETSC_COMM_WORLD,"mat.output",&viewer);
00680 //    MatView(mLhsMatrix, viewer);
00681 //    PetscViewerFlush(viewer);
00682 //    PetscViewerDestroy(viewer);
00683 //    // Dump the rhs vector to file
00684 //    PetscViewerASCIIOpen(PETSC_COMM_WORLD,"vec.output",&viewer);
00685 //    PetscViewerSetFormat(viewer, PETSC_VIEWER_ASCII_MATLAB);
00686 //    VecView(mRhsVector, viewer);
00687 //    PetscViewerFlush(viewer);
00688 //    PetscViewerDestroy(viewer);
00689 
00690     try
00691     {
00692         HeartEventHandler::BeginEvent(HeartEventHandler::SOLVE_LINEAR_SYSTEM);
00693         PETSCEXCEPT(KSPSolve(mKspSolver, mRhsVector, lhs_vector));
00694         HeartEventHandler::EndEvent(HeartEventHandler::SOLVE_LINEAR_SYSTEM);
00695 
00696         // Check that solver converged and throw if not
00697         KSPConvergedReason reason;
00698         KSPGetConvergedReason(mKspSolver, &reason);
00699         KSPEXCEPT(reason);
00700         
00701 #ifdef TRACE_KSP        
00702         PetscInt num_it;
00703         KSPGetIterationNumber(mKspSolver, &num_it);
00704         std::cout << "++ Solve: " << mNumSolves << " NumIterations: " << num_it << std::endl << std::flush;
00705 
00706         mNumSolves++;
00707         mTotalNumIterations += num_it;
00708         if ((unsigned) num_it > mMaxNumIterations)
00709         {
00710             mMaxNumIterations = num_it;
00711         } 
00712 #endif    
00713         
00714     }
00715     catch (const Exception& e)
00716     {
00717         // Destroy solution vector on error to avoid memory leaks
00718         VecDestroy(lhs_vector);
00719         throw e;
00720     }
00721 
00722     return lhs_vector;
00723 }

Generated on Tue Aug 4 16:10:22 2009 for Chaste by  doxygen 1.5.5