Loading [MathJax]/extensions/tex2jax.js
Mesh Oriented datABase  (version 5.5.1)
An array-based unstructured mesh library
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
HypreParMatrix.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.org. 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 /// This HYPRE library interface has been taken originally from MFEM and modified 13 /// to suit the needs for the MOAB library. 14 /// Modified by: Vijay Mahadevan 15  16 #ifndef MOAB_HYPREPARMATRIX 17 #define MOAB_HYPREPARMATRIX 18  19 #include "moab/MOABConfig.h" 20 #include "moab/Core.hpp" 21  22 #ifdef MOAB_HAVE_EIGEN3 23 #include <Eigen/Core> 24 #include <Eigen/Sparse> 25 #else 26 #error Configure with Eigen3 enabled 27 #endif 28  29 #ifdef MOAB_HAVE_MPI 30 #include "moab/ParallelComm.hpp" 31  32 // hypre header files 33 // #include "HYPRE.h" 34 // #include "HYPRE_parcsr_ls.h" 35 // #include "HYPRE_MatvecFunctions.h" 36  37 #include "seq_mv.h" 38 #include "HypreParVector.hpp" 39 #include "_hypre_parcsr_mv.h" 40 #include "_hypre_parcsr_ls.h" 41 #include "interpreter.h" 42 #include "HYPRE_MatvecFunctions.h" 43  44 #include "temp_multivector.h" 45  46 #ifdef HYPRE_COMPLEX 47 #error "MOAB does not work with HYPRE's complex numbers support" 48 #endif 49  50 #include "hypre_parcsr.hpp" 51  52 namespace moab 53 { 54  55 namespace internal 56 { 57  58  // Convert a HYPRE_Int to int 59  inline int to_int( HYPRE_Int i ) 60  { 61 #ifdef HYPRE_BIGINT 62  MFEM_ASSERT( HYPRE_Int( int( i ) ) == i, "overflow converting HYPRE_Int to int" ); 63 #endif 64  return int( i ); 65  } 66  67 } // namespace internal 68  69 /// Wrapper for hypre's ParCSR matrix class 70 class HypreParMatrix 71 { 72  private: 73  /// The actual object 74  HYPRE_IJMatrix A; 75  hypre_ParCSRMatrix* A_parcsr; 76  77  mv_InterfaceInterpreter* interpreter; 78  79  // Does the object own the pointer A? 80  char ParCSROwner; 81  82  // Store the dimensions of the matrix 83  int height, gnrows; 84  int width, gncols; 85  86  moab::ParallelComm* pcomm; 87  char initialized; 88  89  // Initialize with defaults. Does not initialize inherited members. 90  void Init(); 91  92  // Delete all owned data. Does not perform re-initialization with defaults. 93  void Destroy(); 94  95  friend class HypreSolver; 96  97  public: 98  typedef Eigen::VectorXd Vector; 99  typedef Eigen::SparseMatrix< double, Eigen::RowMajor > MOABSparseMatrix; 100  // typedef template Eigen::ArrayXX<T> Array2D<T>; 101  102  public: 103  /// An empty matrix to be used as a reference to an existing matrix 104  HypreParMatrix( moab::ParallelComm* p_comm ); 105  106  /// Converts hypre's format to HypreParMatrix 107  HypreParMatrix( HYPRE_IJMatrix a ) 108  { 109  Init(); 110  A = a; 111  height = GetNumRows(); 112  width = GetNumCols(); 113  } 114  115  /** Creates block-diagonal square parallel matrix. Diagonal is given by diag 116  which must be in CSR format (finalized). The new HypreParMatrix does not 117  take ownership of any of the input arrays. */ 118  HypreParMatrix( moab::ParallelComm* p_comm, HYPRE_Int glob_size, HYPRE_Int* row_starts, HYPRE_Int nnz_pr_diag = 0 ); 119  120  /** Creates block-diagonal rectangular parallel matrix. Diagonal is given by 121  diag which must be in CSR format (finalized). The new HypreParMatrix does 122  not take ownership of any of the input arrays. */ 123  HypreParMatrix( moab::ParallelComm* p_comm, 124  HYPRE_Int global_num_rows, 125  HYPRE_Int global_num_cols, 126  HYPRE_Int* row_starts, 127  HYPRE_Int* col_starts, 128  HYPRE_Int nnz_pr_diag = 0, 129  HYPRE_Int onz_pr_diag = 0, 130  HYPRE_Int nnz_pr_offdiag = 0 ); 131  132  /** Creates a general parallel matrix from a local CSR matrix on each 133  processor described by the I, J and data arrays. The local matrix should 134  be of size (local) nrows by (global) glob_ncols. The new parallel matrix 135  contains copies of all input arrays (so they can be deleted). */ 136  // HypreParMatrix(MPI_Comm comm, int nrows, HYPRE_Int glob_nrows, 137  // HYPRE_Int glob_ncols, int *I, HYPRE_Int *J, 138  // double *data, HYPRE_Int *rows, HYPRE_Int *cols); 139  140  /// Make this HypreParMatrix a reference to 'master' 141  void MakeRef( const HypreParMatrix& master ); 142  143  /// MPI communicator 144  moab::ParallelComm* GetParallelCommunicator() const 145  { 146  return pcomm; 147  } 148  149  /// Typecasting to hypre's HYPRE_IJMatrix* 150  operator HYPRE_IJMatrix() 151  { 152  return A; 153  } 154  /// Typecasting to hypre's HYPRE_ParCSRMatrix, a.k.a. void * 155  operator HYPRE_ParCSRMatrix() 156  { 157  return (HYPRE_ParCSRMatrix)A_parcsr; 158  } 159  160  /// Changes the ownership of the matrix 161  HYPRE_IJMatrix StealData(); 162  /// Changes the ownership of the matrix to A 163  void StealData( HypreParMatrix& A ); 164  165  /** If the HypreParMatrix does not own the row-starts array, make a copy of 166  it that the HypreParMatrix will own. If the col-starts array is the same 167  as the row-starts array, col-starts is also replaced. */ 168  // void CopyRowStarts(); 169  /** If the HypreParMatrix does not own the col-starts array, make a copy of 170  it that the HypreParMatrix will own. If the row-starts array is the same 171  as the col-starts array, row-starts is also replaced. */ 172  // void CopyColStarts(); 173  174  /// Returns the global number of nonzeros 175  inline HYPRE_Int NNZ() 176  { 177  return A_parcsr->num_nonzeros; 178  } 179  /// Returns the row partitioning 180  inline HYPRE_Int* RowPart() 181  { 182  return A->row_partitioning; 183  } 184  /// Returns the column partitioning 185  inline HYPRE_Int* ColPart() 186  { 187  return A->col_partitioning; 188  } 189  /// Returns the global number of rows 190  inline HYPRE_Int M() 191  { 192  return A->global_num_rows; 193  } 194  /// Returns the global number of columns 195  inline HYPRE_Int N() 196  { 197  return A->global_num_cols; 198  } 199  /// Returns the global number of rows 200  inline HYPRE_Int FirstRow() 201  { 202  return A->global_first_row; 203  } 204  /// Returns the global number of columns 205  inline HYPRE_Int FirstCol() 206  { 207  return A->global_first_col; 208  } 209  210  /// Get the local diagonal of the matrix. 211  void GetDiag( Vector& diag ) const; 212  /// Get the local diagonal block. NOTE: 'diag' will not own any data. 213  void GetDiag( MOABSparseMatrix& diag ) const; 214  /// Get the local off-diagonal block. NOTE: 'offd' will not own any data. 215  void GetOffd( MOABSparseMatrix& offd, HYPRE_Int*& cmap ) const; 216  217  /** Split the matrix into M x N equally sized blocks of parallel matrices. 218  The size of 'blocks' must already be set to M x N. */ 219  // void GetBlocks(Eigen::Array<HypreParMatrix*,Eigen::Dynamic,Eigen::Dynamic> &blocks, 220  // bool interleaved_rows = false, 221  // bool interleaved_cols = false) const; 222  223  /// Returns the transpose of *this 224  // HypreParMatrix * Transpose(); 225  226  /** Destroy and resize block-diagonal square parallel matrix. Diagonal is given by diag 227  which must be in CSR format (finalized). The new HypreParMatrix does not 228  take ownership of any of the input arrays. */ 229  void resize( HYPRE_Int glob_size, HYPRE_Int* row_starts, HYPRE_Int nnz_pr_diag = 0, HYPRE_Int nnz_pr_offdiag = 0 ); 230  231  /** Destroy and resize block-diagonal rectangular parallel matrix. Diagonal is given by 232  diag which must be in CSR format (finalized). The new HypreParMatrix does 233  not take ownership of any of the input arrays. */ 234  void resize( HYPRE_Int global_num_rows, 235  HYPRE_Int global_num_cols, 236  HYPRE_Int* row_starts, 237  HYPRE_Int* col_starts, 238  HYPRE_Int* nnz_pr_diag = NULL, 239  HYPRE_Int* onz_pr_diag = NULL, 240  HYPRE_Int nnz_pr_offdiag = 0 ); 241  242  /// Returns the number of rows in the diagonal block of the ParCSRMatrix 243  int GetNumRows() const 244  { 245  return internal::to_int( hypre_CSRMatrixNumRows( hypre_ParCSRMatrixDiag( A_parcsr ) ) ); 246  } 247  248  /// Returns the number of columns in the diagonal block of the ParCSRMatrix 249  int GetNumCols() const 250  { 251  return internal::to_int( hypre_CSRMatrixNumCols( hypre_ParCSRMatrixDiag( A_parcsr ) ) ); 252  } 253  254  /// Computes y = alpha * A * x + beta * y 255  HYPRE_Int Mult( HypreParVector& x, HypreParVector& y, double alpha = 1.0, double beta = 0.0 ); 256  /// Computes y = alpha * A * x + beta * y 257  HYPRE_Int Mult( HYPRE_ParVector x, HYPRE_ParVector y, double alpha = 1.0, double beta = 0.0 ); 258  /// Computes y = alpha * A^t * x + beta * y 259  HYPRE_Int MultTranspose( HypreParVector& x, HypreParVector& y, double alpha = 1.0, double beta = 0.0 ); 260  261  void Mult( double a, const HypreParVector& x, double b, HypreParVector& y ) const; 262  void MultTranspose( double a, const HypreParVector& x, double b, HypreParVector& y ) const; 263  264  // virtual void Mult(const Vector &x, Vector &y) const 265  // { Mult(1.0, x, 0.0, y); } 266  // virtual void MultTranspose(const Vector &x, Vector &y) const 267  // { MultTranspose(1.0, x, 0.0, y); } 268  269  /** The "Boolean" analog of y = alpha * A * x + beta * y, where elements in 270  the sparsity pattern of the matrix are treated as "true". */ 271  // void BooleanMult(int alpha, int *x, int beta, int *y) 272  // { 273  // internal::hypre_ParCSRMatrixBooleanMatvec(A_parcsr, alpha, x, beta, y); 274  // } 275  276  /** Multiply A on the left by a block-diagonal parallel matrix D. Return 277  a new parallel matrix, D*A. If D has a different number of rows than A, 278  D's row starts array needs to be given (as returned by the methods 279  GetDofOffsets/GetTrueDofOffsets of ParFiniteElementSpace). The new matrix 280  D*A uses copies of the row-, column-starts arrays, so "this" matrix and 281  "row_starts" can be deleted. 282  NOTE: this operation is local and does not require communication. */ 283  // HypreParMatrix* LeftDiagMult(const MOABSparseMatrix &D, 284  // HYPRE_Int* row_starts = NULL) const; 285  286  /// Scale the local row i by s(i). 287  void ScaleRows( const Vector& s ); 288  /// Scale the local row i by 1./s(i) 289  void InvScaleRows( const Vector& s ); 290  /// Scale all entries by s: A_scaled = s*A. 291  void operator*=( double s ); 292  293  /// Remove values smaller in absolute value than some threshold 294  void Threshold( double threshold = 0.0 ); 295  296  /// If a row contains only zeros, set its diagonal to 1. 297  void EliminateZeroRows() 298  { 299  hypre_ParCSRMatrixFixZeroRows( A_parcsr ); 300  } 301  302  /** Eliminate rows and columns from the matrix, and rows from the vector B. 303  Modify B with the BC values in X. */ 304  void EliminateRowsCols( const std::vector< HYPRE_Int >& rows_cols, const HypreParVector& X, HypreParVector& B ); 305  306  /** Eliminate rows and columns from the matrix and store the eliminated 307  elements in a new matrix Ae (returned), so that the modified matrix and 308  Ae sum to the original matrix. */ 309  HypreParMatrix* EliminateRowsCols( const std::vector< HYPRE_Int >& rows_cols ); 310  311  HYPRE_Int GetValues( const HYPRE_Int nrows, 312  HYPRE_Int* ncols, 313  HYPRE_Int* rows, 314  HYPRE_Int* cols, 315  HYPRE_Complex* values ); 316  HYPRE_Int SetValues( const HYPRE_Int nrows, 317  HYPRE_Int* ncols, 318  const HYPRE_Int* rows, 319  const HYPRE_Int* cols, 320  const HYPRE_Complex* values ); 321  HYPRE_Int AddToValues( const HYPRE_Int nrows, 322  HYPRE_Int* ncols, 323  const HYPRE_Int* rows, 324  const HYPRE_Int* cols, 325  const HYPRE_Complex* values ); 326  327  HYPRE_Int FinalizeAssembly(); 328  329  HYPRE_Int verbosity( const HYPRE_Int level ); 330  331  /// Prints the locally owned rows in parallel 332  void Print( const char* fname, HYPRE_Int offi = 0, HYPRE_Int offj = 0 ); 333  /// Reads the matrix from a file 334  void Read( const char* fname ); 335  336  /// Calls hypre's destroy function 337  virtual ~HypreParMatrix() 338  { 339  Destroy(); 340  } 341  342  /// Returns the matrix A * B 343  friend HypreParMatrix* ParMult( HypreParMatrix* A, HypreParMatrix* B ); 344  345  /// Returns the matrix P^t * A * P 346  friend HypreParMatrix* RAP( HypreParMatrix* A, HypreParMatrix* P ); 347  /// Returns the matrix Rt^t * A * P 348  friend HypreParMatrix* RAP( HypreParMatrix* Rt, HypreParMatrix* A, HypreParMatrix* P ); 349  350  /** Eliminate essential BC specified by 'ess_dof_list' from the solution X to 351  the r.h.s. B. Here A is a matrix with eliminated BC, while Ae is such that 352  (A+Ae) is the original (Neumann) matrix before elimination. */ 353  friend void EliminateBC( HypreParMatrix& A, 354  HypreParMatrix& Ae, 355  const std::vector< int >& ess_dof_list, 356  const HypreParVector& X, 357  HypreParVector& B ); 358  359  friend class HypreSolver; 360 }; 361  362 } // namespace moab 363  364 #endif // MOAB_HAVE_MPI 365  366 #endif