MFEM v2.0
sparsemat.hpp
Go to the documentation of this file.
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
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines