1 // The libMesh Finite Element Library. 2 // Copyright (C) 2002-2020 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 3 4 // This library is free software; you can redistribute it and/or 5 // modify it under the terms of the GNU Lesser General Public 6 // License as published by the Free Software Foundation; either 7 // version 2.1 of the License, or (at your option) any later version. 8 9 // This library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 // Lesser General Public License for more details. 13 14 // You should have received a copy of the GNU Lesser General Public 15 // License along with this library; if not, write to the Free Software 16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 18 19 20 #ifndef LIBMESH_SPARSE_MATRIX_H 21 #define LIBMESH_SPARSE_MATRIX_H 22 23 24 // Local includes 25 #include "libmesh/libmesh.h" 26 #include "libmesh/libmesh_common.h" 27 #include "libmesh/id_types.h" 28 #include "libmesh/reference_counted_object.h" 29 #include "libmesh/parallel_object.h" 30 #include "libmesh/enum_parallel_type.h" 31 32 // C++ includes 33 #include <cstddef> 34 #include <iomanip> 35 #include <vector> 36 #include <memory> 37 38 namespace libMesh 39 { 40 41 // forward declarations 42 template <typename T> class SparseMatrix; 43 template <typename T> class DenseMatrix; 44 class DofMap; 45 namespace SparsityPattern { class Graph; } 46 template <typename T> class NumericVector; 47 48 // This template helper function must be declared before it 49 // can be defined below. 50 template <typename T> 51 std::ostream & operator << (std::ostream & os, const SparseMatrix<T> & m); 52 53 54 /** 55 * Generic sparse matrix. This class contains pure virtual members 56 * that must be overridden in derived classes. Using a common base 57 * class allows for uniform access to sparse matrices from various 58 * different solver packages in different formats. 59 * 60 * \author Benjamin S. Kirk 61 * \date 2003 62 */ 63 template <typename T> 64 class SparseMatrix : public ReferenceCountedObject<SparseMatrix<T>>, 65 public ParallelObject 66 { 67 public: 68 /** 69 * Constructor; initializes the matrix to be empty, without any 70 * structure, i.e. the matrix is not usable at all. This 71 * constructor is therefore only useful for matrices which are 72 * members of a class. All other matrices should be created at a 73 * point in the data flow where all necessary information is 74 * available. 75 * 76 * You have to initialize the matrix before usage with 77 * \p init(...). 78 */ 79 explicit 80 SparseMatrix (const Parallel::Communicator & comm); 81 82 /** 83 * The 5 special functions can be defaulted for this class, as it 84 * does not manage any memory itself. 85 */ 86 SparseMatrix (SparseMatrix &&) = default; 87 SparseMatrix (const SparseMatrix &) = default; 88 SparseMatrix & operator= (const SparseMatrix &) = default; 89 SparseMatrix & operator= (SparseMatrix &&) = default; 90 virtual ~SparseMatrix () = default; 91 92 /** 93 * Builds a \p SparseMatrix<T> using the linear solver package specified by 94 * \p solver_package 95 */ 96 static std::unique_ptr<SparseMatrix<T>> 97 build(const Parallel::Communicator & comm, 98 const SolverPackage solver_package = libMesh::default_solver_package()); 99 100 /** 101 * \returns \p true if the matrix has been initialized, 102 * \p false otherwise. 103 */ initialized()104 virtual bool initialized() const { return _is_initialized; } 105 106 /** 107 * Get a pointer to the \p DofMap to use. 108 */ attach_dof_map(const DofMap & dof_map)109 void attach_dof_map (const DofMap & dof_map) 110 { _dof_map = &dof_map; } 111 112 /** 113 * \returns \p true if this sparse matrix format needs to be fed the 114 * graph of the sparse matrix. 115 * 116 * This is true for \p LaspackMatrix, but not \p PetscMatrix. In 117 * the case where the full graph is not required, we can efficiently 118 * approximate it to provide a good estimate of the required size of 119 * the sparse matrix. 120 */ need_full_sparsity_pattern()121 virtual bool need_full_sparsity_pattern() const 122 { return false; } 123 124 /** 125 * Updates the matrix sparsity pattern. When your \p SparseMatrix<T> 126 * implementation does not need this data, simply do not override 127 * this method. 128 */ update_sparsity_pattern(const SparsityPattern::Graph &)129 virtual void update_sparsity_pattern (const SparsityPattern::Graph &) {} 130 131 /** 132 * Initialize SparseMatrix with the specified sizes. 133 * 134 * \param m The global number of rows. 135 * \param n The global number of columns. 136 * \param m_l The local number of rows. 137 * \param n_l The local number of columns. 138 * \param nnz The number of on-diagonal nonzeros per row (defaults to 30). 139 * \param noz The number of off-diagonal nonzeros per row (defaults to 10). 140 * \param blocksize Optional value indicating dense coupled blocks 141 * for systems with multiple variables all of the same type. 142 */ 143 virtual void init (const numeric_index_type m, 144 const numeric_index_type n, 145 const numeric_index_type m_l, 146 const numeric_index_type n_l, 147 const numeric_index_type nnz=30, 148 const numeric_index_type noz=10, 149 const numeric_index_type blocksize=1) = 0; 150 151 /** 152 * Initialize this matrix using the sparsity structure computed by \p dof_map. 153 * @param type The serial/parallel/ghosted type of the matrix 154 */ 155 virtual void init (ParallelType type = PARALLEL) = 0; 156 157 /** 158 * Restores the \p SparseMatrix<T> to a pristine state. 159 */ 160 virtual void clear () = 0; 161 162 /** 163 * Set all entries to 0. 164 */ 165 virtual void zero () = 0; 166 167 /** 168 * \returns A smart pointer to a copy of this matrix with the same 169 * type, size, and partitioning, but with all zero entries. 170 * 171 * \note This must be overridden in the derived classes. 172 */ 173 virtual std::unique_ptr<SparseMatrix<T>> zero_clone () const = 0; 174 175 /** 176 * \returns A smart pointer to a copy of this matrix. 177 * 178 * \note This must be overridden in the derived classes. 179 */ 180 virtual std::unique_ptr<SparseMatrix<T>> clone () const = 0; 181 182 /** 183 * Sets all row entries to 0 then puts \p diag_value in the diagonal entry. 184 */ 185 virtual void zero_rows (std::vector<numeric_index_type> & rows, T diag_value = 0.0); 186 187 /** 188 * Calls the SparseMatrix's internal assembly routines, ensuring 189 * that the values are consistent across processors. 190 */ 191 virtual void close () = 0; 192 193 /** 194 * For PETSc matrix , this function is similar to close but without shrinking memory. 195 * This is useful when we want to switch between ADD_VALUES and INSERT_VALUES. 196 * close should be called before using the matrix. 197 */ flush()198 virtual void flush () { close(); } 199 200 /** 201 * \returns The row-dimension of the matrix. 202 */ 203 virtual numeric_index_type m () const = 0; 204 205 /** 206 * Get the number of rows owned by this process 207 */ local_m()208 virtual numeric_index_type local_m () const { return row_stop() - row_start(); } 209 210 /** 211 * \returns The column-dimension of the matrix. 212 */ 213 virtual numeric_index_type n () const = 0; 214 215 /** 216 * \returns The index of the first matrix row stored on this 217 * processor. 218 */ 219 virtual numeric_index_type row_start () const = 0; 220 221 /** 222 * \returns The index of the last matrix row (+1) stored on this 223 * processor. 224 */ 225 virtual numeric_index_type row_stop () const = 0; 226 227 /** 228 * Set the element \p (i,j) to \p value. Throws an error if the 229 * entry does not exist. Zero values can be "stored" in non-existent 230 * fields. 231 */ 232 virtual void set (const numeric_index_type i, 233 const numeric_index_type j, 234 const T value) = 0; 235 236 /** 237 * Add \p value to the element \p (i,j). Throws an error if the 238 * entry does not exist. Zero values can be "added" to non-existent 239 * entries. 240 */ 241 virtual void add (const numeric_index_type i, 242 const numeric_index_type j, 243 const T value) = 0; 244 245 /** 246 * Add the full matrix \p dm to the SparseMatrix. This is useful 247 * for adding an element matrix at assembly time. 248 */ 249 virtual void add_matrix (const DenseMatrix<T> & dm, 250 const std::vector<numeric_index_type> & rows, 251 const std::vector<numeric_index_type> & cols) = 0; 252 253 /** 254 * Same as \p add_matrix, but assumes the row and column maps are the same. 255 * Thus the matrix \p dm must be square. 256 */ 257 virtual void add_matrix (const DenseMatrix<T> & dm, 258 const std::vector<numeric_index_type> & dof_indices) = 0; 259 260 /** 261 * Add the full matrix \p dm to the SparseMatrix. This is useful 262 * for adding an element matrix at assembly time. The matrix is 263 * assumed blocked, and \p brow, \p bcol correspond to the *block* 264 * row and column indices. 265 */ 266 virtual void add_block_matrix (const DenseMatrix<T> & dm, 267 const std::vector<numeric_index_type> & brows, 268 const std::vector<numeric_index_type> & bcols); 269 270 /** 271 * Same as \p add_block_matrix(), but assumes the row and column 272 * maps are the same. Thus the matrix \p dm must be square. 273 */ add_block_matrix(const DenseMatrix<T> & dm,const std::vector<numeric_index_type> & dof_indices)274 virtual void add_block_matrix (const DenseMatrix<T> & dm, 275 const std::vector<numeric_index_type> & dof_indices) 276 { this->add_block_matrix (dm, dof_indices, dof_indices); } 277 278 /** 279 * Compute \f$ A \leftarrow A + a*X \f$ for scalar \p a, matrix \p X. 280 */ 281 virtual void add (const T a, const SparseMatrix<T> & X) = 0; 282 283 /** 284 * Compute Y = A*X for matrix \p X. 285 */ matrix_matrix_mult(SparseMatrix<T> &,SparseMatrix<T> &)286 virtual void matrix_matrix_mult (SparseMatrix<T> & /*X*/, SparseMatrix<T> & /*Y*/) 287 { libmesh_not_implemented(); } 288 289 /** 290 * Add \p scalar* \p spm to the rows and cols of this matrix (A): 291 * A(rows[i], cols[j]) += scalar * spm(i,j) 292 */ add_sparse_matrix(const SparseMatrix<T> &,const std::map<numeric_index_type,numeric_index_type> &,const std::map<numeric_index_type,numeric_index_type> &,const T)293 virtual void add_sparse_matrix (const SparseMatrix<T> & /*spm*/, 294 const std::map<numeric_index_type, numeric_index_type> & /*rows*/, 295 const std::map<numeric_index_type, numeric_index_type> & /*cols*/, 296 const T /*scalar*/) 297 { libmesh_not_implemented(); } 298 299 /** 300 * \returns A copy of matrix entry \p (i,j). 301 * 302 * \note This may be an expensive operation, and you should always 303 * be careful where you call this function. 304 */ 305 virtual T operator () (const numeric_index_type i, 306 const numeric_index_type j) const = 0; 307 308 /** 309 * \returns The \f$ \ell_1 \f$-norm of the matrix, that is the max column sum: 310 * \f$ |M|_1 = \max_{j} \sum_{i} |M_{ij}| \f$ 311 * 312 * This is the natural matrix norm that is compatible with the 313 * \f$ \ell_1 \f$-norm for vectors, i.e. \f$ |Mv|_1 \leq |M|_1 |v|_1 \f$. 314 * (cf. Haemmerlin-Hoffmann : Numerische Mathematik) 315 */ 316 virtual Real l1_norm () const = 0; 317 318 /** 319 * \returns The \f$ \ell_{\infty} \f$-norm of the matrix, that is the max row sum: 320 * 321 * \f$ |M|_{\infty} = \max_{i} \sum_{j} |M_{ij}| \f$ 322 * 323 * This is the natural matrix norm that is compatible to the 324 * \f$ \ell_{\infty} \f$-norm of vectors, i.e. 325 * \f$ |Mv|_{\infty} \leq |M|_{\infty} |v|_{\infty} \f$. 326 * (cf. Haemmerlin-Hoffmann : Numerische Mathematik) 327 */ 328 virtual Real linfty_norm () const = 0; 329 330 /** 331 * \returns \p true if the matrix has been assembled. 332 */ 333 virtual bool closed() const = 0; 334 335 /** 336 * Print the contents of the matrix to the screen in a uniform 337 * style, regardless of matrix/solver package being used. 338 */ 339 void print(std::ostream & os=libMesh::out, const bool sparse=false) const; 340 341 /** 342 * Same as the print method above, but allows you to print to a 343 * stream in the standard syntax. 344 * 345 * \code 346 * template <typename U> 347 * friend std::ostream & operator << (std::ostream & os, const SparseMatrix<U> & m); 348 * \endcode 349 * 350 * \note The above syntax, which does not require any 351 * prior declaration of operator<<, declares *any* instantiation of 352 * SparseMatrix<X> is friend to *any* instantiation of 353 * operator<<(ostream &, SparseMatrix<Y> &). It would not happen in 354 * practice, but in principle it means that SparseMatrix<Complex> 355 * would be friend to operator<<(ostream &, SparseMatrix<Real>). 356 * 357 * \note The form below, which requires a previous 358 * declaration of the operator<<(stream &, SparseMatrix<T> &) function 359 * (see top of this file), means that any instantiation of 360 * SparseMatrix<T> is friend to the specialization 361 * operator<<(ostream &, SparseMatrix<T> &), but e.g. SparseMatrix<U> 362 * is *not* friend to the same function. So this is slightly 363 * different to the form above... 364 * 365 * This method seems to be the "preferred" technique, see 366 * http://www.parashift.com/c++-faq-lite/template-friends.html 367 */ 368 friend std::ostream & operator << <>(std::ostream & os, const SparseMatrix<T> & m); 369 370 /** 371 * Print the contents of the matrix to the screen in a 372 * package-personalized style, if available. 373 */ 374 virtual void print_personal(std::ostream & os=libMesh::out) const = 0; 375 376 /** 377 * Print the contents of the matrix in Matlab's sparse matrix 378 * format. Optionally prints the matrix to the file named \p name. 379 * If \p name is not specified it is dumped to the screen. 380 */ 381 virtual void print_matlab(const std::string & /*name*/ = "") const 382 { 383 libmesh_not_implemented(); 384 } 385 386 /** 387 * This function creates a matrix called "submatrix" which is defined 388 * by the row and column indices given in the "rows" and "cols" entries. 389 * Currently this operation is only defined for the PetscMatrix type. 390 */ create_submatrix(SparseMatrix<T> & submatrix,const std::vector<numeric_index_type> & rows,const std::vector<numeric_index_type> & cols)391 virtual void create_submatrix(SparseMatrix<T> & submatrix, 392 const std::vector<numeric_index_type> & rows, 393 const std::vector<numeric_index_type> & cols) const 394 { 395 this->_get_submatrix(submatrix, 396 rows, 397 cols, 398 false); // false means DO NOT REUSE submatrix 399 } 400 401 /** 402 * This function is similar to the one above, but it allows you to reuse 403 * the existing sparsity pattern of "submatrix" instead of reallocating 404 * it again. This should hopefully be more efficient if you are frequently 405 * extracting submatrices of the same size. 406 */ reinit_submatrix(SparseMatrix<T> & submatrix,const std::vector<numeric_index_type> & rows,const std::vector<numeric_index_type> & cols)407 virtual void reinit_submatrix(SparseMatrix<T> & submatrix, 408 const std::vector<numeric_index_type> & rows, 409 const std::vector<numeric_index_type> & cols) const 410 { 411 this->_get_submatrix(submatrix, 412 rows, 413 cols, 414 true); // true means REUSE submatrix 415 } 416 417 /** 418 * Multiplies the matrix by the NumericVector \p arg and stores the 419 * result in NumericVector \p dest. 420 */ 421 void vector_mult (NumericVector<T> & dest, 422 const NumericVector<T> & arg) const; 423 424 /** 425 * Multiplies the matrix by the NumericVector \p arg and adds the 426 * result to the NumericVector \p dest. 427 */ 428 void vector_mult_add (NumericVector<T> & dest, 429 const NumericVector<T> & arg) const; 430 431 /** 432 * Copies the diagonal part of the matrix into \p dest. 433 */ 434 virtual void get_diagonal (NumericVector<T> & dest) const = 0; 435 436 /** 437 * Copies the transpose of the matrix into \p dest, which may be 438 * *this. 439 */ 440 virtual void get_transpose (SparseMatrix<T> & dest) const = 0; 441 442 /** 443 * Get a row from the matrix 444 * @param i The matrix row to get 445 * @param indices A container that will be filled with the column indices 446 * corresponding to (possibly) non-zero values 447 * @param values A container holding the column values 448 */ get_row(numeric_index_type,std::vector<numeric_index_type> &,std::vector<T> &)449 virtual void get_row(numeric_index_type /*i*/, 450 std::vector<numeric_index_type> & /*indices*/, 451 std::vector<T> & /*values*/) const 452 { 453 libmesh_not_implemented(); 454 } 455 456 protected: 457 458 /** 459 * Protected implementation of the create_submatrix and reinit_submatrix 460 * routines. 461 * 462 * \note This function must be overridden in derived classes for it 463 * to work properly! 464 */ _get_submatrix(SparseMatrix<T> &,const std::vector<numeric_index_type> &,const std::vector<numeric_index_type> &,const bool)465 virtual void _get_submatrix(SparseMatrix<T> & /*submatrix*/, 466 const std::vector<numeric_index_type> & /*rows*/, 467 const std::vector<numeric_index_type> & /*cols*/, 468 const bool /*reuse_submatrix*/) const 469 { 470 libmesh_not_implemented(); 471 } 472 473 /** 474 * The \p DofMap object associated with this object. 475 */ 476 DofMap const * _dof_map; 477 478 /** 479 * Flag indicating whether or not the matrix has been initialized. 480 */ 481 bool _is_initialized; 482 }; 483 484 485 486 //----------------------------------------------------------------------- 487 // SparseMatrix inline members 488 489 // For SGI MIPSpro this implementation must occur after 490 // the full specialization of the print() member. 491 // 492 // It's generally easier to define these friend functions in the header 493 // file. 494 template <typename T> 495 std::ostream & operator << (std::ostream & os, const SparseMatrix<T> & m) 496 { 497 m.print(os); 498 return os; 499 } 500 501 502 } // namespace libMesh 503 504 505 #endif // LIBMESH_SPARSE_MATRIX_H 506