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 "ArchiveLocationInfo.hpp"
00041
00042 #include <petscvec.h>
00043 #include <petscmat.h>
00044 #include <petscksp.h>
00045 #include <petscviewer.h>
00046
00047 #include <string>
00048 #include <cassert>
00049
00055 class LinearSystem
00056 {
00057 friend class TestLinearSystem;
00058 friend class TestPCBlockDiagonal;
00059 friend class TestPCLDUFactorisation;
00060
00061 private:
00062
00063 Mat mLhsMatrix;
00064 Vec mRhsVector;
00065 PetscInt mSize;
00071 PetscInt mOwnershipRangeLo;
00072 PetscInt mOwnershipRangeHi;
00074 MatNullSpace mMatNullSpace;
00077 bool mDestroyMatAndVec;
00078
00079 KSP mKspSolver;
00080 bool mKspIsSetup;
00081 double mNonZerosUsed;
00082 bool mMatrixIsConstant;
00083 double mTolerance;
00088 bool mUseAbsoluteTolerance;
00089 std::string mKspType;
00090 std::string mPcType;
00092 Vec mDirichletBoundaryConditionsVector;
00095 PCBlockDiagonal* mpBlockDiagonalPC;
00097 PCLDUFactorisation* mpLDUFactorisationPC;
00098
00099
00100 #ifdef TRACE_KSP
00101 unsigned mNumSolves;
00102 unsigned mTotalNumIterations;
00103 unsigned mMaxNumIterations;
00104 #endif
00105
00106 friend class boost::serialization::access;
00113 template<class Archive>
00114 void serialize(Archive & archive, const unsigned int version)
00115 {
00116
00117
00118 archive & mNonZerosUsed;
00119 archive & mMatrixIsConstant;
00120 archive & mTolerance;
00121 archive & mUseAbsoluteTolerance;
00122 archive & mKspType;
00123 archive & mPcType;
00124
00125
00126 }
00127
00128 public:
00129
00136 LinearSystem(PetscInt lhsVectorSize, MatType matType=(MatType) MATMPIAIJ);
00137
00150 LinearSystem(Vec templateVector);
00151
00164 LinearSystem(Vec residualVector, Mat jacobianMatrix);
00165
00174 LinearSystem(PetscInt lhsVectorSize, Mat lhsMatrix, Vec rhsVector, MatType matType=(MatType) MATMPIAIJ);
00175
00179 ~LinearSystem();
00180
00186 void SetupVectorAndMatrix(MatType matType);
00187
00188
00189
00190
00198 void SetMatrixElement(PetscInt row, PetscInt col, double value);
00199
00207 void AddToMatrixElement(PetscInt row, PetscInt col, double value);
00208
00214 void AssembleFinalLinearSystem();
00215
00221 void AssembleIntermediateLinearSystem();
00222
00226 void AssembleFinalLhsMatrix();
00227
00231 void AssembleIntermediateLhsMatrix();
00232
00236 void AssembleRhsVector();
00237
00243 void SetMatrixIsSymmetric(bool isSymmetric=true);
00244
00250 bool IsMatrixSymmetric();
00251
00257 void SetMatrixIsConstant(bool matrixIsConstant);
00258
00264 void SetRelativeTolerance(double relativeTolerance);
00265
00271 void SetAbsoluteTolerance(double absoluteTolerance);
00272
00278 void SetKspType(const char* kspType);
00279
00285 void SetPcType(const char* pcType);
00286
00290 void DisplayMatrix();
00291
00295 void DisplayRhs();
00296
00305 void SetMatrixRow(PetscInt row, double value);
00306
00313 Vec GetMatrixRowDistributed(unsigned row_index);
00314
00323 void ZeroMatrixRowsWithValueOnDiagonal(std::vector<unsigned>& rRows, double diagonalValue);
00324
00325
00332 void ZeroMatrixRowsAndColumnsWithValueOnDiagonal(std::vector<unsigned>& rRowColIndices, double diagonalValue);
00333
00334
00344 void ZeroMatrixColumn(PetscInt col);
00345
00349 void ZeroLhsMatrix();
00350
00354 void ZeroRhsVector();
00355
00359 void ZeroLinearSystem();
00360
00366 Vec Solve(Vec lhsGuess=NULL);
00367
00374 void SetRhsVectorElement(PetscInt row, double value);
00375
00382 void AddToRhsVectorElement(PetscInt row, double value);
00383
00387 unsigned GetSize() const;
00388
00401 void SetNullBasis(Vec nullbasis[], unsigned numberOfBases);
00402
00409 void RemoveNullSpace();
00410
00414 Vec& rGetRhsVector();
00415
00419 Vec GetRhsVector() const;
00420
00424 Mat& rGetLhsMatrix();
00425
00429 Mat GetLhsMatrix() const;
00430
00436 Vec& rGetDirichletBoundaryConditionsVector();
00437
00438
00445 void GetOwnershipRange(PetscInt& lo, PetscInt& hi);
00446
00454 double GetMatrixElement(PetscInt row, PetscInt col);
00455
00462 double GetRhsVectorElement(PetscInt row);
00463
00467 unsigned GetNumIterations() const;
00468
00478 template<size_t MATRIX_SIZE>
00479 void AddLhsMultipleValues(unsigned* matrixRowAndColIndices, c_matrix<double, MATRIX_SIZE, MATRIX_SIZE>& rSmallMatrix)
00480 {
00481 PetscInt matrix_row_indices[MATRIX_SIZE];
00482 PetscInt num_rows_owned = 0;
00483 PetscInt global_row;
00484
00485 for (unsigned row = 0; row<MATRIX_SIZE; row++)
00486 {
00487 global_row = matrixRowAndColIndices[row];
00488 if (global_row >=mOwnershipRangeLo && global_row <mOwnershipRangeHi)
00489 {
00490 matrix_row_indices[num_rows_owned++] = global_row;
00491 }
00492 }
00493
00494 if ( num_rows_owned == MATRIX_SIZE)
00495 {
00496 MatSetValues(mLhsMatrix,
00497 num_rows_owned,
00498 matrix_row_indices,
00499 MATRIX_SIZE,
00500 (PetscInt*) matrixRowAndColIndices,
00501 rSmallMatrix.data(),
00502 ADD_VALUES);
00503 }
00504 else
00505 {
00506
00507
00508 double values[MATRIX_SIZE*MATRIX_SIZE];
00509 unsigned num_values_owned = 0;
00510 for (unsigned row = 0; row<MATRIX_SIZE; row++)
00511 {
00512 global_row = matrixRowAndColIndices[row];
00513 if (global_row >=mOwnershipRangeLo && global_row <mOwnershipRangeHi)
00514 {
00515 for (unsigned col=0; col<MATRIX_SIZE; col++)
00516 {
00517 values[num_values_owned++] = rSmallMatrix(row, col);
00518 }
00519 }
00520 }
00521
00522 MatSetValues(mLhsMatrix,
00523 num_rows_owned,
00524 matrix_row_indices,
00525 MATRIX_SIZE,
00526 (PetscInt*) matrixRowAndColIndices,
00527 values,
00528 ADD_VALUES);
00529 }
00530 };
00531
00541 template<size_t VECTOR_SIZE>
00542 void AddRhsMultipleValues(unsigned* vectorIndices, c_vector<double, VECTOR_SIZE>& smallVector)
00543 {
00544 PetscInt indices_owned[VECTOR_SIZE];
00545 PetscInt num_indices_owned = 0;
00546 PetscInt global_row;
00547
00548 for (unsigned row = 0; row<VECTOR_SIZE; row++)
00549 {
00550 global_row = vectorIndices[row];
00551 if (global_row >=mOwnershipRangeLo && global_row <mOwnershipRangeHi)
00552 {
00553 indices_owned[num_indices_owned++] = global_row;
00554 }
00555 }
00556
00557 if (num_indices_owned == VECTOR_SIZE)
00558 {
00559 VecSetValues(mRhsVector,
00560 num_indices_owned,
00561 indices_owned,
00562 smallVector.data(),
00563 ADD_VALUES);
00564 }
00565 else
00566 {
00567
00568
00569 double values[VECTOR_SIZE];
00570 unsigned num_values_owned = 0;
00571
00572 for (unsigned row = 0; row<VECTOR_SIZE; row++)
00573 {
00574 global_row = vectorIndices[row];
00575 if (global_row >=mOwnershipRangeLo && global_row <mOwnershipRangeHi)
00576 {
00577 values[num_values_owned++] = smallVector(row);
00578 }
00579 }
00580
00581 VecSetValues(mRhsVector,
00582 num_indices_owned,
00583 indices_owned,
00584 values,
00585 ADD_VALUES);
00586 }
00587 }
00588
00589 };
00590
00591 #include "SerializationExportWrapper.hpp"
00592
00593 CHASTE_CLASS_EXPORT(LinearSystem);
00594
00595 namespace boost
00596 {
00597 namespace serialization
00598 {
00599
00600 template<class Archive>
00601 inline void save_construct_data(
00602 Archive & ar, const LinearSystem * t, const unsigned int file_version)
00603 {
00604
00605 std::string archive_filename_lhs = ArchiveLocationInfo::GetArchiveDirectory() + "lhs.mat";
00606 std::string archive_filename_rhs = ArchiveLocationInfo::GetArchiveDirectory() + "rhs.vec";
00607 const unsigned size = t->GetSize();
00608 ar << size;
00609
00610 PetscTools::DumpPetscObject(t->GetRhsVector(), archive_filename_rhs);
00611 PetscTools::DumpPetscObject(t->GetLhsMatrix(), archive_filename_lhs);
00612
00613
00614 PetscTruth symm_set, is_symmetric;
00615 is_symmetric = PETSC_FALSE;
00616
00617 MatIsSymmetricKnown(t->GetLhsMatrix(), &symm_set, &is_symmetric);
00618 assert(symm_set == is_symmetric);
00619 ar << symm_set;
00620 }
00621
00626 template<class Archive>
00627 inline void load_construct_data(
00628 Archive & ar, LinearSystem * t, const unsigned int file_version)
00629 {
00630 std::string archive_filename_lhs = ArchiveLocationInfo::GetArchiveDirectory() + "lhs.mat";
00631 std::string archive_filename_rhs = ArchiveLocationInfo::GetArchiveDirectory() + "rhs.vec";
00632
00633 PetscInt size;
00634 ar >> size;
00635
00636 Vec new_vec;
00637 PetscTools::ReadPetscObject(new_vec, archive_filename_rhs);
00638
00639 Mat new_mat;
00640 PetscTools::ReadPetscObject(new_mat, archive_filename_lhs);
00641
00642
00643
00644 PetscTruth symm_set;
00645 ar >> symm_set;
00646 if (symm_set == PETSC_TRUE)
00647 {
00648 #if (PETSC_VERSION_MAJOR == 3) //PETSc 3.x.x
00649 MatSetOption(new_mat, MAT_SYMMETRIC, PETSC_TRUE);
00650 MatSetOption(new_mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE);
00651 #else
00652 MatSetOption(new_mat, MAT_SYMMETRIC);
00653 MatSetOption(new_mat, MAT_SYMMETRY_ETERNAL);
00654 #endif
00655 }
00656
00657 ::new(t)LinearSystem(size, new_mat, new_vec, (MatType)MATMPIMAIJ);
00658 }
00659 }
00660 }
00661
00662 #endif //_LINEARSYSTEM_HPP_