LinearSystem.hpp

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 
00030 #ifndef _LINEARSYSTEM_HPP_
00031 #define _LINEARSYSTEM_HPP_
00032 
00033 #include <boost/serialization/access.hpp>
00034 #include "UblasCustomFunctions.hpp" // meeds to be 'first'
00035 
00036 #include "PetscTools.hpp"
00037 #include "OutputFileHandler.hpp"
00038 #include "PCBlockDiagonal.hpp"
00039 #include "ArchiveLocationInfo.hpp"
00040 
00041 #include <petscvec.h>
00042 #include <petscmat.h>
00043 #include <petscksp.h>
00044 #include <petscviewer.h>
00045 
00046 #include <string>
00047 #include <cassert>
00048  
00049 // Needs to be included last
00050 #include <boost/serialization/export.hpp>
00051 
00057 class LinearSystem
00058 {
00059     friend class TestLinearSystem;
00060     friend class TestPCBlockDiagonal;
00061 
00062 private:
00063 
00064     Mat mLhsMatrix;  
00065     Vec mRhsVector;  
00066     PetscInt mSize;  
00072     PetscInt mOwnershipRangeLo; 
00073     PetscInt mOwnershipRangeHi; 
00075     MatNullSpace mMatNullSpace; 
00078     bool mDestroyMatAndVec;
00079 
00080     KSP mKspSolver;   
00081     bool mKspIsSetup; 
00082     double mNonZerosUsed;  
00083     bool mMatrixIsConstant; 
00084     double mTolerance; 
00089     bool mUseAbsoluteTolerance;
00090     std::string mKspType;
00091     std::string mPcType;
00093     Vec mDirichletBoundaryConditionsVector; 
00096     PCBlockDiagonal *mpBlockDiagonalPC;
00097 
00098 #ifdef TRACE_KSP
00099     unsigned mNumSolves;
00100     unsigned mTotalNumIterations;
00101     unsigned mMaxNumIterations;
00102 #endif    
00103 
00104     friend class boost::serialization::access;
00111     template<class Archive>
00112     void serialize(Archive & archive, const unsigned int version)
00113     {
00114         //MatNullSpace mMatNullSpace; ///\todo archive mMatNullSpace.
00115   
00116         archive & mNonZerosUsed;  
00117         archive & mMatrixIsConstant;
00118         archive & mTolerance; 
00119         archive & mUseAbsoluteTolerance;
00120         archive & mKspType;
00121         archive & mPcType;
00122 
00123         //Vec mDirichletBoundaryConditionsVector; ///\todo archive mDirichletBoundaryConditionsVector.
00124     }    
00125 
00126 public:
00127 
00134     LinearSystem(PetscInt lhsVectorSize, MatType matType=(MatType) MATMPIAIJ);
00135 
00148     LinearSystem(Vec templateVector);
00149 
00162     LinearSystem(Vec residualVector, Mat jacobianMatrix);
00163 
00172     LinearSystem(PetscInt lhsVectorSize, Mat lhsMatrix, Vec rhsVector, MatType matType=(MatType) MATMPIAIJ);
00173 
00177     ~LinearSystem();
00178 
00184     void SetupVectorAndMatrix(MatType matType);
00185 
00186 //    bool IsMatrixEqualTo(Mat testMatrix);
00187 //    bool IsRhsVectorEqualTo(Vec testVector);
00188 
00196     void SetMatrixElement(PetscInt row, PetscInt col, double value);
00197 
00205     void AddToMatrixElement(PetscInt row, PetscInt col, double value);
00206 
00212     void AssembleFinalLinearSystem();
00213 
00219     void AssembleIntermediateLinearSystem();
00220 
00224     void AssembleFinalLhsMatrix();
00225 
00229     void AssembleIntermediateLhsMatrix();
00230 
00234     void AssembleRhsVector();
00235 
00241     void SetMatrixIsSymmetric(bool isSymmetric=true);
00242 
00248     void SetMatrixIsConstant(bool matrixIsConstant);
00249 
00255     void SetRelativeTolerance(double relativeTolerance);
00256 
00262     void SetAbsoluteTolerance(double absoluteTolerance);
00263 
00269     void SetKspType(const char* kspType);
00270 
00276     void SetPcType(const char* pcType);
00277 
00281     void DisplayMatrix();
00282 
00286     void DisplayRhs();
00287 
00296     void SetMatrixRow(PetscInt row, double value);
00297 
00306     void ZeroMatrixRow(PetscInt row);
00307 
00317     void ZeroMatrixColumn(PetscInt col);
00318 
00322     void ZeroLhsMatrix();
00323 
00327     void ZeroRhsVector();
00328 
00332     void ZeroLinearSystem();
00333 
00339     Vec Solve(Vec lhsGuess=NULL);
00340 
00347     void SetRhsVectorElement(PetscInt row, double value);
00348 
00355     void AddToRhsVectorElement(PetscInt row, double value);
00356 
00360     unsigned GetSize() const;
00361 
00368     void SetNullBasis(Vec nullbasis[], unsigned numberOfBases);
00369 
00373     Vec& rGetRhsVector();
00374     
00378     Vec GetRhsVector() const;
00379     
00383     Mat& rGetLhsMatrix();
00384     
00388     Mat GetLhsMatrix() const;
00389 
00395     Vec& rGetDirichletBoundaryConditionsVector();
00396 
00397     // DEBUGGING CODE:
00404     void GetOwnershipRange(PetscInt& lo, PetscInt& hi);
00405 
00413     double GetMatrixElement(PetscInt row, PetscInt col);
00414 
00421     double GetRhsVectorElement(PetscInt row);
00422 
00426     unsigned GetNumIterations() const;
00427 
00437     template<size_t MATRIX_SIZE>
00438     void AddLhsMultipleValues(unsigned* matrixRowAndColIndices, c_matrix<double, MATRIX_SIZE, MATRIX_SIZE>& rSmallMatrix)
00439     {
00440         PetscInt matrix_row_indices[MATRIX_SIZE];
00441         PetscInt num_rows_owned = 0;
00442         PetscInt global_row;
00443 
00444         for (unsigned row = 0; row<MATRIX_SIZE; row++)
00445         {
00446             global_row = matrixRowAndColIndices[row];
00447             if (global_row >=mOwnershipRangeLo && global_row <mOwnershipRangeHi)
00448             {
00449                 matrix_row_indices[num_rows_owned++] = global_row;
00450             }
00451         }
00452 
00453         if ( num_rows_owned == MATRIX_SIZE)
00454         {
00455             MatSetValues(mLhsMatrix,
00456                          num_rows_owned,
00457                          matrix_row_indices,
00458                          MATRIX_SIZE,
00459                          (PetscInt*) matrixRowAndColIndices,
00460                          rSmallMatrix.data(),
00461                          ADD_VALUES);
00462         }
00463         else
00464         {
00465             // We need continuous data, if some of the rows do not belong to the processor their values
00466             // are not passed to MatSetValues
00467             double values[MATRIX_SIZE*MATRIX_SIZE];
00468             unsigned num_values_owned = 0;
00469             for (unsigned row = 0; row<MATRIX_SIZE; row++)
00470             {
00471                 global_row = matrixRowAndColIndices[row];
00472                 if (global_row >=mOwnershipRangeLo && global_row <mOwnershipRangeHi)
00473                 {
00474                     for (unsigned col=0; col<MATRIX_SIZE; col++)
00475                     {
00476                         values[num_values_owned++] = rSmallMatrix(row, col);
00477                     }
00478                 }
00479             }
00480 
00481             MatSetValues(mLhsMatrix,
00482                          num_rows_owned,
00483                          matrix_row_indices,
00484                          MATRIX_SIZE,
00485                          (PetscInt*) matrixRowAndColIndices,
00486                          values,
00487                          ADD_VALUES);
00488         }
00489     };
00490 
00500     template<size_t VECTOR_SIZE>
00501     void AddRhsMultipleValues(unsigned* vectorIndices, c_vector<double, VECTOR_SIZE>& smallVector)
00502     {
00503         PetscInt indices_owned[VECTOR_SIZE];
00504         PetscInt num_indices_owned = 0;
00505         PetscInt global_row;
00506 
00507         for (unsigned row = 0; row<VECTOR_SIZE; row++)
00508         {
00509             global_row = vectorIndices[row];
00510             if (global_row >=mOwnershipRangeLo && global_row <mOwnershipRangeHi)
00511             {
00512                 indices_owned[num_indices_owned++] = global_row;
00513             }
00514         }
00515 
00516         if (num_indices_owned == VECTOR_SIZE)
00517         {
00518             VecSetValues(mRhsVector,
00519                          num_indices_owned,
00520                          indices_owned,
00521                          smallVector.data(),
00522                          ADD_VALUES);
00523         }
00524         else
00525         {
00526             // We need continuous data, if some of the rows do not belong to the processor their values
00527             // are not passed to MatSetValues
00528             double values[VECTOR_SIZE];
00529             unsigned num_values_owned = 0;
00530 
00531             for (unsigned row = 0; row<VECTOR_SIZE; row++)
00532             {
00533                 global_row = vectorIndices[row];
00534                 if (global_row >=mOwnershipRangeLo && global_row <mOwnershipRangeHi)
00535                 {
00536                     values[num_values_owned++] = smallVector(row);
00537                 }
00538             }
00539 
00540             VecSetValues(mRhsVector,
00541                          num_indices_owned,
00542                          indices_owned,
00543                          values,
00544                          ADD_VALUES);
00545         }
00546     }
00547 
00548 };
00549 
00550 // Declare identifier for the serializer
00551 BOOST_CLASS_EXPORT(LinearSystem);
00552 
00553 namespace boost
00554 {
00555 namespace serialization
00556 {
00557 
00558 template<class Archive>
00559 inline void save_construct_data(
00560     Archive & ar, const LinearSystem * t, const unsigned int file_version)
00561 {
00562     
00563     std::string archive_filename_lhs = ArchiveLocationInfo::GetArchiveDirectory() + "lhs.mat";   
00564     std::string archive_filename_rhs = ArchiveLocationInfo::GetArchiveDirectory() + "rhs.vec"; 
00565     const unsigned size = t->GetSize();
00566     ar << size;
00567     
00568     PetscTools::DumpPetscObject(t->GetRhsVector(), archive_filename_rhs);
00569     PetscTools::DumpPetscObject(t->GetLhsMatrix(), archive_filename_lhs);
00570 
00571     //Is the matrix structurally symmetric?
00572     PetscTruth symm_set, is_symmetric;
00573     is_symmetric = PETSC_FALSE;
00574     //Note that the following call only changes is_symmetric when symm_set is true
00575     MatIsSymmetricKnown(t->GetLhsMatrix(), &symm_set, &is_symmetric);
00576     assert(symm_set == is_symmetric);
00577     ar << symm_set;
00578 }    
00579     
00584 template<class Archive>
00585 inline void load_construct_data(
00586     Archive & ar, LinearSystem * t, const unsigned int file_version)
00587 {
00588      std::string archive_filename_lhs = ArchiveLocationInfo::GetArchiveDirectory() + "lhs.mat";
00589      std::string archive_filename_rhs = ArchiveLocationInfo::GetArchiveDirectory() + "rhs.vec";
00590       
00591      PetscInt size; 
00592      ar >> size;
00593      
00594      Vec new_vec;
00595      PetscTools::ReadPetscObject(new_vec, archive_filename_rhs);
00596 
00597      Mat new_mat;
00598      PetscTools::ReadPetscObject(new_mat, archive_filename_lhs);
00599      
00600      //This has to occur after the call to MatLoad as the matrix does not exist until MatLoad is called.
00601      //The property will be copied & set correctly in the LinearSystem constructor.
00602      PetscTruth symm_set;
00603      ar >> symm_set;
00604      if (symm_set == PETSC_TRUE)
00605      {
00606         MatSetOption(new_mat, MAT_SYMMETRIC);
00607         MatSetOption(new_mat, MAT_SYMMETRY_ETERNAL);
00608      }
00609 
00610      ::new(t)LinearSystem(size, new_mat, new_vec, MATMPIMAIJ);
00611 }
00612 }
00613 } // namespace ...
00614 
00615 #endif //_LINEARSYSTEM_HPP_

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