MFEM v2.0
|
00001 // Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at 00002 // the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights 00003 // reserved. See file COPYRIGHT for details. 00004 // 00005 // This file is part of the MFEM library. For more information and source code 00006 // availability see http://mfem.googlecode.com. 00007 // 00008 // MFEM is free software; you can redistribute it and/or modify it under the 00009 // terms of the GNU Lesser General Public License (as published by the Free 00010 // Software Foundation) version 2.1 dated February 1999. 00011 00012 #ifndef MFEM_SPARSEMAT 00013 #define MFEM_SPARSEMAT 00014 00015 // Data types for sparse matrix 00016 00017 #include "../general/mem_alloc.hpp" 00018 #include "../general/table.hpp" 00019 #include "densemat.hpp" 00020 00021 class RowNode 00022 { 00023 public: 00024 RowNode *Prev; 00025 int Column; 00026 double Value; 00027 }; 00028 00030 class SparseMatrix : public Matrix 00031 { 00032 private: 00033 00037 int *I, *J, width; 00038 00040 double *A; 00041 00042 RowNode **Rows; 00043 00044 int current_row; 00045 union { int *J; RowNode **Node; } ColPtr; 00046 00047 #ifdef MFEM_USE_MEMALLOC 00048 MemAlloc <RowNode, 1024> NodesMem; 00049 #endif 00050 00051 inline void SetColPtr(const int row); 00052 inline void ClearColPtr(); 00053 inline double &SearchRow(const int col); 00054 inline void _Add_(const int col, const double a) 00055 { SearchRow(col) += a; } 00056 inline void _Set_(const int col, const double a) 00057 { SearchRow(col) = a; } 00058 inline double _Get_(const int col); 00059 00060 inline double &SearchRow(const int row, const int col); 00061 inline void _Add_(const int row, const int col, const double a) 00062 { SearchRow(row, col) += a; } 00063 inline void _Set_(const int row, const int col, const double a) 00064 { SearchRow(row, col) = a; } 00065 00066 public: 00068 explicit SparseMatrix(int nrows, int ncols = 0); 00069 00070 SparseMatrix(int *i, int *j, double *data, int m, int n) 00071 : Matrix (m), I(i), J(j), width(n), A(data) 00072 { Rows = NULL; ColPtr.J = NULL; } 00073 00075 inline int *GetI() const { return I; } 00077 inline int *GetJ() const { return J; } 00079 inline double *GetData() const { return A; } 00081 inline int Width() const { return width; } 00083 int RowSize(int i); 00084 00086 virtual double &Elem(int i, int j); 00087 00089 virtual const double &Elem(int i, int j) const; 00090 00092 double &operator()(int i, int j); 00093 00095 const double &operator()(int i, int j) const; 00096 00098 virtual void Mult(const Vector &x, Vector &y) const; 00099 00101 void AddMult(const Vector &x, Vector &y, const double a = 1.0) const; 00102 00104 void MultTranspose(const Vector &x, Vector &y) const; 00105 00107 void AddMultTranspose(const Vector &x, Vector &y, 00108 const double a = 1.0) const; 00109 00110 void PartMult(const Array<int> &rows, const Vector &x, Vector &y); 00111 00113 double InnerProduct(const Vector &x, const Vector &y) const; 00114 00115 void GetRowSums(Vector &x) const; 00116 00118 virtual MatrixInverse *Inverse() const; 00119 00121 void EliminateRow(int row, const double sol, Vector &rhs); 00122 void EliminateRow(int row); 00123 void EliminateCol(int col); 00125 void EliminateCols(Array<int> &cols, Vector *x = NULL, Vector *b = NULL); 00126 00131 void EliminateRowCol(int rc, const double sol, Vector &rhs, int d = 0); 00132 00135 void EliminateRowColMultipleRHS(int rc, const Vector &sol, 00136 DenseMatrix &rhs, int d = 0); 00137 00138 void EliminateRowCol(int rc, int d = 0); 00139 // Same as above + save the eliminated entries in Ae so that 00140 // (*this) + Ae is the original matrix 00141 void EliminateRowCol(int rc, SparseMatrix &Ae, int d = 0); 00142 00144 void SetDiagIdentity(); 00146 void EliminateZeroRows(); 00147 00149 void Gauss_Seidel_forw(const Vector &x, Vector &y) const; 00150 void Gauss_Seidel_back(const Vector &x, Vector &y) const; 00151 00153 double GetJacobiScaling() const; 00156 void Jacobi(const Vector &b, const Vector &x0, Vector &x1, double sc) const; 00157 00159 void Jacobi2(const Vector &b, const Vector &x0, Vector &x1, 00160 double sc = 1.0) const; 00161 00166 virtual void Finalize(int skip_zeros = 1); 00167 00168 int Finalized() { return (A != NULL); } 00169 00173 void GetBlocks(Array2D<SparseMatrix *> &blocks) const; 00174 00175 void GetSubMatrix(const Array<int> &rows, const Array<int> &cols, 00176 DenseMatrix &subm); 00177 00178 void Set(const int i, const int j, const double a); 00179 void Add(const int i, const int j, const double a); 00180 00181 void SetSubMatrix(const Array<int> &rows, const Array<int> &cols, 00182 const DenseMatrix &subm, int skip_zeros = 1); 00183 00184 void SetSubMatrixTranspose(const Array<int> &rows, const Array<int> &cols, 00185 const DenseMatrix &subm, int skip_zeros = 1); 00186 00187 void AddSubMatrix(const Array<int> &rows, const Array<int> &cols, 00188 const DenseMatrix &subm, int skip_zeros = 1); 00189 00190 void AddRow(const int row, const Array<int> &cols, const Vector &srow); 00191 00192 void ScaleRow(const int row, const double scale); 00193 00196 SparseMatrix &operator+=(SparseMatrix &B); 00197 00198 SparseMatrix &operator=(double a); 00199 00201 void Print(ostream &out = cout, int width = 4) const; 00202 00204 void PrintMatlab(ostream &out = cout) const; 00205 00207 void PrintMM(ostream &out = cout) const; 00208 00210 void PrintCSR(ostream &out) const; 00211 00213 void PrintCSR2(ostream &out) const; 00214 00216 int Walk(int &i, int &j, double &a); 00217 00219 double IsSymmetric() const; 00220 00222 void Symmetrize(); 00223 00225 int NumNonZeroElems() const; 00226 00227 double MaxNorm() const; 00228 00230 int CountSmallElems(double tol); 00231 00233 void LoseData() { I=0; J=0; A=0; } 00234 00236 virtual ~SparseMatrix(); 00237 }; 00238 00240 void SparseMatrixFunction(SparseMatrix &S, double (*f)(double)); 00241 00242 00244 SparseMatrix *Transpose(SparseMatrix &A); 00245 00252 SparseMatrix *Mult(SparseMatrix &A, SparseMatrix &B, 00253 SparseMatrix *OAB = NULL); 00254 00255 00258 SparseMatrix *RAP(SparseMatrix &A, SparseMatrix &R, 00259 SparseMatrix *ORAP = NULL); 00260 00263 SparseMatrix *Mult_AtDA(SparseMatrix &A, Vector &D, 00264 SparseMatrix *OAtDA = NULL); 00265 00266 00267 // Inline methods 00268 00269 inline void SparseMatrix::SetColPtr(const int row) 00270 { 00271 if (Rows) 00272 { 00273 if (ColPtr.Node == NULL) 00274 { 00275 ColPtr.Node = new RowNode *[width]; 00276 for (int i = 0; i < width; i++) 00277 ColPtr.Node[i] = NULL; 00278 } 00279 for (RowNode *node_p = Rows[row]; node_p != NULL; node_p = node_p->Prev) 00280 { 00281 ColPtr.Node[node_p->Column] = node_p; 00282 } 00283 } 00284 else 00285 { 00286 if (ColPtr.J == NULL) 00287 { 00288 ColPtr.J = new int[width]; 00289 for (int i = 0; i < width; i++) 00290 ColPtr.J[i] = -1; 00291 } 00292 for (int j = I[row], end = I[row+1]; j < end; j++) 00293 { 00294 ColPtr.J[J[j]] = j; 00295 } 00296 } 00297 current_row = row; 00298 } 00299 00300 inline void SparseMatrix::ClearColPtr() 00301 { 00302 if (Rows) 00303 for (RowNode *node_p = Rows[current_row]; node_p != NULL; 00304 node_p = node_p->Prev) 00305 { 00306 ColPtr.Node[node_p->Column] = NULL; 00307 } 00308 else 00309 for (int j = I[current_row], end = I[current_row+1]; j < end; j++) 00310 { 00311 ColPtr.J[J[j]] = -1; 00312 } 00313 } 00314 00315 inline double &SparseMatrix::SearchRow(const int col) 00316 { 00317 if (Rows) 00318 { 00319 RowNode *node_p = ColPtr.Node[col]; 00320 if (node_p == NULL) 00321 { 00322 #ifdef MFEM_USE_MEMALLOC 00323 node_p = NodesMem.Alloc(); 00324 #else 00325 node_p = new RowNode; 00326 #endif 00327 node_p->Prev = Rows[current_row]; 00328 node_p->Column = col; 00329 node_p->Value = 0.0; 00330 Rows[current_row] = ColPtr.Node[col] = node_p; 00331 } 00332 return node_p->Value; 00333 } 00334 else 00335 { 00336 const int j = ColPtr.J[col]; 00337 if (j == -1) 00338 mfem_error("SparseMatrix::SearchRow : entry is not allocated!"); 00339 return A[j]; 00340 } 00341 } 00342 00343 inline double SparseMatrix::_Get_(const int col) 00344 { 00345 if (Rows) 00346 { 00347 RowNode *node_p = ColPtr.Node[col]; 00348 return (node_p == NULL) ? 0.0 : node_p->Value; 00349 } 00350 else 00351 { 00352 const int j = ColPtr.J[col]; 00353 return (j == -1) ? 0.0 : A[j]; 00354 } 00355 } 00356 00357 inline double &SparseMatrix::SearchRow(const int row, const int col) 00358 { 00359 if (Rows) 00360 { 00361 RowNode *node_p; 00362 00363 for (node_p = Rows[row]; 1; node_p = node_p->Prev) 00364 if (node_p == NULL) 00365 { 00366 #ifdef MFEM_USE_MEMALLOC 00367 node_p = NodesMem.Alloc(); 00368 #else 00369 node_p = new RowNode; 00370 #endif 00371 node_p->Prev = Rows[row]; 00372 node_p->Column = col; 00373 node_p->Value = 0.0; 00374 Rows[row] = node_p; 00375 break; 00376 } 00377 else if (node_p->Column == col) 00378 { 00379 break; 00380 } 00381 return node_p->Value; 00382 } 00383 else 00384 { 00385 int *Ip = I+row, *Jp = J; 00386 for (int k = Ip[0], end = Ip[1]; k < end; k++) 00387 if (Jp[k] == col) 00388 return A[k]; 00389 mfem_error("SparseMatrix::SearchRow(...)"); 00390 } 00391 return A[0]; 00392 } 00393 00394 #endif