MFEM v4.10.0
Finite element discretization library
Loading...
Searching...
No Matches
sparsemat.hpp
Go to the documentation of this file.
1// Copyright (c) 2010-2026, Lawrence Livermore National Security, LLC. Produced
2// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
3// LICENSE and NOTICE for details. LLNL-CODE-806117.
4//
5// This file is part of the MFEM library. For more information and source code
6// availability visit https://mfem.org.
7//
8// MFEM is free software; you can redistribute it and/or modify it under the
9// terms of the BSD-3 license. We welcome feedback and contributions, see file
10// CONTRIBUTING.md for details.
11
12#ifndef MFEM_SPARSEMAT_HPP
13#define MFEM_SPARSEMAT_HPP
14
15// Data types for sparse matrix
16
20#include "../general/device.hpp"
21#include "../general/table.hpp"
23#include "densemat.hpp"
24
25#if defined(MFEM_USE_HIP)
26#if (HIP_VERSION_MAJOR * 100 + HIP_VERSION_MINOR) < 502
27#include <hipsparse.h>
28#else
29#include <hipsparse/hipsparse.h>
30#endif
31#endif
32
33
34namespace mfem
35{
36
37class
38#if defined(__alignas_is_defined)
39 alignas(real_t)
40#endif
42{
43public:
46 int Column;
47};
48
49/// Data type sparse matrix
51{
52public:
53 /** @brief Use the GPU vendor sparse library (cusparse/hipsparse), if
54 available, for sparse matrix operations. True by default. */
55 /** Performance is expected to be worse when set to false on the GPU, only
56 use false for debugging. This has no effect on CPUs.
57 */
59
60protected:
61 /// @name Arrays used by the CSR storage format.
62 /** */
63 ///@{
64 /// @brief %Array with size (#height+1) containing the row offsets.
65 /** The data for row r, 0 <= r < height, is at offsets j, I[r] <= j < I[r+1].
66 The offsets, j, are indices in the #J and #A arrays. The first entry in
67 this array is always zero, I[0] = 0, and the last entry, I[height], gives
68 the total number of entries stored (at a minimum, all nonzeros must be
69 represented) in the sparse matrix. */
71 /** @brief %Array with size #I[#height], containing the column indices for
72 all matrix entries, as indexed by the #I array. */
74 /** @brief %Array with size #I[#height], containing the actual entries of the
75 sparse matrix, as indexed by the #I array. */
77 ///@}
78
79 /** @brief %Array of linked lists, one for every row. This array represents
80 the linked list (LIL) storage format. */
82
83 mutable int current_row;
84 mutable int* ColPtrJ;
85 mutable RowNode ** ColPtrNode;
86
87 /// Transpose of A. Owned. Used to perform MultTranspose() on devices.
88 mutable SparseMatrix *At;
89
90#ifdef MFEM_USE_MEMALLOC
91 typedef MemAlloc <RowNode, 1024> RowNodeAlloc;
93#endif
94
95 /// Are the columns sorted already.
97
98 void Destroy(); // Delete all owned data
99 void SetEmpty(); // Init all entries with empty values
100
101 bool useGPUSparse = true; // Use cuSPARSE or hipSPARSE if available
102
103 // Initialize cuSPARSE/hipSPARSE
104 void InitGPUSparse();
105
106#ifdef MFEM_USE_CUDA_OR_HIP
107 // common for hipSPARSE and cuSPARSE
109 mutable bool initBuffers = false;
110
111#if defined(MFEM_USE_CUDA) && CUDA_VERSION >= 12300 && CUDA_VERSION < 12602
112 // Workaround for bug CUSPARSE-1897
113#define MFEM_CUDA_1897_WORKAROUND
114 mutable size_t bufferSize = 0;
115 mutable void *dBuffer = nullptr;
116#else
117 static size_t bufferSize;
118 static void *dBuffer;
119#endif
120
121#if defined(MFEM_USE_CUDA)
122 cusparseStatus_t status;
123 static cusparseHandle_t handle;
124 cusparseMatDescr_t descr = 0;
125
126#if CUDA_VERSION >= 10010
127 mutable cusparseSpMatDescr_t matA_descr;
128 mutable cusparseDnVecDescr_t vecX_descr;
129 mutable cusparseDnVecDescr_t vecY_descr;
130#else // CUDA_VERSION >= 10010
131 mutable cusparseMatDescr_t matA_descr;
132#endif // CUDA_VERSION >= 10010
133
134#else // defined(MFEM_USE_CUDA)
135 hipsparseStatus_t status;
136 static hipsparseHandle_t handle;
137 hipsparseMatDescr_t descr = 0;
138
139 mutable hipsparseSpMatDescr_t matA_descr;
140 mutable hipsparseDnVecDescr_t vecX_descr;
141 mutable hipsparseDnVecDescr_t vecY_descr;
142#endif // defined(MFEM_USE_CUDA)
143#endif // MFEM_USE_CUDA_OR_HIP
144
145public:
146 /// Create an empty SparseMatrix.
148 {
149 SetEmpty();
150
152 }
153
154 /** @brief Create a sparse matrix with flexible sparsity structure using a
155 row-wise linked list (LIL) format. */
156 /** New entries are added as needed by methods like AddSubMatrix(),
157 SetSubMatrix(), etc. Calling Finalize() will convert the SparseMatrix to
158 the more compact compressed sparse row (CSR) format. */
159 explicit SparseMatrix(int nrows, int ncols = -1);
160
161 /** @brief Create a sparse matrix in CSR format. Ownership of @a i, @a j, and
162 @a data is transferred to the SparseMatrix. */
163 SparseMatrix(int *i, int *j, real_t *data, int m, int n);
164
165 /** @brief Create a sparse matrix in CSR format. Ownership of @a i, @a j, and
166 @a data is optionally transferred to the SparseMatrix. */
167 /** If the parameter @a data is NULL, then the internal #A array is allocated
168 by this constructor (initializing it with zeros and taking ownership,
169 regardless of the parameter @a owna). */
170 SparseMatrix(int *i, int *j, real_t *data, int m, int n, bool ownij,
171 bool owna, bool issorted);
172
173 /** @brief Create a sparse matrix in CSR format where each row has space
174 allocated for exactly @a rowsize entries. */
175 /** SetRow() can then be called or the #I, #J, #A arrays can be used
176 directly. */
177 SparseMatrix(int nrows, int ncols, int rowsize);
178
179 /// Copy constructor (deep copy).
180 /** If @a mat is finalized and @a copy_graph is false, the #I and #J arrays
181 will use a shallow copy (copy the pointers only) without transferring
182 ownership.
183 If @a mt is MemoryType::PRESERVE the memory type of the resulting
184 SparseMatrix's #I, #J, and #A arrays will be the same as @a mat,
185 otherwise the type will be @a mt for those arrays that are deep
186 copied. */
187 SparseMatrix(const SparseMatrix &mat, bool copy_graph = true,
189
190 /// Create a SparseMatrix with diagonal @a v, i.e. A = Diag(v)
191 SparseMatrix(const Vector & v);
192
193 /// @brief Sets the height and width of the matrix.
194 /** @warning This does not modify in any way the underlying CSR or LIL
195 representation of the matrix.
196
197 This function should generally be called when manually constructing the
198 CSR #I, #J, and #A arrays in conjunction with the
199 SparseMatrix::SparseMatrix() constructor. */
200 void OverrideSize(int height_, int width_);
201
202 /** @brief Runtime option to use cuSPARSE or hipSPARSE. Only valid when using
203 a CUDA or HIP backend.
204
205 @note This option is enabled by default, so typically one would use this
206 method to disable the use of cuSPARSE/hipSPARSE. */
207 void UseGPUSparse(bool useGPUSparse_ = true) { useGPUSparse = useGPUSparse_;}
208 /// Deprecated equivalent of UseGPUSparse().
209 MFEM_DEPRECATED
210 void UseCuSparse(bool useCuSparse_ = true) { UseGPUSparse(useCuSparse_); }
211
212 /// Assignment operator: deep copy
214
215 /** @brief Clear the contents of the SparseMatrix and make it a reference to
216 @a master */
217 /** After this call, the matrix will point to the same data as @a master but
218 it will not own its data. The @a master must be finalized. */
219 void MakeRef(const SparseMatrix &master);
220
221 /// For backward compatibility, define Size() to be synonym of Height().
222 int Size() const { return Height(); }
223
224 /// Clear the contents of the SparseMatrix.
225 void Clear() { Destroy(); SetEmpty(); }
226
227 /** @brief Clear the cuSPARSE/hipSPARSE descriptors.
228 This must be called after releasing the device memory of A. */
229 void ClearGPUSparse();
230 /// Deprecated equivalent of ClearGPUSparse().
231 MFEM_DEPRECATED
233
234 /// Check if the SparseMatrix is empty.
235 bool Empty() const { return A.Empty() && (Rows == NULL); }
236
237 /// Return the array #I.
238 inline int *GetI() { return I; }
239 /// Return the array #I, const version.
240 inline const int *GetI() const { return I; }
241
242 /// Return the array #J.
243 inline int *GetJ() { return J; }
244 /// Return the array #J, const version.
245 inline const int *GetJ() const { return J; }
246
247 /// Return the element data, i.e. the array #A.
248 inline real_t *GetData() { return A; }
249 /// Return the element data, i.e. the array #A, const version.
250 inline const real_t *GetData() const { return A; }
251
252 // Memory access methods for the #I array.
253 Memory<int> &GetMemoryI() { return I; }
254 const Memory<int> &GetMemoryI() const { return I; }
255 const int *ReadI(bool on_dev = true) const
256 { return mfem::Read(I, Height()+1, on_dev); }
257 int *WriteI(bool on_dev = true)
258 { return mfem::Write(I, Height()+1, on_dev); }
259 int *ReadWriteI(bool on_dev = true)
260 { return mfem::ReadWrite(I, Height()+1, on_dev); }
261 const int *HostReadI() const
262 { return mfem::Read(I, Height()+1, false); }
264 { return mfem::Write(I, Height()+1, false); }
266 { return mfem::ReadWrite(I, Height()+1, false); }
267
268 // Memory access methods for the #J array.
269 Memory<int> &GetMemoryJ() { return J; }
270 const Memory<int> &GetMemoryJ() const { return J; }
271 const int *ReadJ(bool on_dev = true) const
272 { return mfem::Read(J, J.Capacity(), on_dev); }
273 int *WriteJ(bool on_dev = true)
274 { return mfem::Write(J, J.Capacity(), on_dev); }
275 int *ReadWriteJ(bool on_dev = true)
276 { return mfem::ReadWrite(J, J.Capacity(), on_dev); }
277 const int *HostReadJ() const
278 { return mfem::Read(J, J.Capacity(), false); }
280 { return mfem::Write(J, J.Capacity(), false); }
282 { return mfem::ReadWrite(J, J.Capacity(), false); }
283
284 // Memory access methods for the #A array.
286 const Memory<real_t> &GetMemoryData() const { return A; }
287 const real_t *ReadData(bool on_dev = true) const
288 { return mfem::Read(A, A.Capacity(), on_dev); }
289 real_t *WriteData(bool on_dev = true)
290 { return mfem::Write(A, A.Capacity(), on_dev); }
291 real_t *ReadWriteData(bool on_dev = true)
292 { return mfem::ReadWrite(A, A.Capacity(), on_dev); }
293 const real_t *HostReadData() const
294 { return mfem::Read(A, A.Capacity(), false); }
296 { return mfem::Write(A, A.Capacity(), false); }
298 { return mfem::ReadWrite(A, A.Capacity(), false); }
299
300 /// Returns the number of elements in row @a i.
301 int RowSize(const int i) const;
302
303 /// Returns the maximum number of elements among all rows.
304 int MaxRowSize() const;
305
306 /// Return a pointer to the column indices in a row.
307 int *GetRowColumns(const int row);
308 /// Return a pointer to the column indices in a row, const version.
309 const int *GetRowColumns(const int row) const;
310
311 /// Return a pointer to the entries in a row.
312 real_t *GetRowEntries(const int row);
313 /// Return a pointer to the entries in a row, const version.
314 const real_t *GetRowEntries(const int row) const;
315
316 /// Change the width of a SparseMatrix.
317 /*!
318 * If width_ = -1 (DEFAULT), this routine will set the new width
319 * to the actual Width of the matrix awidth = max(J) + 1.
320 * Values 0 <= width_ < awidth are not allowed (error check in Debug Mode only)
321 *
322 * This method can be called for matrices finalized or not.
323 */
324 void SetWidth(int width_ = -1);
325
326 /// Returns the actual Width of the matrix.
327 /*! This method can be called for matrices finalized or not. */
328 int ActualWidth() const;
329
330 /// Sort the column indices corresponding to each row.
331 void SortColumnIndices();
332
333 /** @brief Move the diagonal entry to the first position in each row,
334 preserving the order of the rest of the columns. */
335 void MoveDiagonalFirst();
336
337 /// Returns reference to a_{ij}.
338 real_t &Elem(int i, int j) override;
339
340 /// Returns constant reference to a_{ij}.
341 const real_t &Elem(int i, int j) const override;
342
343 /// Returns reference to A[i][j].
344 real_t &operator()(int i, int j);
345
346 /// Returns reference to A[i][j].
347 const real_t &operator()(int i, int j) const;
348
349 /// Returns the Diagonal of A
350 void GetDiag(Vector & d) const;
351
352 /// Produces a DenseMatrix from a SparseMatrix
353 DenseMatrix *ToDenseMatrix() const;
354
355 /// Produces a DenseMatrix from a SparseMatrix
356 void ToDenseMatrix(DenseMatrix & B) const;
357
363
364 /// Matrix vector multiplication.
365 void Mult(const Vector &x, Vector &y) const override;
366
367 /// y += A * x (default) or y += a * A * x
368 void AddMult(const Vector &x, Vector &y,
369 const real_t a = 1.0) const override;
370
371 /// Multiply a vector with the transposed matrix. y = At * x
372 /** If the matrix is modified, call ResetTranspose() and optionally
373 EnsureMultTranspose() to make sure this method uses the correct updated
374 transpose. */
375 void MultTranspose(const Vector &x, Vector &y) const override;
376
377 /// y += At * x (default) or y += a * At * x
378 /** If the matrix is modified, call ResetTranspose() and optionally
379 EnsureMultTranspose() to make sure this method uses the correct updated
380 transpose. */
381 void AddMultTranspose(const Vector &x, Vector &y,
382 const real_t a = 1.0) const override;
383
384 /** @brief Build and store internally the transpose of this matrix which will
385 be used in the methods AddMultTranspose(), MultTranspose(), and
386 AbsMultTranspose(). */
387 /** If this method has been called, the internal transpose matrix will be
388 used to perform the action of the transpose matrix in AddMultTranspose(),
389 MultTranspose(), and AbsMultTranspose().
390
391 Warning: any changes in this matrix will invalidate the internal
392 transpose. To rebuild the transpose, call ResetTranspose() followed by
393 (optionally) a call to this method. If the internal transpose is already
394 built, this method has no effect.
395
396 When any non-serial-CPU backend is enabled, i.e. the call
397 Device::Allows(~ Backend::CPU_MASK) returns true, the above methods
398 require the internal transpose to be built. If that is not the case (i.e.
399 the internal transpose is not built), these methods will automatically
400 call EnsureMultTranspose(). When using any backend from
401 Backend::CPU_MASK, calling this method is optional.
402
403 This method can only be used when the sparse matrix is finalized.
404
405 @sa EnsureMultTranspose(), ResetTranspose(). */
406 void BuildTranspose() const;
407
408 /** Reset (destroy) the internal transpose matrix. See BuildTranspose() for
409 more details. */
410 void ResetTranspose() const;
411
412 /** @brief Ensures that the matrix is capable of performing MultTranspose(),
413 AddMultTranspose(), and AbsMultTranspose(). */
414 /** For non-serial-CPU backends (e.g. GPU, OpenMP), multiplying by the
415 transpose requires that the internal transpose matrix be already built.
416 When such a backend is enabled, this function will build the internal
417 transpose matrix, see BuildTranspose().
418
419 For the serial CPU backends, the internal transpose is not required, and
420 this function is a no-op. This allows for significant memory savings
421 when the internal transpose matrix is not required. */
422 void EnsureMultTranspose() const;
423
424 void PartMult(const Array<int> &rows, const Vector &x, Vector &y) const;
425 void PartAddMult(const Array<int> &rows, const Vector &x, Vector &y,
426 const real_t a=1.0) const;
427
428 /// y = A * x, treating all entries as booleans (zero=false, nonzero=true).
429 /** The actual values stored in the data array, #A, are not used - this means
430 that all entries in the sparsity pattern are considered to be true by
431 this method. */
432 void BooleanMult(const Array<int> &x, Array<int> &y) const;
433
434 /// y = At * x, treating all entries as booleans (zero=false, nonzero=true).
435 /** The actual values stored in the data array, #A, are not used - this means
436 that all entries in the sparsity pattern are considered to be true by
437 this method. */
438 void BooleanMultTranspose(const Array<int> &x, Array<int> &y) const;
439
440 /// y = |A| * x, using entry-wise absolute values of matrix A
441 void AbsMult(const Vector &x, Vector &y) const override;
442
443 /// y = |At| * x, using entry-wise absolute values of the transpose of matrix A
444 /** If the matrix is modified, call ResetTranspose() and optionally
445 EnsureMultTranspose() to make sure this method uses the correct updated
446 transpose. */
447 void AbsMultTranspose(const Vector &x, Vector &y) const override;
448
449 /// Compute y^t A x
450 real_t InnerProduct(const Vector &x, const Vector &y) const;
451
452 /// For all i compute $ x_i = \sum_j A_{ij} $
453 void GetRowSums(Vector &x) const;
454 /// For i = irow compute $ x_i = \sum_j | A_{i, j} | $
455 real_t GetRowNorml1(int irow) const;
456
457 /// This virtual method is not supported: it always returns NULL.
458 MatrixInverse *Inverse() const override;
459
460 /// Eliminates a column from the transpose matrix.
461 void EliminateRow(int row, const real_t sol, Vector &rhs);
462
463 /// Eliminates a row from the matrix.
464 /*!
465 * - If @a dpolicy = #DIAG_ZERO, all the entries in the row will be set to 0.
466 * - If @a dpolicy = #DIAG_ONE (matrix must be square), the diagonal entry
467 * will be set equal to 1 and all other entries in the row to 0.
468 * - The policy #DIAG_KEEP is not supported.
469 */
470 void EliminateRow(int row, DiagonalPolicy dpolicy = DIAG_ZERO);
471
472 /// Eliminates the column @a col from the matrix.
473 /** - If @a dpolicy = #DIAG_ZERO, all entries in the column will be set to 0.
474 - If @a dpolicy = #DIAG_ONE (matrix must be square), the diagonal entry
475 will be set equal to 1 and all other entries in the column to 0.
476 - The policy #DIAG_KEEP is not supported. */
477 void EliminateCol(int col, DiagonalPolicy dpolicy = DIAG_ZERO);
478
479 /// Eliminate all columns i for which @a cols[i] != 0.
480 /** Elimination of a column means that all entries in the column are set to
481 zero. In addition, if the pointers @a x and @a b are not NULL, the
482 eliminated matrix entries are multiplied by the corresponding solution
483 value in @a *x and subtracted from the r.h.s. vector, @a *b. */
484 void EliminateCols(const Array<int> &cols, const Vector *x = NULL,
485 Vector *b = NULL);
486
487 /** @brief Similar to EliminateCols + save the eliminated entries into
488 @a Ae so that (*this) + Ae is equal to the original matrix. */
489 void EliminateCols(const Array<int> &col_marker, SparseMatrix &Ae);
490
491 /// Eliminate row @a rc and column @a rc and modify the @a rhs using @a sol.
492 /** Eliminates the column @a rc to the @a rhs, deletes the row @a rc and
493 replaces the element (rc,rc) with 1.0; assumes that element (i,rc)
494 is assembled if and only if the element (rc,i) is assembled.
495 By default, elements (rc,rc) are set to 1.0, although this behavior
496 can be adjusted by changing the @a dpolicy parameter. */
497 void EliminateRowCol(int rc, const real_t sol, Vector &rhs,
498 DiagonalPolicy dpolicy = DIAG_ONE);
499
500 /** @brief Similar to
501 EliminateRowCol(int, const double, Vector &, DiagonalPolicy), but
502 multiple values for eliminated unknowns are accepted, and accordingly
503 multiple right-hand-sides are used. */
504 void EliminateRowColMultipleRHS(int rc, const Vector &sol,
505 DenseMatrix &rhs,
506 DiagonalPolicy dpolicy = DIAG_ONE);
507
508 /// Perform elimination and set the diagonal entry to the given value
509 void EliminateRowColDiag(int rc, real_t value);
510
511 /// Eliminate row @a rc and column @a rc.
512 void EliminateRowCol(int rc, DiagonalPolicy dpolicy = DIAG_ONE);
513
514 /** @brief Similar to EliminateRowCol(int, DiagonalPolicy) + save the
515 eliminated entries into @a Ae so that (*this) + Ae is equal to the
516 original matrix */
517 void EliminateRowCol(int rc, SparseMatrix &Ae,
518 DiagonalPolicy dpolicy = DIAG_ONE);
519
520 /** @brief Eliminate essential (Dirichlet) boundary conditions.
521
522 @param[in] ess_dofs indices of the degrees of freedom belonging to the
523 essential boundary conditions.
524 @param[in] diag_policy policy for diagonal entries. */
525 void EliminateBC(const Array<int> &ess_dofs,
526 DiagonalPolicy diag_policy);
527
528 /// If a row contains only one diag entry of zero, set it to 1.
529 void SetDiagIdentity();
530 /// If a row contains only zeros, set its diagonal to 1.
531 void EliminateZeroRows(const real_t threshold = 1e-12) override;
532
533 /// Gauss-Seidel forward and backward iterations over a vector x.
534 void Gauss_Seidel_forw(const Vector &x, Vector &y) const;
535 void Gauss_Seidel_back(const Vector &x, Vector &y) const;
536
537 /// Determine appropriate scaling for Jacobi iteration
538 real_t GetJacobiScaling() const;
539 /** One scaled Jacobi iteration for the system A x = b.
540 x1 = x0 + sc D^{-1} (b - A x0) where D is the diag of A.
541 Absolute values of D are used when use_abs_diag = true. */
542 void Jacobi(const Vector &b, const Vector &x0, Vector &x1,
543 real_t sc, bool use_abs_diag = false) const;
544
545 /// x = sc b / A_ii. When use_abs_diag = true, |A_ii| is used.
546 void DiagScale(const Vector &b, Vector &x,
547 real_t sc = 1.0, bool use_abs_diag = false) const;
548
549 /** x1 = x0 + sc D^{-1} (b - A x0) where $ D_{ii} = \sum_j |A_{ij}| $. */
550 void Jacobi2(const Vector &b, const Vector &x0, Vector &x1,
551 real_t sc = 1.0) const;
552
553 /** x1 = x0 + sc D^{-1} (b - A x0) where $ D_{ii} = \sum_j A_{ij} $. */
554 void Jacobi3(const Vector &b, const Vector &x0, Vector &x1,
555 real_t sc = 1.0) const;
556
557 /** @brief Finalize the matrix initialization, switching the storage format
558 from LIL to CSR. */
559 /** This method should be called once, after the matrix has been initialized.
560 Internally, this method converts the matrix from row-wise linked list
561 (LIL) format into CSR (compressed sparse row) format. */
562 void Finalize(int skip_zeros = 1) override { Finalize(skip_zeros, false); }
563
564 /// A slightly more general version of the Finalize(int) method.
565 void Finalize(int skip_zeros, bool fix_empty_rows);
566
567 /// Returns whether or not CSR format has been finalized.
568 bool Finalized() const { return !A.Empty(); }
569 /// Returns whether or not the columns are sorted.
570 bool ColumnsAreSorted() const { return isSorted; }
571
572 /** @brief Remove entries smaller in absolute value than a given tolerance
573 @a tol. If @a fix_empty_rows is true, a zero value is inserted in the
574 diagonal entry (for square matrices only) */
575 void Threshold(real_t tol, bool fix_empty_rows = false);
576
577 /** Split the matrix into M x N blocks of sparse matrices in CSR format.
578 The 'blocks' array is M x N (i.e. M and N are determined by its
579 dimensions) and its entries are overwritten by the new blocks. */
580 void GetBlocks(Array2D<SparseMatrix *> &blocks) const;
581
582 void GetSubMatrix(const Array<int> &rows, const Array<int> &cols,
583 DenseMatrix &subm) const;
584
585 /** @brief Initialize the SparseMatrix for fast access to the entries of the
586 given @a row which becomes the "current row". */
587 /** Fast access to the entries of the "current row" can be performed using
588 the methods: SearchRow(const int), _Add_(const int, const double),
589 _Set_(const int, const double), and _Get_(const int). */
590 inline void SetColPtr(const int row) const;
591 /** @brief Reset the "current row" set by calling SetColPtr(). This method
592 must be called between any two calls to SetColPtr(). */
593 inline void ClearColPtr() const;
594 /// Perform a fast search for an entry in the "current row". See SetColPtr().
595 /** If the matrix is not finalized and the entry is not found in the
596 SparseMatrix, it will be added to the sparsity pattern initialized with
597 zero. If the matrix is finalized and the entry is not found, an error
598 will be generated. */
599 inline real_t &SearchRow(const int col);
600 /// Add a value to an entry in the "current row". See SetColPtr().
601 inline void _Add_(const int col, const real_t a)
602 { SearchRow(col) += a; }
603 /// Set an entry in the "current row". See SetColPtr().
604 inline void _Set_(const int col, const real_t a)
605 { SearchRow(col) = a; }
606 /// Read the value of an entry in the "current row". See SetColPtr().
607 inline real_t _Get_(const int col) const;
608
609 inline real_t &SearchRow(const int row, const int col);
610 inline void _Add_(const int row, const int col, const real_t a)
611 { SearchRow(row, col) += a; }
612 inline void _Set_(const int row, const int col, const real_t a)
613 { SearchRow(row, col) = a; }
614
615 void Set(const int i, const int j, const real_t val);
616 void Add(const int i, const int j, const real_t val);
617
618 void SetSubMatrix(const Array<int> &rows, const Array<int> &cols,
619 const DenseMatrix &subm, int skip_zeros = 1);
620
621 void SetSubMatrixTranspose(const Array<int> &rows, const Array<int> &cols,
622 const DenseMatrix &subm, int skip_zeros = 1);
623
624 /** Insert the DenseMatrix into this SparseMatrix at the specified rows and
625 columns. If \c skip_zeros==0 , all entries from the DenseMatrix are
626 added including zeros. If \c skip_zeros==2 , no zeros are added to the
627 SparseMatrix regardless of their position in the matrix. Otherwise, the
628 default \c skip_zeros behavior is to omit the zero from the SparseMatrix
629 unless it would break the symmetric structure of the SparseMatrix. */
630 void AddSubMatrix(const Array<int> &rows, const Array<int> &cols,
631 const DenseMatrix &subm, int skip_zeros = 1);
632
633 bool RowIsEmpty(const int row) const;
634
635 /// Extract all column indices and values from a given row.
636 /** If the matrix is finalized (i.e. in CSR format), @a cols and @a srow will
637 simply be references to the specific portion of the #J and #A arrays.
638 As required by the AbstractSparseMatrix interface this method returns:
639 - 0, if @a cols and @a srow are copies of the values in the matrix, i.e.
640 when the matrix is open.
641 - 1, if @a cols and @a srow are views of the values in the matrix, i.e.
642 when the matrix is finalized.
643 @warning This method breaks the const-ness when the matrix is finalized
644 because it gives write access to the #J and #A arrays. */
645 int GetRow(const int row, Array<int> &cols, Vector &srow) const override;
646
647 void SetRow(const int row, const Array<int> &cols, const Vector &srow);
648 void AddRow(const int row, const Array<int> &cols, const Vector &srow);
649
650 void ScaleRow(const int row, const real_t scale);
651 /// this = diag(sl) * this;
652 void ScaleRows(const Vector & sl);
653 /// this = this * diag(sr);
654 void ScaleColumns(const Vector & sr);
655
656 /** @brief Add the sparse matrix 'B' to '*this'. This operation will cause an
657 error if '*this' is finalized and 'B' has larger sparsity pattern. */
659
660 /** @brief Add the sparse matrix 'B' scaled by the scalar 'a' into '*this'.
661 Only entries in the sparsity pattern of '*this' are added. */
662 void Add(const real_t a, const SparseMatrix &B);
663
665
667
668 /// Prints matrix to stream out.
669 /** @note The host in synchronized when the finalized matrix is on the device. */
670 void Print(std::ostream &out = mfem::out, int width_ = 4) const override;
671
672 /// Prints matrix in matlab format.
673 /** @note The host in synchronized when the finalized matrix is on the device. */
674 void PrintMatlab(std::ostream &out = mfem::out) const override;
675
676 /// Prints matrix as a SparseArray for importing into Mathematica.
677 /** The resulting file can be read into Mathematica using an expression such
678 as: myMat = Get["output_file_name"]
679 The Mathematica variable "myMat" will then be assigned to a new
680 SparseArray object containing the data from this MFEM SparseMatrix.
681
682 @note Mathematica uses 1-based indexing so the MFEM row and column
683 indices will be sifted up by one in the Mathematica output.
684
685 @note The host in synchronized when the finalized matrix is on the
686 device. */
687 virtual void PrintMathematica(std::ostream &out = mfem::out) const;
688
689 /// Prints matrix in Matrix Market sparse format.
690 /** @note The host in synchronized when the finalized matrix is on the device. */
691 void PrintMM(std::ostream &out = mfem::out) const;
692
693 /// Prints matrix to stream out in hypre_CSRMatrix format.
694 /** @note The host in synchronized when the finalized matrix is on the device. */
695 void PrintCSR(std::ostream &out) const;
696
697 /// Prints a sparse matrix to stream out in CSR format.
698 /** @note The host in synchronized when the finalized matrix is on the device. */
699 void PrintCSR2(std::ostream &out) const;
700
701 /// Print various sparse matrix statistics.
702 void PrintInfo(std::ostream &out) const;
703
704 /// Returns max_{i,j} |(i,j)-(j,i)| for a finalized matrix
705 real_t IsSymmetric() const;
706
707 /// (*this) = 1/2 ((*this) + (*this)^t)
708 void Symmetrize();
709
710 /// Returns the number of the nonzero elements in the matrix
711 int NumNonZeroElems() const override;
712
713 real_t MaxNorm() const;
714
715 /// Count the number of entries with |a_ij| <= tol.
716 int CountSmallElems(real_t tol) const;
717
718 /// Count the number of entries that are NOT finite, i.e. Inf or Nan.
719 int CheckFinite() const;
720
721 /// Set the graph ownership flag (I and J arrays).
722 void SetGraphOwner(bool ownij)
723 { I.SetHostPtrOwner(ownij); J.SetHostPtrOwner(ownij); }
724
725 /// Set the data ownership flag (A array).
726 void SetDataOwner(bool owna) { A.SetHostPtrOwner(owna); }
727
728 /// Get the graph ownership flag (I and J arrays).
729 bool OwnsGraph() const { return I.OwnsHostPtr() && J.OwnsHostPtr(); }
730
731 /// Get the data ownership flag (A array).
732 bool OwnsData() const { return A.OwnsHostPtr(); }
733
734 /// Lose the ownership of the graph (I, J) and data (A) arrays.
735 void LoseData() { SetGraphOwner(false); SetDataOwner(false); }
736
737 void Swap(SparseMatrix &other);
738
739 /// Destroys sparse matrix.
740 virtual ~SparseMatrix();
741
742 Type GetType() const { return MFEM_SPARSEMAT; }
743};
744
745inline std::ostream& operator<<(std::ostream& os, SparseMatrix const& mat)
746{
747 mat.Print(os);
748 return os;
749}
750
751/// Applies f() to each element of the matrix (after it is finalized).
752void SparseMatrixFunction(SparseMatrix &S, real_t (*f)(real_t));
753
754
755/// Transpose of a sparse matrix. A must be finalized.
756SparseMatrix *Transpose(const SparseMatrix &A);
757/// Transpose of a sparse matrix. A does not need to be a CSR matrix.
758SparseMatrix *TransposeAbstractSparseMatrix (const AbstractSparseMatrix &A,
759 int useActualWidth);
760
761/// Matrix product A.B.
762/** If @a OAB is not NULL, we assume it has the structure of A.B and store the
763 result in @a OAB. If @a OAB is NULL, we create a new SparseMatrix to store
764 the result and return a pointer to it.
765
766 All matrices must be finalized. */
767SparseMatrix *Mult(const SparseMatrix &A, const SparseMatrix &B,
768 SparseMatrix *OAB = NULL);
769
770/// C = A^T B
771SparseMatrix *TransposeMult(const SparseMatrix &A, const SparseMatrix &B);
772
773/// Matrix product of sparse matrices. A and B do not need to be CSR matrices
774SparseMatrix *MultAbstractSparseMatrix (const AbstractSparseMatrix &A,
775 const AbstractSparseMatrix &B);
776
777/// Matrix product A.B
778DenseMatrix *Mult(const SparseMatrix &A, DenseMatrix &B);
779
780/// RAP matrix product (with R=P^T)
781DenseMatrix *RAP(const SparseMatrix &A, DenseMatrix &P);
782
783/// RAP matrix product (with R=P^T)
784DenseMatrix *RAP(DenseMatrix &A, const SparseMatrix &P);
785
786/** RAP matrix product (with P=R^T). ORAP is like OAB above.
787 All matrices must be finalized. */
788SparseMatrix *RAP(const SparseMatrix &A, const SparseMatrix &R,
789 SparseMatrix *ORAP = NULL);
790
791/// General RAP with given R^T, A and P
792SparseMatrix *RAP(const SparseMatrix &Rt, const SparseMatrix &A,
793 const SparseMatrix &P);
794
795/// Matrix multiplication A^t D A. All matrices must be finalized.
796SparseMatrix *Mult_AtDA(const SparseMatrix &A, const Vector &D,
797 SparseMatrix *OAtDA = NULL);
798
799
800/// Matrix addition result = A + B.
801SparseMatrix * Add(const SparseMatrix & A, const SparseMatrix & B);
802/// Matrix addition result = a*A + b*B
803SparseMatrix * Add(real_t a, const SparseMatrix & A, real_t b,
804 const SparseMatrix & B);
805/// Matrix addition result = sum_i A_i
806SparseMatrix * Add(Array<SparseMatrix *> & Ai);
807
808/// B += alpha * A
809void Add(const SparseMatrix &A, real_t alpha, DenseMatrix &B);
810
811/// Produces a block matrix with blocks A_{ij}*B
812DenseMatrix *OuterProduct(const DenseMatrix &A, const DenseMatrix &B);
813
814/// Produces a block matrix with blocks A_{ij}*B
815SparseMatrix *OuterProduct(const DenseMatrix &A, const SparseMatrix &B);
816
817/// Produces a block matrix with blocks A_{ij}*B
818SparseMatrix *OuterProduct(const SparseMatrix &A, const DenseMatrix &B);
819
820/// Produces a block matrix with blocks A_{ij}*B
821SparseMatrix *OuterProduct(const SparseMatrix &A, const SparseMatrix &B);
822
823
824// Inline methods
825
826inline void SparseMatrix::SetColPtr(const int row) const
827{
828 if (Rows)
829 {
830 if (ColPtrNode == NULL)
831 {
832 ColPtrNode = new RowNode *[width];
833 for (int i = 0; i < width; i++)
834 {
835 ColPtrNode[i] = NULL;
836 }
837 }
838 for (RowNode *node_p = Rows[row]; node_p != NULL; node_p = node_p->Prev)
839 {
840 ColPtrNode[node_p->Column] = node_p;
841 }
842 }
843 else
844 {
845 if (ColPtrJ == NULL)
846 {
847 ColPtrJ = new int[width];
848 for (int i = 0; i < width; i++)
849 {
850 ColPtrJ[i] = -1;
851 }
852 }
853 for (int j = I[row], end = I[row+1]; j < end; j++)
854 {
855 ColPtrJ[J[j]] = j;
856 }
857 }
858 current_row = row;
859}
860
861inline void SparseMatrix::ClearColPtr() const
862{
863 if (Rows)
864 {
865 for (RowNode *node_p = Rows[current_row]; node_p != NULL;
866 node_p = node_p->Prev)
867 {
868 ColPtrNode[node_p->Column] = NULL;
869 }
870 }
871 else
872 {
873 for (int j = I[current_row], end = I[current_row+1]; j < end; j++)
874 {
875 ColPtrJ[J[j]] = -1;
876 }
877 }
878}
879
880inline real_t &SparseMatrix::SearchRow(const int col)
881{
882 if (Rows)
883 {
884 RowNode *node_p = ColPtrNode[col];
885 if (node_p == NULL)
886 {
887#ifdef MFEM_USE_MEMALLOC
888 node_p = NodesMem->Alloc();
889#else
890 node_p = new RowNode;
891#endif
892 node_p->Prev = Rows[current_row];
893 node_p->Column = col;
894 node_p->Value = 0.0;
895 Rows[current_row] = ColPtrNode[col] = node_p;
896 }
897 return node_p->Value;
898 }
899 else
900 {
901 const int j = ColPtrJ[col];
902 MFEM_VERIFY(j != -1, "Entry for column " << col << " is not allocated.");
903 return A[j];
904 }
905}
906
907inline real_t SparseMatrix::_Get_(const int col) const
908{
909 if (Rows)
910 {
911 RowNode *node_p = ColPtrNode[col];
912 return (node_p == NULL) ? 0.0 : node_p->Value;
913 }
914 else
915 {
916 const int j = ColPtrJ[col];
917 return (j == -1) ? 0.0 : A[j];
918 }
919}
920
921inline real_t &SparseMatrix::SearchRow(const int row, const int col)
922{
923 if (Rows)
924 {
925 RowNode *node_p;
926
927 for (node_p = Rows[row]; 1; node_p = node_p->Prev)
928 {
929 if (node_p == NULL)
930 {
931#ifdef MFEM_USE_MEMALLOC
932 node_p = NodesMem->Alloc();
933#else
934 node_p = new RowNode;
935#endif
936 node_p->Prev = Rows[row];
937 node_p->Column = col;
938 node_p->Value = 0.0;
939 Rows[row] = node_p;
940 break;
941 }
942 else if (node_p->Column == col)
943 {
944 break;
945 }
946 }
947 return node_p->Value;
948 }
949 else
950 {
951 int *Ip = I+row, *Jp = J;
952 for (int k = Ip[0], end = Ip[1]; k < end; k++)
953 {
954 if (Jp[k] == col)
955 {
956 return A[k];
957 }
958 }
959 MFEM_ABORT("Could not find entry for row = " << row << ", col = " << col);
960 }
961 return A[0];
962}
963
964/// Specialization of the template function Swap<> for class SparseMatrix
966{
967 a.Swap(b);
968}
969
970} // namespace mfem
971
972#endif
Abstract data type for sparse matrices.
Definition matrix.hpp:74
Dynamic 2D array using row-major layout.
Definition array.hpp:459
Data type dense matrix using column-major storage.
Definition densemat.hpp:24
static MemoryClass GetHostMemoryClass()
Get the current Host MemoryClass. This is the MemoryClass used by most MFEM host Memory objects.
Definition device.hpp:293
static MemoryClass GetDeviceMemoryClass()
Get the current Device MemoryClass. This is the MemoryClass used by most MFEM device kernels to acces...
Definition device.hpp:306
Abstract data type for matrix inverse.
Definition matrix.hpp:63
Class used by MFEM to store pointers to host and/or device memory.
void SetHostPtrOwner(bool own) const
Set/clear the ownership flag for the host pointer. Ownership indicates whether the pointer will be de...
int Capacity() const
Return the size of the allocated memory.
void Swap(Memory &other)
Swap without using move assignment, avoiding Reset() calls.
bool OwnsHostPtr() const
Return true if the host pointer is owned. Ownership indicates whether the pointer will be deleted by ...
bool Empty() const
Return true if the Memory object is empty, see Reset().
int width
Dimension of the input / number of columns in the matrix.
Definition operator.hpp:30
int Height() const
Get the height (size of output) of the Operator. Synonym with NumRows().
Definition operator.hpp:68
DiagonalPolicy
Defines operator diagonal policy upon elimination of rows and/or columns.
Definition operator.hpp:50
@ DIAG_ONE
Set the diagonal value to one.
Definition operator.hpp:52
@ DIAG_ZERO
Set the diagonal value to zero.
Definition operator.hpp:51
Type
Enumeration defining IDs for some classes derived from Operator.
Definition operator.hpp:319
@ MFEM_SPARSEMAT
ID for class SparseMatrix.
Definition operator.hpp:321
RowNode * Prev
Definition sparsemat.hpp:45
Data type sparse matrix.
Definition sparsemat.hpp:51
int GetRow(const int row, Array< int > &cols, Vector &srow) const override
Extract all column indices and values from a given row.
void PrintCSR2(std::ostream &out) const
Prints a sparse matrix to stream out in CSR format.
real_t MaxNorm() const
const int * HostReadJ() const
void GetDiag(Vector &d) const
Returns the Diagonal of A.
int * ReadWriteI(bool on_dev=true)
real_t GetRowNorml1(int irow) const
For i = irow compute .
void PartMult(const Array< int > &rows, const Vector &x, Vector &y) const
bool isSorted
Are the columns sorted already.
Definition sparsemat.hpp:96
RowNodeAlloc * NodesMem
Definition sparsemat.hpp:92
bool ColumnsAreSorted() const
Returns whether or not the columns are sorted.
void Gauss_Seidel_back(const Vector &x, Vector &y) const
bool RowIsEmpty(const int row) const
void ClearColPtr() const
Reset the "current row" set by calling SetColPtr(). This method must be called between any two calls ...
MatrixInverse * Inverse() const override
This virtual method is not supported: it always returns NULL.
void Jacobi3(const Vector &b, const Vector &x0, Vector &x1, real_t sc=1.0) const
real_t * ReadWriteData(bool on_dev=true)
Memory< real_t > A
Array with size I[height], containing the actual entries of the sparse matrix, as indexed by the I ar...
Definition sparsemat.hpp:76
void EliminateRowCol(int rc, const real_t sol, Vector &rhs, DiagonalPolicy dpolicy=DIAG_ONE)
Eliminate row rc and column rc and modify the rhs using sol.
void SetDataOwner(bool owna)
Set the data ownership flag (A array).
SparseMatrix & operator*=(real_t a)
void MultTranspose(const Vector &x, Vector &y) const override
Multiply a vector with the transposed matrix. y = At * x.
hipsparseDnVecDescr_t vecY_descr
void SetWidth(int width_=-1)
Change the width of a SparseMatrix.
MemAlloc< RowNode, 1024 > RowNodeAlloc
Definition sparsemat.hpp:91
bool Empty() const
Check if the SparseMatrix is empty.
static hipsparseHandle_t handle
void GetSubMatrix(const Array< int > &rows, const Array< int > &cols, DenseMatrix &subm) const
SparseMatrix * At
Transpose of A. Owned. Used to perform MultTranspose() on devices.
Definition sparsemat.hpp:88
void PartAddMult(const Array< int > &rows, const Vector &x, Vector &y, const real_t a=1.0) const
const int * GetJ() const
Return the array J, const version.
void GetRowSums(Vector &x) const
For all i compute .
void AbsMult(const Vector &x, Vector &y) const override
y = |A| * x, using entry-wise absolute values of matrix A
int NumNonZeroElems() const override
Returns the number of the nonzero elements in the matrix.
cusparseMatDescr_t descr
bool Finalized() const
Returns whether or not CSR format has been finalized.
Type GetType() const
void EliminateBC(const Array< int > &ess_dofs, DiagonalPolicy diag_policy)
Eliminate essential (Dirichlet) boundary conditions.
void PrintInfo(std::ostream &out) const
Print various sparse matrix statistics.
void MoveDiagonalFirst()
Move the diagonal entry to the first position in each row, preserving the order of the rest of the co...
void Add(const int i, const int j, const real_t val)
void EliminateRowColMultipleRHS(int rc, const Vector &sol, DenseMatrix &rhs, DiagonalPolicy dpolicy=DIAG_ONE)
Similar to EliminateRowCol(int, const double, Vector &, DiagonalPolicy), but multiple values for elim...
void Jacobi(const Vector &b, const Vector &x0, Vector &x1, real_t sc, bool use_abs_diag=false) const
void SetColPtr(const int row) const
Initialize the SparseMatrix for fast access to the entries of the given row which becomes the "curren...
void SetDiagIdentity()
If a row contains only one diag entry of zero, set it to 1.
MFEM_DEPRECATED void UseCuSparse(bool useCuSparse_=true)
Deprecated equivalent of UseGPUSparse().
const Memory< int > & GetMemoryJ() const
void Gauss_Seidel_forw(const Vector &x, Vector &y) const
Gauss-Seidel forward and backward iterations over a vector x.
void MakeRef(const SparseMatrix &master)
Clear the contents of the SparseMatrix and make it a reference to master.
int CheckFinite() const
Count the number of entries that are NOT finite, i.e. Inf or Nan.
void UseGPUSparse(bool useGPUSparse_=true)
Runtime option to use cuSPARSE or hipSPARSE. Only valid when using a CUDA or HIP backend.
int * WriteJ(bool on_dev=true)
Memory< int > J
Array with size I[height], containing the column indices for all matrix entries, as indexed by the I ...
Definition sparsemat.hpp:73
cusparseMatDescr_t matA_descr
void EliminateCol(int col, DiagonalPolicy dpolicy=DIAG_ZERO)
Eliminates the column col from the matrix.
void LoseData()
Lose the ownership of the graph (I, J) and data (A) arrays.
void EnsureMultTranspose() const
Ensures that the matrix is capable of performing MultTranspose(), AddMultTranspose(),...
void Print(std::ostream &out=mfem::out, int width_=4) const override
Prints matrix to stream out.
void _Add_(const int col, const real_t a)
Add a value to an entry in the "current row". See SetColPtr().
SparseMatrix()
Create an empty SparseMatrix.
cusparseSpMatDescr_t matA_descr
real_t & Elem(int i, int j) override
Returns reference to a_{ij}.
virtual void PrintMathematica(std::ostream &out=mfem::out) const
Prints matrix as a SparseArray for importing into Mathematica.
void ClearGPUSparse()
Clear the cuSPARSE/hipSPARSE descriptors. This must be called after releasing the device memory of A.
void Threshold(real_t tol, bool fix_empty_rows=false)
Remove entries smaller in absolute value than a given tolerance tol. If fix_empty_rows is true,...
Memory< int > & GetMemoryI()
void SetSubMatrix(const Array< int > &rows, const Array< int > &cols, const DenseMatrix &subm, int skip_zeros=1)
void PrintMatlab(std::ostream &out=mfem::out) const override
Prints matrix in matlab format.
const int * ReadI(bool on_dev=true) const
real_t InnerProduct(const Vector &x, const Vector &y) const
Compute y^t A x.
Memory< int > I
Array with size (height+1) containing the row offsets.
Definition sparsemat.hpp:70
real_t & operator()(int i, int j)
Returns reference to A[i][j].
const real_t * HostReadData() const
void PrintMM(std::ostream &out=mfem::out) const
Prints matrix in Matrix Market sparse format.
void ScaleColumns(const Vector &sr)
this = this * diag(sr);
void _Add_(const int row, const int col, const real_t a)
void PrintCSR(std::ostream &out) const
Prints matrix to stream out in hypre_CSRMatrix format.
void Swap(SparseMatrix &other)
MFEM_DEPRECATED void ClearCuSparse()
Deprecated equivalent of ClearGPUSparse().
const Memory< real_t > & GetMemoryData() const
int * ReadWriteJ(bool on_dev=true)
cusparseDnVecDescr_t vecY_descr
void BooleanMultTranspose(const Array< int > &x, Array< int > &y) const
y = At * x, treating all entries as booleans (zero=false, nonzero=true).
RowNode ** Rows
Array of linked lists, one for every row. This array represents the linked list (LIL) storage format.
Definition sparsemat.hpp:81
void SetGraphOwner(bool ownij)
Set the graph ownership flag (I and J arrays).
real_t & SearchRow(const int col)
Perform a fast search for an entry in the "current row". See SetColPtr().
int * WriteI(bool on_dev=true)
const Memory< int > & GetMemoryI() const
static int SparseMatrixCount
void AddSubMatrix(const Array< int > &rows, const Array< int > &cols, const DenseMatrix &subm, int skip_zeros=1)
void _Set_(const int row, const int col, const real_t a)
void Symmetrize()
(*this) = 1/2 ((*this) + (*this)^t)
void BooleanMult(const Array< int > &x, Array< int > &y) const
y = A * x, treating all entries as booleans (zero=false, nonzero=true).
void AddMultTranspose(const Vector &x, Vector &y, const real_t a=1.0) const override
y += At * x (default) or y += a * At * x
int * GetRowColumns(const int row)
Return a pointer to the column indices in a row.
real_t GetJacobiScaling() const
Determine appropriate scaling for Jacobi iteration.
RowNode ** ColPtrNode
Definition sparsemat.hpp:85
int RowSize(const int i) const
Returns the number of elements in row i.
real_t * HostReadWriteData()
int CountSmallElems(real_t tol) const
Count the number of entries with |a_ij| <= tol.
const int * ReadJ(bool on_dev=true) const
int MaxRowSize() const
Returns the maximum number of elements among all rows.
real_t _Get_(const int col) const
Read the value of an entry in the "current row". See SetColPtr().
void AddMult(const Vector &x, Vector &y, const real_t a=1.0) const override
y += A * x (default) or y += a * A * x
virtual ~SparseMatrix()
Destroys sparse matrix.
SparseMatrix & operator=(const SparseMatrix &rhs)
Assignment operator: deep copy.
void Mult(const Vector &x, Vector &y) const override
Matrix vector multiplication.
const real_t * GetData() const
Return the element data, i.e. the array A, const version.
void OverrideSize(int height_, int width_)
Sets the height and width of the matrix.
real_t * HostWriteData()
cusparseStatus_t status
static cusparseHandle_t handle
void EliminateRow(int row, const real_t sol, Vector &rhs)
Eliminates a column from the transpose matrix.
bool OwnsGraph() const
Get the graph ownership flag (I and J arrays).
hipsparseSpMatDescr_t matA_descr
void GetBlocks(Array2D< SparseMatrix * > &blocks) const
SparseMatrix & operator+=(const SparseMatrix &B)
Add the sparse matrix 'B' to '*this'. This operation will cause an error if '*this' is finalized and ...
hipsparseStatus_t status
void Clear()
Clear the contents of the SparseMatrix.
void ResetTranspose() const
void EliminateRowColDiag(int rc, real_t value)
Perform elimination and set the diagonal entry to the given value.
real_t * GetRowEntries(const int row)
Return a pointer to the entries in a row.
void ScaleRows(const Vector &sl)
this = diag(sl) * this;
void SetRow(const int row, const Array< int > &cols, const Vector &srow)
bool OwnsData() const
Get the data ownership flag (A array).
const int * GetI() const
Return the array I, const version.
void DiagScale(const Vector &b, Vector &x, real_t sc=1.0, bool use_abs_diag=false) const
x = sc b / A_ii. When use_abs_diag = true, |A_ii| is used.
void AbsMultTranspose(const Vector &x, Vector &y) const override
y = |At| * x, using entry-wise absolute values of the transpose of matrix A
real_t * GetData()
Return the element data, i.e. the array A.
void SetSubMatrixTranspose(const Array< int > &rows, const Array< int > &cols, const DenseMatrix &subm, int skip_zeros=1)
void BuildTranspose() const
Build and store internally the transpose of this matrix which will be used in the methods AddMultTran...
MemoryClass GetMemoryClass() const override
Return the MemoryClass preferred by the Operator.
void SortColumnIndices()
Sort the column indices corresponding to each row.
void Finalize(int skip_zeros=1) override
Finalize the matrix initialization, switching the storage format from LIL to CSR.
real_t IsSymmetric() const
Returns max_{i,j} |(i,j)-(j,i)| for a finalized matrix.
DenseMatrix * ToDenseMatrix() const
Produces a DenseMatrix from a SparseMatrix.
void _Set_(const int col, const real_t a)
Set an entry in the "current row". See SetColPtr().
void EliminateZeroRows(const real_t threshold=1e-12) override
If a row contains only zeros, set its diagonal to 1.
void EliminateCols(const Array< int > &cols, const Vector *x=NULL, Vector *b=NULL)
Eliminate all columns i for which cols[i] != 0.
int * GetJ()
Return the array J.
Memory< int > & GetMemoryJ()
Memory< real_t > & GetMemoryData()
cusparseDnVecDescr_t vecX_descr
const real_t * ReadData(bool on_dev=true) const
void ScaleRow(const int row, const real_t scale)
real_t * WriteData(bool on_dev=true)
hipsparseDnVecDescr_t vecX_descr
void AddRow(const int row, const Array< int > &cols, const Vector &srow)
void Jacobi2(const Vector &b, const Vector &x0, Vector &x1, real_t sc=1.0) const
int * GetI()
Return the array I.
static void * dBuffer
static bool use_gpu_vendor_sparse_if_available
Use the GPU vendor sparse library (cusparse/hipsparse), if available, for sparse matrix operations....
Definition sparsemat.hpp:58
int ActualWidth() const
Returns the actual Width of the matrix.
const int * HostReadI() const
void Set(const int i, const int j, const real_t val)
int Size() const
For backward compatibility, define Size() to be synonym of Height().
Vector data type.
Definition vector.hpp:82
const real_t alpha
Definition ex15.cpp:369
real_t b
Definition lissajous.cpp:42
real_t a
Definition lissajous.cpp:41
mfem::real_t real_t
std::ostream & operator<<(std::ostream &os, SparseMatrix const &mat)
DenseMatrix * OuterProduct(const DenseMatrix &A, const DenseMatrix &B)
Produces a block matrix with blocks A_{ij}*B.
const T * Read(const Memory< T > &mem, int size, bool on_dev=true)
Get a pointer for read access to mem with the mfem::Device's DeviceMemoryClass, if on_dev = true,...
Definition device.hpp:369
void Swap< SparseMatrix >(SparseMatrix &a, SparseMatrix &b)
Specialization of the template function Swap<> for class SparseMatrix.
void Mult(const Table &A, const Table &B, Table &C)
C = A * B (as boolean matrices)
Definition table.cpp:505
T * Write(Memory< T > &mem, int size, bool on_dev=true)
Get a pointer for write access to mem with the mfem::Device's DeviceMemoryClass, if on_dev = true,...
Definition device.hpp:386
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
Definition globals.hpp:66
void Transpose(const Table &A, Table &At, int ncols_A_)
Transpose a Table.
Definition table.cpp:443
MemoryClass
Memory classes identify sets of memory types.
T * ReadWrite(Memory< T > &mem, int size, bool on_dev=true)
Get a pointer for read+write access to mem with the mfem::Device's DeviceMemoryClass,...
Definition device.hpp:403
void RAP(const DenseMatrix &A, const DenseMatrix &P, DenseMatrix &RAP)
SparseMatrix * MultAbstractSparseMatrix(const AbstractSparseMatrix &A, const AbstractSparseMatrix &B)
Matrix product of sparse matrices. A and B do not need to be CSR matrices.
SparseMatrix * TransposeAbstractSparseMatrix(const AbstractSparseMatrix &A, int useActualWidth)
Transpose of a sparse matrix. A does not need to be a CSR matrix.
SparseMatrix * Mult_AtDA(const SparseMatrix &A, const Vector &D, SparseMatrix *OAtDA)
Matrix multiplication A^t D A. All matrices must be finalized.
float real_t
Definition config.hpp:46
MemoryType
Memory types supported by MFEM.
std::function< real_t(const Vector &)> f(real_t mass_coeff)
Definition lor_mms.hpp:30
SparseMatrix * TransposeMult(const SparseMatrix &A, const SparseMatrix &B)
C = A^T B.
void Add(const DenseMatrix &A, const DenseMatrix &B, real_t alpha, DenseMatrix &C)
C = A + alpha*B.
void SparseMatrixFunction(SparseMatrix &S, real_t(*f)(real_t))
Applies f() to each element of the matrix (after it is finalized).
real_t sol(const Vector &x)