Mesh Oriented datABase  (version 5.4.1)
Array-based unstructured mesh datastructure
HypreParMatrix.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.org.
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 /// This HYPRE library interface has been taken originally from MFEM and modified
00013 /// to suit the needs for the MOAB library.
00014 /// Modified by: Vijay Mahadevan
00015 
00016 #ifndef MOAB_HYPREPARMATRIX
00017 #define MOAB_HYPREPARMATRIX
00018 
00019 #include "moab/MOABConfig.h"
00020 #include "moab/Core.hpp"
00021 
00022 #ifdef MOAB_HAVE_EIGEN3
00023 #include <Eigen/Core>
00024 #include <Eigen/Sparse>
00025 #else
00026 #error Configure with Eigen3 enabled
00027 #endif
00028 
00029 #ifdef MOAB_HAVE_MPI
00030 #include "moab/ParallelComm.hpp"
00031 
00032 // hypre header files
00033 // #include "HYPRE.h"
00034 // #include "HYPRE_parcsr_ls.h"
00035 // #include "HYPRE_MatvecFunctions.h"
00036 
00037 #include "seq_mv.h"
00038 #include "HypreParVector.hpp"
00039 #include "_hypre_parcsr_mv.h"
00040 #include "_hypre_parcsr_ls.h"
00041 #include "interpreter.h"
00042 #include "HYPRE_MatvecFunctions.h"
00043 
00044 #include "temp_multivector.h"
00045 
00046 #ifdef HYPRE_COMPLEX
00047 #error "MOAB does not work with HYPRE's complex numbers support"
00048 #endif
00049 
00050 #include "hypre_parcsr.hpp"
00051 
00052 namespace moab
00053 {
00054 
00055 namespace internal
00056 {
00057 
00058     // Convert a HYPRE_Int to int
00059     inline int to_int( HYPRE_Int i )
00060     {
00061 #ifdef HYPRE_BIGINT
00062         MFEM_ASSERT( HYPRE_Int( int( i ) ) == i, "overflow converting HYPRE_Int to int" );
00063 #endif
00064         return int( i );
00065     }
00066 
00067 }  // namespace internal
00068 
00069 /// Wrapper for hypre's ParCSR matrix class
00070 class HypreParMatrix
00071 {
00072   private:
00073     /// The actual object
00074     HYPRE_IJMatrix A;
00075     hypre_ParCSRMatrix* A_parcsr;
00076 
00077     mv_InterfaceInterpreter* interpreter;
00078 
00079     // Does the object own the pointer A?
00080     char ParCSROwner;
00081 
00082     // Store the dimensions of the matrix
00083     int height, gnrows;
00084     int width, gncols;
00085 
00086     moab::ParallelComm* pcomm;
00087     char initialized;
00088 
00089     // Initialize with defaults. Does not initialize inherited members.
00090     void Init();
00091 
00092     // Delete all owned data. Does not perform re-initialization with defaults.
00093     void Destroy();
00094 
00095     friend class HypreSolver;
00096 
00097   public:
00098     typedef Eigen::VectorXd Vector;
00099     typedef Eigen::SparseMatrix< double, Eigen::RowMajor > MOABSparseMatrix;
00100     // typedef template Eigen::ArrayXX<T> Array2D<T>;
00101 
00102   public:
00103     /// An empty matrix to be used as a reference to an existing matrix
00104     HypreParMatrix( moab::ParallelComm* p_comm );
00105 
00106     /// Converts hypre's format to HypreParMatrix
00107     HypreParMatrix( HYPRE_IJMatrix a )
00108     {
00109         Init();
00110         A      = a;
00111         height = GetNumRows();
00112         width  = GetNumCols();
00113     }
00114 
00115     /** Creates block-diagonal square parallel matrix. Diagonal is given by diag
00116         which must be in CSR format (finalized). The new HypreParMatrix does not
00117         take ownership of any of the input arrays. */
00118     HypreParMatrix( moab::ParallelComm* p_comm, HYPRE_Int glob_size, HYPRE_Int* row_starts, HYPRE_Int nnz_pr_diag = 0 );
00119 
00120     /** Creates block-diagonal rectangular parallel matrix. Diagonal is given by
00121         diag which must be in CSR format (finalized). The new HypreParMatrix does
00122         not take ownership of any of the input arrays. */
00123     HypreParMatrix( moab::ParallelComm* p_comm,
00124                     HYPRE_Int global_num_rows,
00125                     HYPRE_Int global_num_cols,
00126                     HYPRE_Int* row_starts,
00127                     HYPRE_Int* col_starts,
00128                     HYPRE_Int nnz_pr_diag    = 0,
00129                     HYPRE_Int onz_pr_diag    = 0,
00130                     HYPRE_Int nnz_pr_offdiag = 0 );
00131 
00132     /** Creates a general parallel matrix from a local CSR matrix on each
00133         processor described by the I, J and data arrays. The local matrix should
00134         be of size (local) nrows by (global) glob_ncols. The new parallel matrix
00135         contains copies of all input arrays (so they can be deleted). */
00136     // HypreParMatrix(MPI_Comm comm, int nrows, HYPRE_Int glob_nrows,
00137     //                HYPRE_Int glob_ncols, int *I, HYPRE_Int *J,
00138     //                double *data, HYPRE_Int *rows, HYPRE_Int *cols);
00139 
00140     /// Make this HypreParMatrix a reference to 'master'
00141     void MakeRef( const HypreParMatrix& master );
00142 
00143     /// MPI communicator
00144     moab::ParallelComm* GetParallelCommunicator() const
00145     {
00146         return pcomm;
00147     }
00148 
00149     /// Typecasting to hypre's HYPRE_IJMatrix*
00150     operator HYPRE_IJMatrix()
00151     {
00152         return A;
00153     }
00154     /// Typecasting to hypre's HYPRE_ParCSRMatrix, a.k.a. void *
00155     operator HYPRE_ParCSRMatrix()
00156     {
00157         return (HYPRE_ParCSRMatrix)A_parcsr;
00158     }
00159 
00160     /// Changes the ownership of the matrix
00161     HYPRE_IJMatrix StealData();
00162     /// Changes the ownership of the matrix to A
00163     void StealData( HypreParMatrix& A );
00164 
00165     /** If the HypreParMatrix does not own the row-starts array, make a copy of
00166         it that the HypreParMatrix will own. If the col-starts array is the same
00167         as the row-starts array, col-starts is also replaced. */
00168     // void CopyRowStarts();
00169     /** If the HypreParMatrix does not own the col-starts array, make a copy of
00170         it that the HypreParMatrix will own. If the row-starts array is the same
00171         as the col-starts array, row-starts is also replaced. */
00172     // void CopyColStarts();
00173 
00174     /// Returns the global number of nonzeros
00175     inline HYPRE_Int NNZ()
00176     {
00177         return A_parcsr->num_nonzeros;
00178     }
00179     /// Returns the row partitioning
00180     inline HYPRE_Int* RowPart()
00181     {
00182         return A->row_partitioning;
00183     }
00184     /// Returns the column partitioning
00185     inline HYPRE_Int* ColPart()
00186     {
00187         return A->col_partitioning;
00188     }
00189     /// Returns the global number of rows
00190     inline HYPRE_Int M()
00191     {
00192         return A->global_num_rows;
00193     }
00194     /// Returns the global number of columns
00195     inline HYPRE_Int N()
00196     {
00197         return A->global_num_cols;
00198     }
00199     /// Returns the global number of rows
00200     inline HYPRE_Int FirstRow()
00201     {
00202         return A->global_first_row;
00203     }
00204     /// Returns the global number of columns
00205     inline HYPRE_Int FirstCol()
00206     {
00207         return A->global_first_col;
00208     }
00209 
00210     /// Get the local diagonal of the matrix.
00211     void GetDiag( Vector& diag ) const;
00212     /// Get the local diagonal block. NOTE: 'diag' will not own any data.
00213     void GetDiag( MOABSparseMatrix& diag ) const;
00214     /// Get the local off-diagonal block. NOTE: 'offd' will not own any data.
00215     void GetOffd( MOABSparseMatrix& offd, HYPRE_Int*& cmap ) const;
00216 
00217     /** Split the matrix into M x N equally sized blocks of parallel matrices.
00218         The size of 'blocks' must already be set to M x N. */
00219     // void GetBlocks(Eigen::Array<HypreParMatrix*,Eigen::Dynamic,Eigen::Dynamic> &blocks,
00220     //                bool interleaved_rows = false,
00221     //                bool interleaved_cols = false) const;
00222 
00223     /// Returns the transpose of *this
00224     // HypreParMatrix * Transpose();
00225 
00226     /** Destroy and resize block-diagonal square parallel matrix. Diagonal is given by diag
00227         which must be in CSR format (finalized). The new HypreParMatrix does not
00228         take ownership of any of the input arrays. */
00229     void resize( HYPRE_Int glob_size, HYPRE_Int* row_starts, HYPRE_Int nnz_pr_diag = 0, HYPRE_Int nnz_pr_offdiag = 0 );
00230 
00231     /** Destroy and resize block-diagonal rectangular parallel matrix. Diagonal is given by
00232         diag which must be in CSR format (finalized). The new HypreParMatrix does
00233         not take ownership of any of the input arrays. */
00234     void resize( HYPRE_Int global_num_rows,
00235                  HYPRE_Int global_num_cols,
00236                  HYPRE_Int* row_starts,
00237                  HYPRE_Int* col_starts,
00238                  HYPRE_Int* nnz_pr_diag   = NULL,
00239                  HYPRE_Int* onz_pr_diag   = NULL,
00240                  HYPRE_Int nnz_pr_offdiag = 0 );
00241 
00242     /// Returns the number of rows in the diagonal block of the ParCSRMatrix
00243     int GetNumRows() const
00244     {
00245         return internal::to_int( hypre_CSRMatrixNumRows( hypre_ParCSRMatrixDiag( A_parcsr ) ) );
00246     }
00247 
00248     /// Returns the number of columns in the diagonal block of the ParCSRMatrix
00249     int GetNumCols() const
00250     {
00251         return internal::to_int( hypre_CSRMatrixNumCols( hypre_ParCSRMatrixDiag( A_parcsr ) ) );
00252     }
00253 
00254     /// Computes y = alpha * A * x + beta * y
00255     HYPRE_Int Mult( HypreParVector& x, HypreParVector& y, double alpha = 1.0, double beta = 0.0 );
00256     /// Computes y = alpha * A * x + beta * y
00257     HYPRE_Int Mult( HYPRE_ParVector x, HYPRE_ParVector y, double alpha = 1.0, double beta = 0.0 );
00258     /// Computes y = alpha * A^t * x + beta * y
00259     HYPRE_Int MultTranspose( HypreParVector& x, HypreParVector& y, double alpha = 1.0, double beta = 0.0 );
00260 
00261     void Mult( double a, const HypreParVector& x, double b, HypreParVector& y ) const;
00262     void MultTranspose( double a, const HypreParVector& x, double b, HypreParVector& y ) const;
00263 
00264     // virtual void Mult(const Vector &x, Vector &y) const
00265     // { Mult(1.0, x, 0.0, y); }
00266     // virtual void MultTranspose(const Vector &x, Vector &y) const
00267     // { MultTranspose(1.0, x, 0.0, y); }
00268 
00269     /** The "Boolean" analog of y = alpha * A * x + beta * y, where elements in
00270         the sparsity pattern of the matrix are treated as "true". */
00271     // void BooleanMult(int alpha, int *x, int beta, int *y)
00272     // {
00273     //    internal::hypre_ParCSRMatrixBooleanMatvec(A_parcsr, alpha, x, beta, y);
00274     // }
00275 
00276     /** Multiply A on the left by a block-diagonal parallel matrix D. Return
00277         a new parallel matrix, D*A. If D has a different number of rows than A,
00278         D's row starts array needs to be given (as returned by the methods
00279         GetDofOffsets/GetTrueDofOffsets of ParFiniteElementSpace). The new matrix
00280         D*A uses copies of the row-, column-starts arrays, so "this" matrix and
00281         "row_starts" can be deleted.
00282         NOTE: this operation is local and does not require communication. */
00283     // HypreParMatrix* LeftDiagMult(const MOABSparseMatrix &D,
00284     //                              HYPRE_Int* row_starts = NULL) const;
00285 
00286     /// Scale the local row i by s(i).
00287     void ScaleRows( const Vector& s );
00288     /// Scale the local row i by 1./s(i)
00289     void InvScaleRows( const Vector& s );
00290     /// Scale all entries by s: A_scaled = s*A.
00291     void operator*=( double s );
00292 
00293     /// Remove values smaller in absolute value than some threshold
00294     void Threshold( double threshold = 0.0 );
00295 
00296     /// If a row contains only zeros, set its diagonal to 1.
00297     void EliminateZeroRows()
00298     {
00299         hypre_ParCSRMatrixFixZeroRows( A_parcsr );
00300     }
00301 
00302     /** Eliminate rows and columns from the matrix, and rows from the vector B.
00303         Modify B with the BC values in X. */
00304     void EliminateRowsCols( const std::vector< HYPRE_Int >& rows_cols, const HypreParVector& X, HypreParVector& B );
00305 
00306     /** Eliminate rows and columns from the matrix and store the eliminated
00307         elements in a new matrix Ae (returned), so that the modified matrix and
00308         Ae sum to the original matrix. */
00309     HypreParMatrix* EliminateRowsCols( const std::vector< HYPRE_Int >& rows_cols );
00310 
00311     HYPRE_Int GetValues( const HYPRE_Int nrows,
00312                          HYPRE_Int* ncols,
00313                          HYPRE_Int* rows,
00314                          HYPRE_Int* cols,
00315                          HYPRE_Complex* values );
00316     HYPRE_Int SetValues( const HYPRE_Int nrows,
00317                          HYPRE_Int* ncols,
00318                          const HYPRE_Int* rows,
00319                          const HYPRE_Int* cols,
00320                          const HYPRE_Complex* values );
00321     HYPRE_Int AddToValues( const HYPRE_Int nrows,
00322                            HYPRE_Int* ncols,
00323                            const HYPRE_Int* rows,
00324                            const HYPRE_Int* cols,
00325                            const HYPRE_Complex* values );
00326 
00327     HYPRE_Int FinalizeAssembly();
00328 
00329     HYPRE_Int verbosity( const HYPRE_Int level );
00330 
00331     /// Prints the locally owned rows in parallel
00332     void Print( const char* fname, HYPRE_Int offi = 0, HYPRE_Int offj = 0 );
00333     /// Reads the matrix from a file
00334     void Read( const char* fname );
00335 
00336     /// Calls hypre's destroy function
00337     virtual ~HypreParMatrix()
00338     {
00339         Destroy();
00340     }
00341 
00342     /// Returns the matrix A * B
00343     friend HypreParMatrix* ParMult( HypreParMatrix* A, HypreParMatrix* B );
00344 
00345     /// Returns the matrix P^t * A * P
00346     friend HypreParMatrix* RAP( HypreParMatrix* A, HypreParMatrix* P );
00347     /// Returns the matrix Rt^t * A * P
00348     friend HypreParMatrix* RAP( HypreParMatrix* Rt, HypreParMatrix* A, HypreParMatrix* P );
00349 
00350     /** Eliminate essential BC specified by 'ess_dof_list' from the solution X to
00351         the r.h.s. B. Here A is a matrix with eliminated BC, while Ae is such that
00352         (A+Ae) is the original (Neumann) matrix before elimination. */
00353     friend void EliminateBC( HypreParMatrix& A,
00354                              HypreParMatrix& Ae,
00355                              const std::vector< int >& ess_dof_list,
00356                              const HypreParVector& X,
00357                              HypreParVector& B );
00358 
00359     friend class HypreSolver;
00360 };
00361 
00362 }  // namespace moab
00363 
00364 #endif  // MOAB_HAVE_MPI
00365 
00366 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines