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
00030 #ifndef _LINEARSYSTEM_HPP_
00031 #define _LINEARSYSTEM_HPP_
00032
00033 #include "ChasteSerialization.hpp"
00034 #include "UblasCustomFunctions.hpp"
00035
00036 #include "PetscTools.hpp"
00037 #include "OutputFileHandler.hpp"
00038 #include "PCBlockDiagonal.hpp"
00039 #include "PCLDUFactorisation.hpp"
00040 #include "PCTwoLevelsBlockDiagonal.hpp"
00041 #include "ArchiveLocationInfo.hpp"
00042 #include <boost/serialization/shared_ptr.hpp>
00043
00044 #include <petscvec.h>
00045 #include <petscmat.h>
00046 #include <petscksp.h>
00047 #include <petscviewer.h>
00048
00049 #include <string>
00050 #include <cassert>
00051
00057 class LinearSystem
00058 {
00059 friend class TestLinearSystem;
00060 friend class TestPCBlockDiagonal;
00061 friend class TestPCTwoLevelsBlockDiagonal;
00062 friend class TestPCLDUFactorisation;
00063
00064 private:
00065
00066 Mat mLhsMatrix;
00067 Vec mRhsVector;
00068 PetscInt mSize;
00074 PetscInt mOwnershipRangeLo;
00075 PetscInt mOwnershipRangeHi;
00077 MatNullSpace mMatNullSpace;
00080 bool mDestroyMatAndVec;
00081
00082 KSP mKspSolver;
00083 bool mKspIsSetup;
00084 double mNonZerosUsed;
00085 bool mMatrixIsConstant;
00086 double mTolerance;
00091 bool mUseAbsoluteTolerance;
00092 std::string mKspType;
00093 std::string mPcType;
00095 Vec mDirichletBoundaryConditionsVector;
00097
00098
00099 PCBlockDiagonal* mpBlockDiagonalPC;
00101 PCLDUFactorisation* mpLDUFactorisationPC;
00103 PCTwoLevelsBlockDiagonal* mpTwoLevelsBlockDiagonalPC;
00104
00106 boost::shared_ptr<std::vector<PetscInt> > mpBathNodes;
00107
00108
00109 #ifdef TRACE_KSP
00110 unsigned mNumSolves;
00111 unsigned mTotalNumIterations;
00112 unsigned mMaxNumIterations;
00113 #endif
00114
00115 friend class boost::serialization::access;
00122 template<class Archive>
00123 void serialize(Archive & archive, const unsigned int version)
00124 {
00125
00126
00127 archive & mNonZerosUsed;
00128 archive & mMatrixIsConstant;
00129 archive & mTolerance;
00130 archive & mUseAbsoluteTolerance;
00131 archive & mKspType;
00132 archive & mPcType;
00133
00134
00135 }
00136
00137 public:
00138
00149 LinearSystem(PetscInt lhsVectorSize, unsigned rowPreallocation=UINT_MAX);
00150
00164 LinearSystem(Vec templateVector, unsigned rowPreallocation);
00165
00178 LinearSystem(Vec residualVector, Mat jacobianMatrix);
00179
00187 LinearSystem(PetscInt lhsVectorSize, Mat lhsMatrix, Vec rhsVector);
00188
00192 ~LinearSystem();
00193
00194
00195
00196
00197
00205 void SetMatrixElement(PetscInt row, PetscInt col, double value);
00206
00214 void AddToMatrixElement(PetscInt row, PetscInt col, double value);
00215
00221 void AssembleFinalLinearSystem();
00222
00228 void AssembleIntermediateLinearSystem();
00229
00233 void AssembleFinalLhsMatrix();
00234
00238 void AssembleIntermediateLhsMatrix();
00239
00243 void AssembleRhsVector();
00244
00250 void SetMatrixIsSymmetric(bool isSymmetric=true);
00251
00257 bool IsMatrixSymmetric();
00258
00264 void SetMatrixIsConstant(bool matrixIsConstant);
00265
00271 void SetRelativeTolerance(double relativeTolerance);
00272
00278 void SetAbsoluteTolerance(double absoluteTolerance);
00279
00285 void SetKspType(const char* kspType);
00286
00293
00294 void SetPcType(const char* pcType, boost::shared_ptr<std::vector<PetscInt> > pBathNodes=boost::shared_ptr<std::vector<PetscInt> >() );
00295
00299 void DisplayMatrix();
00300
00304 void DisplayRhs();
00305
00314 void SetMatrixRow(PetscInt row, double value);
00315
00322 Vec GetMatrixRowDistributed(unsigned row_index);
00323
00332 void ZeroMatrixRowsWithValueOnDiagonal(std::vector<unsigned>& rRows, double diagonalValue);
00333
00334
00341 void ZeroMatrixRowsAndColumnsWithValueOnDiagonal(std::vector<unsigned>& rRowColIndices, double diagonalValue);
00342
00343
00353 void ZeroMatrixColumn(PetscInt col);
00354
00358 void ZeroLhsMatrix();
00359
00363 void ZeroRhsVector();
00364
00368 void ZeroLinearSystem();
00369
00375 Vec Solve(Vec lhsGuess=NULL);
00376
00383 void SetRhsVectorElement(PetscInt row, double value);
00384
00391 void AddToRhsVectorElement(PetscInt row, double value);
00392
00396 unsigned GetSize() const;
00397
00410 void SetNullBasis(Vec nullbasis[], unsigned numberOfBases);
00411
00418 void RemoveNullSpace();
00419
00423 Vec& rGetRhsVector();
00424
00428 Vec GetRhsVector() const;
00429
00433 Mat& rGetLhsMatrix();
00434
00438 Mat GetLhsMatrix() const;
00439
00445 Vec& rGetDirichletBoundaryConditionsVector();
00446
00447
00454 void GetOwnershipRange(PetscInt& lo, PetscInt& hi);
00455
00463 double GetMatrixElement(PetscInt row, PetscInt col);
00464
00471 double GetRhsVectorElement(PetscInt row);
00472
00476 unsigned GetNumIterations() const;
00477
00487 template<size_t MATRIX_SIZE>
00488 void AddLhsMultipleValues(unsigned* matrixRowAndColIndices, c_matrix<double, MATRIX_SIZE, MATRIX_SIZE>& rSmallMatrix)
00489 {
00490 PetscInt matrix_row_indices[MATRIX_SIZE];
00491 PetscInt num_rows_owned = 0;
00492 PetscInt global_row;
00493
00494 for (unsigned row = 0; row<MATRIX_SIZE; row++)
00495 {
00496 global_row = matrixRowAndColIndices[row];
00497 if (global_row >=mOwnershipRangeLo && global_row <mOwnershipRangeHi)
00498 {
00499 matrix_row_indices[num_rows_owned++] = global_row;
00500 }
00501 }
00502
00503 if ( num_rows_owned == MATRIX_SIZE)
00504 {
00505 MatSetValues(mLhsMatrix,
00506 num_rows_owned,
00507 matrix_row_indices,
00508 MATRIX_SIZE,
00509 (PetscInt*) matrixRowAndColIndices,
00510 rSmallMatrix.data(),
00511 ADD_VALUES);
00512 }
00513 else
00514 {
00515
00516
00517 double values[MATRIX_SIZE*MATRIX_SIZE];
00518 unsigned num_values_owned = 0;
00519 for (unsigned row = 0; row<MATRIX_SIZE; row++)
00520 {
00521 global_row = matrixRowAndColIndices[row];
00522 if (global_row >=mOwnershipRangeLo && global_row <mOwnershipRangeHi)
00523 {
00524 for (unsigned col=0; col<MATRIX_SIZE; col++)
00525 {
00526 values[num_values_owned++] = rSmallMatrix(row, col);
00527 }
00528 }
00529 }
00530
00531 MatSetValues(mLhsMatrix,
00532 num_rows_owned,
00533 matrix_row_indices,
00534 MATRIX_SIZE,
00535 (PetscInt*) matrixRowAndColIndices,
00536 values,
00537 ADD_VALUES);
00538 }
00539 }
00540
00550 template<size_t VECTOR_SIZE>
00551 void AddRhsMultipleValues(unsigned* vectorIndices, c_vector<double, VECTOR_SIZE>& smallVector)
00552 {
00553 PetscInt indices_owned[VECTOR_SIZE];
00554 PetscInt num_indices_owned = 0;
00555 PetscInt global_row;
00556
00557 for (unsigned row = 0; row<VECTOR_SIZE; row++)
00558 {
00559 global_row = vectorIndices[row];
00560 if (global_row >=mOwnershipRangeLo && global_row <mOwnershipRangeHi)
00561 {
00562 indices_owned[num_indices_owned++] = global_row;
00563 }
00564 }
00565
00566 if (num_indices_owned == VECTOR_SIZE)
00567 {
00568 VecSetValues(mRhsVector,
00569 num_indices_owned,
00570 indices_owned,
00571 smallVector.data(),
00572 ADD_VALUES);
00573 }
00574 else
00575 {
00576
00577
00578 double values[VECTOR_SIZE];
00579 unsigned num_values_owned = 0;
00580
00581 for (unsigned row = 0; row<VECTOR_SIZE; row++)
00582 {
00583 global_row = vectorIndices[row];
00584 if (global_row >=mOwnershipRangeLo && global_row <mOwnershipRangeHi)
00585 {
00586 values[num_values_owned++] = smallVector(row);
00587 }
00588 }
00589
00590 VecSetValues(mRhsVector,
00591 num_indices_owned,
00592 indices_owned,
00593 values,
00594 ADD_VALUES);
00595 }
00596 }
00597
00598 };
00599
00600 #include "SerializationExportWrapper.hpp"
00601
00602 CHASTE_CLASS_EXPORT(LinearSystem)
00603
00604 namespace boost
00605 {
00606 namespace serialization
00607 {
00608
00609 template<class Archive>
00610 inline void save_construct_data(
00611 Archive & ar, const LinearSystem * t, const unsigned int file_version)
00612 {
00613
00614 std::string archive_filename_lhs = ArchiveLocationInfo::GetArchiveDirectory() + "lhs.mat";
00615 std::string archive_filename_rhs = ArchiveLocationInfo::GetArchiveDirectory() + "rhs.vec";
00616 const unsigned size = t->GetSize();
00617 ar << size;
00618
00619 PetscTools::DumpPetscObject(t->GetRhsVector(), archive_filename_rhs);
00620 PetscTools::DumpPetscObject(t->GetLhsMatrix(), archive_filename_lhs);
00621
00622
00623 PetscTruth symm_set, is_symmetric;
00624 is_symmetric = PETSC_FALSE;
00625
00626 MatIsSymmetricKnown(t->GetLhsMatrix(), &symm_set, &is_symmetric);
00627 assert(symm_set == is_symmetric);
00628 ar << symm_set;
00629 }
00630
00635 template<class Archive>
00636 inline void load_construct_data(
00637 Archive & ar, LinearSystem * t, const unsigned int file_version)
00638 {
00639 std::string archive_filename_lhs = ArchiveLocationInfo::GetArchiveDirectory() + "lhs.mat";
00640 std::string archive_filename_rhs = ArchiveLocationInfo::GetArchiveDirectory() + "rhs.vec";
00641
00642 PetscInt size;
00643 ar >> size;
00644
00645 Vec new_vec;
00646 PetscTools::ReadPetscObject(new_vec, archive_filename_rhs);
00647
00648 Mat new_mat;
00649 PetscTools::ReadPetscObject(new_mat, archive_filename_lhs);
00650
00651
00652
00653 PetscTruth symm_set;
00654 ar >> symm_set;
00655 if (symm_set == PETSC_TRUE)
00656 {
00657 #if (PETSC_VERSION_MAJOR == 3) //PETSc 3.x.x
00658 MatSetOption(new_mat, MAT_SYMMETRIC, PETSC_TRUE);
00659 MatSetOption(new_mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE);
00660 #else
00661 MatSetOption(new_mat, MAT_SYMMETRIC);
00662 MatSetOption(new_mat, MAT_SYMMETRY_ETERNAL);
00663 #endif
00664 }
00665
00666 ::new(t)LinearSystem(size, new_mat, new_vec);
00667 }
00668 }
00669 }
00670
00671 #endif //_LINEARSYSTEM_HPP_