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 <boost/serialization/access.hpp>
00034 #include "UblasCustomFunctions.hpp"
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
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
00115
00116 archive & mNonZerosUsed;
00117 archive & mMatrixIsConstant;
00118 archive & mTolerance;
00119 archive & mUseAbsoluteTolerance;
00120 archive & mKspType;
00121 archive & mPcType;
00122
00123
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
00187
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
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
00466
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
00527
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
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
00572 PetscTruth symm_set, is_symmetric;
00573 is_symmetric = PETSC_FALSE;
00574
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
00601
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 }
00614
00615 #endif //_LINEARSYSTEM_HPP_