libmesh解析
本工作只是尝试解析原libmesh的代码,供学习使用
 全部  命名空间 文件 函数 变量 类型定义 枚举 枚举值 友元 
petsc_vector.h
浏览该文件的文档.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2023 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 
21 #ifndef LIBMESH_PETSC_VECTOR_H
22 #define LIBMESH_PETSC_VECTOR_H
23 
24 
25 #include "libmesh/libmesh_config.h"
26 
27 #ifdef LIBMESH_HAVE_PETSC
28 
29 // Local includes
30 #include "libmesh/numeric_vector.h"
31 #include "libmesh/petsc_macro.h"
32 #include "libmesh/int_range.h"
33 #include "libmesh/libmesh_common.h"
34 #include "libmesh/petsc_solver_exception.h"
35 #include "libmesh/parallel_only.h"
36 #include "libmesh/enum_to_string.h"
37 
38 // PETSc include files.
39 #ifdef I
40 # define LIBMESH_SAW_I
41 #endif
42 #include <petscvec.h>
43 #ifndef LIBMESH_SAW_I
44 # undef I // Avoid complex.h contamination
45 #endif
46 
47 // C++ includes
48 #include <cstddef>
49 #include <cstring>
50 #include <vector>
51 #include <unordered_map>
52 #include <limits>
53 
54 #include <atomic>
55 #include <mutex>
56 #include <condition_variable>
57 
58 namespace libMesh
59 {
60 
61 // forward declarations
62 template <typename T> class SparseMatrix;
63 
64 
65 cpp
66 Copy code
74 template <typename T>
75 class PetscVector final : public NumericVector<T>
76 {
77 public:
78 
85  explicit
86  PetscVector (const Parallel::Communicator & comm_in,
87  const ParallelType type = AUTOMATIC);
88 
96  explicit
97  PetscVector (const Parallel::Communicator & comm_in,
98  const numeric_index_type n,
99  const ParallelType type = AUTOMATIC);
100 
109  PetscVector (const Parallel::Communicator & comm_in,
110  const numeric_index_type n,
111  const numeric_index_type n_local,
112  const ParallelType type = AUTOMATIC);
113 
123  PetscVector (const Parallel::Communicator & comm_in,
124  const numeric_index_type N,
125  const numeric_index_type n_local,
126  const std::vector<numeric_index_type> & ghost,
127  const ParallelType type = AUTOMATIC);
128 
136  PetscVector(Vec v,
137  const Parallel::Communicator & comm_in);
138 
147 
151  PetscVector (PetscVector &&) = delete;
152  PetscVector (const PetscVector &) = delete;
153  PetscVector & operator= (PetscVector &&) = delete;
154 
158  virtual ~PetscVector ();
159 
163  virtual void close () override;
164 
168  virtual void clear () noexcept override;
169 
173  virtual void zero () override;
174 
175 
181  virtual std::unique_ptr<NumericVector<T>> zero_clone () const override;
182 
188  virtual std::unique_ptr<NumericVector<T>> clone () const override;
189 
198  virtual void init (const numeric_index_type N,
199  const numeric_index_type n_local,
200  const bool fast=false,
201  const ParallelType type=AUTOMATIC) override;
202 
210  virtual void init (const numeric_index_type N,
211  const bool fast=false,
212  const ParallelType type=AUTOMATIC) override;
213 
223  virtual void init (const numeric_index_type N,
224  const numeric_index_type n_local,
225  const std::vector<numeric_index_type> & ghost,
226  const bool fast = false,
227  const ParallelType = AUTOMATIC) override;
228 
235  virtual void init (const NumericVector<T> & other,
236  const bool fast = false) override;
237 
244  virtual NumericVector<T> & operator= (const T s) override;
245 
252  virtual NumericVector<T> & operator= (const NumericVector<T> & v) override;
253 
260  virtual NumericVector<T> & operator= (const std::vector<T> & v) override;
261 
267  virtual Real min () const override;
268 
274  virtual Real max () const override;
275 
281  virtual T sum () const override;
282 
288  virtual Real l1_norm () const override;
289 
295  virtual Real l2_norm () const override;
296 
302  virtual Real linfty_norm () const override;
303 
309  virtual numeric_index_type size () const override;
310 
316  virtual numeric_index_type local_size() const override;
317 
323  virtual numeric_index_type first_local_index() const override;
324 
330  virtual numeric_index_type last_local_index() const override;
331 
339 
346  virtual T operator() (const numeric_index_type i) const override;
347 
354  virtual void get(const std::vector<numeric_index_type> & index,
355  T * values) const override;
356 
362  PetscScalar * get_array();
363 
369  const PetscScalar * get_array_read() const;
370 
376  void restore_array();
377 
384  virtual NumericVector<T> & operator += (const NumericVector<T> & v) override;
385 
392  virtual NumericVector<T> & operator -= (const NumericVector<T> & v) override;
393 
397  virtual void reciprocal() override;
398 
402  virtual void conjugate() override;
403 
410  virtual void set (const numeric_index_type i,
411  const T value) override;
412 
419  virtual void add (const numeric_index_type i,
420  const T value) override;
421 
427  virtual void add (const T s) override;
428 
434  virtual void add (const NumericVector<T> & v) override;
435 
442  virtual void add (const T a, const NumericVector<T> & v) override;
443 
448 
455  virtual void add_vector (const T * v,
456  const std::vector<numeric_index_type> & dof_indices) override;
457 
464  virtual void add_vector (const NumericVector<T> & v,
465  const SparseMatrix<T> & A) override;
466 
473  virtual void add_vector_transpose (const NumericVector<T> & v,
474  const SparseMatrix<T> & A) override;
475 
485  const SparseMatrix<T> & A);
486 
491 
498  virtual void insert (const T * v,
499  const std::vector<numeric_index_type> & dof_indices) override;
500 
506  virtual void scale (const T factor) override;
507 
513  virtual NumericVector<T> & operator *= (const NumericVector<T> & v) override;
514 
520  virtual NumericVector<T> & operator /= (const NumericVector<T> & v) override;
521 
525  virtual void abs() override;
526 
533  virtual T dot(const NumericVector<T> & v) const override;
534 
541  T indefinite_dot(const NumericVector<T> & v) const;
542 
548  virtual void localize (std::vector<T> & v_local) const override;
549 
555  virtual void localize (NumericVector<T> & v_local) const override;
556 
563  virtual void localize (NumericVector<T> & v_local,
564  const std::vector<numeric_index_type> & indices) const override;
565 
573  virtual void localize (const numeric_index_type first_local_idx,
574  const numeric_index_type last_local_idx,
575  const std::vector<numeric_index_type> & send_list) override;
576 
583  virtual void localize_to_one (std::vector<T> & v_local,
584  const processor_id_type proc_id=0) const override;
585 
591  virtual void pointwise_mult (const NumericVector<T> & vec1,
592  const NumericVector<T> & vec2) override;
593 
599  virtual void pointwise_divide (const NumericVector<T> & vec1,
600  const NumericVector<T> & vec2) override;
601 
607  virtual void print_matlab(const std::string & name = "") const override;
608 
615  virtual void create_subvector(NumericVector<T> & subvector,
616  const std::vector<numeric_index_type> & rows) const override;
617 
623  virtual void swap (NumericVector<T> & v) override;
624 
630  virtual std::size_t max_allowed_id() const override;
631 
641  Vec vec () { libmesh_assert (_vec); return _vec; }
642 
652  Vec vec () const { libmesh_assert (_vec); return _vec; }
653 
654  private:
655 
659  Vec _vec;
660 
664  #ifdef LIBMESH_HAVE_CXX11_THREAD
665  // 我们不能在这里使用 std::atomic_flag,因为我们需要 load 和 store 操作。
666  mutable std::atomic<bool> _array_is_present;
667  #else
668  mutable bool _array_is_present;
669  #endif
670 
677 
684 
689 
693  mutable Vec _local_form;
694 
698  mutable const PetscScalar * _read_only_values;
699 
704  mutable PetscScalar * _values;
705 
709  mutable std::mutex _petsc_get_restore_array_mutex;
710 
716  void _get_array(bool read_only) const;
717 
721  void _restore_array() const;
722 
726  typedef std::unordered_map<numeric_index_type, numeric_index_type> GlobalToLocalMap;
727 
732 
737 
742 
746  mutable bool _values_read_only;
747 };
748 
749 
750 /*----------------------- Inline functions ----------------------------------*/
751 
752 
753 
754 template <typename T>
755 inline
756 PetscVector<T>::PetscVector (const Parallel::Communicator & comm_in, const ParallelType ptype) :
757  NumericVector<T>(comm_in, ptype),
758  _array_is_present(false),
759  _first(0),
760  _last(0),
761  _local_form(nullptr),
762  _values(nullptr),
763  _global_to_local_map(),
764  _destroy_vec_on_exit(true),
765  _values_manually_retrieved(false),
766  _values_read_only(false)
767 {
768  this->_type = ptype;
769 }
770 
771 
772 
773 template <typename T>
774 inline
775 PetscVector<T>::PetscVector (const Parallel::Communicator & comm_in,
776  const numeric_index_type n,
777  const ParallelType ptype) :
778  NumericVector<T>(comm_in, ptype),
779  _array_is_present(false),
780  _local_form(nullptr),
781  _values(nullptr),
782  _global_to_local_map(),
783  _destroy_vec_on_exit(true),
784  _values_manually_retrieved(false),
785  _values_read_only(false)
786 {
787  this->init(n, n, false, ptype);
788 }
789 
790 
791 
792 template <typename T>
793 inline
794 PetscVector<T>::PetscVector (const Parallel::Communicator & comm_in,
795  const numeric_index_type n,
796  const numeric_index_type n_local,
797  const ParallelType ptype) :
798  NumericVector<T>(comm_in, ptype),
799  _array_is_present(false),
800  _local_form(nullptr),
801  _values(nullptr),
802  _global_to_local_map(),
803  _destroy_vec_on_exit(true),
804  _values_manually_retrieved(false),
805  _values_read_only(false)
806 {
807  this->init(n, n_local, false, ptype);
808 }
809 
810 
811 
812 template <typename T>
813 inline
814 PetscVector<T>::PetscVector (const Parallel::Communicator & comm_in,
815  const numeric_index_type n,
816  const numeric_index_type n_local,
817  const std::vector<numeric_index_type> & ghost,
818  const ParallelType ptype) :
819  NumericVector<T>(comm_in, ptype),
820  _array_is_present(false),
821  _local_form(nullptr),
822  _values(nullptr),
823  _global_to_local_map(),
824  _destroy_vec_on_exit(true),
825  _values_manually_retrieved(false),
826  _values_read_only(false)
827 {
828  this->init(n, n_local, ghost, false, ptype);
829 }
830 
831 
832 
833 
842 template <typename T>
843 inline
845  const Parallel::Communicator & comm_in) :
846  NumericVector<T>(comm_in, AUTOMATIC),
847  _array_is_present(false),
848  _local_form(nullptr),
849  _values(nullptr),
850  _global_to_local_map(),
851  _destroy_vec_on_exit(false),
852  _values_manually_retrieved(false),
853  _values_read_only(false)
854 {
855  this->_vec = v;
856  this->_is_closed = true;
857  this->_is_initialized = true;
858 
859  /* 需要向 PETSc 查询(本地到全局)幽灵值映射并从中创建逆映射。*/
860  PetscErrorCode ierr=0;
861  PetscInt petsc_local_size=0;
862  ierr = VecGetLocalSize(_vec, &petsc_local_size);
863  LIBMESH_CHKERR(ierr);
864 
865  // 从 PETSc 获取向量类型。
866  VecType ptype;
867  ierr = VecGetType(_vec, &ptype);
868  LIBMESH_CHKERR(ierr);
869 
870 #if PETSC_RELEASE_GREATER_EQUALS(3, 21, 0)
871  // Fande 仅为 VECMPI 实现了 VecGhostGetGhostIS
872  if (std::strcmp(ptype, VECMPI) == 0)
873  {
874  IS ghostis;
875  ierr = VecGhostGetGhostIS(_vec, &ghostis);
876  LIBMESH_CHKERR(ierr);
877 
878  Vec localrep;
879  ierr = VecGhostGetLocalForm(_vec, &localrep);
880  LIBMESH_CHKERR(ierr);
881 
882  // 如果是稀疏存储的向量,设置我们的新映射
883  // 仅检查映射不足以确定向量是否被幽灵化
884  // 我们需要检查向量是否有本地表示
885  if (ghostis && localrep)
886  {
887  PetscInt ghost_size;
888  ierr = ISGetSize(ghostis, &ghost_size);
889  LIBMESH_CHKERR(ierr);
890 
891  const PetscInt * indices;
892  ierr = ISGetIndices(ghostis, &indices);
893  LIBMESH_CHKERR(ierr);
894 
895  for (const auto i : make_range(ghost_size))
896  _global_to_local_map[indices[i]] = i;
897  this->_type = GHOSTED;
898  ierr = ISRestoreIndices(ghostis, &indices);
899  LIBMESH_CHKERR(ierr);
900  }
901  }
902  else if (std::strcmp(ptype,VECSHARED) == 0)
903 #else
904  if ((std::strcmp(ptype,VECSHARED) == 0) || (std::strcmp(ptype,VECMPI) == 0))
905 #endif
906  {
907  ISLocalToGlobalMapping mapping;
908  ierr = VecGetLocalToGlobalMapping(_vec, &mapping);
909  LIBMESH_CHKERR(ierr);
910 
911  Vec localrep;
912  ierr = VecGhostGetLocalForm(_vec,&localrep);
913  LIBMESH_CHKERR(ierr);
914  // 如果是稀疏存储的向量,设置我们的新映射
915  // 仅检查映射不足以确定向量是否被幽灵化
916  // 我们需要检查向量是否有本地表示
917  if (mapping && localrep)
918  {
919  const numeric_index_type my_local_size = static_cast<numeric_index_type>(petsc_local_size);
920  const numeric_index_type ghost_begin = static_cast<numeric_index_type>(petsc_local_size);
921  PetscInt n;
922  ierr = ISLocalToGlobalMappingGetSize(mapping, &n);
923  LIBMESH_CHKERR(ierr);
924 
925  const numeric_index_type ghost_end = static_cast<numeric_index_type>(n);
926  const PetscInt * indices;
927  ierr = ISLocalToGlobalMappingGetIndices(mapping,&indices);
928  LIBMESH_CHKERR(ierr);
929 
930  for (numeric_index_type i=ghost_begin; i<ghost_end; i++)
931  _global_to_local_map[indices[i]] = i-my_local_size;
932  this->_type = GHOSTED;
933  ierr = ISLocalToGlobalMappingRestoreIndices(mapping, &indices);
934  LIBMESH_CHKERR(ierr);
935  }
936  else
937  this->_type = PARALLEL;
938 
939  ierr = VecGhostRestoreLocalForm(_vec,&localrep);
940  LIBMESH_CHKERR(ierr);
941  }
942  else
943  this->_type = SERIAL;
944 }
945 
946 
947 
948 template <typename T>
949 inline
951 {
952  this->clear ();
953 }
954 
955 
956 
957 template <typename T>
958 inline
960  const numeric_index_type n_local,
961  const bool fast,
962  const ParallelType ptype)
963 {
964  parallel_object_only();
965 
966  PetscErrorCode ierr=0;
967  PetscInt petsc_n=static_cast<PetscInt>(n);
968 
969  // Clear initialized vectors
970  if (this->initialized())
971  this->clear();
972 
973  if (ptype == AUTOMATIC)
974  {
975  if (n == n_local)
976  this->_type = SERIAL;
977  else
978  this->_type = PARALLEL;
979  }
980  else
981  this->_type = ptype;
982 
983  libmesh_assert ((this->_type==SERIAL && n==n_local) ||
984  this->_type==PARALLEL);
985 
986  // create a sequential vector if on only 1 processor
987  if (this->_type == SERIAL)
988  {
989  ierr = VecCreate(PETSC_COMM_SELF, &_vec);CHKERRABORT(PETSC_COMM_SELF,ierr);
990  ierr = VecSetSizes(_vec, petsc_n, petsc_n); CHKERRABORT(PETSC_COMM_SELF,ierr);
991  ierr = VecSetFromOptions (_vec);
992  CHKERRABORT(PETSC_COMM_SELF,ierr);
993  }
994  // otherwise create an MPI-enabled vector
995  else if (this->_type == PARALLEL)
996  {
997 #ifdef LIBMESH_HAVE_MPI
998  PetscInt petsc_n_local=cast_int<PetscInt>(n_local);
999  libmesh_assert_less_equal (n_local, n);
1000  // Use more generic function instead of VecCreateSeq/MPI
1001  ierr = VecCreate(this->comm().get(), &_vec);LIBMESH_CHKERR(ierr);
1002  ierr = VecSetSizes(_vec, petsc_n_local, petsc_n); LIBMESH_CHKERR(ierr);
1003 #else
1004  libmesh_assert_equal_to (n_local, n);
1005  ierr = VecCreate(PETSC_COMM_SELF, &_vec);CHKERRABORT(PETSC_COMM_SELF,ierr);
1006  ierr = VecSetSizes(_vec, petsc_n, petsc_n); CHKERRABORT(PETSC_COMM_SELF,ierr);
1007 #endif
1008  ierr = VecSetFromOptions (_vec);
1009  LIBMESH_CHKERR(ierr);
1010  }
1011  else
1012  libmesh_error_msg("Unsupported type " << Utility::enum_to_string(this->_type));
1013 
1014  this->_is_initialized = true;
1015  this->_is_closed = true;
1016 
1017 
1018  if (fast == false)
1019  this->zero ();
1020 }
1021 
1022 
1023 
1024 template <typename T>
1025 inline
1027  const bool fast,
1028  const ParallelType ptype)
1029 {
1030  this->init(n,n,fast,ptype);
1031 }
1032 
1033 
1034 
1035 template <typename T>
1036 inline
1038  const numeric_index_type n_local,
1039  const std::vector<numeric_index_type> & ghost,
1040  const bool fast,
1041  const ParallelType libmesh_dbg_var(ptype))
1042 {
1043  parallel_object_only();
1044 
1045  PetscErrorCode ierr=0;
1046  PetscInt petsc_n=static_cast<PetscInt>(n);
1047  PetscInt petsc_n_local=static_cast<PetscInt>(n_local);
1048  PetscInt petsc_n_ghost=static_cast<PetscInt>(ghost.size());
1049 
1050  // 如果网格不是分离的,每个处理器将具有所有的自由度、没有自由度,或在处理器之间的边界上有一些非零自由度。
1051  //
1052  // 但是我们不能断言这一点,因为有人可能希望构造一个不包括邻元素自由度的 GHOSTED 向量。Boyce 在用户代码中尝试过这样做,我们将在 System::project_vector() 中也希望这样做。
1053  //
1054  // libmesh_assert(n_local == 0 || n_local == n || !ghost.empty());
1055 
1056  libmesh_assert(sizeof(PetscInt) == sizeof(numeric_index_type));
1057 
1058  PetscInt * petsc_ghost = ghost.empty() ? LIBMESH_PETSC_NULLPTR :
1059  const_cast<PetscInt *>(reinterpret_cast<const PetscInt *>(ghost.data()));
1060 
1061  // 清除已初始化的向量
1062  if (this->initialized())
1063  this->clear();
1064 
1065  libmesh_assert(ptype == AUTOMATIC || ptype == GHOSTED);
1066  this->_type = GHOSTED;
1067 
1068  /* 创建全局到本地幽灵单元格映射。 */
1069  for (auto i : index_range(ghost))
1070  {
1071  _global_to_local_map[ghost[i]] = i;
1072  }
1073 
1074  /* 创建向量。 */
1075  ierr = VecCreateGhost (this->comm().get(), petsc_n_local, petsc_n,
1076  petsc_n_ghost, petsc_ghost,
1077  &_vec);
1078  LIBMESH_CHKERR(ierr);
1079 
1080  // 添加前缀,以便我们至少可以在使用 Petsc 选项时区分幽灵向量和非幽灵向量。
1081  // PETSc 尚不完全支持 GPU 上的 VecGhost。此更改允许我们触发非幽灵向量在 GPU 上使用,而不会干扰幽灵向量。
1082  ierr = PetscObjectAppendOptionsPrefix((PetscObject)_vec,"ghost_");
1083  LIBMESH_CHKERR(ierr);
1084 
1085  ierr = VecSetFromOptions (_vec);
1086  LIBMESH_CHKERR(ierr);
1087 
1088  this->_is_initialized = true;
1089  this->_is_closed = true;
1090 
1091  if (fast == false)
1092  this->zero ();
1093 }
1094 
1095 
1096 template <typename T>
1097 inline
1099  const bool fast)
1100 {
1101  parallel_object_only();
1102 
1103  // 清除已初始化的向量
1104  if (this->initialized())
1105  this->clear();
1106 
1107  const PetscVector<T> & v = cast_ref<const PetscVector<T> &>(other);
1108 
1109  // 其他向量应该恢复数组。
1110  if (v.initialized())
1111  {
1112  v._restore_array();
1113  }
1114 
1115  this->_global_to_local_map = v._global_to_local_map;
1116 
1117  // 即使我们基于一个未初始化或未关闭的向量来初始化大小,*这个*向量现在正在初始化,最初是关闭的。
1118  this->_is_closed = true; // v._is_closed;
1119  this->_is_initialized = true; // v._is_initialized;
1120 
1121  this->_type = v._type;
1122 
1123  // 我们希望有一个有效的 Vec,即使它最初的大小为零
1124  PetscErrorCode ierr = VecDuplicate (v._vec, &this->_vec);
1125  LIBMESH_CHKERR(ierr);
1126 
1127  if (fast == false)
1128  this->zero ();
1129 }
1130 
1131 
1132 
1133 template <typename T>
1134 inline
1136 {
1137  parallel_object_only();
1138 
1139  this->_restore_array();
1140 
1141  VecAssemblyBeginEnd(this->comm(), _vec);
1142 
1143  if (this->type() == GHOSTED)
1144  VecGhostUpdateBeginEnd(this->comm(), _vec, INSERT_VALUES, SCATTER_FORWARD);
1145 
1146  this->_is_closed = true;
1147 }
1148 
1149 
1150 
1151 template <typename T>
1152 inline
1153 void PetscVector<T>::clear () noexcept
1154 {
1155  exceptionless_parallel_object_only();
1156 
1157  if (this->initialized())
1158  this->_restore_array();
1159 
1160  if ((this->initialized()) && (this->_destroy_vec_on_exit))
1161  {
1162  // If we encounter an error here, print a warning but otherwise
1163  // keep going since we may be recovering from an exception.
1164  PetscErrorCode ierr = VecDestroy(&_vec);
1165  if (ierr)
1166  libmesh_warning("Warning: VecDestroy returned a non-zero error code which we ignored.");
1167  }
1168 
1169  this->_is_closed = this->_is_initialized = false;
1170 
1171  _global_to_local_map.clear();
1172 }
1173 
1174 
1175 
1176 template <typename T>
1177 inline
1179 {
1180  parallel_object_only();
1181 
1182  libmesh_assert(this->closed());
1183 
1184  this->_restore_array();
1185 
1186  PetscErrorCode ierr=0;
1187 
1188  PetscScalar z=0.;
1189 
1190  if (this->type() != GHOSTED)
1191  {
1192  ierr = VecSet (_vec, z);
1193  LIBMESH_CHKERR(ierr);
1194  }
1195  else
1196  {
1197  /* Vectors that include ghost values require a special
1198  handling. */
1199  Vec loc_vec;
1200  ierr = VecGhostGetLocalForm (_vec,&loc_vec);
1201  LIBMESH_CHKERR(ierr);
1202 
1203  ierr = VecSet (loc_vec, z);
1204  LIBMESH_CHKERR(ierr);
1205 
1206  ierr = VecGhostRestoreLocalForm (_vec,&loc_vec);
1207  LIBMESH_CHKERR(ierr);
1208  }
1209 }
1210 
1211 
1212 
1213 template <typename T>
1214 inline
1215 std::unique_ptr<NumericVector<T>> PetscVector<T>::zero_clone () const
1216 {
1217  NumericVector<T> * cloned_vector = new PetscVector<T>(this->comm(), this->type());
1218  cloned_vector->init(*this);
1219  return std::unique_ptr<NumericVector<T>>(cloned_vector);
1220 }
1221 
1222 
1223 
1224 template <typename T>
1225 inline
1226 std::unique_ptr<NumericVector<T>> PetscVector<T>::clone () const
1227 {
1228  NumericVector<T> * cloned_vector = new PetscVector<T>(this->comm(), this->type());
1229  cloned_vector->init(*this, true);
1230  *cloned_vector = *this;
1231  return std::unique_ptr<NumericVector<T>>(cloned_vector);
1232 }
1233 
1234 
1235 
1236 template <typename T>
1237 inline
1239 {
1240  libmesh_assert (this->initialized());
1241 
1242  PetscErrorCode ierr=0;
1243  PetscInt petsc_size=0;
1244 
1245  if (!this->initialized())
1246  return 0;
1247 
1248  ierr = VecGetSize(_vec, &petsc_size);
1249  LIBMESH_CHKERR(ierr);
1250 
1251  return static_cast<numeric_index_type>(petsc_size);
1252 }
1253 
1254 
1255 
1256 template <typename T>
1257 inline
1259 {
1260  libmesh_assert (this->initialized());
1261 
1262  PetscErrorCode ierr=0;
1263  PetscInt petsc_size=0;
1264 
1265  ierr = VecGetLocalSize(_vec, &petsc_size);
1266  LIBMESH_CHKERR(ierr);
1267 
1268  return static_cast<numeric_index_type>(petsc_size);
1269 }
1270 
1271 
1272 
1273 template <typename T>
1274 inline
1276 {
1277  libmesh_assert (this->initialized());
1278 
1279  numeric_index_type first = 0;
1280 
1281  if (_array_is_present) // Can we use cached values?
1282  first = _first;
1283  else
1284  {
1285  PetscErrorCode ierr=0;
1286  PetscInt petsc_first=0, petsc_last=0;
1287  ierr = VecGetOwnershipRange (_vec, &petsc_first, &petsc_last);
1288  LIBMESH_CHKERR(ierr);
1289  first = static_cast<numeric_index_type>(petsc_first);
1290  }
1291 
1292  return first;
1293 }
1294 
1295 
1296 
1297 template <typename T>
1298 inline
1300 {
1301  libmesh_assert (this->initialized());
1302 
1303  numeric_index_type last = 0;
1304 
1305  if (_array_is_present) // Can we use cached values?
1306  last = _last;
1307  else
1308  {
1309  PetscErrorCode ierr=0;
1310  PetscInt petsc_first=0, petsc_last=0;
1311  ierr = VecGetOwnershipRange (_vec, &petsc_first, &petsc_last);
1312  LIBMESH_CHKERR(ierr);
1313  last = static_cast<numeric_index_type>(petsc_last);
1314  }
1315 
1316  return last;
1317 }
1318 
1319 
1320 
1321 template <typename T>
1322 inline
1324 {
1325  libmesh_assert (this->initialized());
1326 
1327  numeric_index_type first=0;
1328  numeric_index_type last=0;
1329 
1330  if (_array_is_present) // Can we use cached values?
1331  {
1332  first = _first;
1333  last = _last;
1334  }
1335  else
1336  {
1337  PetscErrorCode ierr=0;
1338  PetscInt petsc_first=0, petsc_last=0;
1339  ierr = VecGetOwnershipRange (_vec, &petsc_first, &petsc_last);
1340  LIBMESH_CHKERR(ierr);
1341  first = static_cast<numeric_index_type>(petsc_first);
1342  last = static_cast<numeric_index_type>(petsc_last);
1343  }
1344 
1345 
1346  if ((i>=first) && (i<last))
1347  {
1348  return i-first;
1349  }
1350 
1351  GlobalToLocalMap::const_iterator it = _global_to_local_map.find(i);
1352 #ifndef NDEBUG
1353  const GlobalToLocalMap::const_iterator end = _global_to_local_map.end();
1354  if (it == end)
1355  {
1356  std::ostringstream error_message;
1357  error_message << "No index " << i << " in ghosted vector.\n"
1358  << "Vector contains [" << first << ',' << last << ")\n";
1359  GlobalToLocalMap::const_iterator b = _global_to_local_map.begin();
1360  if (b == end)
1361  {
1362  error_message << "And empty ghost array.\n";
1363  }
1364  else
1365  {
1366  error_message << "And ghost array {" << b->first;
1367  for (++b; b != end; ++b)
1368  error_message << ',' << b->first;
1369  error_message << "}\n";
1370  }
1371 
1372  libmesh_error_msg(error_message.str());
1373  }
1374  libmesh_assert (it != _global_to_local_map.end());
1375 #endif
1376  return it->second+last-first;
1377 }
1378 
1379 
1380 
1381 template <typename T>
1382 inline
1384 {
1385  this->_get_array(true);
1386 
1387  const numeric_index_type local_index = this->map_global_to_local_index(i);
1388 
1389 #ifndef NDEBUG
1390  if (this->type() == GHOSTED)
1391  {
1392  libmesh_assert_less (local_index, _local_size);
1393  }
1394 #endif
1395 
1396  return static_cast<T>(_read_only_values[local_index]);
1397 }
1398 
1399 
1400 
1401 template <typename T>
1402 inline
1403 void PetscVector<T>::get(const std::vector<numeric_index_type> & index,
1404  T * values) const
1405 {
1406  this->_get_array(true);
1407 
1408  const std::size_t num = index.size();
1409 
1410  for (std::size_t i=0; i<num; i++)
1411  {
1412  const numeric_index_type local_index = this->map_global_to_local_index(index[i]);
1413 #ifndef NDEBUG
1414  if (this->type() == GHOSTED)
1415  {
1416  libmesh_assert_less (local_index, _local_size);
1417  }
1418 #endif
1419  values[i] = static_cast<T>(_read_only_values[local_index]);
1420  }
1421 }
1422 
1423 
1424 template <typename T>
1425 inline
1427 {
1428  _get_array(false);
1429  _values_manually_retrieved = true;
1430 
1431  return _values;
1432 }
1433 
1434 
1435 template <typename T>
1436 inline
1437 const PetscScalar * PetscVector<T>::get_array_read() const
1438 {
1439  _get_array(true);
1440  _values_manually_retrieved = true;
1441 
1442  return _read_only_values;
1443 }
1444 
1445 template <typename T>
1446 inline
1448 {
1449  // \note \p _values_manually_retrieved needs to be set to \p false
1450  // \e before calling \p _restore_array()!
1451  _values_manually_retrieved = false;
1452  _restore_array();
1453 }
1454 
1455 template <typename T>
1456 inline
1458 {
1459  parallel_object_only();
1460 
1461  this->_restore_array();
1462 
1463  PetscErrorCode ierr=0;
1464  PetscInt index=0;
1465  PetscReal returnval=0.;
1466 
1467  ierr = VecMin (_vec, &index, &returnval);
1468  LIBMESH_CHKERR(ierr);
1469 
1470  // this return value is correct: VecMin returns a PetscReal
1471  return static_cast<Real>(returnval);
1472 }
1473 
1474 
1475 
1476 template <typename T>
1477 inline
1479 {
1480  parallel_object_only();
1481 
1482  this->_restore_array();
1483 
1484  PetscErrorCode ierr=0;
1485  PetscInt index=0;
1486  PetscReal returnval=0.;
1487 
1488  ierr = VecMax (_vec, &index, &returnval);
1489  LIBMESH_CHKERR(ierr);
1490 
1491  // this return value is correct: VecMax returns a PetscReal
1492  return static_cast<Real>(returnval);
1493 }
1494 
1495 
1496 
1497 template <typename T>
1498 inline
1500 {
1501  parallel_object_only();
1502 
1503  NumericVector<T>::swap(other);
1504 
1505  PetscVector<T> & v = cast_ref<PetscVector<T> &>(other);
1506 
1507  std::swap(_vec, v._vec);
1508  std::swap(_destroy_vec_on_exit, v._destroy_vec_on_exit);
1509  std::swap(_global_to_local_map, v._global_to_local_map);
1510 
1511 #ifdef LIBMESH_HAVE_CXX11_THREAD
1512  // Only truly atomic for v... but swap() doesn't really need to be thread safe!
1513  _array_is_present = v._array_is_present.exchange(_array_is_present);
1514 #else
1515  std::swap(_array_is_present, v._array_is_present);
1516 #endif
1517 
1518  std::swap(_local_form, v._local_form);
1519  std::swap(_values, v._values);
1520 }
1521 
1522 
1523 
1524 template <typename T>
1525 inline
1527 {
1528  // The PetscInt type is used for indexing, it may be either a signed
1529  // 4-byte or 8-byte integer depending on how PETSc is configured.
1530  return std::numeric_limits<PetscInt>::max();
1531 }
1532 
1533 
1534 
1535 #ifdef LIBMESH_HAVE_CXX11
1536 static_assert(sizeof(PetscInt) == sizeof(numeric_index_type),
1537  "PETSc and libMesh integer sizes must match!");
1538 #endif
1539 
1540 
1541 inline
1543 {
1544  return reinterpret_cast<PetscInt *>(const_cast<numeric_index_type *>(p));
1545 }
1546 
1547 } // namespace libMesh
1548 
1549 
1550 #endif // #ifdef LIBMESH_HAVE_PETSC
1551 #endif // LIBMESH_PETSC_VECTOR_H
void _get_array(bool read_only) const
从 PETSc 查询数组(如果向量是幽灵的,则还包括本地形式)。
virtual Real l2_norm() const override
计算 NumericVector 的 L2 范数。
Definition: petsc_vector.C:77
PetscVector(const Parallel::Communicator &comm_in, const ParallelType type=AUTOMATIC)
无效的构造函数。维度=0。
Definition: petsc_vector.h:756
bool closed()
Checks that the library has been closed.
Definition: libmesh.C:268
virtual void localize(std::vector< T > &v_local) const override
将当前向量的数据本地化到 std::vector v_local 中。
Definition: petsc_vector.C:863
该类提供了一个良好的接口,用于访问 PETSc 的 Vec 对象。所有重写的虚拟函数都在 numeric_vector.h 中有文档说明。
Definition: petsc_vector.h:75
void add_vector_conjugate_transpose(const NumericVector< T > &v, const SparseMatrix< T > &A)
.
Definition: petsc_vector.C:299
virtual void add_vector_transpose(const NumericVector< T > &v, const SparseMatrix< T > &A) override
使用 SparseMatrix A 的共轭转置与向量 v 进行矩阵乘法,并将结果添加到当前向量。
Definition: petsc_vector.C:269
virtual void zero() override
将 PetscVector 的所有元素设置为零。
bool _destroy_vec_on_exit
此布尔值仅在接受 PETSc Vec 对象的构造函数中设置为 false。
Definition: petsc_vector.h:736
virtual numeric_index_type size() const override
获取 NumericVector 的大小(维度)。
virtual Real linfty_norm() const override
计算 NumericVector 的 Linf 范数。
Definition: petsc_vector.C:97
numeric_index_type _local_size
从 _get_array() 获取本地值的大小。
Definition: petsc_vector.h:688
virtual numeric_index_type first_local_index() const override
获取 NumericVector 的第一个本地索引。
virtual numeric_index_type local_size() const override
获取 NumericVector 的本地大小(本地维度)。
virtual void add(const numeric_index_type i, const T value) override
将索引为 i 的元素值增加 value。
Definition: petsc_vector.C:196
Vec _vec
用于保存向量元素的实际 PETSc 向量数据类型。
Definition: petsc_vector.h:659
numeric_index_type _last
最后一个本地索引。
Definition: petsc_vector.h:683
提供了不同线性代数库的向量存储方案的统一接口。
Definition: dof_map.h:67
PetscScalar * _values
指向当前 PETSc 向量值的实际数组的指针。仅当 _array_is_present 为真时,此指针才有效。 我们使用了 PETSc 的 VecGetArrayRead() 函数,它需要一个常量 Pe...
Definition: petsc_vector.h:704
bool _is_initialized
在调用 init() 后设置为 true。
virtual bool initialized() const
检查向量是否已经初始化。
bool _values_read_only
数据数组是否仅用于只读访问。
Definition: petsc_vector.h:746
virtual void get(const std::vector< numeric_index_type > &index, T *values) const override
获取指定索引的元素值。
const Number zero
.
Definition: libmesh.h:248
virtual void pointwise_divide(const NumericVector< T > &vec1, const NumericVector< T > &vec2) override
逐元素将当前向量与 vec1 相除,结果存储在当前向量中。
virtual void init(const numeric_index_type n, const numeric_index_type n_local, const bool fast=false, const ParallelType ptype=AUTOMATIC)=0
更改向量的维度为 n 。如果可能的话 ,该向量的保留内存保持不变。 如果 n==0 ,所有内存都将被释放。因此,如果要调整向量的大小并释放不需要的内存, 必须首先调用 init(0) ,然后调用 ini...
Vec vec()
获取当前向量的原始 PETSc Vec 指针。
Definition: petsc_vector.h:641
std::atomic< bool > _array_is_present
如果为 true,则当前 PETSc 向量值的实际数组当前可访问。这意味着成员 _local_form 和 _values 有效。
Definition: petsc_vector.h:666
uint8_t processor_id_type
Definition: id_types.h:104
PetscInt * numeric_petsc_cast(const numeric_index_type *p)
virtual void swap(NumericVector< T > &v) override
交换当前向量与另一个 NumericVector v 的数据。
这是一个通用的稀疏矩阵类。该类包含了必须在派生类中覆盖的纯虚拟成员。 使用一个公共的基类允许从不同的求解器包中以不同的格式统一访问稀疏矩阵。
Definition: dof_map.h:66
virtual void insert(const T *v, const std::vector< numeric_index_type > &dof_indices) override
将指定索引数组的元素设置为向量 v 的元素。
Definition: petsc_vector.C:390
const PetscScalar * _read_only_values
指向当前 PETSc 向量值的实际数组的指针。仅当 _array_is_present 为真时,此指针才有效。
Definition: petsc_vector.h:698
numeric_index_type map_global_to_local_index(const numeric_index_type i) const
virtual void pointwise_mult(const NumericVector< T > &vec1, const NumericVector< T > &vec2) override
逐元素将当前向量与 vec1 相乘,结果存储在当前向量中。
virtual Real l1_norm() const override
计算 NumericVector 的 L1 范数。
Definition: petsc_vector.C:60
Vec _local_form
用于保存幽灵向量的本地形式的 PETSc 向量数据类型。仅当向量是幽灵的且 _array_is_present 为真时,此字段的内容才有效。
Definition: petsc_vector.h:693
GlobalToLocalMap _global_to_local_map
用于将全局幽灵单元格映射到本地单元格的映射(如果不是幽灵单元格模式,则为空)。
Definition: petsc_vector.h:731
virtual void abs() override
对当前向量的所有元素取绝对值。
Definition: petsc_vector.C:459
dof_id_type numeric_index_type
Definition: id_types.h:99
bool _is_initialized
Flag that tells if init() has been called.
Definition: libmesh.C:242
virtual NumericVector< T > & operator+=(const NumericVector< T > &v) override
将当前 NumericVector 与另一个 NumericVector v 相加。
Definition: petsc_vector.C:118
void _restore_array() const
将数组(如果向量是幽灵的,则还包括本地形式)恢复到 PETSc。
virtual void conjugate() override
对 NumericVector 中的所有元素取共轭。
Definition: petsc_vector.C:182
virtual T operator()(const numeric_index_type i) const override
访问 NumericVector 对象的元素。
const PetscScalar * get_array_read() const
获取对 PETSc Vector 数据数组的只读访问权限。
virtual void localize_to_one(std::vector< T > &v_local, const processor_id_type proc_id=0) const override
将当前向量的数据本地化到 std::vector v_local 中,只包括一个进程的数据。
virtual void create_subvector(NumericVector< T > &subvector, const std::vector< numeric_index_type > &rows) const override
创建当前向量的子向量,并将其赋值给 subvector。
T indefinite_dot(const NumericVector< T > &v) const
计算 (*this) 与向量 v 的点积,不使用复数值的共轭。
Definition: petsc_vector.C:498
virtual std::size_t max_allowed_id() const override
获取当前向量允许的最大 ID。
ParallelType _type
向量的类型。
virtual numeric_index_type last_local_index() const override
获取 NumericVector 的最后一个本地索引。
virtual T sum() const override
计算 NumericVector 中的元素之和。
Definition: petsc_vector.C:44
std::mutex _petsc_get_restore_array_mutex
用于 _get_array 和 _restore_array 的互斥锁。这是对象的一部分,以减少从多个 PetscVectors 同时读取时的线程争用。
Definition: petsc_vector.h:709
void restore_array()
恢复数据数组。
virtual void set(const numeric_index_type i, const T value) override
设置索引为 i 的元素值为 value。
Definition: petsc_vector.C:149
virtual std::unique_ptr< NumericVector< T > > clone() const override
克隆该 NumericVector 的独立副本。
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
virtual void swap(NumericVector< T > &v)
交换该向量的内容与向量 v 的内容。子类应提供足够的间接性以使此操作成为 O(1) 的头部交换操作。
virtual void init(const numeric_index_type N, const numeric_index_type n_local, const bool fast=false, const ParallelType type=AUTOMATIC) override
初始化 NumericVector 对象。
Definition: petsc_vector.h:959
virtual Real max() const override
获取 NumericVector 中的最大值。
ParallelType type() const
获取向量的类型。
bool initialized()
Checks that library initialization has been done.
Definition: libmesh.C:261
numeric_index_type _first
第一个本地索引。
Definition: petsc_vector.h:676
PetscVector< T > & operator=(const PetscVector< T > &v)
复制赋值运算符。 在执行各种检查后调用 VecCopy。
Definition: petsc_vector.C:566
virtual ~PetscVector()
析构函数。
Definition: petsc_vector.h:950
virtual void reciprocal() override
对 NumericVector 中的所有元素取倒数。
Definition: petsc_vector.C:168
virtual void add_vector(const T *v, const std::vector< numeric_index_type > &dof_indices) override
向指定索引数组的元素中添加向量 v 的元素。
Definition: petsc_vector.C:215
virtual NumericVector< T > & operator*=(const NumericVector< T > &v) override
将当前向量与另一个 NumericVector v 逐元素相乘并赋值给当前向量。
Definition: petsc_vector.C:429
bool _values_manually_retrieved
数据数组是否已经通过 get_array() 或 get_array_read() 手动检索。
Definition: petsc_vector.h:741
virtual void print_matlab(const std::string &name="") const override
将当前向量的数据以 MATLAB 格式打印输出。
std::unordered_map< numeric_index_type, numeric_index_type > GlobalToLocalMap
用于将全局幽灵单元格映射到本地单元格的映射类型。
Definition: petsc_vector.h:726
virtual void scale(const T factor) override
缩放当前向量的所有元素。
Definition: petsc_vector.C:411
Vec vec() const
获取当前向量的原始 PETSc Vec 指针(const 版本)。
Definition: petsc_vector.h:652
virtual void clear() noexceptoverride
从析构函数中调用 clear(),所以它不应引发异常。
PetscScalar * get_array()
获取对 PETSc Vector 数据数组的读/写访问权限。
virtual std::unique_ptr< NumericVector< T > > zero_clone() const override
获取一个零副本的独立指针。
virtual Real min() const override
获取 NumericVector 中的最小值。
bool _is_closed
用于跟踪向量的值在在一些或全部处理器上进行插入或添加值操作后是否在所有处理器上保持一致的标志。
virtual void close() override
关闭 PetscVector。
virtual NumericVector< T > & operator/=(const NumericVector< T > &v) override
将当前向量与另一个 NumericVector v 逐元素相除并赋值给当前向量。
Definition: petsc_vector.C:444
virtual NumericVector< T > & operator-=(const NumericVector< T > &v) override
将当前 NumericVector 与另一个 NumericVector v 相减。
Definition: petsc_vector.C:134
virtual T dot(const NumericVector< T > &v) const override
计算当前向量与向量 v 的点积。
Definition: petsc_vector.C:475