Reference documentation for deal.II version 9.0.0
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 at
12 // the top level of the deal.II distribution.
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/subscriptor.h>
25 # include <deal.II/lac/exceptions.h>
26 # include <deal.II/lac/vector.h>
27 # include <deal.II/lac/vector_operation.h>
28 
29 # include <vector>
30 # include <utility>
31 
32 # include <petscvec.h>
33 # include <deal.II/base/index_set.h>
34 
35 DEAL_II_NAMESPACE_OPEN
36 
37 // forward declaration
38 template <typename number> class Vector;
39 
40 
48 namespace PETScWrappers
49 {
50  // forward declaration
51  class VectorBase;
52 
62  namespace internal
63  {
76  class VectorReference
77  {
78  public:
83 
84  private:
89  VectorReference (const VectorBase &vector,
90  const size_type index);
91 
92 
93  public:
94 
106  const VectorReference &operator = (const VectorReference &r) const;
107 
113  VectorReference &operator = (const VectorReference &r);
114 
118  const VectorReference &operator = (const PetscScalar &s) const;
119 
123  const VectorReference &operator += (const PetscScalar &s) const;
124 
128  const VectorReference &operator -= (const PetscScalar &s) const;
129 
133  const VectorReference &operator *= (const PetscScalar &s) const;
134 
138  const VectorReference &operator /= (const PetscScalar &s) const;
139 
143  PetscReal real () const;
144 
151  PetscReal imag () const;
152 
157  operator PetscScalar () const;
161  DeclException3 (ExcAccessToNonlocalElement,
162  int, int, int,
163  << "You tried to access element " << arg1
164  << " of a distributed vector, but only elements "
165  << arg2 << " through " << arg3
166  << " are stored locally and can be accessed.");
170  DeclException2 (ExcWrongMode,
171  int, int,
172  << "You tried to do a "
173  << (arg1 == 1 ?
174  "'set'" :
175  (arg1 == 2 ?
176  "'add'" : "???"))
177  << " operation but the vector is currently in "
178  << (arg2 == 1 ?
179  "'set'" :
180  (arg2 == 2 ?
181  "'add'" : "???"))
182  << " mode. You first have to call 'compress()'.");
183 
184  private:
188  const VectorBase &vector;
189 
193  const size_type index;
194 
199  friend class ::PETScWrappers::VectorBase;
200  };
201  }
233  class VectorBase : public Subscriptor
234  {
235  public:
241  typedef PetscScalar value_type;
242  typedef PetscReal real_type;
243  typedef types::global_dof_index size_type;
244  typedef internal::VectorReference reference;
245  typedef const internal::VectorReference const_reference;
246 
251  VectorBase ();
252 
257  VectorBase (const VectorBase &v);
258 
264  explicit VectorBase (const Vec &v);
265 
269  virtual ~VectorBase ();
270 
275  virtual void clear ();
276 
287  void compress (const VectorOperation::values operation);
288 
302  VectorBase &operator = (const PetscScalar s);
303 
309  bool operator == (const VectorBase &v) const;
310 
316  bool operator != (const VectorBase &v) const;
317 
321  size_type size () const;
322 
331  size_type local_size () const;
332 
341  std::pair<size_type, size_type>
342  local_range () const;
343 
348  bool in_local_range (const size_type index) const;
349 
364 
371  bool has_ghost_elements() const;
372 
379  void update_ghost_values () const;
380 
384  reference
385  operator () (const size_type index);
386 
390  PetscScalar
391  operator () (const size_type index) const;
392 
398  reference
399  operator [] (const size_type index);
400 
406  PetscScalar
407  operator [] (const size_type index) const;
408 
415  void set (const std::vector<size_type> &indices,
416  const std::vector<PetscScalar> &values);
417 
433  void extract_subvector_to (const std::vector<size_type> &indices,
434  std::vector<PetscScalar> &values) const;
435 
463  template <typename ForwardIterator, typename OutputIterator>
464  void extract_subvector_to (const ForwardIterator indices_begin,
465  const ForwardIterator indices_end,
466  OutputIterator values_begin) const;
467 
472  void add (const std::vector<size_type> &indices,
473  const std::vector<PetscScalar> &values);
474 
479  void add (const std::vector<size_type> &indices,
480  const ::Vector<PetscScalar> &values);
481 
487  void add (const size_type n_elements,
488  const size_type *indices,
489  const PetscScalar *values);
490 
497  PetscScalar operator * (const VectorBase &vec) const;
498 
502  real_type norm_sqr () const;
503 
507  PetscScalar mean_value () const;
508 
516  real_type l1_norm () const;
517 
522  real_type l2_norm () const;
523 
528  real_type lp_norm (const real_type p) const;
529 
534  real_type linfty_norm () const;
535 
554  PetscScalar add_and_dot (const PetscScalar a,
555  const VectorBase &V,
556  const VectorBase &W);
557 
561  real_type min () const;
562 
566  real_type max () const;
567 
573  bool all_zero () const;
574 
580  bool is_non_negative () const;
581 
585  VectorBase &operator *= (const PetscScalar factor);
586 
590  VectorBase &operator /= (const PetscScalar factor);
591 
596 
601 
606  void add (const PetscScalar s);
607 
611  void add (const PetscScalar a, const VectorBase &V);
612 
616  void add (const PetscScalar a, const VectorBase &V,
617  const PetscScalar b, const VectorBase &W);
618 
622  void sadd (const PetscScalar s,
623  const VectorBase &V);
624 
628  void sadd (const PetscScalar s,
629  const PetscScalar a,
630  const VectorBase &V);
631 
637  void scale (const VectorBase &scaling_factors);
638 
642  void equ (const PetscScalar a, const VectorBase &V);
643 
654  DEAL_II_DEPRECATED
655  void ratio (const VectorBase &a,
656  const VectorBase &b);
657 
665  void write_ascii (const PetscViewerFormat format = PETSC_VIEWER_DEFAULT) ;
666 
674  void print (std::ostream &out,
675  const unsigned int precision = 3,
676  const bool scientific = true,
677  const bool across = true) const;
678 
691  void swap (VectorBase &v);
692 
700  operator const Vec &() const;
701 
705  std::size_t memory_consumption () const;
706 
711  virtual const MPI_Comm &get_mpi_communicator () const;
712 
713  protected:
718  Vec vector;
719 
725  bool ghosted;
726 
733 
740 
745 
752 
758  void do_set_add_operation (const size_type n_elements,
759  const size_type *indices,
760  const PetscScalar *values,
761  const bool add_values);
762 
763  private:
769  VectorBase &operator=(const VectorBase &) = delete;
770  };
771 
772 
773 
774 // ------------------- inline and template functions --------------
775 
784  inline
785  void swap (VectorBase &u, VectorBase &v)
786  {
787  u.swap (v);
788  }
789 
790 #ifndef DOXYGEN
791  namespace internal
792  {
793  inline
794  VectorReference::VectorReference (const VectorBase &vector,
795  const size_type index)
796  :
797  vector (vector),
798  index (index)
799  {}
800 
801 
802  inline
803  const VectorReference &
804  VectorReference::operator = (const VectorReference &r) const
805  {
806  // as explained in the class
807  // documentation, this is not the copy
808  // operator. so simply pass on to the
809  // "correct" assignment operator
810  *this = static_cast<PetscScalar> (r);
811 
812  return *this;
813  }
814 
815 
816 
817  inline
818  VectorReference &
819  VectorReference::operator = (const VectorReference &r)
820  {
821  // as explained in the class
822  // documentation, this is not the copy
823  // operator. so simply pass on to the
824  // "correct" assignment operator
825  *this = static_cast<PetscScalar> (r);
826 
827  return *this;
828  }
829 
830 
831 
832  inline
833  const VectorReference &
834  VectorReference::operator = (const PetscScalar &value) const
835  {
836  Assert ((vector.last_action == VectorOperation::insert)
837  ||
838  (vector.last_action == VectorOperation::unknown),
839  ExcWrongMode (VectorOperation::insert,
840  vector.last_action));
841 
842  Assert (!vector.has_ghost_elements(), ExcGhostsPresent());
843 
844  const PetscInt petsc_i = index;
845 
846  const PetscErrorCode ierr = VecSetValues (vector, 1, &petsc_i, &value,
847  INSERT_VALUES);
848  AssertThrow (ierr == 0, ExcPETScError(ierr));
849 
850  vector.last_action = VectorOperation::insert;
851 
852  return *this;
853  }
854 
855 
856 
857  inline
858  const VectorReference &
859  VectorReference::operator += (const PetscScalar &value) const
860  {
861  Assert ((vector.last_action == VectorOperation::add)
862  ||
863  (vector.last_action == VectorOperation::unknown),
864  ExcWrongMode (VectorOperation::add,
865  vector.last_action));
866 
867  Assert (!vector.has_ghost_elements(), ExcGhostsPresent());
868 
869  vector.last_action = VectorOperation::add;
870 
871  // we have to do above actions in any
872  // case to be consistent with the MPI
873  // communication model (see the
874  // comments in the documentation of
875  // PETScWrappers::MPI::Vector), but we
876  // can save some work if the addend is
877  // zero
878  if (value == PetscScalar())
879  return *this;
880 
881  // use the PETSc function to add something
882  const PetscInt petsc_i = index;
883  const PetscErrorCode ierr = VecSetValues (vector, 1, &petsc_i, &value,
884  ADD_VALUES);
885  AssertThrow (ierr == 0, ExcPETScError(ierr));
886 
887 
888  return *this;
889  }
890 
891 
892 
893  inline
894  const VectorReference &
895  VectorReference::operator -= (const PetscScalar &value) const
896  {
897  Assert ((vector.last_action == VectorOperation::add)
898  ||
899  (vector.last_action == VectorOperation::unknown),
900  ExcWrongMode (VectorOperation::add,
901  vector.last_action));
902 
903  Assert (!vector.has_ghost_elements(), ExcGhostsPresent());
904 
905  vector.last_action = VectorOperation::add;
906 
907  // we have to do above actions in any
908  // case to be consistent with the MPI
909  // communication model (see the
910  // comments in the documentation of
911  // PETScWrappers::MPI::Vector), but we
912  // can save some work if the addend is
913  // zero
914  if (value == PetscScalar())
915  return *this;
916 
917  // use the PETSc function to
918  // add something
919  const PetscInt petsc_i = index;
920  const PetscScalar subtractand = -value;
921  const PetscErrorCode ierr = VecSetValues (vector, 1, &petsc_i, &subtractand,
922  ADD_VALUES);
923  AssertThrow (ierr == 0, ExcPETScError(ierr));
924 
925  return *this;
926  }
927 
928 
929 
930  inline
931  const VectorReference &
932  VectorReference::operator *= (const PetscScalar &value) const
933  {
934  Assert ((vector.last_action == VectorOperation::insert)
935  ||
936  (vector.last_action == VectorOperation::unknown),
937  ExcWrongMode (VectorOperation::insert,
938  vector.last_action));
939 
940  Assert (!vector.has_ghost_elements(), ExcGhostsPresent());
941 
942  vector.last_action = VectorOperation::insert;
943 
944  // we have to do above actions in any
945  // case to be consistent with the MPI
946  // communication model (see the
947  // comments in the documentation of
948  // PETScWrappers::MPI::Vector), but we
949  // can save some work if the factor is
950  // one
951  if (value == 1.)
952  return *this;
953 
954  const PetscInt petsc_i = index;
955  const PetscScalar new_value
956  = static_cast<PetscScalar>(*this) * value;
957 
958  const PetscErrorCode ierr = VecSetValues (vector, 1, &petsc_i, &new_value,
959  INSERT_VALUES);
960  AssertThrow (ierr == 0, ExcPETScError(ierr));
961 
962  return *this;
963  }
964 
965 
966 
967  inline
968  const VectorReference &
969  VectorReference::operator /= (const PetscScalar &value) const
970  {
971  Assert ((vector.last_action == VectorOperation::insert)
972  ||
973  (vector.last_action == VectorOperation::unknown),
974  ExcWrongMode (VectorOperation::insert,
975  vector.last_action));
976 
977  Assert (!vector.has_ghost_elements(), ExcGhostsPresent());
978 
979  vector.last_action = VectorOperation::insert;
980 
981  // we have to do above actions in any
982  // case to be consistent with the MPI
983  // communication model (see the
984  // comments in the documentation of
985  // PETScWrappers::MPI::Vector), but we
986  // can save some work if the factor is
987  // one
988  if (value == 1.)
989  return *this;
990 
991  const PetscInt petsc_i = index;
992  const PetscScalar new_value
993  = static_cast<PetscScalar>(*this) / value;
994 
995  const PetscErrorCode ierr = VecSetValues (vector, 1, &petsc_i, &new_value,
996  INSERT_VALUES);
997  AssertThrow (ierr == 0, ExcPETScError(ierr));
998 
999  return *this;
1000  }
1001 
1002 
1003 
1004  inline
1005  PetscReal
1006  VectorReference::real () const
1007  {
1008 #ifndef PETSC_USE_COMPLEX
1009  return static_cast<PetscScalar>(*this);
1010 #else
1011  return PetscRealPart (static_cast<PetscScalar>(*this));
1012 #endif
1013  }
1014 
1015 
1016 
1017  inline
1018  PetscReal
1019  VectorReference::imag () const
1020  {
1021 #ifndef PETSC_USE_COMPLEX
1022  return PetscReal (0);
1023 #else
1024  return PetscImaginaryPart (static_cast<PetscScalar>(*this));
1025 #endif
1026  }
1027 
1028  } // namespace internal
1029 
1030  inline
1031  bool
1032  VectorBase::in_local_range (const size_type index) const
1033  {
1034  PetscInt begin, end;
1035  const PetscErrorCode ierr = VecGetOwnershipRange (static_cast<const Vec &>(vector),
1036  &begin, &end);
1037  AssertThrow (ierr == 0, ExcPETScError(ierr));
1038 
1039  return ((index >= static_cast<size_type>(begin)) &&
1040  (index < static_cast<size_type>(end)));
1041  }
1042 
1043 
1044  inline
1045  IndexSet
1046  VectorBase::locally_owned_elements() const
1047  {
1048  IndexSet is (size());
1049 
1050  // PETSc only allows for contiguous local ranges, so this is simple
1051  const std::pair<size_type, size_type> x = local_range();
1052  is.add_range (x.first, x.second);
1053  return is;
1054  }
1055 
1056 
1057 
1058  inline
1059  bool
1060  VectorBase::has_ghost_elements() const
1061  {
1062  return ghosted;
1063  }
1064 
1065 
1066 
1067  inline
1068  void
1069  VectorBase::update_ghost_values () const
1070  {}
1071 
1072 
1073 
1074  inline
1075  internal::VectorReference
1076  VectorBase::operator () (const size_type index)
1077  {
1078  return internal::VectorReference (*this, index);
1079  }
1080 
1081 
1082 
1083  inline
1084  PetscScalar
1085  VectorBase::operator () (const size_type index) const
1086  {
1087  return static_cast<PetscScalar>(internal::VectorReference (*this, index));
1088  }
1089 
1090 
1091 
1092  inline
1093  internal::VectorReference
1094  VectorBase::operator [] (const size_type index)
1095  {
1096  return operator()(index);
1097  }
1098 
1099 
1100 
1101  inline
1102  PetscScalar
1103  VectorBase::operator [] (const size_type index) const
1104  {
1105  return operator()(index);
1106  }
1107 
1108  inline
1109  const MPI_Comm &
1110  VectorBase::get_mpi_communicator () const
1111  {
1112  static MPI_Comm comm;
1113  PetscObjectGetComm((PetscObject)vector, &comm);
1114  return comm;
1115  }
1116 
1117  inline
1118  void VectorBase::extract_subvector_to (const std::vector<size_type> &indices,
1119  std::vector<PetscScalar> &values) const
1120  {
1121  extract_subvector_to(&(indices[0]), &(indices[0]) + indices.size(), &(values[0]));
1122  }
1123 
1124  template <typename ForwardIterator, typename OutputIterator>
1125  inline
1126  void VectorBase::extract_subvector_to (const ForwardIterator indices_begin,
1127  const ForwardIterator indices_end,
1128  OutputIterator values_begin) const
1129  {
1130  const PetscInt n_idx = static_cast<PetscInt>(indices_end - indices_begin);
1131  if (n_idx == 0)
1132  return;
1133 
1134  // if we are dealing
1135  // with a parallel vector
1136  if (ghosted )
1137  {
1138  // there is the possibility
1139  // that the vector has
1140  // ghost elements. in that
1141  // case, we first need to
1142  // figure out which
1143  // elements we own locally,
1144  // then get a pointer to
1145  // the elements that are
1146  // stored here (both the
1147  // ones we own as well as
1148  // the ghost elements). in
1149  // this array, the locally
1150  // owned elements come
1151  // first followed by the
1152  // ghost elements whose
1153  // position we can get from
1154  // an index set
1155  PetscInt begin, end;
1156  PetscErrorCode ierr = VecGetOwnershipRange (vector, &begin, &end);
1157  AssertThrow (ierr == 0, ExcPETScError(ierr));
1158 
1159  Vec locally_stored_elements = nullptr;
1160  ierr = VecGhostGetLocalForm(vector, &locally_stored_elements);
1161  AssertThrow (ierr == 0, ExcPETScError(ierr));
1162 
1163  PetscInt lsize;
1164  ierr = VecGetSize(locally_stored_elements, &lsize);
1165  AssertThrow (ierr == 0, ExcPETScError(ierr));
1166 
1167  PetscScalar *ptr;
1168  ierr = VecGetArray(locally_stored_elements, &ptr);
1169  AssertThrow (ierr == 0, ExcPETScError(ierr));
1170 
1171  for (PetscInt i=0; i<n_idx; ++i)
1172  {
1173  const unsigned int index = *(indices_begin+i);
1174  if ( index>=static_cast<unsigned int>(begin)
1175  && index<static_cast<unsigned int>(end) )
1176  {
1177  //local entry
1178  *(values_begin+i) = *(ptr+index-begin);
1179  }
1180  else
1181  {
1182  //ghost entry
1183  const unsigned int ghostidx
1184  = ghost_indices.index_within_set(index);
1185 
1186  Assert(ghostidx+end-begin<(unsigned int)lsize, ExcInternalError());
1187  *(values_begin+i) = *(ptr+ghostidx+end-begin);
1188  }
1189  }
1190 
1191  ierr = VecRestoreArray(locally_stored_elements, &ptr);
1192  AssertThrow (ierr == 0, ExcPETScError(ierr));
1193 
1194  ierr = VecGhostRestoreLocalForm(vector, &locally_stored_elements);
1195  AssertThrow (ierr == 0, ExcPETScError(ierr));
1196 
1197  }
1198  // if the vector is local or the
1199  // caller, then simply access the
1200  // element we are interested in
1201  else
1202  {
1203  PetscInt begin, end;
1204  PetscErrorCode ierr = VecGetOwnershipRange (vector, &begin, &end);
1205  AssertThrow (ierr == 0, ExcPETScError(ierr));
1206 
1207  PetscScalar *ptr;
1208  ierr = VecGetArray(vector, &ptr);
1209  AssertThrow (ierr == 0, ExcPETScError(ierr));
1210 
1211  for (PetscInt i=0; i<n_idx; ++i)
1212  {
1213  const unsigned int index = *(indices_begin+i);
1214 
1215  Assert(index>=static_cast<unsigned int>(begin)
1216  && index<static_cast<unsigned int>(end), ExcInternalError());
1217 
1218  *(values_begin+i) = *(ptr+index-begin);
1219  }
1220 
1221  ierr = VecRestoreArray(vector, &ptr);
1222  AssertThrow (ierr == 0, ExcPETScError(ierr));
1223 
1224  }
1225  }
1226 
1227 #endif // DOXYGEN
1228 }
1229 
1230 DEAL_II_NAMESPACE_CLOSE
1231 
1232 #endif // DEAL_II_WITH_PETSC
1233 
1234 /*---------------------------- petsc_vector_base.h ---------------------------*/
1235 
1236 #endif
1237 /*---------------------------- petsc_vector_base.h ---------------------------*/
reference operator[](const size_type index)
#define DeclException2(Exception2, type1, type2, outsequence)
Definition: exceptions.h:358
VectorBase & operator-=(const VectorBase &V)
void sadd(const PetscScalar s, const VectorBase &V)
void update_ghost_values() const
void ratio(const VectorBase &a, const VectorBase &b)
void swap(VectorBase &u, VectorBase &v)
VectorBase & operator/=(const PetscScalar factor)
#define AssertThrow(cond, exc)
Definition: exceptions.h:1221
VectorBase & operator=(const PetscScalar s)
bool in_local_range(const size_type index) const
void scale(const VectorBase &scaling_factors)
std::pair< size_type, size_type > local_range() const
real_type lp_norm(const real_type p) const
void compress(const VectorOperation::values operation)
unsigned int global_dof_index
Definition: types.h:88
void do_set_add_operation(const size_type n_elements, const size_type *indices, const PetscScalar *values, const bool add_values)
VectorOperation::values last_action
#define Assert(cond, exc)
Definition: exceptions.h:1142
PetscScalar add_and_dot(const PetscScalar a, const VectorBase &V, const VectorBase &W)
std::size_t memory_consumption() const
void equ(const PetscScalar a, const VectorBase &V)
friend class internal::VectorReference
VectorBase & operator*=(const PetscScalar factor)
static ::ExceptionBase & ExcGhostsPresent()
VectorBase & operator+=(const VectorBase &V)
void print(std::ostream &out, const unsigned int precision=3, const bool scientific=true, const bool across=true) const
PetscScalar operator*(const VectorBase &vec) const
bool has_ghost_elements() const
PetscScalar mean_value() const
reference operator()(const size_type index)
bool operator==(const VectorBase &v) const
IndexSet locally_owned_elements() const
void add(const std::vector< size_type > &indices, const std::vector< PetscScalar > &values)
void write_ascii(const PetscViewerFormat format=PETSC_VIEWER_DEFAULT)
#define DeclException3(Exception3, type1, type2, type3, outsequence)
Definition: exceptions.h:370
void extract_subvector_to(const std::vector< size_type > &indices, std::vector< PetscScalar > &values) const
virtual const MPI_Comm & get_mpi_communicator() const
static ::ExceptionBase & ExcInternalError()
bool operator!=(const VectorBase &v) const