libMesh
Loading...
Searching...
No Matches
petsc_matrix.C
Go to the documentation of this file.
1// The libMesh Finite Element Library.
2// Copyright (C) 2002-2026 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#include "libmesh/libmesh_config.h"
21
22#ifdef LIBMESH_HAVE_PETSC
23
24// Local includes
25#include "libmesh/petsc_matrix.h"
26
27// libMesh includes
28#include "libmesh/dof_map.h"
29#include "libmesh/dense_matrix.h"
30#include "libmesh/libmesh_logging.h"
31#include "libmesh/petsc_vector.h"
32#include "libmesh/parallel.h"
33#include "libmesh/utility.h"
34#include "libmesh/wrapped_petsc.h"
35
36// C++ includes
37#ifdef LIBMESH_HAVE_UNISTD_H
38#include <unistd.h> // mkstemp
39#endif
40#include <fstream>
41
42#ifdef LIBMESH_ENABLE_BLOCKED_STORAGE
43
44namespace
45{
46using namespace libMesh;
47
48// historic libMesh n_nz & n_oz arrays are set up for PETSc's AIJ format.
49// however, when the blocksize is >1, we need to transform these into
50// their BAIJ counterparts.
51inline
52void transform_preallocation_arrays (const PetscInt blocksize,
53 const std::vector<numeric_index_type> & n_nz,
54 const std::vector<numeric_index_type> & n_oz,
55 std::vector<numeric_index_type> & b_n_nz,
56 std::vector<numeric_index_type> & b_n_oz)
57{
58 libmesh_assert_equal_to (n_nz.size(), n_oz.size());
59 libmesh_assert_equal_to (n_nz.size()%blocksize, 0);
60
61 b_n_nz.clear(); b_n_nz.reserve(n_nz.size()/blocksize);
62 b_n_oz.clear(); b_n_oz.reserve(n_oz.size()/blocksize);
63
64 for (std::size_t nn=0, nnzs=n_nz.size(); nn<nnzs; nn += blocksize)
65 {
66 b_n_nz.push_back (n_nz[nn]/blocksize);
67 b_n_oz.push_back (n_oz[nn]/blocksize);
68 }
69}
70}
71
72#endif
73
74
75
76namespace libMesh
77{
78
79
80//-----------------------------------------------------------------------
81// PetscMatrix members
82
83
84// Constructor
85template <typename T>
87 PetscMatrixBase<T>(comm_in), _mat_type(AIJ)
88{
89}
90
91
92
93// Constructor taking an existing Mat but not the responsibility
94// for destroying it
95template <typename T>
97 const Parallel::Communicator & comm_in,
98 const bool destroy_on_exit) :
99 PetscMatrixBase<T>(mat_in, comm_in, destroy_on_exit)
100{
101 MatType mat_type;
102 LibmeshPetscCall(MatGetType(mat_in, &mat_type));
103 PetscBool is_hypre;
104 LibmeshPetscCall(PetscStrcmp(mat_type, MATHYPRE, &is_hypre));
105 if (is_hypre == PETSC_TRUE)
107 else
108 _mat_type = AIJ;
109}
110
111
112// Constructor taking global and local dimensions and, optionally,
113// number of on- and off-diagonal non-zeros and a block size
114template <typename T>
116 const numeric_index_type m_in,
117 const numeric_index_type n_in,
118 const numeric_index_type m_l,
119 const numeric_index_type n_l,
120 const numeric_index_type n_nz,
121 const numeric_index_type n_oz,
122 const numeric_index_type blocksize_in) :
123 PetscMatrixBase<T>(comm_in), _mat_type(AIJ)
124{
125 this->init(m_in, n_in, m_l, n_l, n_nz, n_oz, blocksize_in);
126}
127
128
129// Destructor
130template <typename T>
132
133template <typename T>
134void
136 const numeric_index_type n_in,
137 const numeric_index_type m_l,
138 const numeric_index_type n_l,
139 const numeric_index_type blocksize_in)
140{
141 // So compilers don't warn when !LIBMESH_ENABLE_BLOCKED_STORAGE
142 libmesh_ignore(blocksize_in);
143
144 // Clear initialized matrices
145 if (this->initialized())
146 this->clear();
147
148 PetscInt m_global = static_cast<PetscInt>(m_in);
149 PetscInt n_global = static_cast<PetscInt>(n_in);
150 PetscInt m_local = static_cast<PetscInt>(m_l);
151 PetscInt n_local = static_cast<PetscInt>(n_l);
152
153 LibmeshPetscCall(MatCreate(this->comm().get(), &this->_mat));
154 LibmeshPetscCall(MatSetSizes(this->_mat, m_local, n_local, m_global, n_global));
155 PetscInt blocksize = static_cast<PetscInt>(blocksize_in);
156 LibmeshPetscCall(MatSetBlockSize(this->_mat,blocksize));
157 LibmeshPetscCall(MatSetOptionsPrefix(this->_mat, ""));
158
159#ifdef LIBMESH_ENABLE_BLOCKED_STORAGE
160 if (blocksize > 1)
161 {
162 // specified blocksize, bs>1.
163 // double check sizes.
164 libmesh_assert_equal_to (m_local % blocksize, 0);
165 libmesh_assert_equal_to (n_local % blocksize, 0);
166 libmesh_assert_equal_to (m_global % blocksize, 0);
167 libmesh_assert_equal_to (n_global % blocksize, 0);
168 libmesh_assert_equal_to (n_nz % blocksize, 0);
169 libmesh_assert_equal_to (n_oz % blocksize, 0);
170
171 LibmeshPetscCall(MatSetType(this->_mat, MATBAIJ)); // Automatically chooses seqbaij or mpibaij
172
173 // MatSetFromOptions needs to happen before Preallocation routines
174 // since MatSetFromOptions can change matrix type and remove incompatible
175 // preallocation
176 LibmeshPetscCall(MatSetFromOptions(this->_mat));
177 }
178 else
179#endif
180 {
181 switch (this->_mat_type) {
182 case AIJ:
183 LibmeshPetscCall(MatSetType(this->_mat, MATAIJ)); // Automatically chooses seqaij or mpiaij
184
185 // MatSetFromOptions needs to happen before Preallocation routines
186 // since MatSetFromOptions can change matrix type and remove incompatible
187 // preallocation
188 LibmeshPetscCall(MatSetFromOptions(this->_mat));
189 break;
190
191 case HYPRE:
192#if !PETSC_VERSION_LESS_THAN(3,9,4) && LIBMESH_HAVE_PETSC_HYPRE
193 LibmeshPetscCall(MatSetType(this->_mat, MATHYPRE));
194
195 // MatSetFromOptions needs to happen before Preallocation routines
196 // since MatSetFromOptions can change matrix type and remove incompatible
197 // preallocation
198 LibmeshPetscCall(MatSetFromOptions(this->_mat));
199#else
200 libmesh_error_msg("PETSc 3.9.4 or higher with hypre is required for MatHypre");
201#endif
202 break;
203
204 default: libmesh_error_msg("Unsupported petsc matrix type");
205 }
206 }
207
208 this->set_context ();
209}
210
211
212
213template <typename T>
215 const numeric_index_type n_in,
216 const numeric_index_type m_l,
217 const numeric_index_type n_l,
218 const numeric_index_type nnz,
219 const numeric_index_type noz,
220 const numeric_index_type blocksize_in)
221{
222 this->init_without_preallocation(m_in, n_in, m_l, n_l, blocksize_in);
223
224 PetscInt n_nz = static_cast<PetscInt>(nnz);
225 PetscInt n_oz = static_cast<PetscInt>(noz);
226
227#ifdef LIBMESH_ENABLE_BLOCKED_STORAGE
228 if (blocksize > 1)
229 {
230 LibmeshPetscCall(MatSeqBAIJSetPreallocation(this->_mat, blocksize, n_nz/blocksize, NULL));
231 LibmeshPetscCall(MatMPIBAIJSetPreallocation(this->_mat, blocksize,
232 n_nz/blocksize, NULL,
233 n_oz/blocksize, NULL));
234 }
235 else
236#endif
237 {
238 switch (this->_mat_type) {
239 case AIJ:
240 LibmeshPetscCall(MatSeqAIJSetPreallocation(this->_mat, n_nz, NULL));
241 LibmeshPetscCall(MatMPIAIJSetPreallocation(this->_mat, n_nz, NULL, n_oz, NULL));
242 break;
243
244 case HYPRE:
245#if !PETSC_VERSION_LESS_THAN(3,9,4) && LIBMESH_HAVE_PETSC_HYPRE
246 LibmeshPetscCall(MatHYPRESetPreallocation(this->_mat, n_nz, NULL, n_oz, NULL));
247#else
248 libmesh_error_msg("PETSc 3.9.4 or higher with hypre is required for MatHypre");
249#endif
250 break;
251
252 default: libmesh_error_msg("Unsupported petsc matrix type");
253 }
254 }
255
256 this->finish_initialization();
257}
258
259template <typename T>
260void PetscMatrix<T>::preallocate(const numeric_index_type libmesh_dbg_var(m_l),
261 const std::vector<numeric_index_type> & n_nz,
262 const std::vector<numeric_index_type> & n_oz,
263 const numeric_index_type blocksize_in)
264{
265 // Make sure the sparsity pattern isn't empty unless the matrix is 0x0
266 libmesh_assert_equal_to (n_nz.size(), m_l);
267 libmesh_assert_equal_to (n_oz.size(), m_l);
268 // Avoid unused warnings when not configured with block storage
269 libmesh_ignore(blocksize_in);
270
271#ifdef LIBMESH_ENABLE_BLOCKED_STORAGE
272 PetscInt blocksize = static_cast<PetscInt>(blocksize_in);
273
274 if (blocksize > 1)
275 {
276 // transform the per-entry n_nz and n_oz arrays into their block counterparts.
277 std::vector<numeric_index_type> b_n_nz, b_n_oz;
278
279 transform_preallocation_arrays (blocksize,
280 n_nz, n_oz,
281 b_n_nz, b_n_oz);
282
283 LibmeshPetscCall(MatSeqBAIJSetPreallocation (this->_mat,
284 blocksize,
285 0,
286 numeric_petsc_cast(b_n_nz.empty() ? nullptr : b_n_nz.data())));
287
288 LibmeshPetscCall(MatMPIBAIJSetPreallocation (this->_mat,
289 blocksize,
290 0,
291 numeric_petsc_cast(b_n_nz.empty() ? nullptr : b_n_nz.data()),
292 0,
293 numeric_petsc_cast(b_n_oz.empty() ? nullptr : b_n_oz.data())));
294 }
295 else
296#endif
297 {
298 switch (this->_mat_type) {
299 case AIJ:
300 LibmeshPetscCall(MatSeqAIJSetPreallocation (this->_mat,
301 0,
302 numeric_petsc_cast(n_nz.empty() ? nullptr : n_nz.data())));
303 LibmeshPetscCall(MatMPIAIJSetPreallocation (this->_mat,
304 0,
305 numeric_petsc_cast(n_nz.empty() ? nullptr : n_nz.data()),
306 0,
307 numeric_petsc_cast(n_oz.empty() ? nullptr : n_oz.data())));
308 break;
309
310 case HYPRE:
311#if !PETSC_VERSION_LESS_THAN(3,9,4) && LIBMESH_HAVE_PETSC_HYPRE
312 LibmeshPetscCall(MatHYPRESetPreallocation (this->_mat,
313 0,
314 numeric_petsc_cast(n_nz.empty() ? nullptr : n_nz.data()),
315 0,
316 numeric_petsc_cast(n_oz.empty() ? nullptr : n_oz.data())));
317#else
318 libmesh_error_msg("PETSc 3.9.4 or higher with hypre is required for MatHypre");
319#endif
320 break;
321
322 default: libmesh_error_msg("Unsupported petsc matrix type");
323 }
324
325 }
326}
327
328template <typename T>
330{
331 // Make it an error for PETSc to allocate new nonzero entries during assembly. For old PETSc
332 // versions this option must be set after preallocation for MPIAIJ matrices
333 LibmeshPetscCall(MatSetOption(this->_mat, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE));
334 this->_is_initialized = true;
335}
336
337template <typename T>
339 const numeric_index_type n_in,
340 const numeric_index_type m_l,
341 const numeric_index_type n_l,
342 const std::vector<numeric_index_type> & n_nz,
343 const std::vector<numeric_index_type> & n_oz,
344 const numeric_index_type blocksize_in)
345{
346 this->init_without_preallocation(m_in, n_in, m_l, n_l, blocksize_in);
347 this->preallocate(m_l, n_nz, n_oz, blocksize_in);
348
349 this->finish_initialization();
350}
351
352
353template <typename T>
354void PetscMatrix<T>::init (const ParallelType libmesh_dbg_var(type))
355{
356 libmesh_assert(this->_dof_map);
357
358 const numeric_index_type m_in = this->_dof_map->n_dofs();
359 const numeric_index_type m_l = this->_dof_map->n_local_dofs();
360 if (m_in != m_l)
361 libmesh_assert(type != SERIAL);
362
363 const auto blocksize = this->_dof_map->block_size();
364
365 this->init_without_preallocation(m_in, m_in, m_l, m_l, blocksize);
366 if (!this->_use_hash_table)
367 {
368 const std::vector<numeric_index_type> & n_nz = this->_sp->get_n_nz();
369 const std::vector<numeric_index_type> & n_oz = this->_sp->get_n_oz();
370
371 this->preallocate(m_l, n_nz, n_oz, blocksize);
372 }
373
374 this->finish_initialization();
375}
376
377
378template <typename T>
380{
381 libmesh_not_implemented();
382}
383
384template <typename T>
386{
387 semiparallel_only();
388
389#if !PETSC_VERSION_LESS_THAN(3,9,0)
390 libmesh_assert (this->initialized());
391
392 LibmeshPetscCall(MatResetPreallocation(this->_mat));
393#else
394 libmesh_warning("Your version of PETSc doesn't support resetting of "
395 "preallocation, so we will use your most recent sparsity "
396 "pattern. This may result in a degradation of performance\n");
397#endif
398}
399
400template <typename T>
402{
403 libmesh_assert (this->initialized());
404
405 semiparallel_only();
406
407 PetscInt m_l, n_l;
408
409 LibmeshPetscCall(MatGetLocalSize(this->_mat,&m_l,&n_l));
410
411 if (n_l)
412 LibmeshPetscCall(MatZeroEntries(this->_mat));
413}
414
415template <typename T>
416void PetscMatrix<T>::zero_rows (std::vector<numeric_index_type> & rows, T diag_value)
417{
418 libmesh_assert (this->initialized());
419
420 semiparallel_only();
421
422 // As of petsc-dev at the time of 3.1.0, MatZeroRows now takes two additional
423 // optional arguments. The optional arguments (x,b) can be used to specify the
424 // solutions for the zeroed rows (x) and right hand side (b) to update.
425 // Could be useful for setting boundary conditions...
426 if (!rows.empty())
427 LibmeshPetscCall(MatZeroRows(this->_mat, cast_int<PetscInt>(rows.size()),
428 numeric_petsc_cast(rows.data()), PS(diag_value),
429 NULL, NULL));
430 else
431 LibmeshPetscCall(MatZeroRows(this->_mat, 0, NULL, PS(diag_value), NULL, NULL));
432}
433
434template <typename T>
435std::unique_ptr<SparseMatrix<T>> PetscMatrix<T>::zero_clone () const
436{
437 libmesh_error_msg_if(!this->closed(), "Matrix must be closed before it can be cloned!");
438
439 // Copy the nonzero pattern only
440 Mat copy;
441 LibmeshPetscCall(MatDuplicate(this->_mat, MAT_DO_NOT_COPY_VALUES, &copy));
442
443 // Call wrapping PetscMatrix constructor, have it take over
444 // ownership.
445 auto ret = std::make_unique<PetscMatrix<T>>(copy, this->comm());
446 ret->set_destroy_mat_on_exit(true);
447
448 return ret;
449}
450
451
452
453template <typename T>
454std::unique_ptr<SparseMatrix<T>> PetscMatrix<T>::clone () const
455{
456 libmesh_error_msg_if(!this->closed(), "Matrix must be closed before it can be cloned!");
457
458 // Copy the nonzero pattern and numerical values
459 Mat copy;
460 LibmeshPetscCall(MatDuplicate(this->_mat, MAT_COPY_VALUES, &copy));
461
462 // Call wrapping PetscMatrix constructor, have it take over
463 // ownership.
464 auto ret = std::make_unique<PetscMatrix<T>>(copy, this->comm());
465 ret->set_destroy_mat_on_exit(true);
466
467 return ret;
468}
469
470
471
472template <typename T>
473template <NormType N>
475{
476 libmesh_assert (this->initialized());
477
478 semiparallel_only();
479
480 PetscReal petsc_value;
481 Real value;
482
483 libmesh_assert (this->closed());
484
485 LibmeshPetscCall(MatNorm(this->_mat, N, &petsc_value));
486
487 value = static_cast<Real>(petsc_value);
488
489 return value;
490}
491template <typename T>
496template <typename T>
501template <typename T>
506
507
508
509template <typename T>
510void PetscMatrix<T>::print_matlab (const std::string & name) const
511{
512 libmesh_assert (this->initialized());
513
514 semiparallel_only();
515
516 if (!this->closed())
517 {
518 libmesh_deprecated();
519 libmesh_warning("The matrix must be assembled before calling PetscMatrix::print_matlab().\n"
520 "Please update your code, as this warning will become an error in a future release.");
521 const_cast<PetscMatrix<T> *>(this)->close();
522 }
523
524 // Create an ASCII file containing the matrix
525 // if a filename was provided.
526 if (name != "")
527 {
528 WrappedPetsc<PetscViewer> petsc_viewer;
529
530 LibmeshPetscCall(PetscViewerASCIIOpen( this->comm().get(),
531 name.c_str(),
532 petsc_viewer.get()));
533
534#if PETSC_VERSION_LESS_THAN(3,7,0)
535 LibmeshPetscCall(PetscViewerSetFormat (petsc_viewer,
536 PETSC_VIEWER_ASCII_MATLAB));
537#else
538 LibmeshPetscCall(PetscViewerPushFormat (petsc_viewer,
539 PETSC_VIEWER_ASCII_MATLAB));
540#endif
541
542 LibmeshPetscCall(MatView (this->_mat, petsc_viewer));
543 }
544
545 // Otherwise the matrix will be dumped to the screen.
546 else
547 {
548#if PETSC_VERSION_LESS_THAN(3,7,0)
549 LibmeshPetscCall(PetscViewerSetFormat (PETSC_VIEWER_STDOUT_WORLD,
550 PETSC_VIEWER_ASCII_MATLAB));
551#else
552 LibmeshPetscCall(PetscViewerPushFormat (PETSC_VIEWER_STDOUT_WORLD,
553 PETSC_VIEWER_ASCII_MATLAB));
554#endif
555
556 LibmeshPetscCall(MatView (this->_mat, PETSC_VIEWER_STDOUT_WORLD));
557 }
558}
559
560
561
562
563
564template <typename T>
565void PetscMatrix<T>::print_personal(std::ostream & os) const
566{
567 libmesh_assert (this->initialized());
568
569 // Routine must be called in parallel on parallel matrices
570 // and serial on serial matrices.
571 semiparallel_only();
572
573 // #ifndef NDEBUG
574 // if (os != std::cout)
575 // libMesh::err << "Warning! PETSc can only print to std::cout!" << std::endl;
576 // #endif
577
578 // Matrix must be in an assembled state to be printed
579 if (!this->closed())
580 {
581 libmesh_deprecated();
582 libmesh_warning("The matrix must be assembled before calling PetscMatrix::print_personal().\n"
583 "Please update your code, as this warning will become an error in a future release.");
584 const_cast<PetscMatrix<T> *>(this)->close();
585 }
586
587 // Print to screen if ostream is stdout
588 if (os.rdbuf() == std::cout.rdbuf())
589 LibmeshPetscCall(MatView(this->_mat, NULL));
590
591 // Otherwise, print to the requested file, in a roundabout way...
592 else
593 {
594 // We will create a temporary filename, and file, for PETSc to
595 // write to.
596 std::string temp_filename;
597
598 {
599 // Template for temporary filename
600 char c[] = "temp_petsc_matrix.XXXXXX";
601
602 // Generate temporary, unique filename only on processor 0. We will
603 // use this filename for PetscViewerASCIIOpen, before copying it into
604 // the user's stream
605 if (this->processor_id() == 0)
606 {
607 int fd = mkstemp(c);
608
609 // Check to see that mkstemp did not fail.
610 libmesh_error_msg_if(fd == -1, "mkstemp failed in PetscMatrix::print_personal()");
611
612 // mkstemp returns a file descriptor for an open file,
613 // so let's close it before we hand it to PETSc!
614 ::close (fd);
615 }
616
617 // Store temporary filename as string, makes it easier to broadcast
618 temp_filename = c;
619 }
620
621 // Now broadcast the filename from processor 0 to all processors.
622 this->comm().broadcast(temp_filename);
623
624 // PetscViewer object for passing to MatView
625 PetscViewer petsc_viewer;
626
627 // This PETSc function only takes a string and handles the opening/closing
628 // of the file internally. Since print_personal() takes a reference to
629 // an ostream, we have to do an extra step... print_personal() should probably
630 // have a version that takes a string to get rid of this problem.
631 LibmeshPetscCall(PetscViewerASCIIOpen( this->comm().get(),
632 temp_filename.c_str(),
633 &petsc_viewer));
634
635 // Probably don't need to set the format if it's default...
636 // ierr = PetscViewerSetFormat (petsc_viewer,
637 // PETSC_VIEWER_DEFAULT);
638 // LIBMESH_CHKERR(ierr);
639
640 // Finally print the matrix using the viewer
641 LibmeshPetscCall(MatView (this->_mat, petsc_viewer));
642
643 if (this->processor_id() == 0)
644 {
645 // Now the inefficient bit: open temp_filename as an ostream and copy the contents
646 // into the user's desired ostream. We can't just do a direct file copy, we don't even have the filename!
647 std::ifstream input_stream(temp_filename.c_str());
648 os << input_stream.rdbuf(); // The "most elegant" way to copy one stream into another.
649 // os.close(); // close not defined in ostream
650
651 // Now remove the temporary file
652 input_stream.close();
653 std::remove(temp_filename.c_str());
654 }
655 }
656}
657
658
659
660template <typename T>
661void PetscMatrix<T>::_petsc_viewer(const std::string & filename,
662 PetscViewerType viewertype,
663 PetscFileMode filemode)
664{
665 parallel_object_only();
666
667 // We'll get matrix sizes from the file, but we need to at least
668 // have a Mat object
669 if (!this->initialized())
670 {
671 LibmeshPetscCall(MatCreate(this->comm().get(), &this->_mat));
672 this->_is_initialized = true;
673 }
674
675 PetscViewer viewer;
676 LibmeshPetscCall(PetscViewerCreate(this->comm().get(), &viewer));
677 LibmeshPetscCall(PetscViewerSetType(viewer, viewertype));
678 LibmeshPetscCall(PetscViewerSetFromOptions(viewer));
679 LibmeshPetscCall(PetscViewerFileSetMode(viewer, filemode));
680 LibmeshPetscCall(PetscViewerFileSetName(viewer, filename.c_str()));
681 if (filemode == FILE_MODE_READ)
682 LibmeshPetscCall(MatLoad(this->_mat, viewer));
683 else
684 LibmeshPetscCall(MatView(this->_mat, viewer));
685 LibmeshPetscCall(PetscViewerDestroy(&viewer));
686}
687
688
689
690template <typename T>
691void PetscMatrix<T>::print_petsc_binary(const std::string & filename) const
692{
693 libmesh_assert (this->initialized());
694
695 // Our helper here isn't const-correct for writes
696 PetscMatrix<T> * nonconst_this = const_cast<PetscMatrix<T>*>(this);
697 nonconst_this->_petsc_viewer(filename, PETSCVIEWERBINARY, FILE_MODE_WRITE);
698}
699
700
701
702template <typename T>
703void PetscMatrix<T>::print_petsc_hdf5(const std::string & filename) const
704{
705 libmesh_assert (this->initialized());
706
707 // Our helper here isn't const-correct for writes
708 PetscMatrix<T> * nonconst_this = const_cast<PetscMatrix<T>*>(this);
709 nonconst_this->_petsc_viewer(filename, PETSCVIEWERHDF5, FILE_MODE_WRITE);
710}
711
712
713
714template <typename T>
715void PetscMatrix<T>::read_petsc_binary(const std::string & filename)
716{
717 LOG_SCOPE("read_petsc_binary()", "PetscMatrix");
718
719 this->_petsc_viewer(filename, PETSCVIEWERBINARY, FILE_MODE_READ);
720}
721
722
723
724template <typename T>
725void PetscMatrix<T>::read_petsc_hdf5(const std::string & filename)
726{
727 LOG_SCOPE("read_petsc_hdf5()", "PetscMatrix");
728
729 this->_petsc_viewer(filename, PETSCVIEWERHDF5, FILE_MODE_READ);
730}
731
732
733
734template <typename T>
736 const std::vector<numeric_index_type> & rows,
737 const std::vector<numeric_index_type> & cols)
738{
739 libmesh_assert (this->initialized());
740
741 const numeric_index_type n_rows = dm.m();
742 const numeric_index_type n_cols = dm.n();
743
744 libmesh_assert_equal_to (rows.size(), n_rows);
745 libmesh_assert_equal_to (cols.size(), n_cols);
746
747 std::scoped_lock lock(this->_petsc_matrix_mutex);
748 LibmeshPetscCall(MatSetValues(this->_mat,
749 n_rows, numeric_petsc_cast(rows.data()),
750 n_cols, numeric_petsc_cast(cols.data()),
751 pPS(const_cast<T*>(dm.get_values().data())),
752 ADD_VALUES));
753}
754
755
756
757
758
759
760template <typename T>
762 const std::vector<numeric_index_type> & brows,
763 const std::vector<numeric_index_type> & bcols)
764{
765 libmesh_assert (this->initialized());
766
767 const numeric_index_type n_brows =
768 cast_int<numeric_index_type>(brows.size());
769 const numeric_index_type n_bcols =
770 cast_int<numeric_index_type>(bcols.size());
771
772#ifndef NDEBUG
773 const numeric_index_type n_rows =
774 cast_int<numeric_index_type>(dm.m());
775 const numeric_index_type n_cols =
776 cast_int<numeric_index_type>(dm.n());
777 const numeric_index_type blocksize = n_rows / n_brows;
778
779 libmesh_assert_equal_to (n_cols / n_bcols, blocksize);
780 libmesh_assert_equal_to (blocksize*n_brows, n_rows);
781 libmesh_assert_equal_to (blocksize*n_bcols, n_cols);
782
783 PetscInt petsc_blocksize;
784 LibmeshPetscCall(MatGetBlockSize(this->_mat, &petsc_blocksize));
785 libmesh_assert_equal_to (blocksize, static_cast<numeric_index_type>(petsc_blocksize));
786#endif
787
788 std::scoped_lock lock(this->_petsc_matrix_mutex);
789 // These casts are required for PETSc <= 2.1.5
790 LibmeshPetscCall(MatSetValuesBlocked(this->_mat,
791 n_brows, numeric_petsc_cast(brows.data()),
792 n_bcols, numeric_petsc_cast(bcols.data()),
793 pPS(const_cast<T*>(dm.get_values().data())),
794 ADD_VALUES));
795}
796
797
798
799
800
801template <typename T>
803 const std::vector<numeric_index_type> & rows,
804 const std::vector<numeric_index_type> & cols,
805 const bool reuse_submatrix) const
806{
807 if (!this->closed())
808 {
809 libmesh_deprecated();
810 libmesh_warning("The matrix must be assembled before calling PetscMatrix::create_submatrix().\n"
811 "Please update your code, as this warning will become an error in a future release.");
812 const_cast<PetscMatrix<T> *>(this)->close();
813 }
814
815 semiparallel_only();
816
817 // Make sure the SparseMatrix passed in is really a PetscMatrix
818 PetscMatrix<T> * petsc_submatrix = cast_ptr<PetscMatrix<T> *>(&submatrix);
819
820 // If we're not reusing submatrix and submatrix is already initialized
821 // then we need to clear it, otherwise we get a memory leak.
822 if (!reuse_submatrix && submatrix.initialized())
823 submatrix.clear();
824
825 // Construct row and column index sets.
826 WrappedPetsc<IS> isrow;
827 LibmeshPetscCall(ISCreateGeneral(this->comm().get(),
828 cast_int<PetscInt>(rows.size()),
829 numeric_petsc_cast(rows.data()),
830 PETSC_USE_POINTER,
831 isrow.get()));
832
833 WrappedPetsc<IS> iscol;
834 LibmeshPetscCall(ISCreateGeneral(this->comm().get(),
835 cast_int<PetscInt>(cols.size()),
836 numeric_petsc_cast(cols.data()),
837 PETSC_USE_POINTER,
838 iscol.get()));
839
840 // Extract submatrix
841 LibmeshPetscCall(LibMeshCreateSubMatrix(this->_mat,
842 isrow,
843 iscol,
844 (reuse_submatrix ? MAT_REUSE_MATRIX : MAT_INITIAL_MATRIX),
845 (&petsc_submatrix->_mat)));
846
847 // Specify that the new submatrix is initialized and close it.
848 petsc_submatrix->_is_initialized = true;
849 petsc_submatrix->close();
850}
851
852template <typename T>
854 const std::vector<numeric_index_type> & rows,
855 const std::vector<numeric_index_type> & cols) const
856{
857 if (!this->closed())
858 {
859 libmesh_deprecated();
860 libmesh_warning("The matrix must be assembled before calling PetscMatrix::create_submatrix_nosort().\n"
861 "Please update your code, as this warning will become an error in a future release.");
862 const_cast<PetscMatrix<T> *>(this)->close();
863 }
864
865 // Make sure the SparseMatrix passed in is really a PetscMatrix
866 PetscMatrix<T> * petsc_submatrix = cast_ptr<PetscMatrix<T> *>(&submatrix);
867
868 LibmeshPetscCall(MatZeroEntries(petsc_submatrix->_mat));
869
870 PetscInt pc_ncols = 0;
871 const PetscInt * pc_cols;
872 const PetscScalar * pc_vals;
873
874 // // data for creating the submatrix
875 std::vector<PetscInt> sub_cols;
876 std::vector<PetscScalar> sub_vals;
877
878 for (auto i : index_range(rows))
879 {
880 PetscInt sub_rid[] = {static_cast<PetscInt>(i)};
881 PetscInt rid = static_cast<PetscInt>(rows[i]);
882 // only get value from local rows, and set values to the corresponding columns in the submatrix
883 if (rows[i]>= this->row_start() && rows[i]< this->row_stop())
884 {
885 // get one row of data from the original matrix
886 LibmeshPetscCall(MatGetRow(this->_mat, rid, &pc_ncols, &pc_cols, &pc_vals));
887 // extract data from certain cols, save the indices and entries sub_cols and sub_vals
888 for (auto j : index_range(cols))
889 {
890 for (unsigned int idx = 0; idx< static_cast<unsigned int>(pc_ncols); idx++)
891 {
892 if (pc_cols[idx] == static_cast<PetscInt>(cols[j]))
893 {
894 sub_cols.push_back(static_cast<PetscInt>(j));
895 sub_vals.push_back(pc_vals[idx]);
896 }
897 }
898 }
899 // set values
900 LibmeshPetscCall(MatSetValues(petsc_submatrix->_mat,
901 1,
902 sub_rid,
903 static_cast<PetscInt>(sub_vals.size()),
904 sub_cols.data(),
905 sub_vals.data(),
906 INSERT_VALUES));
907 LibmeshPetscCall(MatRestoreRow(this->_mat, rid, &pc_ncols, &pc_cols, &pc_vals));
908 // clear data for this row
909 sub_cols.clear();
910 sub_vals.clear();
911 }
912 }
913 MatAssemblyBeginEnd(petsc_submatrix->comm(), petsc_submatrix->_mat, MAT_FINAL_ASSEMBLY);
914 // Specify that the new submatrix is initialized and close it.
915 petsc_submatrix->_is_initialized = true;
916 petsc_submatrix->close();
917}
918
919
920template <typename T>
922{
923 // Make sure the NumericVector passed in is really a PetscVector
924 PetscVector<T> & petsc_dest = cast_ref<PetscVector<T> &>(dest);
925
926 // Needs a const_cast since PETSc does not work with const.
927 LibmeshPetscCall(MatGetDiagonal(const_cast<PetscMatrix<T> *>(this)->mat(),petsc_dest.vec()));
928}
929
930
931
932template <typename T>
934{
935 // Make sure the SparseMatrix passed in is really a PetscMatrix
936 PetscMatrix<T> & petsc_dest = cast_ref<PetscMatrix<T> &>(dest);
937
938 // If we aren't reusing the matrix then need to clear dest,
939 // otherwise we get a memory leak
940 if (&petsc_dest != this)
941 dest.clear();
942
943 if (&petsc_dest == this)
944 // The MAT_REUSE_MATRIX flag was replaced by MAT_INPLACE_MATRIX
945 // in PETSc 3.7.0
946#if PETSC_VERSION_LESS_THAN(3,7,0)
947 LibmeshPetscCall(MatTranspose(this->_mat,MAT_REUSE_MATRIX, &petsc_dest._mat));
948#else
949 LibmeshPetscCall(MatTranspose(this->_mat, MAT_INPLACE_MATRIX, &petsc_dest._mat));
950#endif
951 else
952 LibmeshPetscCall(MatTranspose(this->_mat,MAT_INITIAL_MATRIX, &petsc_dest._mat));
953
954 // Specify that the transposed matrix is initialized and close it.
955 petsc_dest._is_initialized = true;
956 petsc_dest.close();
957}
958
959
960
961template <typename T>
963{
964 semiparallel_only();
965
966 MatAssemblyBeginEnd(this->comm(), this->_mat, MAT_FLUSH_ASSEMBLY);
967}
968
969
970
971template <typename T>
973 const numeric_index_type j,
974 const T value)
975{
976 libmesh_assert (this->initialized());
977
978 PetscInt i_val=i, j_val=j;
979
980 PetscScalar petsc_value = static_cast<PetscScalar>(value);
981 std::scoped_lock lock(this->_petsc_matrix_mutex);
982 LibmeshPetscCall(MatSetValues(this->_mat, 1, &i_val, 1, &j_val,
983 &petsc_value, INSERT_VALUES));
984}
985
986
987
988template <typename T>
990 const numeric_index_type j,
991 const T value)
992{
993 libmesh_assert (this->initialized());
994
995 PetscInt i_val=i, j_val=j;
996
997 PetscScalar petsc_value = static_cast<PetscScalar>(value);
998 std::scoped_lock lock(this->_petsc_matrix_mutex);
999 LibmeshPetscCall(MatSetValues(this->_mat, 1, &i_val, 1, &j_val,
1000 &petsc_value, ADD_VALUES));
1001}
1002
1003
1004
1005template <typename T>
1007 const std::vector<numeric_index_type> & dof_indices)
1008{
1009 this->add_matrix (dm, dof_indices, dof_indices);
1010}
1011
1012
1013
1014
1015
1016
1017
1018template <typename T>
1019void PetscMatrix<T>::add (const T a_in, const SparseMatrix<T> & X_in)
1020{
1021 libmesh_assert (this->initialized());
1022
1023 // sanity check. but this cannot avoid
1024 // crash due to incompatible sparsity structure...
1025 libmesh_assert_equal_to (this->m(), X_in.m());
1026 libmesh_assert_equal_to (this->n(), X_in.n());
1027
1028 PetscScalar a = static_cast<PetscScalar> (a_in);
1029 const PetscMatrix<T> * X = cast_ptr<const PetscMatrix<T> *> (&X_in);
1030
1031 libmesh_assert (X);
1032
1033 // the matrix from which we copy the values has to be assembled/closed
1034 libmesh_assert(X->closed());
1035
1036 semiparallel_only();
1037
1038 LibmeshPetscCall(MatAXPY(this->_mat, a, X->_mat, DIFFERENT_NONZERO_PATTERN));
1039}
1040
1041
1042template <typename T>
1044{
1045 libmesh_assert (this->initialized());
1046
1047 // sanity check
1048 // we do not check the Y_out size here as we will initialize & close it at the end
1049 libmesh_assert_equal_to (this->n(), X_in.m());
1050
1051 const PetscMatrix<T> * X = cast_ptr<const PetscMatrix<T> *> (&X_in);
1052 PetscMatrix<T> * Y = cast_ptr<PetscMatrix<T> *> (&Y_out);
1053
1054 // the matrix from which we copy the values has to be assembled/closed
1055 libmesh_assert(X->closed());
1056
1057 semiparallel_only();
1058
1059 if (reuse)
1060 LibmeshPetscCall(MatMatMult(this->_mat, X->_mat, MAT_REUSE_MATRIX, PETSC_DEFAULT, &Y->_mat));
1061 else
1062 {
1063 Y->clear();
1064 LibmeshPetscCall(MatMatMult(this->_mat, X->_mat, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &Y->_mat));
1065 }
1066 // Specify that the new matrix is initialized
1067 // We do not close it here as `MatMatMult` ensures Y being closed
1068 Y->_is_initialized = true;
1069}
1070
1071template <typename T>
1072void
1074 const std::map<numeric_index_type, numeric_index_type> & row_ltog,
1075 const std::map<numeric_index_type, numeric_index_type> & col_ltog,
1076 const T scalar)
1077{
1078 // size of spm is usually greater than row_ltog and col_ltog in parallel as the indices are owned by the processor
1079 // also, we should allow adding certain parts of spm to _mat
1080 libmesh_assert_greater_equal(spm.m(), row_ltog.size());
1081 libmesh_assert_greater_equal(spm.n(), col_ltog.size());
1082
1083 // make sure matrix has larger size than spm
1084 libmesh_assert_greater_equal(this->m(), spm.m());
1085 libmesh_assert_greater_equal(this->n(), spm.n());
1086
1087 if (!this->closed())
1088 this->close();
1089
1090 auto pscm = cast_ptr<const PetscMatrix<T> *>(&spm);
1091
1092 PetscInt ncols = 0;
1093
1094 const PetscInt * lcols;
1095 const PetscScalar * vals;
1096
1097 std::vector<PetscInt> gcols;
1098 std::vector<PetscScalar> values;
1099
1100 for (auto ltog : row_ltog)
1101 {
1102 PetscInt grow[] = {static_cast<PetscInt>(ltog.second)}; // global row index
1103
1104 LibmeshPetscCall(MatGetRow(pscm->_mat, static_cast<PetscInt>(ltog.first), &ncols, &lcols, &vals));
1105
1106 // get global indices (gcols) from lcols, increment values = vals*scalar
1107 gcols.resize(ncols);
1108 values.resize(ncols);
1109 for (auto i : index_range(gcols))
1110 {
1111 gcols[i] = libmesh_map_find(col_ltog, lcols[i]);
1112 values[i] = PS(scalar) * vals[i];
1113 }
1114
1115 LibmeshPetscCall(MatSetValues(this->_mat, 1, grow, ncols, gcols.data(), values.data(), ADD_VALUES));
1116 LibmeshPetscCall(MatRestoreRow(pscm->_mat, static_cast<PetscInt>(ltog.first), &ncols, &lcols, &vals));
1117 }
1118 // Note: We are not closing the matrix because it is expensive to do so when adding multiple sparse matrices.
1119 // Remember to manually close the matrix once all changes to the matrix have been made.
1120}
1121
1122template <typename T>
1124 const numeric_index_type j_in) const
1125{
1126 libmesh_assert (this->initialized());
1127
1128 // If the entry is not in the sparse matrix, it is 0.
1129 T value=0.;
1130
1131 PetscInt
1132 i_val=static_cast<PetscInt>(i_in),
1133 j_val=static_cast<PetscInt>(j_in);
1134
1135
1136 // the matrix needs to be closed for this to work
1137 // this->close();
1138 // but closing it is a semiparallel operation; we want operator()
1139 // to run on one processor.
1140 libmesh_assert(this->closed());
1141
1142 LibmeshPetscCall(MatGetValue(this->_mat, i_val, j_val, &value));
1143
1144 return value;
1145}
1146
1147template <typename T>
1149 std::vector<numeric_index_type> & indices,
1150 std::vector<T> & values) const
1151{
1152 libmesh_assert (this->initialized());
1153
1154 const PetscScalar * petsc_row;
1155 const PetscInt * petsc_cols;
1156
1157 PetscInt
1158 ncols=0,
1159 i_val = static_cast<PetscInt>(i_in);
1160
1161 // the matrix needs to be closed for this to work
1162 // this->close();
1163 // but closing it is a semiparallel operation; we want operator()
1164 // to run on one processor.
1165 libmesh_assert(this->closed());
1166
1167 // PETSc makes no effort at being thread safe. Helgrind complains about
1168 // possible data races even just in PetscFunctionBegin (due to things
1169 // like stack counter incrementing). Perhaps we could ignore
1170 // this, but there are legitimate data races for Mat data members like
1171 // mat->getrowactive between MatGetRow and MatRestoreRow. Moreover,
1172 // there could be a write into mat->rowvalues during MatGetRow from
1173 // one thread while we are attempting to read from mat->rowvalues
1174 // (through petsc_cols) during data copy in another thread. So
1175 // the safe thing to do is to lock the whole method
1176
1177 std::lock_guard<std::mutex> lock(_petsc_matrix_mutex);
1178
1179 LibmeshPetscCall(MatGetRow(this->_mat, i_val, &ncols, &petsc_cols, &petsc_row));
1180
1181 // Copy the data
1182 indices.resize(static_cast<std::size_t>(ncols));
1183 values.resize(static_cast<std::size_t>(ncols));
1184
1185 for (auto i : index_range(indices))
1186 {
1187 indices[i] = static_cast<numeric_index_type>(petsc_cols[i]);
1188 values[i] = static_cast<T>(petsc_row[i]);
1189 }
1190
1191 LibmeshPetscCall(MatRestoreRow(this->_mat, i_val,
1192 &ncols, &petsc_cols, &petsc_row));
1193}
1194
1195
1196
1197template <typename T>
1199{
1200 semiparallel_only();
1201
1202 if (this->_mat)
1203 {
1204 PetscBool assembled;
1205 LibmeshPetscCall(MatAssembled(this->_mat, &assembled));
1206#ifndef NDEBUG
1207 const bool cxx_assembled = (assembled == PETSC_TRUE) ? true : false;
1208 libmesh_assert(this->_communicator.verify(cxx_assembled));
1209#endif
1210
1211 if (!assembled)
1212 // MatCopy does not work with an unassembled matrix. We could use MatDuplicate but then we
1213 // would have to destroy the matrix we manage and others might be relying on that data. So
1214 // we just assemble here regardless of the preceding level of matrix fill
1215 this->close();
1216 LibmeshPetscCall(MatCopy(v._mat, this->_mat, DIFFERENT_NONZERO_PATTERN));
1217 }
1218 else
1219 LibmeshPetscCall(MatDuplicate(v._mat, MAT_COPY_VALUES, &this->_mat));
1220
1221 this->_is_initialized = true;
1222
1223 return *this;
1224}
1225
1226template <typename T>
1228{
1229 *this = cast_ref<const PetscMatrix<T> &>(v);
1230 return *this;
1231}
1232
1233template <typename T>
1234void PetscMatrix<T>::scale(const T scale)
1235{
1236 libmesh_assert(this->closed());
1237
1238 LibmeshPetscCall(MatScale(this->_mat, PS(scale)));
1239}
1240
1241template <typename T>
1243{
1244#if PETSC_RELEASE_LESS_THAN(3,19,0)
1245 return false;
1246#else
1247 return true;
1248#endif
1249}
1250
1251#if PETSC_RELEASE_GREATER_EQUALS(3,23,0)
1252template <typename T>
1253std::unique_ptr<PetscMatrix<T>>
1255{
1256 Mat xaij;
1257 libmesh_assert(this->initialized());
1258 libmesh_assert(!this->closed());
1259 LibmeshPetscCall(MatDuplicate(this->_mat, MAT_DO_NOT_COPY_VALUES, &xaij));
1260 LibmeshPetscCall(MatCopyHashToXAIJ(this->_mat, xaij));
1261 return std::make_unique<PetscMatrix<T>>(xaij, this->comm(), /*destroy_on_exit=*/true);
1262}
1263#endif
1264
1265template <typename T>
1266void
1268{
1269 semiparallel_only();
1270
1271 if (this->_use_hash_table)
1272#if PETSC_RELEASE_GREATER_EQUALS(3, 23, 0)
1273 // This performs MatReset plus re-establishes the hash table
1274 LibmeshPetscCall(MatResetHash(this->_mat));
1275#else
1276 libmesh_error_msg("Resetting hash tables not supported until PETSc version 3.23");
1277#endif
1278 else
1279 this->reset_preallocation();
1280}
1281
1282//------------------------------------------------------------------
1283// Explicit instantiations
1284template class LIBMESH_EXPORT PetscMatrix<Number>;
1285
1286} // namespace libMesh
1287
1288
1289#endif // #ifdef LIBMESH_HAVE_PETSC
void finish_initialization()
Definition initial.C:11
Defines a dense matrix for use in Finite Element-type computations.
std::vector< T > & get_values()
Provides a uniform interface to vector storage schemes for different linear algebra libraries.
const Parallel::Communicator & comm() const
This class provides a nice interface to the PETSc C-based data structures for parallel,...
virtual void close() override
Calls the SparseMatrix's internal assembly routines, ensuring that the values are consistent across p...
virtual bool closed() const override
Mat _mat
PETSc matrix datatype to store values.
This class provides a nice interface to the PETSc C-based AIJ data structures for parallel,...
void update_preallocation_and_zero()
Update the sparsity pattern based on dof_map, and set the matrix to zero.
virtual Real l1_norm() const override
virtual void _get_submatrix(SparseMatrix< T > &submatrix, const std::vector< numeric_index_type > &rows, const std::vector< numeric_index_type > &cols, const bool reuse_submatrix) const override
This function either creates or re-initializes a matrix called submatrix which is defined by the indi...
virtual void flush() override
For PETSc matrix , this function is similar to close but without shrinking memory.
virtual void add_matrix(const DenseMatrix< T > &dm, const std::vector< numeric_index_type > &rows, const std::vector< numeric_index_type > &cols) override
Add the full matrix dm to the SparseMatrix.
virtual void get_row(numeric_index_type i, std::vector< numeric_index_type > &indices, std::vector< T > &values) const override
Get a row from the matrix.
virtual void zero_rows(std::vector< numeric_index_type > &rows, T diag_value=0.0) override
Sets all row entries to 0 then puts diag_value in the diagonal entry.
virtual bool supports_hash_table() const override
virtual void print_petsc_hdf5(const std::string &filename) const override
Write the contents of the matrix to a file in PETSc's HDF5 sparse matrix format.
virtual void get_diagonal(NumericVector< T > &dest) const override
Copies the diagonal part of the matrix into dest.
std::unique_ptr< PetscMatrix< T > > copy_from_hash()
Creates a copy of the current hash table matrix and then performs assembly.
virtual void matrix_matrix_mult(SparseMatrix< T > &X, SparseMatrix< T > &Y, bool reuse=false) override
Compute Y = A*X for matrix X.
virtual void add_sparse_matrix(const SparseMatrix< T > &spm, const std::map< numeric_index_type, numeric_index_type > &row_ltog, const std::map< numeric_index_type, numeric_index_type > &col_ltog, const T scalar) override
Add scalar* spm to the rows and cols of this matrix (A): A(rows[i], cols[j]) += scalar * spm(i,...
virtual void add(const numeric_index_type i, const numeric_index_type j, const T value) override
Add value to the element (i,j).
virtual std::unique_ptr< SparseMatrix< T > > zero_clone() const override
virtual void create_submatrix_nosort(SparseMatrix< T > &submatrix, const std::vector< numeric_index_type > &rows, const std::vector< numeric_index_type > &cols) const override
Similar to the create_submatrix function, this function creates a submatrix which is defined by the i...
virtual void restore_original_nonzero_pattern() override
Reset the memory storage of the matrix.
PetscMatrix(const Parallel::Communicator &comm_in)
Constructor; initializes the matrix to be empty, without any structure, i.e.
virtual void read_petsc_binary(const std::string &filename) override
Read the contents of the matrix from a file in PETSc's binary sparse matrix format.
void reset_preallocation()
Reset matrix to use the original nonzero pattern provided by users.
void preallocate(numeric_index_type m_l, const std::vector< numeric_index_type > &n_nz, const std::vector< numeric_index_type > &n_oz, numeric_index_type blocksize)
virtual void print_personal(std::ostream &os=libMesh::out) const override
Print the contents of the matrix to the screen with the PETSc viewer.
virtual void get_transpose(SparseMatrix< T > &dest) const override
Copies the transpose of the matrix into dest, which may be *this.
PetscMatrixType _mat_type
virtual std::unique_ptr< SparseMatrix< T > > clone() const override
virtual void scale(const T scale) override
Scales all elements of this matrix by scale.
void finish_initialization()
Finish up the initialization process.
virtual void read_petsc_hdf5(const std::string &filename) override
Read the contents of the matrix from a file in PETSc's HDF5 sparse matrix format.
virtual void init(const numeric_index_type m, const numeric_index_type n, const numeric_index_type m_l, const numeric_index_type n_l, const numeric_index_type n_nz=30, const numeric_index_type n_oz=10, const numeric_index_type blocksize=1) override
Initialize a PETSc matrix.
PetscMatrix & operator=(PetscMatrix &&)=delete
virtual Real linfty_norm() const override
void init_without_preallocation(numeric_index_type m, numeric_index_type n, numeric_index_type m_l, numeric_index_type n_l, numeric_index_type blocksize)
Perform matrix initialization steps sans preallocation.
virtual void print_matlab(const std::string &name="") const override
Print the contents of the matrix in Matlab's sparse matrix format.
virtual void add_block_matrix(const DenseMatrix< T > &dm, const std::vector< numeric_index_type > &brows, const std::vector< numeric_index_type > &bcols) override
Add the full matrix dm to the SparseMatrix.
void _petsc_viewer(const std::string &filename, PetscViewerType viewertype, PetscFileMode filemode)
virtual void zero() override
Set all entries to 0.
virtual T operator()(const numeric_index_type i, const numeric_index_type j) const override
virtual void set(const numeric_index_type i, const numeric_index_type j, const T value) override
Set the element (i,j) to value.
Real frobenius_norm() const
virtual void print_petsc_binary(const std::string &filename) const override
Write the contents of the matrix to a file in PETSc's binary sparse matrix format.
This class provides a nice interface to PETSc's Vec object.
Generic sparse matrix.
virtual bool initialized() const
virtual numeric_index_type n() const =0
virtual void clear()=0
Restores the SparseMatrix<T> to a pristine state.
virtual numeric_index_type m() const =0
bool _is_initialized
Flag indicating whether or not the matrix has been initialized.
The libMesh namespace provides an interface to certain functionality in the library.
auto index_range(const T &sizable)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
Definition int_range.h:153
ParallelType
Defines an enum for parallel data structure types.
bool closed()
Checks that the library has been closed.
Definition libmesh.C:331
void libmesh_ignore(const Args &...)
libmesh_assert(ctx)
PetscScalar * pPS(T *ptr)
dof_id_type numeric_index_type
Definition id_types.h:99
PetscInt * numeric_petsc_cast(const numeric_index_type *p)
bool initialized()
Checks that library initialization has been done.
Definition libmesh.C:324
PetscScalar PS(T val)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
int mkstemp(char *tmpl)
Definition win_mkstemp.h:13
static const bool value
Definition xdr_io.C:55