21 #ifndef LIBMESH_PETSC_VECTOR_H
22 #define LIBMESH_PETSC_VECTOR_H
25 #include "libmesh/libmesh_config.h"
27 #ifdef LIBMESH_HAVE_PETSC
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"
40 # define LIBMESH_SAW_I
44 # undef I // Avoid complex.h contamination
51 #include <unordered_map>
56 #include <condition_variable>
62 template <
typename T>
class SparseMatrix;
86 PetscVector (
const Parallel::Communicator & comm_in,
87 const ParallelType
type = AUTOMATIC);
97 PetscVector (
const Parallel::Communicator & comm_in,
99 const ParallelType
type = AUTOMATIC);
109 PetscVector (
const Parallel::Communicator & comm_in,
112 const ParallelType
type = AUTOMATIC);
123 PetscVector (
const Parallel::Communicator & comm_in,
126 const std::vector<numeric_index_type> & ghost,
127 const ParallelType
type = AUTOMATIC);
137 const Parallel::Communicator & comm_in);
163 virtual void close ()
override;
168 virtual void clear () noexcept
override;
173 virtual void zero ()
override;
181 virtual std::unique_ptr<NumericVector<T>>
zero_clone ()
const override;
188 virtual std::unique_ptr<NumericVector<T>>
clone ()
const override;
200 const bool fast=
false,
201 const ParallelType
type=AUTOMATIC)
override;
211 const bool fast=
false,
212 const ParallelType
type=AUTOMATIC)
override;
225 const std::vector<numeric_index_type> & ghost,
226 const bool fast =
false,
227 const ParallelType = AUTOMATIC)
override;
236 const bool fast =
false)
override;
267 virtual Real min ()
const override;
274 virtual Real max ()
const override;
281 virtual T
sum ()
const override;
354 virtual void get(
const std::vector<numeric_index_type> & index,
355 T * values)
const override;
411 const T value)
override;
420 const T value)
override;
427 virtual void add (
const T s)
override;
456 const std::vector<numeric_index_type> & dof_indices)
override;
498 virtual void insert (
const T * v,
499 const std::vector<numeric_index_type> & dof_indices)
override;
506 virtual void scale (
const T factor)
override;
525 virtual void abs()
override;
548 virtual void localize (std::vector<T> & v_local)
const override;
564 const std::vector<numeric_index_type> & indices)
const override;
575 const std::vector<numeric_index_type> & send_list)
override;
607 virtual void print_matlab(
const std::string & name =
"")
const override;
616 const std::vector<numeric_index_type> & rows)
const override;
664 #ifdef LIBMESH_HAVE_CXX11_THREAD
754 template <
typename T>
758 _array_is_present(false),
761 _local_form(nullptr),
763 _global_to_local_map(),
764 _destroy_vec_on_exit(true),
765 _values_manually_retrieved(false),
766 _values_read_only(false)
773 template <
typename T>
777 const ParallelType ptype) :
779 _array_is_present(false),
780 _local_form(nullptr),
782 _global_to_local_map(),
783 _destroy_vec_on_exit(true),
784 _values_manually_retrieved(false),
785 _values_read_only(false)
787 this->
init(n, n,
false, ptype);
792 template <
typename T>
797 const ParallelType ptype) :
799 _array_is_present(false),
800 _local_form(nullptr),
802 _global_to_local_map(),
803 _destroy_vec_on_exit(true),
804 _values_manually_retrieved(false),
805 _values_read_only(false)
807 this->
init(n, n_local,
false, ptype);
812 template <
typename T>
817 const std::vector<numeric_index_type> & ghost,
818 const ParallelType ptype) :
820 _array_is_present(false),
821 _local_form(nullptr),
823 _global_to_local_map(),
824 _destroy_vec_on_exit(true),
825 _values_manually_retrieved(false),
826 _values_read_only(false)
828 this->
init(n, n_local, ghost,
false, ptype);
842 template <
typename T>
845 const Parallel::Communicator & comm_in) :
847 _array_is_present(false),
848 _local_form(nullptr),
850 _global_to_local_map(),
851 _destroy_vec_on_exit(false),
852 _values_manually_retrieved(false),
853 _values_read_only(false)
860 PetscErrorCode ierr=0;
861 PetscInt petsc_local_size=0;
862 ierr = VecGetLocalSize(
_vec, &petsc_local_size);
863 LIBMESH_CHKERR(ierr);
867 ierr = VecGetType(
_vec, &ptype);
868 LIBMESH_CHKERR(ierr);
870 #if PETSC_RELEASE_GREATER_EQUALS(3, 21, 0)
872 if (std::strcmp(ptype, VECMPI) == 0)
875 ierr = VecGhostGetGhostIS(
_vec, &ghostis);
876 LIBMESH_CHKERR(ierr);
879 ierr = VecGhostGetLocalForm(
_vec, &localrep);
880 LIBMESH_CHKERR(ierr);
885 if (ghostis && localrep)
888 ierr = ISGetSize(ghostis, &ghost_size);
889 LIBMESH_CHKERR(ierr);
891 const PetscInt * indices;
892 ierr = ISGetIndices(ghostis, &indices);
893 LIBMESH_CHKERR(ierr);
895 for (
const auto i : make_range(ghost_size))
897 this->
_type = GHOSTED;
898 ierr = ISRestoreIndices(ghostis, &indices);
899 LIBMESH_CHKERR(ierr);
902 else if (std::strcmp(ptype,VECSHARED) == 0)
904 if ((std::strcmp(ptype,VECSHARED) == 0) || (std::strcmp(ptype,VECMPI) == 0))
907 ISLocalToGlobalMapping mapping;
908 ierr = VecGetLocalToGlobalMapping(
_vec, &mapping);
909 LIBMESH_CHKERR(ierr);
912 ierr = VecGhostGetLocalForm(
_vec,&localrep);
913 LIBMESH_CHKERR(ierr);
917 if (mapping && localrep)
922 ierr = ISLocalToGlobalMappingGetSize(mapping, &n);
923 LIBMESH_CHKERR(ierr);
926 const PetscInt * indices;
927 ierr = ISLocalToGlobalMappingGetIndices(mapping,&indices);
928 LIBMESH_CHKERR(ierr);
932 this->
_type = GHOSTED;
933 ierr = ISLocalToGlobalMappingRestoreIndices(mapping, &indices);
934 LIBMESH_CHKERR(ierr);
937 this->
_type = PARALLEL;
939 ierr = VecGhostRestoreLocalForm(
_vec,&localrep);
940 LIBMESH_CHKERR(ierr);
943 this->
_type = SERIAL;
948 template <
typename T>
957 template <
typename T>
962 const ParallelType ptype)
964 parallel_object_only();
966 PetscErrorCode ierr=0;
967 PetscInt petsc_n=
static_cast<PetscInt
>(n);
973 if (ptype == AUTOMATIC)
976 this->_type = SERIAL;
978 this->_type = PARALLEL;
983 libmesh_assert ((this->_type==SERIAL && n==n_local) ||
984 this->_type==PARALLEL);
987 if (this->_type == SERIAL)
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);
995 else if (this->_type == PARALLEL)
997 #ifdef LIBMESH_HAVE_MPI
998 PetscInt petsc_n_local=cast_int<PetscInt>(n_local);
999 libmesh_assert_less_equal (n_local, n);
1001 ierr = VecCreate(this->comm().
get(), &_vec);LIBMESH_CHKERR(ierr);
1002 ierr = VecSetSizes(_vec, petsc_n_local, petsc_n); LIBMESH_CHKERR(ierr);
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);
1008 ierr = VecSetFromOptions (_vec);
1009 LIBMESH_CHKERR(ierr);
1012 libmesh_error_msg(
"Unsupported type " << Utility::enum_to_string(this->_type));
1015 this->_is_closed =
true;
1024 template <
typename T>
1028 const ParallelType ptype)
1030 this->init(n,n,fast,ptype);
1035 template <
typename T>
1039 const std::vector<numeric_index_type> & ghost,
1041 const ParallelType libmesh_dbg_var(ptype))
1043 parallel_object_only();
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());
1058 PetscInt * petsc_ghost = ghost.empty() ? LIBMESH_PETSC_NULLPTR :
1059 const_cast<PetscInt *
>(
reinterpret_cast<const PetscInt *
>(ghost.data()));
1065 libmesh_assert(ptype == AUTOMATIC || ptype == GHOSTED);
1066 this->_type = GHOSTED;
1069 for (
auto i : index_range(ghost))
1071 _global_to_local_map[ghost[i]] = i;
1075 ierr = VecCreateGhost (this->comm().
get(), petsc_n_local, petsc_n,
1076 petsc_n_ghost, petsc_ghost,
1078 LIBMESH_CHKERR(ierr);
1082 ierr = PetscObjectAppendOptionsPrefix((PetscObject)_vec,
"ghost_");
1083 LIBMESH_CHKERR(ierr);
1085 ierr = VecSetFromOptions (_vec);
1086 LIBMESH_CHKERR(ierr);
1089 this->_is_closed =
true;
1096 template <
typename T>
1101 parallel_object_only();
1107 const PetscVector<T> & v = cast_ref<const PetscVector<T> &>(other);
1118 this->_is_closed =
true;
1121 this->_type = v.
_type;
1124 PetscErrorCode ierr = VecDuplicate (v.
_vec, &this->_vec);
1125 LIBMESH_CHKERR(ierr);
1133 template <
typename T>
1137 parallel_object_only();
1139 this->_restore_array();
1141 VecAssemblyBeginEnd(this->comm(), _vec);
1143 if (this->type() == GHOSTED)
1144 VecGhostUpdateBeginEnd(this->comm(), _vec, INSERT_VALUES, SCATTER_FORWARD);
1146 this->_is_closed =
true;
1151 template <
typename T>
1155 exceptionless_parallel_object_only();
1158 this->_restore_array();
1160 if ((this->
initialized()) && (this->_destroy_vec_on_exit))
1164 PetscErrorCode ierr = VecDestroy(&_vec);
1166 libmesh_warning(
"Warning: VecDestroy returned a non-zero error code which we ignored.");
1171 _global_to_local_map.clear();
1176 template <
typename T>
1180 parallel_object_only();
1182 libmesh_assert(this->
closed());
1184 this->_restore_array();
1186 PetscErrorCode ierr=0;
1190 if (this->type() != GHOSTED)
1192 ierr = VecSet (_vec, z);
1193 LIBMESH_CHKERR(ierr);
1200 ierr = VecGhostGetLocalForm (_vec,&loc_vec);
1201 LIBMESH_CHKERR(ierr);
1203 ierr = VecSet (loc_vec, z);
1204 LIBMESH_CHKERR(ierr);
1206 ierr = VecGhostRestoreLocalForm (_vec,&loc_vec);
1207 LIBMESH_CHKERR(ierr);
1213 template <
typename T>
1218 cloned_vector->
init(*
this);
1219 return std::unique_ptr<NumericVector<T>>(cloned_vector);
1224 template <
typename T>
1229 cloned_vector->
init(*
this,
true);
1230 *cloned_vector = *
this;
1231 return std::unique_ptr<NumericVector<T>>(cloned_vector);
1236 template <
typename T>
1242 PetscErrorCode ierr=0;
1243 PetscInt petsc_size=0;
1248 ierr = VecGetSize(_vec, &petsc_size);
1249 LIBMESH_CHKERR(ierr);
1256 template <
typename T>
1262 PetscErrorCode ierr=0;
1263 PetscInt petsc_size=0;
1265 ierr = VecGetLocalSize(_vec, &petsc_size);
1266 LIBMESH_CHKERR(ierr);
1273 template <
typename T>
1281 if (_array_is_present)
1285 PetscErrorCode ierr=0;
1286 PetscInt petsc_first=0, petsc_last=0;
1287 ierr = VecGetOwnershipRange (_vec, &petsc_first, &petsc_last);
1288 LIBMESH_CHKERR(ierr);
1297 template <
typename T>
1305 if (_array_is_present)
1309 PetscErrorCode ierr=0;
1310 PetscInt petsc_first=0, petsc_last=0;
1311 ierr = VecGetOwnershipRange (_vec, &petsc_first, &petsc_last);
1312 LIBMESH_CHKERR(ierr);
1321 template <
typename T>
1330 if (_array_is_present)
1337 PetscErrorCode ierr=0;
1338 PetscInt petsc_first=0, petsc_last=0;
1339 ierr = VecGetOwnershipRange (_vec, &petsc_first, &petsc_last);
1340 LIBMESH_CHKERR(ierr);
1346 if ((i>=first) && (i<last))
1351 GlobalToLocalMap::const_iterator it = _global_to_local_map.find(i);
1353 const GlobalToLocalMap::const_iterator end = _global_to_local_map.end();
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();
1362 error_message <<
"And empty ghost array.\n";
1366 error_message <<
"And ghost array {" << b->first;
1367 for (++b; b != end; ++b)
1368 error_message <<
',' << b->first;
1369 error_message <<
"}\n";
1372 libmesh_error_msg(error_message.str());
1374 libmesh_assert (it != _global_to_local_map.end());
1376 return it->second+last-first;
1381 template <
typename T>
1385 this->_get_array(
true);
1390 if (this->type() == GHOSTED)
1392 libmesh_assert_less (local_index, _local_size);
1396 return static_cast<T
>(_read_only_values[local_index]);
1401 template <
typename T>
1406 this->_get_array(
true);
1408 const std::size_t num = index.size();
1410 for (std::size_t i=0; i<num; i++)
1414 if (this->type() == GHOSTED)
1416 libmesh_assert_less (local_index, _local_size);
1419 values[i] =
static_cast<T
>(_read_only_values[local_index]);
1424 template <
typename T>
1429 _values_manually_retrieved =
true;
1435 template <
typename T>
1440 _values_manually_retrieved =
true;
1442 return _read_only_values;
1445 template <
typename T>
1451 _values_manually_retrieved =
false;
1455 template <
typename T>
1459 parallel_object_only();
1461 this->_restore_array();
1463 PetscErrorCode ierr=0;
1465 PetscReal returnval=0.;
1467 ierr = VecMin (_vec, &index, &returnval);
1468 LIBMESH_CHKERR(ierr);
1471 return static_cast<Real>(returnval);
1476 template <
typename T>
1480 parallel_object_only();
1482 this->_restore_array();
1484 PetscErrorCode ierr=0;
1486 PetscReal returnval=0.;
1488 ierr = VecMax (_vec, &index, &returnval);
1489 LIBMESH_CHKERR(ierr);
1492 return static_cast<Real>(returnval);
1497 template <
typename T>
1501 parallel_object_only();
1507 std::swap(_vec, v.
_vec);
1511 #ifdef LIBMESH_HAVE_CXX11_THREAD
1519 std::swap(_values, v.
_values);
1524 template <
typename T>
1530 return std::numeric_limits<PetscInt>::max();
1535 #ifdef LIBMESH_HAVE_CXX11
1537 "PETSc and libMesh integer sizes must match!");
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 范数。
PetscVector(const Parallel::Communicator &comm_in, const ParallelType type=AUTOMATIC)
无效的构造函数。维度=0。
bool closed()
Checks that the library has been closed.
virtual void localize(std::vector< T > &v_local) const override
将当前向量的数据本地化到 std::vector v_local 中。
该类提供了一个良好的接口,用于访问 PETSc 的 Vec 对象。所有重写的虚拟函数都在 numeric_vector.h 中有文档说明。
void add_vector_conjugate_transpose(const NumericVector< T > &v, const SparseMatrix< T > &A)
.
virtual void add_vector_transpose(const NumericVector< T > &v, const SparseMatrix< T > &A) override
使用 SparseMatrix A 的共轭转置与向量 v 进行矩阵乘法,并将结果添加到当前向量。
virtual void zero() override
将 PetscVector 的所有元素设置为零。
bool _destroy_vec_on_exit
此布尔值仅在接受 PETSc Vec 对象的构造函数中设置为 false。
virtual numeric_index_type size() const override
获取 NumericVector 的大小(维度)。
virtual Real linfty_norm() const override
计算 NumericVector 的 Linf 范数。
numeric_index_type _local_size
从 _get_array() 获取本地值的大小。
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。
Vec _vec
用于保存向量元素的实际 PETSc 向量数据类型。
numeric_index_type _last
最后一个本地索引。
PetscScalar * _values
指向当前 PETSc 向量值的实际数组的指针。仅当 _array_is_present 为真时,此指针才有效。 我们使用了 PETSc 的 VecGetArrayRead() 函数,它需要一个常量 Pe...
bool _is_initialized
在调用 init() 后设置为 true。
virtual bool initialized() const
检查向量是否已经初始化。
bool _values_read_only
数据数组是否仅用于只读访问。
virtual void get(const std::vector< numeric_index_type > &index, T *values) const override
获取指定索引的元素值。
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 指针。
std::atomic< bool > _array_is_present
如果为 true,则当前 PETSc 向量值的实际数组当前可访问。这意味着成员 _local_form 和 _values 有效。
uint8_t processor_id_type
PetscInt * numeric_petsc_cast(const numeric_index_type *p)
virtual void swap(NumericVector< T > &v) override
交换当前向量与另一个 NumericVector v 的数据。
这是一个通用的稀疏矩阵类。该类包含了必须在派生类中覆盖的纯虚拟成员。 使用一个公共的基类允许从不同的求解器包中以不同的格式统一访问稀疏矩阵。
virtual void insert(const T *v, const std::vector< numeric_index_type > &dof_indices) override
将指定索引数组的元素设置为向量 v 的元素。
const PetscScalar * _read_only_values
指向当前 PETSc 向量值的实际数组的指针。仅当 _array_is_present 为真时,此指针才有效。
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 范数。
Vec _local_form
用于保存幽灵向量的本地形式的 PETSc 向量数据类型。仅当向量是幽灵的且 _array_is_present 为真时,此字段的内容才有效。
GlobalToLocalMap _global_to_local_map
用于将全局幽灵单元格映射到本地单元格的映射(如果不是幽灵单元格模式,则为空)。
virtual void abs() override
对当前向量的所有元素取绝对值。
dof_id_type numeric_index_type
bool _is_initialized
Flag that tells if init() has been called.
virtual NumericVector< T > & operator+=(const NumericVector< T > &v) override
将当前 NumericVector 与另一个 NumericVector v 相加。
void _restore_array() const
将数组(如果向量是幽灵的,则还包括本地形式)恢复到 PETSc。
virtual void conjugate() override
对 NumericVector 中的所有元素取共轭。
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 的点积,不使用复数值的共轭。
virtual std::size_t max_allowed_id() const override
获取当前向量允许的最大 ID。
virtual numeric_index_type last_local_index() const override
获取 NumericVector 的最后一个本地索引。
virtual T sum() const override
计算 NumericVector 中的元素之和。
std::mutex _petsc_get_restore_array_mutex
用于 _get_array 和 _restore_array 的互斥锁。这是对象的一部分,以减少从多个 PetscVectors 同时读取时的线程争用。
void restore_array()
恢复数据数组。
virtual void set(const numeric_index_type i, const T value) override
设置索引为 i 的元素值为 value。
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 对象。
virtual Real max() const override
获取 NumericVector 中的最大值。
ParallelType type() const
获取向量的类型。
bool initialized()
Checks that library initialization has been done.
numeric_index_type _first
第一个本地索引。
PetscVector< T > & operator=(const PetscVector< T > &v)
复制赋值运算符。 在执行各种检查后调用 VecCopy。
virtual ~PetscVector()
析构函数。
virtual void reciprocal() override
对 NumericVector 中的所有元素取倒数。
virtual void add_vector(const T *v, const std::vector< numeric_index_type > &dof_indices) override
向指定索引数组的元素中添加向量 v 的元素。
virtual NumericVector< T > & operator*=(const NumericVector< T > &v) override
将当前向量与另一个 NumericVector v 逐元素相乘并赋值给当前向量。
bool _values_manually_retrieved
数据数组是否已经通过 get_array() 或 get_array_read() 手动检索。
virtual void print_matlab(const std::string &name="") const override
将当前向量的数据以 MATLAB 格式打印输出。
std::unordered_map< numeric_index_type, numeric_index_type > GlobalToLocalMap
用于将全局幽灵单元格映射到本地单元格的映射类型。
virtual void scale(const T factor) override
缩放当前向量的所有元素。
Vec vec() const
获取当前向量的原始 PETSc Vec 指针(const 版本)。
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 逐元素相除并赋值给当前向量。
virtual NumericVector< T > & operator-=(const NumericVector< T > &v) override
将当前 NumericVector 与另一个 NumericVector v 相减。
virtual T dot(const NumericVector< T > &v) const override
计算当前向量与向量 v 的点积。