LinearSystem.hpp

00001 /*
00002 
00003 Copyright (C) University of Oxford, 2005-2010
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 
00030 #ifndef _LINEARSYSTEM_HPP_
00031 #define _LINEARSYSTEM_HPP_
00032 
00033 #include "ChasteSerialization.hpp"
00034 #include "UblasCustomFunctions.hpp" // meeds to be 'first'
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         //MatNullSpace mMatNullSpace; ///\todo archive mMatNullSpace.
00117 
00118         archive & mNonZerosUsed;
00119         archive & mMatrixIsConstant;
00120         archive & mTolerance;
00121         archive & mUseAbsoluteTolerance;
00122         archive & mKspType;
00123         archive & mPcType;
00124 
00125         //Vec mDirichletBoundaryConditionsVector; ///\todo archive mDirichletBoundaryConditionsVector.
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 //    bool IsMatrixEqualTo(Mat testMatrix);
00189 //    bool IsRhsVectorEqualTo(Vec testVector);
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     // DEBUGGING CODE:
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             // We need continuous data, if some of the rows do not belong to the processor their values
00507             // are not passed to MatSetValues
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             // We need continuous data, if some of the rows do not belong to the processor their values
00568             // are not passed to MatSetValues
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 // Declare identifier for the serializer
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     //Is the matrix structurally symmetric?
00614     PetscTruth symm_set, is_symmetric;
00615     is_symmetric = PETSC_FALSE;
00616     //Note that the following call only changes is_symmetric when symm_set is true
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      //This has to occur after the call to MatLoad as the matrix does not exist until MatLoad is called.
00643      //The property will be copied & set correctly in the LinearSystem constructor.
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 } // namespace ...
00661 
00662 #endif //_LINEARSYSTEM_HPP_

Generated by  doxygen 1.6.2