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 "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         //MatNullSpace mMatNullSpace; ///\todo archive mMatNullSpace.
00126 
00127         archive & mNonZerosUsed;
00128         archive & mMatrixIsConstant;
00129         archive & mTolerance;
00130         archive & mUseAbsoluteTolerance;
00131         archive & mKspType;
00132         archive & mPcType;
00133 
00134         //Vec mDirichletBoundaryConditionsVector; ///\todo archive mDirichletBoundaryConditionsVector.
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 //    bool IsMatrixEqualTo(Mat testMatrix);
00196 //    bool IsRhsVectorEqualTo(Vec testVector);
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     // DEBUGGING CODE:
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             // We need continuous data, if some of the rows do not belong to the processor their values
00516             // are not passed to MatSetValues
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             // We need continuous data, if some of the rows do not belong to the processor their values
00577             // are not passed to MatSetValues
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 // Declare identifier for the serializer
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     //Is the matrix structurally symmetric?
00623     PetscTruth symm_set, is_symmetric;
00624     is_symmetric = PETSC_FALSE;
00625     //Note that the following call only changes is_symmetric when symm_set is true
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      //This has to occur after the call to MatLoad as the matrix does not exist until MatLoad is called.
00652      //The property will be copied & set correctly in the LinearSystem constructor.
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 } // namespace ...
00670 
00671 #endif //_LINEARSYSTEM_HPP_

Generated on Mon Nov 1 12:35:17 2010 for Chaste by  doxygen 1.5.5