Reference documentation for deal.II version GIT b8135fa6eb 2023-03-25 15:55:02+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_vector_base.h
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 
16 #ifndef dealii_petsc_vector_base_h
17 #define dealii_petsc_vector_base_h
18 
19 
20 #include <deal.II/base/config.h>
21 
22 #ifdef DEAL_II_WITH_PETSC
23 
24 # include <deal.II/base/index_set.h>
26 
27 # include <deal.II/lac/exceptions.h>
28 # include <deal.II/lac/vector.h>
30 
31 # include <petscvec.h>
32 
33 # include <utility>
34 # include <vector>
35 
37 
38 // forward declaration
39 # ifndef DOXYGEN
40 template <typename number>
41 class Vector;
42 
43 namespace PETScWrappers
44 {
45  class VectorBase;
46 }
47 # endif
48 
55 namespace PETScWrappers
56 {
66  namespace internal
67  {
80  class VectorReference
81  {
82  public:
87 
88  private:
93  VectorReference(const VectorBase &vector, const size_type index);
94 
95  public:
96  /*
97  * Copy constructor.
98  */
99  VectorReference(const VectorReference &vector) = default;
100 
112  const VectorReference &
113  operator=(const VectorReference &r) const;
114 
120  VectorReference &
121  operator=(const VectorReference &r);
122 
126  const VectorReference &
127  operator=(const PetscScalar &s) const;
128 
132  const VectorReference &
133  operator+=(const PetscScalar &s) const;
134 
138  const VectorReference &
139  operator-=(const PetscScalar &s) const;
140 
144  const VectorReference &
145  operator*=(const PetscScalar &s) const;
146 
150  const VectorReference &
151  operator/=(const PetscScalar &s) const;
152 
156  PetscReal
157  real() const;
158 
165  PetscReal
166  imag() const;
167 
172  operator PetscScalar() const;
177  ExcAccessToNonlocalElement,
178  int,
179  int,
180  int,
181  << "You tried to access element " << arg1
182  << " of a distributed vector, but only elements in range [" << arg2
183  << ',' << arg3 << "] are stored locally and can be accessed."
184  << "\n\n"
185  << "A common source for this kind of problem is that you "
186  << "are passing a 'fully distributed' vector into a function "
187  << "that needs read access to vector elements that correspond "
188  << "to degrees of freedom on ghost cells (or at least to "
189  << "'locally active' degrees of freedom that are not also "
190  << "'locally owned'). You need to pass a vector that has these "
191  << "elements as ghost entries.");
195  DeclException2(ExcWrongMode,
196  int,
197  int,
198  << "You tried to do a "
199  << (arg1 == 1 ? "'set'" : (arg1 == 2 ? "'add'" : "???"))
200  << " operation but the vector is currently in "
201  << (arg2 == 1 ? "'set'" : (arg2 == 2 ? "'add'" : "???"))
202  << " mode. You first have to call 'compress()'.");
203 
204  private:
208  const VectorBase &vector;
209 
213  const size_type index;
214 
215  // Make the vector class a friend, so that it can create objects of the
216  // present type.
217  friend class ::PETScWrappers::VectorBase;
218  };
219  } // namespace internal
250  class VectorBase : public Subscriptor
251  {
252  public:
258  using value_type = PetscScalar;
259  using real_type = PetscReal;
263 
268  VectorBase();
269 
274  VectorBase(const VectorBase &v);
275 
280  explicit VectorBase(const Vec &v);
281 
285  virtual ~VectorBase() override;
286 
291  virtual void
292  clear();
293 
304  void
305  compress(const VectorOperation::values operation);
306 
310  VectorBase &
311  operator=(const VectorBase &);
312 
326  VectorBase &
327  operator=(const PetscScalar s);
328 
335  void
336  reinit(Vec v);
337 
343  bool
344  operator==(const VectorBase &v) const;
345 
351  bool
352  operator!=(const VectorBase &v) const;
353 
357  size_type
358  size() const;
359 
371  size_type
372  local_size() const;
373 
382  size_type
383  locally_owned_size() const;
384 
393  std::pair<size_type, size_type>
394  local_range() const;
395 
400  bool
401  in_local_range(const size_type index) const;
402 
416  IndexSet
418 
425  bool
427 
434  void
436 
440  reference
441  operator()(const size_type index);
442 
446  PetscScalar
447  operator()(const size_type index) const;
448 
454  reference
455  operator[](const size_type index);
456 
462  PetscScalar
463  operator[](const size_type index) const;
464 
471  void
472  set(const std::vector<size_type> & indices,
473  const std::vector<PetscScalar> &values);
474 
490  void
491  extract_subvector_to(const std::vector<size_type> &indices,
492  std::vector<PetscScalar> & values) const;
493 
521  template <typename ForwardIterator, typename OutputIterator>
522  void
523  extract_subvector_to(const ForwardIterator indices_begin,
524  const ForwardIterator indices_end,
525  OutputIterator values_begin) const;
526 
531  void
532  add(const std::vector<size_type> & indices,
533  const std::vector<PetscScalar> &values);
534 
539  void
540  add(const std::vector<size_type> & indices,
541  const ::Vector<PetscScalar> &values);
542 
548  void
549  add(const size_type n_elements,
550  const size_type * indices,
551  const PetscScalar *values);
552 
559  PetscScalar
560  operator*(const VectorBase &vec) const;
561 
565  real_type
566  norm_sqr() const;
567 
571  PetscScalar
572  mean_value() const;
573 
581  real_type
582  l1_norm() const;
583 
588  real_type
589  l2_norm() const;
590 
595  real_type
596  lp_norm(const real_type p) const;
597 
602  real_type
603  linfty_norm() const;
604 
624  PetscScalar
625  add_and_dot(const PetscScalar a, const VectorBase &V, const VectorBase &W);
626 
635  real_type
636  min() const;
637 
646  real_type
647  max() const;
648 
654  bool
655  all_zero() const;
656 
666  bool
667  is_non_negative() const;
668 
672  VectorBase &
673  operator*=(const PetscScalar factor);
674 
678  VectorBase &
679  operator/=(const PetscScalar factor);
680 
684  VectorBase &
685  operator+=(const VectorBase &V);
686 
690  VectorBase &
691  operator-=(const VectorBase &V);
692 
697  void
698  add(const PetscScalar s);
699 
703  void
704  add(const PetscScalar a, const VectorBase &V);
705 
709  void
710  add(const PetscScalar a,
711  const VectorBase &V,
712  const PetscScalar b,
713  const VectorBase &W);
714 
718  void
719  sadd(const PetscScalar s, const VectorBase &V);
720 
724  void
725  sadd(const PetscScalar s, const PetscScalar a, const VectorBase &V);
726 
732  void
733  scale(const VectorBase &scaling_factors);
734 
738  void
739  equ(const PetscScalar a, const VectorBase &V);
740 
748  void
749  write_ascii(const PetscViewerFormat format = PETSC_VIEWER_DEFAULT);
750 
758  void
759  print(std::ostream & out,
760  const unsigned int precision = 3,
761  const bool scientific = true,
762  const bool across = true) const;
763 
776  void
777  swap(VectorBase &v);
778 
786  operator const Vec &() const;
787 
793  Vec &
794  petsc_vector();
795 
799  std::size_t
800  memory_consumption() const;
801 
806  const MPI_Comm &
808 
809  protected:
814  Vec vector;
815 
821  bool ghosted;
822 
829 
836 
837  // Make the reference class a friend.
839 
845  void
846  do_set_add_operation(const size_type n_elements,
847  const size_type * indices,
848  const PetscScalar *values,
849  const bool add_values);
850  };
851 
852 
853 
854  // ------------------- inline and template functions --------------
855 
863  inline void
865  {
866  u.swap(v);
867  }
868 
869 # ifndef DOXYGEN
870  namespace internal
871  {
872  inline VectorReference::VectorReference(const VectorBase &vector,
873  const size_type index)
874  : vector(vector)
875  , index(index)
876  {}
877 
878 
879  inline const VectorReference &
880  VectorReference::operator=(const VectorReference &r) const
881  {
882  // as explained in the class
883  // documentation, this is not the copy
884  // operator. so simply pass on to the
885  // "correct" assignment operator
886  *this = static_cast<PetscScalar>(r);
887 
888  return *this;
889  }
890 
891 
892 
893  inline VectorReference &
894  VectorReference::operator=(const VectorReference &r)
895  {
896  // as explained in the class
897  // documentation, this is not the copy
898  // operator. so simply pass on to the
899  // "correct" assignment operator
900  *this = static_cast<PetscScalar>(r);
901 
902  return *this;
903  }
904 
905 
906 
907  inline const VectorReference &
908  VectorReference::operator=(const PetscScalar &value) const
909  {
910  Assert((vector.last_action == VectorOperation::insert) ||
911  (vector.last_action == VectorOperation::unknown),
912  ExcWrongMode(VectorOperation::insert, vector.last_action));
913 
914  Assert(!vector.has_ghost_elements(), ExcGhostsPresent());
915 
916  const PetscInt petsc_i = index;
917 
918  const PetscErrorCode ierr =
919  VecSetValues(vector, 1, &petsc_i, &value, INSERT_VALUES);
920  AssertThrow(ierr == 0, ExcPETScError(ierr));
921 
922  vector.last_action = VectorOperation::insert;
923 
924  return *this;
925  }
926 
927 
928 
929  inline const VectorReference &
930  VectorReference::operator+=(const PetscScalar &value) const
931  {
932  Assert((vector.last_action == VectorOperation::add) ||
933  (vector.last_action == VectorOperation::unknown),
934  ExcWrongMode(VectorOperation::add, vector.last_action));
935 
936  Assert(!vector.has_ghost_elements(), ExcGhostsPresent());
937 
938  vector.last_action = VectorOperation::add;
939 
940  // we have to do above actions in any
941  // case to be consistent with the MPI
942  // communication model (see the
943  // comments in the documentation of
944  // PETScWrappers::MPI::Vector), but we
945  // can save some work if the addend is
946  // zero
947  if (value == PetscScalar())
948  return *this;
949 
950  // use the PETSc function to add something
951  const PetscInt petsc_i = index;
952  const PetscErrorCode ierr =
953  VecSetValues(vector, 1, &petsc_i, &value, ADD_VALUES);
954  AssertThrow(ierr == 0, ExcPETScError(ierr));
955 
956 
957  return *this;
958  }
959 
960 
961 
962  inline const VectorReference &
963  VectorReference::operator-=(const PetscScalar &value) const
964  {
965  Assert((vector.last_action == VectorOperation::add) ||
966  (vector.last_action == VectorOperation::unknown),
967  ExcWrongMode(VectorOperation::add, vector.last_action));
968 
969  Assert(!vector.has_ghost_elements(), ExcGhostsPresent());
970 
971  vector.last_action = VectorOperation::add;
972 
973  // we have to do above actions in any
974  // case to be consistent with the MPI
975  // communication model (see the
976  // comments in the documentation of
977  // PETScWrappers::MPI::Vector), but we
978  // can save some work if the addend is
979  // zero
980  if (value == PetscScalar())
981  return *this;
982 
983  // use the PETSc function to
984  // add something
985  const PetscInt petsc_i = index;
986  const PetscScalar subtractand = -value;
987  const PetscErrorCode ierr =
988  VecSetValues(vector, 1, &petsc_i, &subtractand, ADD_VALUES);
989  AssertThrow(ierr == 0, ExcPETScError(ierr));
990 
991  return *this;
992  }
993 
994 
995 
996  inline const VectorReference &
997  VectorReference::operator*=(const PetscScalar &value) const
998  {
999  Assert((vector.last_action == VectorOperation::insert) ||
1000  (vector.last_action == VectorOperation::unknown),
1001  ExcWrongMode(VectorOperation::insert, vector.last_action));
1002 
1003  Assert(!vector.has_ghost_elements(), ExcGhostsPresent());
1004 
1005  vector.last_action = VectorOperation::insert;
1006 
1007  // we have to do above actions in any
1008  // case to be consistent with the MPI
1009  // communication model (see the
1010  // comments in the documentation of
1011  // PETScWrappers::MPI::Vector), but we
1012  // can save some work if the factor is
1013  // one
1014  if (value == 1.)
1015  return *this;
1016 
1017  const PetscInt petsc_i = index;
1018  const PetscScalar new_value = static_cast<PetscScalar>(*this) * value;
1019 
1020  const PetscErrorCode ierr =
1021  VecSetValues(vector, 1, &petsc_i, &new_value, INSERT_VALUES);
1022  AssertThrow(ierr == 0, ExcPETScError(ierr));
1023 
1024  return *this;
1025  }
1026 
1027 
1028 
1029  inline const VectorReference &
1030  VectorReference::operator/=(const PetscScalar &value) const
1031  {
1032  Assert((vector.last_action == VectorOperation::insert) ||
1033  (vector.last_action == VectorOperation::unknown),
1034  ExcWrongMode(VectorOperation::insert, vector.last_action));
1035 
1036  Assert(!vector.has_ghost_elements(), ExcGhostsPresent());
1037 
1038  vector.last_action = VectorOperation::insert;
1039 
1040  // we have to do above actions in any
1041  // case to be consistent with the MPI
1042  // communication model (see the
1043  // comments in the documentation of
1044  // PETScWrappers::MPI::Vector), but we
1045  // can save some work if the factor is
1046  // one
1047  if (value == 1.)
1048  return *this;
1049 
1050  const PetscInt petsc_i = index;
1051  const PetscScalar new_value = static_cast<PetscScalar>(*this) / value;
1052 
1053  const PetscErrorCode ierr =
1054  VecSetValues(vector, 1, &petsc_i, &new_value, INSERT_VALUES);
1055  AssertThrow(ierr == 0, ExcPETScError(ierr));
1056 
1057  return *this;
1058  }
1059 
1060 
1061 
1062  inline PetscReal
1063  VectorReference::real() const
1064  {
1065 # ifndef PETSC_USE_COMPLEX
1066  return static_cast<PetscScalar>(*this);
1067 # else
1068  return PetscRealPart(static_cast<PetscScalar>(*this));
1069 # endif
1070  }
1071 
1072 
1073 
1074  inline PetscReal
1075  VectorReference::imag() const
1076  {
1077 # ifndef PETSC_USE_COMPLEX
1078  return PetscReal(0);
1079 # else
1080  return PetscImaginaryPart(static_cast<PetscScalar>(*this));
1081 # endif
1082  }
1083 
1084  } // namespace internal
1085 
1086  inline bool
1087  VectorBase::in_local_range(const size_type index) const
1088  {
1089  PetscInt begin, end;
1090  const PetscErrorCode ierr =
1091  VecGetOwnershipRange(static_cast<const Vec &>(vector), &begin, &end);
1092  AssertThrow(ierr == 0, ExcPETScError(ierr));
1093 
1094  return ((index >= static_cast<size_type>(begin)) &&
1095  (index < static_cast<size_type>(end)));
1096  }
1097 
1098 
1099  inline IndexSet
1100  VectorBase::locally_owned_elements() const
1101  {
1102  IndexSet is(size());
1103 
1104  // PETSc only allows for contiguous local ranges, so this is simple
1105  const std::pair<size_type, size_type> x = local_range();
1106  is.add_range(x.first, x.second);
1107  return is;
1108  }
1109 
1110 
1111 
1112  inline bool
1113  VectorBase::has_ghost_elements() const
1114  {
1115  return ghosted;
1116  }
1117 
1118 
1119 
1120  inline void
1121  VectorBase::update_ghost_values() const
1122  {}
1123 
1124 
1125 
1126  inline internal::VectorReference
1127  VectorBase::operator()(const size_type index)
1128  {
1129  return internal::VectorReference(*this, index);
1130  }
1131 
1132 
1133 
1134  inline PetscScalar
1135  VectorBase::operator()(const size_type index) const
1136  {
1137  return static_cast<PetscScalar>(internal::VectorReference(*this, index));
1138  }
1139 
1140 
1141 
1142  inline internal::VectorReference
1143  VectorBase::operator[](const size_type index)
1144  {
1145  return operator()(index);
1146  }
1147 
1148 
1149 
1150  inline PetscScalar
1151  VectorBase::operator[](const size_type index) const
1152  {
1153  return operator()(index);
1154  }
1155 
1156  inline const MPI_Comm &
1157  VectorBase::get_mpi_communicator() const
1158  {
1159  static MPI_Comm comm = PETSC_COMM_SELF;
1160  MPI_Comm pcomm = PetscObjectComm(reinterpret_cast<PetscObject>(vector));
1161  if (pcomm != MPI_COMM_NULL)
1162  comm = pcomm;
1163  return comm;
1164  }
1165 
1166  inline void
1167  VectorBase::extract_subvector_to(const std::vector<size_type> &indices,
1168  std::vector<PetscScalar> & values) const
1169  {
1170  Assert(indices.size() <= values.size(),
1171  ExcDimensionMismatch(indices.size(), values.size()));
1172  extract_subvector_to(indices.begin(), indices.end(), values.begin());
1173  }
1174 
1175  template <typename ForwardIterator, typename OutputIterator>
1176  inline void
1177  VectorBase::extract_subvector_to(const ForwardIterator indices_begin,
1178  const ForwardIterator indices_end,
1179  OutputIterator values_begin) const
1180  {
1181  const PetscInt n_idx = static_cast<PetscInt>(indices_end - indices_begin);
1182  if (n_idx == 0)
1183  return;
1184 
1185  // if we are dealing
1186  // with a parallel vector
1187  if (ghosted)
1188  {
1189  // there is the possibility
1190  // that the vector has
1191  // ghost elements. in that
1192  // case, we first need to
1193  // figure out which
1194  // elements we own locally,
1195  // then get a pointer to
1196  // the elements that are
1197  // stored here (both the
1198  // ones we own as well as
1199  // the ghost elements). in
1200  // this array, the locally
1201  // owned elements come
1202  // first followed by the
1203  // ghost elements whose
1204  // position we can get from
1205  // an index set
1206  PetscInt begin, end;
1207  PetscErrorCode ierr = VecGetOwnershipRange(vector, &begin, &end);
1208  AssertThrow(ierr == 0, ExcPETScError(ierr));
1209 
1210  Vec locally_stored_elements = nullptr;
1211  ierr = VecGhostGetLocalForm(vector, &locally_stored_elements);
1212  AssertThrow(ierr == 0, ExcPETScError(ierr));
1213 
1214  PetscInt lsize;
1215  ierr = VecGetSize(locally_stored_elements, &lsize);
1216  AssertThrow(ierr == 0, ExcPETScError(ierr));
1217 
1218  const PetscScalar *ptr;
1219  ierr = VecGetArrayRead(locally_stored_elements, &ptr);
1220  AssertThrow(ierr == 0, ExcPETScError(ierr));
1221 
1222  for (PetscInt i = 0; i < n_idx; ++i)
1223  {
1224  const unsigned int index = *(indices_begin + i);
1225  if (index >= static_cast<unsigned int>(begin) &&
1226  index < static_cast<unsigned int>(end))
1227  {
1228  // local entry
1229  *(values_begin + i) = *(ptr + index - begin);
1230  }
1231  else
1232  {
1233  // ghost entry
1234  const unsigned int ghostidx =
1235  ghost_indices.index_within_set(index);
1236 
1237  AssertIndexRange(ghostidx + end - begin, lsize);
1238  *(values_begin + i) = *(ptr + ghostidx + end - begin);
1239  }
1240  }
1241 
1242  ierr = VecRestoreArrayRead(locally_stored_elements, &ptr);
1243  AssertThrow(ierr == 0, ExcPETScError(ierr));
1244 
1245  ierr = VecGhostRestoreLocalForm(vector, &locally_stored_elements);
1246  AssertThrow(ierr == 0, ExcPETScError(ierr));
1247  }
1248  // if the vector is local or the
1249  // caller, then simply access the
1250  // element we are interested in
1251  else
1252  {
1253  PetscInt begin, end;
1254  PetscErrorCode ierr = VecGetOwnershipRange(vector, &begin, &end);
1255  AssertThrow(ierr == 0, ExcPETScError(ierr));
1256 
1257  const PetscScalar *ptr;
1258  ierr = VecGetArrayRead(vector, &ptr);
1259  AssertThrow(ierr == 0, ExcPETScError(ierr));
1260 
1261  for (PetscInt i = 0; i < n_idx; ++i)
1262  {
1263  const unsigned int index = *(indices_begin + i);
1264 
1265  Assert(index >= static_cast<unsigned int>(begin) &&
1266  index < static_cast<unsigned int>(end),
1267  ExcMessage("You are accessing elements of a vector without "
1268  "ghost elements that are not actually owned by "
1269  "this vector. A typical case where this may "
1270  "happen is if you are passing a non-ghosted "
1271  "(completely distributed) vector to a function "
1272  "that expects a vector that stores ghost "
1273  "elements for all locally relevant or locally "
1274  "active vector entries."));
1275 
1276  *(values_begin + i) = *(ptr + index - begin);
1277  }
1278 
1279  ierr = VecRestoreArrayRead(vector, &ptr);
1280  AssertThrow(ierr == 0, ExcPETScError(ierr));
1281  }
1282  }
1283 
1284 # endif // DOXYGEN
1285 } // namespace PETScWrappers
1286 
1288 
1289 #endif // DEAL_II_WITH_PETSC
1290 
1291 #endif
real_type lp_norm(const real_type p) const
VectorBase & operator+=(const VectorBase &V)
PetscScalar mean_value() const
VectorOperation::values last_action
PetscScalar operator*(const VectorBase &vec) const
bool operator==(const VectorBase &v) const
VectorBase & operator*=(const PetscScalar factor)
VectorBase & operator-=(const VectorBase &V)
bool operator!=(const VectorBase &v) const
IndexSet locally_owned_elements() const
bool in_local_range(const size_type index) const
std::size_t memory_consumption() const
internal::VectorReference reference
VectorBase & operator/=(const PetscScalar factor)
friend class internal::VectorReference
PetscScalar operator[](const size_type index) const
void scale(const VectorBase &scaling_factors)
void extract_subvector_to(const std::vector< size_type > &indices, std::vector< PetscScalar > &values) const
void update_ghost_values() const
std::pair< size_type, size_type > local_range() const
void sadd(const PetscScalar s, const VectorBase &V)
void compress(const VectorOperation::values operation)
const MPI_Comm & get_mpi_communicator() const
void set(const std::vector< size_type > &indices, const std::vector< PetscScalar > &values)
void print(std::ostream &out, const unsigned int precision=3, const bool scientific=true, const bool across=true) const
PetscScalar add_and_dot(const PetscScalar a, const VectorBase &V, const VectorBase &W)
virtual ~VectorBase() override
reference operator()(const size_type index)
const internal::VectorReference const_reference
void add(const std::vector< size_type > &indices, const std::vector< PetscScalar > &values)
void write_ascii(const PetscViewerFormat format=PETSC_VIEWER_DEFAULT)
bool has_ghost_elements() const
reference operator[](const size_type index)
size_type locally_owned_size() const
void equ(const PetscScalar a, const VectorBase &V)
void do_set_add_operation(const size_type n_elements, const size_type *indices, const PetscScalar *values, const bool add_values)
VectorBase & operator=(const VectorBase &)
types::global_dof_index size_type
void swap(VectorBase &u, VectorBase &v)
PetscScalar operator()(const size_type index) const
void extract_subvector_to(const ForwardIterator indices_begin, const ForwardIterator indices_end, OutputIterator values_begin) const
Definition: vector.h:109
#define DEAL_II_DEPRECATED
Definition: config.h:174
#define DEAL_II_NAMESPACE_OPEN
Definition: config.h:474
#define DEAL_II_NAMESPACE_CLOSE
Definition: config.h:475
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
#define Assert(cond, exc)
Definition: exceptions.h:1586
#define DeclException2(Exception2, type1, type2, outsequence)
Definition: exceptions.h:533
#define AssertIndexRange(index, range)
Definition: exceptions.h:1827
#define DeclException3(Exception3, type1, type2, type3, outsequence)
Definition: exceptions.h:556
static ::ExceptionBase & ExcGhostsPresent()
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
Definition: exceptions.h:1675
static const char V
types::global_dof_index size_type
Definition: cuda_kernels.h:45
SymmetricTensor< 2, dim, Number > b(const Tensor< 2, dim, Number > &F)
VectorType::value_type * begin(VectorType &V)
VectorType::value_type * end(VectorType &V)
unsigned int global_dof_index
Definition: types.h:82
const MPI_Comm & comm