Reference documentation for deal.II version 9.1.0-pre
petsc_vector_base.h
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2004 - 2018 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>
25 # include <deal.II/base/subscriptor.h>
26 
27 # include <deal.II/lac/exceptions.h>
28 # include <deal.II/lac/vector.h>
29 # include <deal.II/lac/vector_operation.h>
30 
31 # include <petscvec.h>
32 
33 # include <utility>
34 # include <vector>
35 
36 DEAL_II_NAMESPACE_OPEN
37 
38 // forward declaration
39 template <typename number>
40 class Vector;
41 
42 
50 namespace PETScWrappers
51 {
52  // forward declaration
53  class VectorBase;
54 
64  namespace internal
65  {
78  class VectorReference
79  {
80  public:
85 
86  private:
91  VectorReference(const VectorBase &vector, const size_type index);
92 
93 
94  public:
106  const VectorReference &
107  operator=(const VectorReference &r) const;
108 
114  VectorReference &
115  operator=(const VectorReference &r);
116 
120  const VectorReference &
121  operator=(const PetscScalar &s) const;
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  PetscReal
151  real() const;
152 
159  PetscReal
160  imag() const;
161 
166  operator PetscScalar() const;
170  DeclException3(ExcAccessToNonlocalElement,
171  int,
172  int,
173  int,
174  << "You tried to access element " << arg1
175  << " of a distributed vector, but only elements " << arg2
176  << " through " << arg3
177  << " are stored locally and can be accessed.");
181  DeclException2(ExcWrongMode,
182  int,
183  int,
184  << "You tried to do a "
185  << (arg1 == 1 ? "'set'" : (arg1 == 2 ? "'add'" : "???"))
186  << " operation but the vector is currently in "
187  << (arg2 == 1 ? "'set'" : (arg2 == 2 ? "'add'" : "???"))
188  << " mode. You first have to call 'compress()'.");
189 
190  private:
194  const VectorBase &vector;
195 
199  const size_type index;
200 
205  friend class ::PETScWrappers::VectorBase;
206  };
207  } // namespace internal
239  class VectorBase : public Subscriptor
240  {
241  public:
247  using value_type = PetscScalar;
248  using real_type = PetscReal;
249  using size_type = types::global_dof_index;
250  using reference = internal::VectorReference;
251  using const_reference = const internal::VectorReference;
252 
257  VectorBase();
258 
263  VectorBase(const VectorBase &v);
264 
270  explicit VectorBase(const Vec &v);
271 
275  virtual ~VectorBase() override;
276 
281  virtual void
282  clear();
283 
294  void
295  compress(const VectorOperation::values operation);
296 
310  VectorBase &
311  operator=(const PetscScalar s);
312 
318  bool
319  operator==(const VectorBase &v) const;
320 
326  bool
327  operator!=(const VectorBase &v) const;
328 
332  size_type
333  size() const;
334 
343  size_type
344  local_size() const;
345 
354  std::pair<size_type, size_type>
355  local_range() const;
356 
361  bool
362  in_local_range(const size_type index) const;
363 
377  IndexSet
378  locally_owned_elements() const;
379 
386  bool
387  has_ghost_elements() const;
388 
395  void
396  update_ghost_values() const;
397 
401  reference
402  operator()(const size_type index);
403 
407  PetscScalar
408  operator()(const size_type index) const;
409 
415  reference operator[](const size_type index);
416 
422  PetscScalar operator[](const size_type index) const;
423 
430  void
431  set(const std::vector<size_type> & indices,
432  const std::vector<PetscScalar> &values);
433 
449  void
450  extract_subvector_to(const std::vector<size_type> &indices,
451  std::vector<PetscScalar> & values) const;
452 
480  template <typename ForwardIterator, typename OutputIterator>
481  void
482  extract_subvector_to(const ForwardIterator indices_begin,
483  const ForwardIterator indices_end,
484  OutputIterator values_begin) const;
485 
490  void
491  add(const std::vector<size_type> & indices,
492  const std::vector<PetscScalar> &values);
493 
498  void
499  add(const std::vector<size_type> & indices,
500  const ::Vector<PetscScalar> &values);
501 
507  void
508  add(const size_type n_elements,
509  const size_type * indices,
510  const PetscScalar *values);
511 
518  PetscScalar operator*(const VectorBase &vec) const;
519 
523  real_type
524  norm_sqr() const;
525 
529  PetscScalar
530  mean_value() const;
531 
539  real_type
540  l1_norm() const;
541 
546  real_type
547  l2_norm() const;
548 
553  real_type
554  lp_norm(const real_type p) const;
555 
560  real_type
561  linfty_norm() const;
562 
582  PetscScalar
583  add_and_dot(const PetscScalar a, const VectorBase &V, const VectorBase &W);
584 
588  real_type
589  min() const;
590 
594  real_type
595  max() const;
596 
602  bool
603  all_zero() const;
604 
610  bool
611  is_non_negative() const;
612 
616  VectorBase &
617  operator*=(const PetscScalar factor);
618 
622  VectorBase &
623  operator/=(const PetscScalar factor);
624 
628  VectorBase &
629  operator+=(const VectorBase &V);
630 
634  VectorBase &
635  operator-=(const VectorBase &V);
636 
641  void
642  add(const PetscScalar s);
643 
647  void
648  add(const PetscScalar a, const VectorBase &V);
649 
653  void
654  add(const PetscScalar a,
655  const VectorBase &V,
656  const PetscScalar b,
657  const VectorBase &W);
658 
662  void
663  sadd(const PetscScalar s, const VectorBase &V);
664 
668  void
669  sadd(const PetscScalar s, const PetscScalar a, const VectorBase &V);
670 
676  void
677  scale(const VectorBase &scaling_factors);
678 
682  void
683  equ(const PetscScalar a, const VectorBase &V);
684 
695  DEAL_II_DEPRECATED
696  void
697  ratio(const VectorBase &a, const VectorBase &b);
698 
706  void
707  write_ascii(const PetscViewerFormat format = PETSC_VIEWER_DEFAULT);
708 
716  void
717  print(std::ostream & out,
718  const unsigned int precision = 3,
719  const bool scientific = true,
720  const bool across = true) const;
721 
734  void
735  swap(VectorBase &v);
736 
744  operator const Vec &() const;
745 
749  std::size_t
750  memory_consumption() const;
751 
756  virtual const MPI_Comm &
757  get_mpi_communicator() const;
758 
759  protected:
764  Vec vector;
765 
771  bool ghosted;
772 
779 
786 
790  friend class internal::VectorReference;
791 
798 
804  void
805  do_set_add_operation(const size_type n_elements,
806  const size_type * indices,
807  const PetscScalar *values,
808  const bool add_values);
809 
810  private:
816  VectorBase &
817  operator=(const VectorBase &) = delete;
818  };
819 
820 
821 
822  // ------------------- inline and template functions --------------
823 
832  inline void
834  {
835  u.swap(v);
836  }
837 
838 # ifndef DOXYGEN
839  namespace internal
840  {
841  inline VectorReference::VectorReference(const VectorBase &vector,
842  const size_type index)
843  : vector(vector)
844  , index(index)
845  {}
846 
847 
848  inline const VectorReference &
849  VectorReference::operator=(const VectorReference &r) const
850  {
851  // as explained in the class
852  // documentation, this is not the copy
853  // operator. so simply pass on to the
854  // "correct" assignment operator
855  *this = static_cast<PetscScalar>(r);
856 
857  return *this;
858  }
859 
860 
861 
862  inline VectorReference &
863  VectorReference::operator=(const VectorReference &r)
864  {
865  // as explained in the class
866  // documentation, this is not the copy
867  // operator. so simply pass on to the
868  // "correct" assignment operator
869  *this = static_cast<PetscScalar>(r);
870 
871  return *this;
872  }
873 
874 
875 
876  inline const VectorReference &
877  VectorReference::operator=(const PetscScalar &value) const
878  {
881  ExcWrongMode(VectorOperation::insert, vector.last_action));
882 
884 
885  const PetscInt petsc_i = index;
886 
887  const PetscErrorCode ierr =
888  VecSetValues(vector, 1, &petsc_i, &value, INSERT_VALUES);
889  AssertThrow(ierr == 0, ExcPETScError(ierr));
890 
892 
893  return *this;
894  }
895 
896 
897 
898  inline const VectorReference &
899  VectorReference::operator+=(const PetscScalar &value) const
900  {
903  ExcWrongMode(VectorOperation::add, vector.last_action));
904 
906 
908 
909  // we have to do above actions in any
910  // case to be consistent with the MPI
911  // communication model (see the
912  // comments in the documentation of
913  // PETScWrappers::MPI::Vector), but we
914  // can save some work if the addend is
915  // zero
916  if (value == PetscScalar())
917  return *this;
918 
919  // use the PETSc function to add something
920  const PetscInt petsc_i = index;
921  const PetscErrorCode ierr =
922  VecSetValues(vector, 1, &petsc_i, &value, ADD_VALUES);
923  AssertThrow(ierr == 0, ExcPETScError(ierr));
924 
925 
926  return *this;
927  }
928 
929 
930 
931  inline const VectorReference &
932  VectorReference::operator-=(const PetscScalar &value) const
933  {
936  ExcWrongMode(VectorOperation::add, vector.last_action));
937 
939 
941 
942  // we have to do above actions in any
943  // case to be consistent with the MPI
944  // communication model (see the
945  // comments in the documentation of
946  // PETScWrappers::MPI::Vector), but we
947  // can save some work if the addend is
948  // zero
949  if (value == PetscScalar())
950  return *this;
951 
952  // use the PETSc function to
953  // add something
954  const PetscInt petsc_i = index;
955  const PetscScalar subtractand = -value;
956  const PetscErrorCode ierr =
957  VecSetValues(vector, 1, &petsc_i, &subtractand, ADD_VALUES);
958  AssertThrow(ierr == 0, ExcPETScError(ierr));
959 
960  return *this;
961  }
962 
963 
964 
965  inline const VectorReference &
966  VectorReference::operator*=(const PetscScalar &value) const
967  {
970  ExcWrongMode(VectorOperation::insert, vector.last_action));
971 
973 
975 
976  // we have to do above actions in any
977  // case to be consistent with the MPI
978  // communication model (see the
979  // comments in the documentation of
980  // PETScWrappers::MPI::Vector), but we
981  // can save some work if the factor is
982  // one
983  if (value == 1.)
984  return *this;
985 
986  const PetscInt petsc_i = index;
987  const PetscScalar new_value = static_cast<PetscScalar>(*this) * value;
988 
989  const PetscErrorCode ierr =
990  VecSetValues(vector, 1, &petsc_i, &new_value, INSERT_VALUES);
991  AssertThrow(ierr == 0, ExcPETScError(ierr));
992 
993  return *this;
994  }
995 
996 
997 
998  inline const VectorReference &
999  VectorReference::operator/=(const PetscScalar &value) const
1000  {
1003  ExcWrongMode(VectorOperation::insert, vector.last_action));
1004 
1006 
1008 
1009  // we have to do above actions in any
1010  // case to be consistent with the MPI
1011  // communication model (see the
1012  // comments in the documentation of
1013  // PETScWrappers::MPI::Vector), but we
1014  // can save some work if the factor is
1015  // one
1016  if (value == 1.)
1017  return *this;
1018 
1019  const PetscInt petsc_i = index;
1020  const PetscScalar new_value = static_cast<PetscScalar>(*this) / value;
1021 
1022  const PetscErrorCode ierr =
1023  VecSetValues(vector, 1, &petsc_i, &new_value, INSERT_VALUES);
1024  AssertThrow(ierr == 0, ExcPETScError(ierr));
1025 
1026  return *this;
1027  }
1028 
1029 
1030 
1031  inline PetscReal
1032  VectorReference::real() const
1033  {
1034 # ifndef PETSC_USE_COMPLEX
1035  return static_cast<PetscScalar>(*this);
1036 # else
1037  return PetscRealPart(static_cast<PetscScalar>(*this));
1038 # endif
1039  }
1040 
1041 
1042 
1043  inline PetscReal
1044  VectorReference::imag() const
1045  {
1046 # ifndef PETSC_USE_COMPLEX
1047  return PetscReal(0);
1048 # else
1049  return PetscImaginaryPart(static_cast<PetscScalar>(*this));
1050 # endif
1051  }
1052 
1053  } // namespace internal
1054 
1055  inline bool
1056  VectorBase::in_local_range(const size_type index) const
1057  {
1058  PetscInt begin, end;
1059  const PetscErrorCode ierr =
1060  VecGetOwnershipRange(static_cast<const Vec &>(vector), &begin, &end);
1061  AssertThrow(ierr == 0, ExcPETScError(ierr));
1062 
1063  return ((index >= static_cast<size_type>(begin)) &&
1064  (index < static_cast<size_type>(end)));
1065  }
1066 
1067 
1068  inline IndexSet
1070  {
1071  IndexSet is(size());
1072 
1073  // PETSc only allows for contiguous local ranges, so this is simple
1074  const std::pair<size_type, size_type> x = local_range();
1075  is.add_range(x.first, x.second);
1076  return is;
1077  }
1078 
1079 
1080 
1081  inline bool
1083  {
1084  return ghosted;
1085  }
1086 
1087 
1088 
1089  inline void
1091  {}
1092 
1093 
1094 
1095  inline internal::VectorReference
1096  VectorBase::operator()(const size_type index)
1097  {
1098  return internal::VectorReference(*this, index);
1099  }
1100 
1101 
1102 
1103  inline PetscScalar
1104  VectorBase::operator()(const size_type index) const
1105  {
1106  return static_cast<PetscScalar>(internal::VectorReference(*this, index));
1107  }
1108 
1109 
1110 
1111  inline internal::VectorReference VectorBase::operator[](const size_type index)
1112  {
1113  return operator()(index);
1114  }
1115 
1116 
1117 
1118  inline PetscScalar VectorBase::operator[](const size_type index) const
1119  {
1120  return operator()(index);
1121  }
1122 
1123  inline const MPI_Comm &
1125  {
1126  static MPI_Comm comm;
1127  PetscObjectGetComm((PetscObject)vector, &comm);
1128  return comm;
1129  }
1130 
1131  inline void
1132  VectorBase::extract_subvector_to(const std::vector<size_type> &indices,
1133  std::vector<PetscScalar> & values) const
1134  {
1135  extract_subvector_to(&(indices[0]),
1136  &(indices[0]) + indices.size(),
1137  &(values[0]));
1138  }
1139 
1140  template <typename ForwardIterator, typename OutputIterator>
1141  inline void
1142  VectorBase::extract_subvector_to(const ForwardIterator indices_begin,
1143  const ForwardIterator indices_end,
1144  OutputIterator values_begin) const
1145  {
1146  const PetscInt n_idx = static_cast<PetscInt>(indices_end - indices_begin);
1147  if (n_idx == 0)
1148  return;
1149 
1150  // if we are dealing
1151  // with a parallel vector
1152  if (ghosted)
1153  {
1154  // there is the possibility
1155  // that the vector has
1156  // ghost elements. in that
1157  // case, we first need to
1158  // figure out which
1159  // elements we own locally,
1160  // then get a pointer to
1161  // the elements that are
1162  // stored here (both the
1163  // ones we own as well as
1164  // the ghost elements). in
1165  // this array, the locally
1166  // owned elements come
1167  // first followed by the
1168  // ghost elements whose
1169  // position we can get from
1170  // an index set
1171  PetscInt begin, end;
1172  PetscErrorCode ierr = VecGetOwnershipRange(vector, &begin, &end);
1173  AssertThrow(ierr == 0, ExcPETScError(ierr));
1174 
1175  Vec locally_stored_elements = nullptr;
1176  ierr = VecGhostGetLocalForm(vector, &locally_stored_elements);
1177  AssertThrow(ierr == 0, ExcPETScError(ierr));
1178 
1179  PetscInt lsize;
1180  ierr = VecGetSize(locally_stored_elements, &lsize);
1181  AssertThrow(ierr == 0, ExcPETScError(ierr));
1182 
1183  PetscScalar *ptr;
1184  ierr = VecGetArray(locally_stored_elements, &ptr);
1185  AssertThrow(ierr == 0, ExcPETScError(ierr));
1186 
1187  for (PetscInt i = 0; i < n_idx; ++i)
1188  {
1189  const unsigned int index = *(indices_begin + i);
1190  if (index >= static_cast<unsigned int>(begin) &&
1191  index < static_cast<unsigned int>(end))
1192  {
1193  // local entry
1194  *(values_begin + i) = *(ptr + index - begin);
1195  }
1196  else
1197  {
1198  // ghost entry
1199  const unsigned int ghostidx =
1200  ghost_indices.index_within_set(index);
1201 
1202  Assert(ghostidx + end - begin < (unsigned int)lsize,
1203  ExcInternalError());
1204  *(values_begin + i) = *(ptr + ghostidx + end - begin);
1205  }
1206  }
1207 
1208  ierr = VecRestoreArray(locally_stored_elements, &ptr);
1209  AssertThrow(ierr == 0, ExcPETScError(ierr));
1210 
1211  ierr = VecGhostRestoreLocalForm(vector, &locally_stored_elements);
1212  AssertThrow(ierr == 0, ExcPETScError(ierr));
1213  }
1214  // if the vector is local or the
1215  // caller, then simply access the
1216  // element we are interested in
1217  else
1218  {
1219  PetscInt begin, end;
1220  PetscErrorCode ierr = VecGetOwnershipRange(vector, &begin, &end);
1221  AssertThrow(ierr == 0, ExcPETScError(ierr));
1222 
1223  PetscScalar *ptr;
1224  ierr = VecGetArray(vector, &ptr);
1225  AssertThrow(ierr == 0, ExcPETScError(ierr));
1226 
1227  for (PetscInt i = 0; i < n_idx; ++i)
1228  {
1229  const unsigned int index = *(indices_begin + i);
1230 
1231  Assert(index >= static_cast<unsigned int>(begin) &&
1232  index < static_cast<unsigned int>(end),
1233  ExcInternalError());
1234 
1235  *(values_begin + i) = *(ptr + index - begin);
1236  }
1237 
1238  ierr = VecRestoreArray(vector, &ptr);
1239  AssertThrow(ierr == 0, ExcPETScError(ierr));
1240  }
1241  }
1242 
1243 # endif // DOXYGEN
1244 } // namespace PETScWrappers
1245 
1246 DEAL_II_NAMESPACE_CLOSE
1247 
1248 # endif // DEAL_II_WITH_PETSC
1249 
1250 #endif
1251 /*---------------------------- petsc_vector_base.h --------------------------*/
reference operator[](const size_type index)
#define DeclException2(Exception2, type1, type2, outsequence)
Definition: exceptions.h:420
void update_ghost_values() const
void swap(VectorBase &u, VectorBase &v)
bool has_ghost_elements() const
#define AssertThrow(cond, exc)
Definition: exceptions.h:1329
SymmetricTensor< rank_, dim, Number > operator*(const SymmetricTensor< rank_, dim, Number > &t, const Number &factor)
unsigned long long int global_dof_index
Definition: types.h:72
virtual const MPI_Comm & get_mpi_communicator() const
VectorOperation::values last_action
#define Assert(cond, exc)
Definition: exceptions.h:1227
void extract_subvector_to(const std::vector< size_type > &indices, std::vector< PetscScalar > &values) const
static::ExceptionBase & ExcGhostsPresent()
void add_range(const size_type begin, const size_type end)
Definition: index_set.cc:96
reference operator()(const size_type index)
#define DeclException3(Exception3, type1, type2, type3, outsequence)
Definition: exceptions.h:432
IndexSet locally_owned_elements() const
static::ExceptionBase & ExcInternalError()
bool in_local_range(const size_type index) const