MFEM  v3.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
sparsemat.hpp
Go to the documentation of this file.
1 // Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
2 // the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
3 // reserved. See file COPYRIGHT for details.
4 //
5 // This file is part of the MFEM library. For more information and source code
6 // availability see http://mfem.googlecode.com.
7 //
8 // MFEM is free software; you can redistribute it and/or modify it under the
9 // terms of the GNU Lesser General Public License (as published by the Free
10 // Software Foundation) version 2.1 dated February 1999.
11 
12 #ifndef MFEM_SPARSEMAT
13 #define MFEM_SPARSEMAT
14 
15 // Data types for sparse matrix
16 
17 #include "../general/mem_alloc.hpp"
18 #include "../general/table.hpp"
19 #include "densemat.hpp"
20 #include <iostream>
21 
22 namespace mfem
23 {
24 
25 class
26 #if defined(__alignas_is_defined)
27 alignas(double)
28 #endif
29  RowNode
30 {
31 public:
32  double Value;
33  RowNode *Prev;
34  int Column;
35 };
36 
39 {
40 private:
41 
45  int *I, *J;
46 
48  double *A;
49 
50  RowNode **Rows;
51 
52  mutable int current_row;
53  mutable int* ColPtrJ;
54  mutable RowNode ** ColPtrNode;
55 
56 #ifdef MFEM_USE_MEMALLOC
58  RowNodeAlloc * NodesMem;
59 #endif
60 
62  bool ownGraph;
64  bool ownData;
65 
67  bool isSorted;
68 
69  inline void SetColPtr(const int row) const;
70  inline void ClearColPtr() const;
71  inline double &SearchRow(const int col);
72  inline void _Add_(const int col, const double a)
73  { SearchRow(col) += a; }
74  inline void _Set_(const int col, const double a)
75  { SearchRow(col) = a; }
76  inline double _Get_(const int col) const;
77 
78  inline double &SearchRow(const int row, const int col);
79  inline void _Add_(const int row, const int col, const double a)
80  { SearchRow(row, col) += a; }
81  inline void _Set_(const int row, const int col, const double a)
82  { SearchRow(row, col) = a; }
83 
84 public:
86  explicit SparseMatrix(int nrows, int ncols = 0);
87 
88  SparseMatrix(int *i, int *j, double *data, int m, int n);
89 
90  SparseMatrix(int *i, int *j, double *data, int m, int n, bool ownij, bool owna,
91  bool issorted);
92 
94  int Size() const { return Height(); }
95 
97  inline int *GetI() const { return I; }
99  inline int *GetJ() const { return J; }
101  inline double *GetData() const { return A; }
103  int RowSize(const int i) const;
105  int MaxRowSize() const;
107  int *GetRowColumns(const int row);
108  const int *GetRowColumns(const int row) const;
110  double *GetRowEntries(const int row);
111  const double *GetRowEntries(const int row) const;
112 
114 
121  void SetWidth(int width_ = -1);
122 
124 
125  int ActualWidth();
126 
128  void SortColumnIndices();
129 
131  virtual double &Elem(int i, int j);
132 
134  virtual const double &Elem(int i, int j) const;
135 
137  double &operator()(int i, int j);
138 
140  const double &operator()(int i, int j) const;
141 
143  void GetDiag(Vector & d) const;
144 
146  virtual void Mult(const Vector &x, Vector &y) const;
147 
149  void AddMult(const Vector &x, Vector &y, const double a = 1.0) const;
150 
152  void MultTranspose(const Vector &x, Vector &y) const;
153 
155  void AddMultTranspose(const Vector &x, Vector &y,
156  const double a = 1.0) const;
157 
158  void PartMult(const Array<int> &rows, const Vector &x, Vector &y) const;
159  void PartAddMult(const Array<int> &rows, const Vector &x, Vector &y,
160  const double a=1.0) const;
161 
163  double InnerProduct(const Vector &x, const Vector &y) const;
164 
166  void GetRowSums(Vector &x) const;
168  double GetRowNorml1(int irow) const;
169 
171  virtual MatrixInverse *Inverse() const;
172 
174  void EliminateRow(int row, const double sol, Vector &rhs);
176 
182  void EliminateRow(int row, int setOneDiagonal = 0);
183  void EliminateCol(int col);
185  void EliminateCols(Array<int> &cols, Vector *x = NULL, Vector *b = NULL);
186 
191  void EliminateRowCol(int rc, const double sol, Vector &rhs, int d = 0);
192 
195  void EliminateRowColMultipleRHS(int rc, const Vector &sol,
196  DenseMatrix &rhs, int d = 0);
197 
198  void EliminateRowCol(int rc, int d = 0);
199  // Same as above + save the eliminated entries in Ae so that
200  // (*this) + Ae is the original matrix
201  void EliminateRowCol(int rc, SparseMatrix &Ae, int d = 0);
202 
204  void SetDiagIdentity();
206  void EliminateZeroRows();
207 
209  void Gauss_Seidel_forw(const Vector &x, Vector &y) const;
210  void Gauss_Seidel_back(const Vector &x, Vector &y) const;
211 
213  double GetJacobiScaling() const;
216  void Jacobi(const Vector &b, const Vector &x0, Vector &x1, double sc) const;
217 
218  void DiagScale(const Vector &b, Vector &x, double sc = 1.0) const;
219 
221  void Jacobi2(const Vector &b, const Vector &x0, Vector &x1,
222  double sc = 1.0) const;
223 
225  void Jacobi3(const Vector &b, const Vector &x0, Vector &x1,
226  double sc = 1.0) const;
227 
232  virtual void Finalize(int skip_zeros = 1);
233 
234  bool Finalized() const { return (A != NULL); }
235  bool areColumnsSorted() const { return isSorted; }
236 
240  void GetBlocks(Array2D<SparseMatrix *> &blocks) const;
241 
242  void GetSubMatrix(const Array<int> &rows, const Array<int> &cols,
243  DenseMatrix &subm);
244 
245  void Set(const int i, const int j, const double a);
246  void Add(const int i, const int j, const double a);
247 
248  void SetSubMatrix(const Array<int> &rows, const Array<int> &cols,
249  const DenseMatrix &subm, int skip_zeros = 1);
250 
251  void SetSubMatrixTranspose(const Array<int> &rows, const Array<int> &cols,
252  const DenseMatrix &subm, int skip_zeros = 1);
253 
254  void AddSubMatrix(const Array<int> &rows, const Array<int> &cols,
255  const DenseMatrix &subm, int skip_zeros = 1);
256 
257  bool RowIsEmpty(const int row) const;
258 
266  virtual int GetRow(const int row, Array<int> &cols, Vector &srow) const;
267 
268  void SetRow(const int row, const Array<int> &cols, const Vector &srow);
269  void AddRow(const int row, const Array<int> &cols, const Vector &srow);
270 
271  void ScaleRow(const int row, const double scale);
272  // this = diag(sl) * this;
273  void ScaleRows(const Vector & sl);
274  //this = this * diag(sr);
275  void ScaleColumns(const Vector & sr);
276 
280 
283  void Add(const double a, const SparseMatrix &B);
284 
285  SparseMatrix &operator=(double a);
286 
287  SparseMatrix &operator*=(double a);
288 
290  void Print(std::ostream &out = std::cout, int width_ = 4) const;
291 
293  void PrintMatlab(std::ostream &out = std::cout) const;
294 
296  void PrintMM(std::ostream &out = std::cout) const;
297 
299  void PrintCSR(std::ostream &out) const;
300 
302  void PrintCSR2(std::ostream &out) const;
303 
305  int Walk(int &i, int &j, double &a);
306 
308  double IsSymmetric() const;
309 
311  void Symmetrize();
312 
314  virtual int NumNonZeroElems() const;
315 
316  double MaxNorm() const;
317 
319  int CountSmallElems(double tol) const;
320 
322  void LoseData() { I=0; J=0; A=0; }
323 
324  friend void Swap(SparseMatrix & A, SparseMatrix & B);
325 
327  virtual ~SparseMatrix();
328 };
329 
331 void SparseMatrixFunction(SparseMatrix &S, double (*f)(double));
332 
333 
335 SparseMatrix *Transpose(const SparseMatrix &A);
337 SparseMatrix *TransposeAbstractSparseMatrix (const AbstractSparseMatrix &A,
338  int useActualWidth);
339 
346 SparseMatrix *Mult(const SparseMatrix &A, const SparseMatrix &B,
347  SparseMatrix *OAB = NULL);
348 
350 SparseMatrix *MultAbstractSparseMatrix (const AbstractSparseMatrix &A,
351  const AbstractSparseMatrix &B);
352 
353 
356 SparseMatrix *RAP(const SparseMatrix &A, const SparseMatrix &R,
357  SparseMatrix *ORAP = NULL);
358 
360 SparseMatrix *RAP(const SparseMatrix &Rt, const SparseMatrix &A,
361  const SparseMatrix &P);
362 
365 SparseMatrix *Mult_AtDA(const SparseMatrix &A, const Vector &D,
366  SparseMatrix *OAtDA = NULL);
367 
368 
370 SparseMatrix * Add(const SparseMatrix & A, const SparseMatrix & B);
372 SparseMatrix * Add(double a, const SparseMatrix & A, double b,
373  const SparseMatrix & B);
375 SparseMatrix * Add(Array<SparseMatrix *> & Ai);
376 
377 
378 // Inline methods
379 
380 inline void SparseMatrix::SetColPtr(const int row) const
381 {
382  if (Rows)
383  {
384  if (ColPtrNode == NULL)
385  {
386  ColPtrNode = new RowNode *[width];
387  for (int i = 0; i < width; i++)
388  {
389  ColPtrNode[i] = NULL;
390  }
391  }
392  for (RowNode *node_p = Rows[row]; node_p != NULL; node_p = node_p->Prev)
393  {
394  ColPtrNode[node_p->Column] = node_p;
395  }
396  }
397  else
398  {
399  if (ColPtrJ == NULL)
400  {
401  ColPtrJ = new int[width];
402  for (int i = 0; i < width; i++)
403  {
404  ColPtrJ[i] = -1;
405  }
406  }
407  for (int j = I[row], end = I[row+1]; j < end; j++)
408  {
409  ColPtrJ[J[j]] = j;
410  }
411  }
412  current_row = row;
413 }
414 
415 inline void SparseMatrix::ClearColPtr() const
416 {
417  if (Rows)
418  for (RowNode *node_p = Rows[current_row]; node_p != NULL;
419  node_p = node_p->Prev)
420  {
421  ColPtrNode[node_p->Column] = NULL;
422  }
423  else
424  for (int j = I[current_row], end = I[current_row+1]; j < end; j++)
425  {
426  ColPtrJ[J[j]] = -1;
427  }
428 }
429 
430 inline double &SparseMatrix::SearchRow(const int col)
431 {
432  if (Rows)
433  {
434  RowNode *node_p = ColPtrNode[col];
435  if (node_p == NULL)
436  {
437 #ifdef MFEM_USE_MEMALLOC
438  node_p = NodesMem->Alloc();
439 #else
440  node_p = new RowNode;
441 #endif
442  node_p->Prev = Rows[current_row];
443  node_p->Column = col;
444  node_p->Value = 0.0;
445  Rows[current_row] = ColPtrNode[col] = node_p;
446  }
447  return node_p->Value;
448  }
449  else
450  {
451  const int j = ColPtrJ[col];
452  MFEM_VERIFY(j != -1, "Entry for column " << col << " is not allocated.");
453  return A[j];
454  }
455 }
456 
457 inline double SparseMatrix::_Get_(const int col) const
458 {
459  if (Rows)
460  {
461  RowNode *node_p = ColPtrNode[col];
462  return (node_p == NULL) ? 0.0 : node_p->Value;
463  }
464  else
465  {
466  const int j = ColPtrJ[col];
467  return (j == -1) ? 0.0 : A[j];
468  }
469 }
470 
471 inline double &SparseMatrix::SearchRow(const int row, const int col)
472 {
473  if (Rows)
474  {
475  RowNode *node_p;
476 
477  for (node_p = Rows[row]; 1; node_p = node_p->Prev)
478  {
479  if (node_p == NULL)
480  {
481 #ifdef MFEM_USE_MEMALLOC
482  node_p = NodesMem->Alloc();
483 #else
484  node_p = new RowNode;
485 #endif
486  node_p->Prev = Rows[row];
487  node_p->Column = col;
488  node_p->Value = 0.0;
489  Rows[row] = node_p;
490  break;
491  }
492  else if (node_p->Column == col)
493  {
494  break;
495  }
496  }
497  return node_p->Value;
498  }
499  else
500  {
501  int *Ip = I+row, *Jp = J;
502  for (int k = Ip[0], end = Ip[1]; k < end; k++)
503  {
504  if (Jp[k] == col)
505  {
506  return A[k];
507  }
508  }
509  MFEM_ABORT("Could not find entry for row = " << row << ", col = " << col);
510  }
511  return A[0];
512 }
513 
514 }
515 
516 #endif
Elem * Alloc()
Definition: mem_alloc.hpp:119
double GetJacobiScaling() const
Determine appropriate scaling for Jacobi iteration.
Definition: sparsemat.cpp:1324
SparseMatrix * TransposeAbstractSparseMatrix(const AbstractSparseMatrix &A, int useActualWidth)
Transpose of a sparse matrix. A does not need to be a CSR matrix.
Definition: sparsemat.cpp:2207
int RowSize(const int i) const
Returns the number of elements in row i.
Definition: sparsemat.cpp:91
virtual int NumNonZeroElems() const
Returns the number of the nonzero elements in the matrix.
Definition: sparsemat.cpp:693
void Add(const int i, const int j, const double a)
Definition: sparsemat.cpp:1525
void Print(std::ostream &out=std::cout, int width_=4) const
Prints matrix to stream out.
Definition: sparsemat.cpp:1936
void DiagScale(const Vector &b, Vector &x, double sc=1.0) const
Definition: sparsemat.cpp:1388
void PrintMM(std::ostream &out=std::cout) const
Prints matrix in Matrix Market sparse format.
Definition: sparsemat.cpp:1998
int * GetRowColumns(const int row)
Return a pointer to the column indices in a row.
Definition: sparsemat.cpp:132
void Mult(const Table &A, const Table &B, Table &C)
C = A * B (as boolean matrices)
Definition: table.cpp:351
Abstract data type for sparse matrices.
Definition: matrix.hpp:69
void EliminateRowCol(int rc, const double sol, Vector &rhs, int d=0)
Definition: sparsemat.cpp:859
Data type dense matrix.
Definition: densemat.hpp:22
void AddMult(const Vector &x, Vector &y, const double a=1.0) const
y += A * x (default) or y += a * A * x
Definition: sparsemat.cpp:318
double MaxNorm() const
Definition: sparsemat.cpp:713
void AddMultTranspose(const Vector &x, Vector &y, const double a=1.0) const
y += At * x (default) or y += a * At * x
Definition: sparsemat.cpp:393
Abstract data type for matrix inverse.
Definition: matrix.hpp:58
void EliminateRowColMultipleRHS(int rc, const Vector &sol, DenseMatrix &rhs, int d=0)
Definition: sparsemat.cpp:923
virtual double & Elem(int i, int j)
Returns reference to a_{ij}.
Definition: sparsemat.cpp:227
void LoseData()
Call this if data has been stolen.
Definition: sparsemat.hpp:322
void AddRow(const int row, const Array< int > &cols, const Vector &srow)
Definition: sparsemat.cpp:1728
double * GetRowEntries(const int row)
Return a pointer to the entries in a row.
Definition: sparsemat.cpp:146
void SortColumnIndices()
Sort the column indices corresponding to each row.
Definition: sparsemat.cpp:198
void PartAddMult(const Array< int > &rows, const Vector &x, Vector &y, const double a=1.0) const
Definition: sparsemat.cpp:450
bool RowIsEmpty(const int row) const
Definition: sparsemat.cpp:1640
void GetBlocks(Array2D< SparseMatrix * > &blocks) const
Definition: sparsemat.cpp:601
void ScaleRow(const int row, const double scale)
Definition: sparsemat.cpp:1760
int ActualWidth()
Returns the actual Width of the matrix.
Definition: sparsemat.cpp:2115
void Symmetrize()
(*this) = 1/2 ((*this) + (*this)^t)
Definition: sparsemat.cpp:678
void Add(const DenseMatrix &A, const DenseMatrix &B, double alpha, DenseMatrix &C)
C = A + alpha*B.
Definition: densemat.cpp:2430
void EliminateCol(int col)
Definition: sparsemat.cpp:814
void ScaleColumns(const Vector &sr)
Definition: sparsemat.cpp:1819
virtual ~SparseMatrix()
Destroys sparse matrix.
Definition: sparsemat.cpp:2067
void PrintCSR2(std::ostream &out) const
Prints a sparse matrix to stream out in CSR format.
Definition: sparsemat.cpp:2042
virtual int GetRow(const int row, Array< int > &cols, Vector &srow) const
Definition: sparsemat.cpp:1661
Data type sparse matrix.
Definition: sparsemat.hpp:38
int Height() const
Get the height (size of output) of the Operator. Synonym with NumRows.
Definition: operator.hpp:35
void EliminateCols(Array< int > &cols, Vector *x=NULL, Vector *b=NULL)
Eliminate all columns &#39;i&#39; for which cols[i] != 0.
Definition: sparsemat.cpp:828
void SetWidth(int width_=-1)
Change the width of a SparseMatrix.
Definition: sparsemat.cpp:160
bool areColumnsSorted() const
Definition: sparsemat.hpp:235
friend void Swap(SparseMatrix &A, SparseMatrix &B)
Definition: sparsemat.cpp:2657
HypreParMatrix * RAP(HypreParMatrix *A, HypreParMatrix *P)
Returns the matrix P^t * A * P.
Definition: hypre.cpp:781
double IsSymmetric() const
Returns max_{i,j} |(i,j)-(j,i)| for a finalized matrix.
Definition: sparsemat.cpp:656
void SetDiagIdentity()
If a row contains only one diag entry of zero, set it to 1.
Definition: sparsemat.cpp:1138
void Transpose(const Table &A, Table &At, int _ncols_A)
Transpose a Table.
Definition: table.cpp:305
void ScaleRows(const Vector &sl)
Definition: sparsemat.cpp:1788
virtual void Finalize(int skip_zeros=1)
Definition: sparsemat.cpp:529
void EliminateZeroRows()
If a row contains only zeros, set its diagonal to 1.
Definition: sparsemat.cpp:1147
double * GetData() const
Return element data.
Definition: sparsemat.hpp:101
void AddSubMatrix(const Array< int > &rows, const Array< int > &cols, const DenseMatrix &subm, int skip_zeros=1)
Definition: sparsemat.cpp:1468
int * GetI() const
Return the array I.
Definition: sparsemat.hpp:97
void Jacobi(const Vector &b, const Vector &x0, Vector &x1, double sc) const
Definition: sparsemat.cpp:1357
void SetSubMatrix(const Array< int > &rows, const Array< int > &cols, const DenseMatrix &subm, int skip_zeros=1)
Definition: sparsemat.cpp:1544
bool Finalized() const
Definition: sparsemat.hpp:234
void SparseMatrixFunction(SparseMatrix &S, double(*f)(double))
Applies f() to each element of the matrix (after it is finalized).
Definition: sparsemat.cpp:2142
virtual MatrixInverse * Inverse() const
Returns a pointer to approximation of the matrix inverse.
Definition: sparsemat.cpp:766
virtual void Mult(const Vector &x, Vector &y) const
Matrix vector multiplication.
Definition: sparsemat.cpp:312
SparseMatrix & operator=(double a)
Definition: sparsemat.cpp:1900
void SetSubMatrixTranspose(const Array< int > &rows, const Array< int > &cols, const DenseMatrix &subm, int skip_zeros=1)
Definition: sparsemat.cpp:1577
void Set(const int i, const int j, const double a)
Definition: sparsemat.cpp:1506
void PrintMatlab(std::ostream &out=std::cout) const
Prints matrix in matlab format.
Definition: sparsemat.cpp:1980
int Size() const
For backward compatibility define Size to be synonym of Height()
Definition: sparsemat.hpp:94
void Gauss_Seidel_back(const Vector &x, Vector &y) const
Definition: sparsemat.cpp:1249
void Gauss_Seidel_forw(const Vector &x, Vector &y) const
Gauss-Seidel forward and backward iterations over a vector x.
Definition: sparsemat.cpp:1174
SparseMatrix(int nrows, int ncols=0)
Creates sparse matrix.
Definition: sparsemat.cpp:27
void EliminateRow(int row, const double sol, Vector &rhs)
Eliminates a column from the transpose matrix.
Definition: sparsemat.cpp:771
void GetDiag(Vector &d) const
Returns the Diagonal of A.
Definition: sparsemat.cpp:284
SparseMatrix * Mult_AtDA(const SparseMatrix &A, const Vector &D, SparseMatrix *OAtDA)
Definition: sparsemat.cpp:2529
double GetRowNorml1(int irow) const
For i = irow compute .
Definition: sparsemat.cpp:509
double & operator()(int i, int j)
Returns reference to A[i][j].
Definition: sparsemat.cpp:237
void MultTranspose(const Vector &x, Vector &y) const
Multiply a vector with the transposed matrix. y = At * x.
Definition: sparsemat.cpp:387
SparseMatrix & operator*=(double a)
Definition: sparsemat.cpp:1918
void SetRow(const int row, const Array< int > &cols, const Vector &srow)
Definition: sparsemat.cpp:1700
Vector data type.
Definition: vector.hpp:29
int Walk(int &i, int &j, double &a)
Walks the sparse matrix.
void GetSubMatrix(const Array< int > &rows, const Array< int > &cols, DenseMatrix &subm)
Definition: sparsemat.cpp:1612
void Jacobi2(const Vector &b, const Vector &x0, Vector &x1, double sc=1.0) const
Definition: sparsemat.cpp:1420
int MaxRowSize() const
Returns the maximum number of elements among all rows.
Definition: sparsemat.cpp:108
void Jacobi3(const Vector &b, const Vector &x0, Vector &x1, double sc=1.0) const
Definition: sparsemat.cpp:1444
SparseMatrix * MultAbstractSparseMatrix(const AbstractSparseMatrix &A, const AbstractSparseMatrix &B)
Matrix product of sparse matrices. A and B do not need to be CSR matrices.
Definition: sparsemat.cpp:2410
SparseMatrix & operator+=(SparseMatrix &B)
Definition: sparsemat.cpp:1847
int * GetJ() const
Return the array J.
Definition: sparsemat.hpp:99
void PrintCSR(std::ostream &out) const
Prints matrix to stream out in hypre_CSRMatrix format.
Definition: sparsemat.cpp:2018
double InnerProduct(const Vector &x, const Vector &y) const
Compute y^t A x.
Definition: sparsemat.cpp:468
int CountSmallElems(double tol) const
Count the number of entries with |a_ij| &lt; tol.
Definition: sparsemat.cpp:736
void PartMult(const Array< int > &rows, const Vector &x, Vector &y) const
Definition: sparsemat.cpp:432
void GetRowSums(Vector &x) const
For all i compute .
Definition: sparsemat.cpp:490