Reference documentation for deal.II version GIT 982a52a150 2023-04-01 20:45:01+00:00
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
petsc_matrix_base.cc
Go to the documentation of this file.
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2004 - 2022 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE.md at
12 // the top level directory of deal.II.
13 //
14 // ---------------------------------------------------------------------
15 
17 
18 #ifdef DEAL_II_WITH_PETSC
19 
20 # include <deal.II/lac/exceptions.h>
25 
27 
28 namespace PETScWrappers
29 {
30  namespace MatrixIterators
31  {
32 # ifndef DOXYGEN
33  void
35  {
36  // if we are asked to visit the past-the-end line (or a line that is not
37  // stored on the current processor), then simply release all our caches
38  // and go on with life
39  if (matrix->in_local_range(this->a_row) == false)
40  {
41  colnum_cache.reset();
42  value_cache.reset();
43 
44  return;
45  }
46 
47  // get a representation of the present row
48  PetscInt ncols;
49  const PetscInt * colnums;
50  const PetscScalar *values;
51 
52  PetscErrorCode ierr =
53  MatGetRow(*matrix, this->a_row, &ncols, &colnums, &values);
54  AssertThrow(ierr == 0, ExcPETScError(ierr));
55 
56  // copy it into our caches if the line
57  // isn't empty. if it is, then we've
58  // done something wrong, since we
59  // shouldn't have initialized an
60  // iterator for an empty line (what
61  // would it point to?)
62  Assert(ncols != 0, ExcInternalError());
63  colnum_cache =
64  std::make_shared<std::vector<size_type>>(colnums, colnums + ncols);
65  value_cache =
66  std::make_shared<std::vector<PetscScalar>>(values, values + ncols);
67 
68  // and finally restore the matrix
69  ierr = MatRestoreRow(*matrix, this->a_row, &ncols, &colnums, &values);
70  AssertThrow(ierr == 0, ExcPETScError(ierr));
71  }
72 # endif
73  } // namespace MatrixIterators
74 
75 
76 
78  : matrix(nullptr)
79  , last_action(VectorOperation::unknown)
80  {}
81 
82 
84  : matrix(A)
85  , last_action(VectorOperation::unknown)
86  {
87  const PetscErrorCode ierr =
88  PetscObjectReference(reinterpret_cast<PetscObject>(matrix));
89  AssertThrow(ierr == 0, ExcPETScError(ierr));
90  }
91 
92  void
94  {
96  ExcMessage("Cannot assign a new Mat."));
97  PetscErrorCode ierr =
98  PetscObjectReference(reinterpret_cast<PetscObject>(A));
99  AssertThrow(ierr == 0, ExcPETScError(ierr));
101  matrix = A;
102  }
103 
105  {
107  }
108 
109  void
111  {
112  // destroy the matrix...
113  {
114  const PetscErrorCode ierr = destroy_matrix(matrix);
115  AssertThrow(ierr == 0, ExcPETScError(ierr));
116  }
117 
118  // ...and replace it by an empty
119  // sequential matrix
120  const int m = 0, n = 0, n_nonzero_per_row = 0;
121  const PetscErrorCode ierr = MatCreateSeqAIJ(
122  PETSC_COMM_SELF, m, n, n_nonzero_per_row, nullptr, &matrix);
123  AssertThrow(ierr == 0, ExcPETScError(ierr));
124  }
125 
126 
127 
128  MatrixBase &
130  {
131  (void)d;
133 
135 
136  const PetscErrorCode ierr = MatZeroEntries(matrix);
137  AssertThrow(ierr == 0, ExcPETScError(ierr));
138 
139  return *this;
140  }
141 
142 
143 
144  void
145  MatrixBase::clear_row(const size_type row, const PetscScalar new_diag_value)
146  {
147  std::vector<size_type> rows(1, row);
148  clear_rows(rows, new_diag_value);
149  }
150 
151 
152 
153  void
154  MatrixBase::clear_rows(const std::vector<size_type> &rows,
155  const PetscScalar new_diag_value)
156  {
158 
159  // now set all the entries of these rows
160  // to zero
161  const std::vector<PetscInt> petsc_rows(rows.begin(), rows.end());
162 
163  // call the functions. note that we have
164  // to call them even if #rows is empty,
165  // since this is a collective operation
166  IS index_set;
167 
168  ISCreateGeneral(get_mpi_communicator(),
169  rows.size(),
170  petsc_rows.data(),
171  PETSC_COPY_VALUES,
172  &index_set);
173 
174  const PetscErrorCode ierr =
175  MatZeroRowsIS(matrix, index_set, new_diag_value, nullptr, nullptr);
176  AssertThrow(ierr == 0, ExcPETScError(ierr));
177  ISDestroy(&index_set);
178  }
179 
180  void
181  MatrixBase::clear_rows_columns(const std::vector<size_type> &rows,
182  const PetscScalar new_diag_value)
183  {
185 
186  // now set all the entries of these rows
187  // to zero
188  const std::vector<PetscInt> petsc_rows(rows.begin(), rows.end());
189 
190  // call the functions. note that we have
191  // to call them even if #rows is empty,
192  // since this is a collective operation
193  IS index_set;
194 
195  ISCreateGeneral(get_mpi_communicator(),
196  rows.size(),
197  petsc_rows.data(),
198  PETSC_COPY_VALUES,
199  &index_set);
200 
201  const PetscErrorCode ierr =
202  MatZeroRowsColumnsIS(matrix, index_set, new_diag_value, nullptr, nullptr);
203  AssertThrow(ierr == 0, ExcPETScError(ierr));
204  ISDestroy(&index_set);
205  }
206 
207 
208 
209  PetscScalar
210  MatrixBase::el(const size_type i, const size_type j) const
211  {
212  PetscInt petsc_i = i, petsc_j = j;
213 
214  PetscScalar value;
215 
216  const PetscErrorCode ierr =
217  MatGetValues(matrix, 1, &petsc_i, 1, &petsc_j, &value);
218  AssertThrow(ierr == 0, ExcPETScError(ierr));
219 
220  return value;
221  }
222 
223 
224 
225  PetscScalar
227  {
228  Assert(m() == n(), ExcNotQuadratic());
229 
230  // this doesn't seem to work any
231  // different than any other element
232  return el(i, i);
233  }
234 
235 
236 
237  void
239  {
240  {
241 # ifdef DEBUG
242 # ifdef DEAL_II_WITH_MPI
243  // Check that all processors agree that last_action is the same (or none!)
244 
245  int my_int_last_action = last_action;
246  int all_int_last_action;
247 
248  const int ierr = MPI_Allreduce(&my_int_last_action,
249  &all_int_last_action,
250  1,
251  MPI_INT,
252  MPI_BOR,
254  AssertThrowMPI(ierr);
255 
256  AssertThrow(all_int_last_action !=
258  ExcMessage("Error: not all processors agree on the last "
259  "VectorOperation before this compress() call."));
260 # endif
261 # endif
262  }
263 
264  AssertThrow(
266  ExcMessage(
267  "Missing compress() or calling with wrong VectorOperation argument."));
268 
269  // flush buffers
270  PetscErrorCode ierr = MatAssemblyBegin(matrix, MAT_FINAL_ASSEMBLY);
271  AssertThrow(ierr == 0, ExcPETScError(ierr));
272 
273  ierr = MatAssemblyEnd(matrix, MAT_FINAL_ASSEMBLY);
274  AssertThrow(ierr == 0, ExcPETScError(ierr));
275 
277  }
278 
279 
280 
283  {
284  PetscInt n_rows, n_cols;
285 
286  const PetscErrorCode ierr = MatGetSize(matrix, &n_rows, &n_cols);
287  AssertThrow(ierr == 0, ExcPETScError(ierr));
288 
289  return n_rows;
290  }
291 
292 
293 
296  {
297  PetscInt n_rows, n_cols;
298 
299  const PetscErrorCode ierr = MatGetSize(matrix, &n_rows, &n_cols);
300  AssertThrow(ierr == 0, ExcPETScError(ierr));
301 
302  return n_cols;
303  }
304 
305 
306 
309  {
310  PetscInt n_rows, n_cols;
311 
312  const PetscErrorCode ierr = MatGetLocalSize(matrix, &n_rows, &n_cols);
313  AssertThrow(ierr == 0, ExcPETScError(ierr));
314 
315  return n_rows;
316  }
317 
318 
319 
320  std::pair<MatrixBase::size_type, MatrixBase::size_type>
322  {
323  PetscInt begin, end;
324 
325  const PetscErrorCode ierr =
326  MatGetOwnershipRange(static_cast<const Mat &>(matrix), &begin, &end);
327  AssertThrow(ierr == 0, ExcPETScError(ierr));
328 
329  return std::make_pair(begin, end);
330  }
331 
332 
333 
334  std::uint64_t
336  {
337  MatInfo mat_info;
338  const PetscErrorCode ierr = MatGetInfo(matrix, MAT_GLOBAL_SUM, &mat_info);
339  AssertThrow(ierr == 0, ExcPETScError(ierr));
340 
341  // MatInfo logs quantities as PetscLogDouble. So we need to cast it to match
342  // our interface.
343  return static_cast<std::uint64_t>(mat_info.nz_used);
344  }
345 
346 
347 
350  {
351  // TODO: this function will probably only work if compress() was called on
352  // the matrix previously. however, we can't do this here, since it would
353  // impose global communication and one would have to make sure that this
354  // function is called the same number of times from all processors,
355  // something that is unreasonable. there should simply be a way in PETSc to
356  // query the number of entries in a row bypassing the call to compress(),
357  // but I can't find one
358  Assert(row < m(), ExcInternalError());
359 
360  // get a representation of the present
361  // row
362  PetscInt ncols;
363  const PetscInt * colnums;
364  const PetscScalar *values;
365 
366  // TODO: this is probably horribly inefficient; we should lobby for a way to
367  // query this information from PETSc
368  PetscErrorCode ierr = MatGetRow(*this, row, &ncols, &colnums, &values);
369  AssertThrow(ierr == 0, ExcPETScError(ierr));
370 
371  // then restore the matrix and return the number of columns in this row as
372  // queried previously. Starting with PETSc 3.4, MatRestoreRow actually
373  // resets the last three arguments to nullptr, to avoid abuse of pointers
374  // now dangling. as a consequence, we need to save the size of the array
375  // and return the saved value.
376  const PetscInt ncols_saved = ncols;
377  ierr = MatRestoreRow(*this, row, &ncols, &colnums, &values);
378  AssertThrow(ierr == 0, ExcPETScError(ierr));
379 
380  return ncols_saved;
381  }
382 
383 
384  PetscReal
386  {
387  PetscReal result;
388 
389  const PetscErrorCode ierr = MatNorm(matrix, NORM_1, &result);
390  AssertThrow(ierr == 0, ExcPETScError(ierr));
391 
392  return result;
393  }
394 
395 
396 
397  PetscReal
399  {
400  PetscReal result;
401 
402  const PetscErrorCode ierr = MatNorm(matrix, NORM_INFINITY, &result);
403  AssertThrow(ierr == 0, ExcPETScError(ierr));
404 
405  return result;
406  }
407 
408 
409 
410  PetscReal
412  {
413  PetscReal result;
414 
415  const PetscErrorCode ierr = MatNorm(matrix, NORM_FROBENIUS, &result);
416  AssertThrow(ierr == 0, ExcPETScError(ierr));
417 
418  return result;
419  }
420 
421 
422  PetscScalar
424  {
425  VectorBase tmp(v);
426  vmult(tmp, v);
427  return tmp * v;
428  }
429 
430 
431  PetscScalar
433  const VectorBase &v) const
434  {
435  VectorBase tmp(u);
436  vmult(tmp, v);
437  return u * tmp;
438  }
439 
440 
441  PetscScalar
443  {
444  PetscScalar result;
445 
446  const PetscErrorCode ierr = MatGetTrace(matrix, &result);
447  AssertThrow(ierr == 0, ExcPETScError(ierr));
448 
449  return result;
450  }
451 
452 
453 
454  MatrixBase &
455  MatrixBase::operator*=(const PetscScalar a)
456  {
457  const PetscErrorCode ierr = MatScale(matrix, a);
458  AssertThrow(ierr == 0, ExcPETScError(ierr));
459 
460  return *this;
461  }
462 
463 
464 
465  MatrixBase &
466  MatrixBase::operator/=(const PetscScalar a)
467  {
468  const PetscScalar factor = 1. / a;
469  const PetscErrorCode ierr = MatScale(matrix, factor);
470  AssertThrow(ierr == 0, ExcPETScError(ierr));
471 
472  return *this;
473  }
474 
475 
476 
477  MatrixBase &
478  MatrixBase::add(const PetscScalar factor, const MatrixBase &other)
479  {
480  const PetscErrorCode ierr =
481  MatAXPY(matrix, factor, other, DIFFERENT_NONZERO_PATTERN);
482  AssertThrow(ierr == 0, ExcPETScError(ierr));
483 
484  return *this;
485  }
486 
487 
488  void
489  MatrixBase::vmult(VectorBase &dst, const VectorBase &src) const
490  {
491  Assert(&src != &dst, ExcSourceEqualsDestination());
492 
493  const PetscErrorCode ierr = MatMult(matrix, src, dst);
494  AssertThrow(ierr == 0, ExcPETScError(ierr));
495  }
496 
497 
498 
499  void
500  MatrixBase::Tvmult(VectorBase &dst, const VectorBase &src) const
501  {
502  Assert(&src != &dst, ExcSourceEqualsDestination());
503 
504  const PetscErrorCode ierr = MatMultTranspose(matrix, src, dst);
505  AssertThrow(ierr == 0, ExcPETScError(ierr));
506  }
507 
508 
509 
510  void
512  {
513  Assert(&src != &dst, ExcSourceEqualsDestination());
514 
515  const PetscErrorCode ierr = MatMultAdd(matrix, src, dst, dst);
516  AssertThrow(ierr == 0, ExcPETScError(ierr));
517  }
518 
519 
520 
521  void
523  {
524  Assert(&src != &dst, ExcSourceEqualsDestination());
525 
526  const PetscErrorCode ierr = MatMultTransposeAdd(matrix, src, dst, dst);
527  AssertThrow(ierr == 0, ExcPETScError(ierr));
528  }
529 
530 
531  namespace internals
532  {
533  void
534  perform_mmult(const MatrixBase &inputleft,
535  const MatrixBase &inputright,
536  MatrixBase & result,
537  const VectorBase &V,
538  const bool transpose_left)
539  {
540  const bool use_vector = (V.size() == inputright.m() ? true : false);
541  if (transpose_left == false)
542  {
543  Assert(inputleft.n() == inputright.m(),
544  ExcDimensionMismatch(inputleft.n(), inputright.m()));
545  }
546  else
547  {
548  Assert(inputleft.m() == inputright.m(),
549  ExcDimensionMismatch(inputleft.m(), inputright.m()));
550  }
551 
552  result.clear();
553 
554  PetscErrorCode ierr;
555 
556  if (use_vector == false)
557  {
558  if (transpose_left)
559  {
560  ierr = MatTransposeMatMult(inputleft,
561  inputright,
562  MAT_INITIAL_MATRIX,
563  PETSC_DEFAULT,
564  &result.petsc_matrix());
565  AssertThrow(ierr == 0, ExcPETScError(ierr));
566  }
567  else
568  {
569  ierr = MatMatMult(inputleft,
570  inputright,
571  MAT_INITIAL_MATRIX,
572  PETSC_DEFAULT,
573  &result.petsc_matrix());
574  AssertThrow(ierr == 0, ExcPETScError(ierr));
575  }
576  }
577  else
578  {
579  Mat tmp;
580  ierr = MatDuplicate(inputleft, MAT_COPY_VALUES, &tmp);
581  AssertThrow(ierr == 0, ExcPETScError(ierr));
582  if (transpose_left)
583  {
584 # if DEAL_II_PETSC_VERSION_LT(3, 8, 0)
585  ierr = MatTranspose(tmp, MAT_REUSE_MATRIX, &tmp);
586 # else
587  ierr = MatTranspose(tmp, MAT_INPLACE_MATRIX, &tmp);
588 # endif
589  AssertThrow(ierr == 0, ExcPETScError(ierr));
590  }
591  ierr = MatDiagonalScale(tmp, nullptr, V);
592  AssertThrow(ierr == 0, ExcPETScError(ierr));
593  ierr = MatMatMult(tmp,
594  inputright,
595  MAT_INITIAL_MATRIX,
596  PETSC_DEFAULT,
597  &result.petsc_matrix());
598  AssertThrow(ierr == 0, ExcPETScError(ierr));
599  ierr = PETScWrappers::destroy_matrix(tmp);
600  AssertThrow(ierr == 0, ExcPETScError(ierr));
601  }
602  }
603  } // namespace internals
604 
605  void
607  const MatrixBase &B,
608  const VectorBase &V) const
609  {
610  internals::perform_mmult(*this, B, C, V, false);
611  }
612 
613  void
615  const MatrixBase &B,
616  const VectorBase &V) const
617  {
618  internals::perform_mmult(*this, B, C, V, true);
619  }
620 
621  PetscScalar
623  const VectorBase &x,
624  const VectorBase &b) const
625  {
626  // avoid the use of a temporary, and
627  // rather do one negation pass more than
628  // necessary
629  vmult(dst, x);
630  dst -= b;
631  dst *= -1;
632 
633  return dst.l2_norm();
634  }
635 
636 
637 
638  MatrixBase::operator Mat() const
639  {
640  return matrix;
641  }
642 
643  Mat &
645  {
646  return matrix;
647  }
648 
649  void
651  {
652 # if DEAL_II_PETSC_VERSION_LT(3, 8, 0)
653  const PetscErrorCode ierr = MatTranspose(matrix, MAT_REUSE_MATRIX, &matrix);
654 # else
655  const PetscErrorCode ierr =
656  MatTranspose(matrix, MAT_INPLACE_MATRIX, &matrix);
657 # endif
658  AssertThrow(ierr == 0, ExcPETScError(ierr));
659  }
660 
661  PetscBool
662  MatrixBase::is_symmetric(const double tolerance)
663  {
664  PetscBool truth;
666  const PetscErrorCode ierr = MatIsSymmetric(matrix, tolerance, &truth);
667  AssertThrow(ierr == 0, ExcPETScError(ierr));
668  return truth;
669  }
670 
671  PetscBool
672  MatrixBase::is_hermitian(const double tolerance)
673  {
674  PetscBool truth;
675 
677  const PetscErrorCode ierr = MatIsHermitian(matrix, tolerance, &truth);
678  AssertThrow(ierr == 0, ExcPETScError(ierr));
679 
680  return truth;
681  }
682 
683  void
684  MatrixBase::write_ascii(const PetscViewerFormat format)
685  {
687  MPI_Comm comm = PetscObjectComm(reinterpret_cast<PetscObject>(matrix));
688 
689  // Set options
690  PetscErrorCode ierr =
691  PetscViewerSetFormat(PETSC_VIEWER_STDOUT_(comm), format);
692  AssertThrow(ierr == 0, ExcPETScError(ierr));
693 
694  // Write to screen
695  ierr = MatView(matrix, PETSC_VIEWER_STDOUT_(comm));
696  AssertThrow(ierr == 0, ExcPETScError(ierr));
697  }
698 
699  void
700  MatrixBase::print(std::ostream &out, const bool /*alternative_output*/) const
701  {
702  PetscBool has;
703 
704  PetscErrorCode ierr = MatHasOperation(matrix, MATOP_GET_ROW, &has);
705  AssertThrow(ierr == 0, ExcPETScError(ierr));
706 
707  Mat vmatrix = matrix;
708  if (!has)
709  {
710  ierr = MatConvert(matrix, MATAIJ, MAT_INITIAL_MATRIX, &vmatrix);
711  AssertThrow(ierr == 0, ExcPETScError(ierr));
712  }
713 
714  std::pair<MatrixBase::size_type, MatrixBase::size_type> loc_range =
715  local_range();
716 
717  PetscInt ncols;
718  const PetscInt * colnums;
719  const PetscScalar *values;
720 
722  for (row = loc_range.first; row < loc_range.second; ++row)
723  {
724  ierr = MatGetRow(vmatrix, row, &ncols, &colnums, &values);
725  AssertThrow(ierr == 0, ExcPETScError(ierr));
726 
727  for (PetscInt col = 0; col < ncols; ++col)
728  {
729  out << "(" << row << "," << colnums[col] << ") " << values[col]
730  << std::endl;
731  }
732 
733  ierr = MatRestoreRow(vmatrix, row, &ncols, &colnums, &values);
734  AssertThrow(ierr == 0, ExcPETScError(ierr));
735  }
736  if (vmatrix != matrix)
737  {
738  ierr = PETScWrappers::destroy_matrix(vmatrix);
739  AssertThrow(ierr == 0, ExcPETScError(ierr));
740  }
741  AssertThrow(out.fail() == false, ExcIO());
742  }
743 
744 
745 
746  std::size_t
748  {
749  MatInfo info;
750  const PetscErrorCode ierr = MatGetInfo(matrix, MAT_LOCAL, &info);
751  AssertThrow(ierr == 0, ExcPETScError(ierr));
752 
753  return sizeof(*this) + static_cast<size_type>(info.memory);
754  }
755 
756 } // namespace PETScWrappers
757 
759 
760 #endif // DEAL_II_WITH_PETSC
void add(const size_type i, const size_type j, const PetscScalar value)
size_type row_length(const size_type row) const
std::size_t memory_consumption() const
VectorOperation::values last_action
void vmult(VectorBase &dst, const VectorBase &src) const
void clear_rows(const std::vector< size_type > &rows, const PetscScalar new_diag_value=0)
PetscScalar diag_element(const size_type i) const
const_iterator begin() const
MatrixBase & operator/=(const PetscScalar factor)
void mmult(MatrixBase &C, const MatrixBase &B, const VectorBase &V) const
PetscBool is_symmetric(const double tolerance=1.e-12)
types::global_dof_index size_type
PetscReal frobenius_norm() const
MatrixBase & operator=(const MatrixBase &)=delete
virtual ~MatrixBase() override
const_iterator end() const
void Tvmult_add(VectorBase &dst, const VectorBase &src) const
void print(std::ostream &out, const bool alternative_output=false) const
PetscScalar el(const size_type i, const size_type j) const
PetscBool is_hermitian(const double tolerance=1.e-12)
PetscScalar matrix_scalar_product(const VectorBase &u, const VectorBase &v) const
void Tvmult(VectorBase &dst, const VectorBase &src) const
void clear_rows_columns(const std::vector< size_type > &row_and_column_indices, const PetscScalar new_diag_value=0)
MatrixBase & operator*=(const PetscScalar factor)
const MPI_Comm & get_mpi_communicator() const
PetscScalar residual(VectorBase &dst, const VectorBase &x, const VectorBase &b) const
void Tmmult(MatrixBase &C, const MatrixBase &B, const VectorBase &V) const
void write_ascii(const PetscViewerFormat format=PETSC_VIEWER_DEFAULT)
void vmult_add(VectorBase &dst, const VectorBase &src) const
std::pair< size_type, size_type > local_range() const
void compress(const VectorOperation::values operation)
PetscScalar matrix_norm_square(const VectorBase &v) const
std::uint64_t n_nonzero_elements() const
void clear_row(const size_type row, const PetscScalar new_diag_value=0)
#define DEAL_II_NAMESPACE_OPEN
Definition: config.h:474
#define DEAL_II_NAMESPACE_CLOSE
Definition: config.h:475
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcScalarAssignmentOnlyForZeroValue()
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
#define Assert(cond, exc)
Definition: exceptions.h:1586
#define AssertThrowMPI(error_code)
Definition: exceptions.h:1886
static ::ExceptionBase & ExcIO()
static ::ExceptionBase & ExcSourceEqualsDestination()
static ::ExceptionBase & ExcMessage(std::string arg1)
static ::ExceptionBase & ExcNotQuadratic()
#define AssertThrow(cond, exc)
Definition: exceptions.h:1675
@ matrix
Contents is actually a matrix.
static const char A
static const char V
void perform_mmult(const MatrixBase &inputleft, const MatrixBase &inputright, MatrixBase &result, const VectorBase &V, const bool transpose_left)
PetscErrorCode destroy_matrix(Mat &matrix)
SymmetricTensor< 2, dim, Number > C(const Tensor< 2, dim, Number > &F)
SymmetricTensor< 2, dim, Number > d(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
SymmetricTensor< 2, dim, Number > b(const Tensor< 2, dim, Number > &F)
const MPI_Comm & comm