petsc_vector.h
Go to the documentation of this file.00001 // The libMesh Finite Element Library. 00002 // Copyright (C) 2002-2012 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 00003 00004 // This library is free software; you can redistribute it and/or 00005 // modify it under the terms of the GNU Lesser General Public 00006 // License as published by the Free Software Foundation; either 00007 // version 2.1 of the License, or (at your option) any later version. 00008 00009 // This library is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 // Lesser General Public License for more details. 00013 00014 // You should have received a copy of the GNU Lesser General Public 00015 // License along with this library; if not, write to the Free Software 00016 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00017 00018 00019 00020 00021 #ifndef LIBMESH_PETSC_VECTOR_H 00022 #define LIBMESH_PETSC_VECTOR_H 00023 00024 00025 #include "libmesh/libmesh_config.h" 00026 00027 #ifdef LIBMESH_HAVE_PETSC 00028 00029 // Local includes 00030 #include "libmesh/numeric_vector.h" 00031 #include "libmesh/petsc_macro.h" 00032 00036 EXTERN_C_FOR_PETSC_BEGIN 00037 # include <petscvec.h> 00038 EXTERN_C_FOR_PETSC_END 00039 00040 // C++ includes 00041 #include <cstddef> 00042 #include <cstring> 00043 #include <vector> 00044 00045 namespace libMesh 00046 { 00047 00048 00049 00050 // forward declarations 00051 template <typename T> class SparseMatrix; 00052 00060 template <typename T> 00061 class PetscVector : public NumericVector<T> 00062 { 00063 public: 00064 00068 explicit 00069 PetscVector (const ParallelType type = AUTOMATIC); 00070 00074 explicit 00075 PetscVector (const numeric_index_type n, 00076 const ParallelType type = AUTOMATIC); 00077 00082 PetscVector (const numeric_index_type n, 00083 const numeric_index_type n_local, 00084 const ParallelType type = AUTOMATIC); 00085 00091 PetscVector (const numeric_index_type N, 00092 const numeric_index_type n_local, 00093 const std::vector<numeric_index_type>& ghost, 00094 const ParallelType type = AUTOMATIC); 00095 00103 PetscVector(Vec v); 00104 00109 ~PetscVector (); 00110 00114 void close (); 00115 00119 void clear (); 00120 00125 void zero (); 00126 00132 virtual AutoPtr<NumericVector<T> > zero_clone () const; 00133 00137 AutoPtr<NumericVector<T> > clone () const; 00138 00152 void init (const numeric_index_type N, 00153 const numeric_index_type n_local, 00154 const bool fast=false, 00155 const ParallelType type=AUTOMATIC); 00156 00160 void init (const numeric_index_type N, 00161 const bool fast=false, 00162 const ParallelType type=AUTOMATIC); 00163 00168 virtual void init (const numeric_index_type /*N*/, 00169 const numeric_index_type /*n_local*/, 00170 const std::vector<numeric_index_type>& /*ghost*/, 00171 const bool /*fast*/ = false, 00172 const ParallelType = AUTOMATIC); 00173 00178 virtual void init (const NumericVector<T>& other, 00179 const bool fast = false); 00180 00181 // /** 00182 // * Change the dimension to that of the 00183 // * vector \p V. The same applies as for 00184 // * the other \p init function. 00185 // * 00186 // * The elements of \p V are not copied, i.e. 00187 // * this function is the same as calling 00188 // * \p init(V.size(),fast). 00189 // */ 00190 // void init (const NumericVector<T>& V, 00191 // const bool fast=false); 00192 00196 NumericVector<T> & operator= (const T s); 00197 00201 NumericVector<T> & operator= (const NumericVector<T> &V); 00202 00206 PetscVector<T> & operator= (const PetscVector<T> &V); 00207 00211 NumericVector<T> & operator= (const std::vector<T> &v); 00212 00218 Real min () const; 00219 00225 Real max () const; 00226 00230 T sum () const; 00231 00236 Real l1_norm () const; 00237 00243 Real l2_norm () const; 00244 00250 Real linfty_norm () const; 00251 00259 numeric_index_type size () const; 00260 00265 numeric_index_type local_size() const; 00266 00271 numeric_index_type first_local_index() const; 00272 00277 numeric_index_type last_local_index() const; 00278 00285 numeric_index_type map_global_to_local_index(const numeric_index_type i) const; 00286 00290 T operator() (const numeric_index_type i) const; 00291 00297 virtual void get(const std::vector<numeric_index_type>& index, std::vector<T>& values) const; 00298 00303 NumericVector<T> & operator += (const NumericVector<T> &V); 00304 00309 NumericVector<T> & operator -= (const NumericVector<T> &V); 00310 00314 virtual void reciprocal(); 00315 00319 void set (const numeric_index_type i, const T value); 00320 00324 void add (const numeric_index_type i, const T value); 00325 00331 void add (const T s); 00332 00338 void add (const NumericVector<T>& V); 00339 00345 void add (const T a, const NumericVector<T>& v); 00346 00352 void add_vector (const std::vector<T>& v, 00353 const std::vector<numeric_index_type>& dof_indices); 00354 00361 void add_vector (const NumericVector<T>& V, 00362 const std::vector<numeric_index_type>& dof_indices); 00363 00364 00369 void add_vector (const NumericVector<T> &V, 00370 const SparseMatrix<T> &A); 00371 00378 void add_vector (const DenseVector<T>& V, 00379 const std::vector<numeric_index_type>& dof_indices); 00380 00386 void add_vector_transpose (const NumericVector<T> &V, 00387 const SparseMatrix<T> &A_trans); 00388 00394 void add_vector_conjugate_transpose (const NumericVector<T> &V, 00395 const SparseMatrix<T> &A_trans); 00396 00401 virtual void insert (const std::vector<T>& v, 00402 const std::vector<numeric_index_type>& dof_indices); 00403 00410 virtual void insert (const NumericVector<T>& V, 00411 const std::vector<numeric_index_type>& dof_indices); 00412 00418 virtual void insert (const DenseVector<T>& V, 00419 const std::vector<numeric_index_type>& dof_indices); 00420 00426 virtual void insert (const DenseSubVector<T>& V, 00427 const std::vector<numeric_index_type>& dof_indices); 00428 00429 00434 void scale (const T factor); 00435 00440 virtual void abs(); 00441 00446 virtual T dot(const NumericVector<T>&) const; 00447 00452 virtual T indefinite_dot(const NumericVector<T>&) const; 00453 00458 void localize (std::vector<T>& v_local) const; 00459 00464 void localize (NumericVector<T>& v_local) const; 00465 00471 void localize (NumericVector<T>& v_local, 00472 const std::vector<numeric_index_type>& send_list) const; 00473 00478 void localize (const numeric_index_type first_local_idx, 00479 const numeric_index_type last_local_idx, 00480 const std::vector<numeric_index_type>& send_list); 00481 00488 void localize_to_one (std::vector<T>& v_local, 00489 const processor_id_type proc_id=0) const; 00490 00495 virtual void pointwise_mult (const NumericVector<T>& vec1, 00496 const NumericVector<T>& vec2); 00497 00504 void print_matlab(const std::string name="NULL") const; 00505 00510 virtual void create_subvector(NumericVector<T>& subvector, 00511 const std::vector<numeric_index_type>& rows) const; 00512 00516 virtual void swap (NumericVector<T> &v); 00517 00523 Vec vec () { libmesh_assert (_vec); return _vec; } 00524 00525 00526 00527 private: 00528 00533 Vec _vec; 00534 00540 mutable bool _array_is_present; 00541 00542 #ifndef NDEBUG 00543 00548 mutable numeric_index_type _local_size; 00549 #endif 00550 00556 mutable Vec _local_form; 00557 00562 mutable PetscScalar* _values; 00563 00568 void _get_array(void) const; 00569 00574 void _restore_array(void) const; 00575 00579 typedef std::map<numeric_index_type,numeric_index_type> GlobalToLocalMap; 00580 00585 GlobalToLocalMap _global_to_local_map; 00586 00591 bool _destroy_vec_on_exit; 00592 }; 00593 00594 00595 /*----------------------- Inline functions ----------------------------------*/ 00596 00597 00598 00599 template <typename T> 00600 inline 00601 PetscVector<T>::PetscVector (const ParallelType ptype) 00602 : _array_is_present(false), 00603 _local_form(NULL), 00604 _values(NULL), 00605 _global_to_local_map(), 00606 _destroy_vec_on_exit(true) 00607 { 00608 this->_type = ptype; 00609 } 00610 00611 00612 00613 template <typename T> 00614 inline 00615 PetscVector<T>::PetscVector (const numeric_index_type n, 00616 const ParallelType ptype) 00617 : _array_is_present(false), 00618 _local_form(NULL), 00619 _values(NULL), 00620 _global_to_local_map(), 00621 _destroy_vec_on_exit(true) 00622 { 00623 this->init(n, n, false, ptype); 00624 } 00625 00626 00627 00628 template <typename T> 00629 inline 00630 PetscVector<T>::PetscVector (const numeric_index_type n, 00631 const numeric_index_type n_local, 00632 const ParallelType ptype) 00633 : _array_is_present(false), 00634 _local_form(NULL), 00635 _values(NULL), 00636 _global_to_local_map(), 00637 _destroy_vec_on_exit(true) 00638 { 00639 this->init(n, n_local, false, ptype); 00640 } 00641 00642 00643 00644 template <typename T> 00645 inline 00646 PetscVector<T>::PetscVector (const numeric_index_type n, 00647 const numeric_index_type n_local, 00648 const std::vector<numeric_index_type>& ghost, 00649 const ParallelType ptype) 00650 : _array_is_present(false), 00651 _local_form(NULL), 00652 _values(NULL), 00653 _global_to_local_map(), 00654 _destroy_vec_on_exit(true) 00655 { 00656 this->init(n, n_local, ghost, false, ptype); 00657 } 00658 00659 00660 00661 00662 00663 template <typename T> 00664 inline 00665 PetscVector<T>::PetscVector (Vec v) 00666 : _array_is_present(false), 00667 _local_form(NULL), 00668 _values(NULL), 00669 _global_to_local_map(), 00670 _destroy_vec_on_exit(false) 00671 { 00672 this->_vec = v; 00673 this->_is_closed = true; 00674 this->_is_initialized = true; 00675 00676 /* We need to ask PETSc about the (local to global) ghost value 00677 mapping and create the inverse mapping out of it. */ 00678 PetscErrorCode ierr=0; 00679 PetscInt petsc_local_size=0; 00680 ierr = VecGetLocalSize(_vec, &petsc_local_size); 00681 CHKERRABORT(libMesh::COMM_WORLD,ierr); 00682 00683 // Get the vector type from PETSc. 00684 // As of Petsc 3.0.0, the VecType #define lost its const-ness, so we 00685 // need to have it in the code 00686 #if PETSC_VERSION_LESS_THAN(3,0,0) || !PETSC_VERSION_RELEASE 00687 // Pre-3.0 and petsc-dev (as of October 2012) use non-const versions 00688 VecType ptype; 00689 #else 00690 const VecType ptype; 00691 #endif 00692 ierr = VecGetType(_vec, &ptype); 00693 CHKERRABORT(libMesh::COMM_WORLD,ierr); 00694 00695 if((std::strcmp(ptype,VECSHARED) == 0) || (std::strcmp(ptype,VECMPI) == 0)) 00696 { 00697 #if PETSC_VERSION_RELEASE && PETSC_VERSION_LESS_THAN(3,1,1) 00698 ISLocalToGlobalMapping mapping = _vec->mapping; 00699 #else 00700 ISLocalToGlobalMapping mapping; 00701 ierr = VecGetLocalToGlobalMapping(_vec, &mapping); 00702 CHKERRABORT(libMesh::COMM_WORLD,ierr); 00703 #endif 00704 00705 // If is a sparsely stored vector, set up our new mapping 00706 if (mapping) 00707 { 00708 const numeric_index_type my_local_size = static_cast<numeric_index_type>(petsc_local_size); 00709 const numeric_index_type ghost_begin = static_cast<numeric_index_type>(petsc_local_size); 00710 const numeric_index_type ghost_end = static_cast<numeric_index_type>(mapping->n); 00711 #if PETSC_VERSION_RELEASE && PETSC_VERSION_LESS_THAN(3,1,1) 00712 const PetscInt *indices = mapping->indices; 00713 #else 00714 const PetscInt *indices = mapping->indices; 00715 ierr = ISLocalToGlobalMappingGetIndices(mapping,&indices); 00716 CHKERRABORT(libMesh::COMM_WORLD,ierr); 00717 #endif 00718 for(numeric_index_type i=ghost_begin; i<ghost_end; i++) 00719 _global_to_local_map[indices[i]] = i-my_local_size; 00720 this->_type = GHOSTED; 00721 } 00722 else 00723 this->_type = PARALLEL; 00724 } 00725 else 00726 this->_type = SERIAL; 00727 00728 this->close(); 00729 } 00730 00731 00732 00733 00734 template <typename T> 00735 inline 00736 PetscVector<T>::~PetscVector () 00737 { 00738 this->clear (); 00739 } 00740 00741 00742 00743 template <typename T> 00744 inline 00745 void PetscVector<T>::init (const numeric_index_type n, 00746 const numeric_index_type n_local, 00747 const bool fast, 00748 const ParallelType ptype) 00749 { 00750 PetscErrorCode ierr=0; 00751 PetscInt petsc_n=static_cast<PetscInt>(n); 00752 PetscInt petsc_n_local=static_cast<PetscInt>(n_local); 00753 00754 00755 // Clear initialized vectors 00756 if (this->initialized()) 00757 this->clear(); 00758 00759 if (ptype == AUTOMATIC) 00760 { 00761 if (n == n_local) 00762 this->_type = SERIAL; 00763 else 00764 this->_type = PARALLEL; 00765 } 00766 else 00767 this->_type = ptype; 00768 00769 libmesh_assert ((this->_type==SERIAL && n==n_local) || 00770 this->_type==PARALLEL); 00771 00772 // create a sequential vector if on only 1 processor 00773 if (this->_type == SERIAL) 00774 { 00775 ierr = VecCreateSeq (PETSC_COMM_SELF, petsc_n, &_vec); 00776 CHKERRABORT(PETSC_COMM_SELF,ierr); 00777 00778 ierr = VecSetFromOptions (_vec); 00779 CHKERRABORT(PETSC_COMM_SELF,ierr); 00780 } 00781 // otherwise create an MPI-enabled vector 00782 else if (this->_type == PARALLEL) 00783 { 00784 #ifdef LIBMESH_HAVE_MPI 00785 libmesh_assert_less_equal (n_local, n); 00786 ierr = VecCreateMPI (libMesh::COMM_WORLD, petsc_n_local, petsc_n, 00787 &_vec); 00788 CHKERRABORT(libMesh::COMM_WORLD,ierr); 00789 #else 00790 libmesh_assert_equal_to (n_local, n); 00791 ierr = VecCreateSeq (PETSC_COMM_SELF, petsc_n, &_vec); 00792 CHKERRABORT(PETSC_COMM_SELF,ierr); 00793 #endif 00794 00795 ierr = VecSetFromOptions (_vec); 00796 CHKERRABORT(libMesh::COMM_WORLD,ierr); 00797 } 00798 else 00799 libmesh_error(); 00800 00801 this->_is_initialized = true; 00802 this->_is_closed = true; 00803 00804 00805 if (fast == false) 00806 this->zero (); 00807 } 00808 00809 00810 00811 template <typename T> 00812 inline 00813 void PetscVector<T>::init (const numeric_index_type n, 00814 const bool fast, 00815 const ParallelType ptype) 00816 { 00817 this->init(n,n,fast,ptype); 00818 } 00819 00820 00821 00822 template <typename T> 00823 inline 00824 void PetscVector<T>::init (const numeric_index_type n, 00825 const numeric_index_type n_local, 00826 const std::vector<numeric_index_type>& ghost, 00827 const bool fast, 00828 const ParallelType libmesh_dbg_var(ptype)) 00829 { 00830 PetscErrorCode ierr=0; 00831 PetscInt petsc_n=static_cast<PetscInt>(n); 00832 PetscInt petsc_n_local=static_cast<PetscInt>(n_local); 00833 PetscInt petsc_n_ghost=static_cast<PetscInt>(ghost.size()); 00834 00835 // If the mesh is not disjoint, every processor will either have 00836 // all the dofs, none of the dofs, or some non-zero dofs at the 00837 // boundary between processors. 00838 // 00839 // However we can't assert this, because someone might want to 00840 // construct a GHOSTED vector which doesn't include neighbor element 00841 // dofs. Boyce tried to do so in user code, and we're going to want 00842 // to do so in System::project_vector(). 00843 // 00844 // libmesh_assert(n_local == 0 || n_local == n || !ghost.empty()); 00845 00846 libmesh_assert(sizeof(PetscInt) == sizeof(numeric_index_type)); 00847 00848 PetscInt* petsc_ghost = ghost.empty() ? PETSC_NULL : 00849 const_cast<PetscInt*>(reinterpret_cast<const PetscInt*>(&ghost[0])); 00850 00851 // Clear initialized vectors 00852 if (this->initialized()) 00853 this->clear(); 00854 00855 libmesh_assert(ptype == AUTOMATIC || ptype == GHOSTED); 00856 this->_type = GHOSTED; 00857 00858 /* Make the global-to-local ghost cell map. */ 00859 for(numeric_index_type i=0; i<ghost.size(); i++) 00860 { 00861 _global_to_local_map[ghost[i]] = i; 00862 } 00863 00864 /* Create vector. */ 00865 ierr = VecCreateGhost (libMesh::COMM_WORLD, petsc_n_local, petsc_n, 00866 petsc_n_ghost, petsc_ghost, 00867 &_vec); 00868 CHKERRABORT(libMesh::COMM_WORLD,ierr); 00869 00870 ierr = VecSetFromOptions (_vec); 00871 CHKERRABORT(libMesh::COMM_WORLD,ierr); 00872 00873 this->_is_initialized = true; 00874 this->_is_closed = true; 00875 00876 if (fast == false) 00877 this->zero (); 00878 } 00879 00880 00881 00882 template <typename T> 00883 inline 00884 void PetscVector<T>::init (const NumericVector<T>& other, 00885 const bool fast) 00886 { 00887 // Clear initialized vectors 00888 if (this->initialized()) 00889 this->clear(); 00890 00891 const PetscVector<T>& v = libmesh_cast_ref<const PetscVector<T>&>(other); 00892 00893 // Other vector should restore array. 00894 if(v.initialized()) 00895 { 00896 v._restore_array(); 00897 } 00898 00899 this->_global_to_local_map = v._global_to_local_map; 00900 this->_is_closed = v._is_closed; 00901 this->_is_initialized = v._is_initialized; 00902 this->_type = v._type; 00903 00904 if (v.size() != 0) 00905 { 00906 PetscErrorCode ierr = 0; 00907 00908 ierr = VecDuplicate (v._vec, &this->_vec); 00909 CHKERRABORT(libMesh::COMM_WORLD,ierr); 00910 } 00911 00912 if (fast == false) 00913 this->zero (); 00914 } 00915 00916 00917 00918 template <typename T> 00919 inline 00920 void PetscVector<T>::close () 00921 { 00922 this->_restore_array(); 00923 00924 PetscErrorCode ierr=0; 00925 00926 ierr = VecAssemblyBegin(_vec); 00927 CHKERRABORT(libMesh::COMM_WORLD,ierr); 00928 ierr = VecAssemblyEnd(_vec); 00929 CHKERRABORT(libMesh::COMM_WORLD,ierr); 00930 00931 if(this->type() == GHOSTED) 00932 { 00933 ierr = VecGhostUpdateBegin(_vec,INSERT_VALUES,SCATTER_FORWARD); 00934 CHKERRABORT(libMesh::COMM_WORLD,ierr); 00935 ierr = VecGhostUpdateEnd(_vec,INSERT_VALUES,SCATTER_FORWARD); 00936 CHKERRABORT(libMesh::COMM_WORLD,ierr); 00937 } 00938 00939 this->_is_closed = true; 00940 } 00941 00942 00943 00944 template <typename T> 00945 inline 00946 void PetscVector<T>::clear () 00947 { 00948 if (this->initialized()) 00949 this->_restore_array(); 00950 00951 if ((this->initialized()) && (this->_destroy_vec_on_exit)) 00952 { 00953 PetscErrorCode ierr=0; 00954 00955 ierr = LibMeshVecDestroy(&_vec); 00956 CHKERRABORT(libMesh::COMM_WORLD,ierr); 00957 } 00958 00959 this->_is_closed = this->_is_initialized = false; 00960 00961 _global_to_local_map.clear(); 00962 } 00963 00964 00965 00966 template <typename T> 00967 inline 00968 void PetscVector<T>::zero () 00969 { 00970 libmesh_assert(this->closed()); 00971 00972 this->_restore_array(); 00973 00974 PetscErrorCode ierr=0; 00975 00976 PetscScalar z=0.; 00977 00978 if(this->type() != GHOSTED) 00979 { 00980 #if PETSC_VERSION_LESS_THAN(2,3,0) 00981 // 2.2.x & earlier style 00982 ierr = VecSet (&z, _vec); 00983 CHKERRABORT(libMesh::COMM_WORLD,ierr); 00984 #else 00985 // 2.3.x & newer 00986 ierr = VecSet (_vec, z); 00987 CHKERRABORT(libMesh::COMM_WORLD,ierr); 00988 #endif 00989 } 00990 else 00991 { 00992 /* Vectors that include ghost values require a special 00993 handling. */ 00994 Vec loc_vec; 00995 ierr = VecGhostGetLocalForm (_vec,&loc_vec); 00996 CHKERRABORT(libMesh::COMM_WORLD,ierr); 00997 #if PETSC_VERSION_LESS_THAN(2,3,0) 00998 // 2.2.x & earlier style 00999 ierr = VecSet (&z, loc_vec); 01000 CHKERRABORT(libMesh::COMM_WORLD,ierr); 01001 #else 01002 // 2.3.x & newer 01003 ierr = VecSet (loc_vec, z); 01004 CHKERRABORT(libMesh::COMM_WORLD,ierr); 01005 #endif 01006 ierr = VecGhostRestoreLocalForm (_vec,&loc_vec); 01007 CHKERRABORT(libMesh::COMM_WORLD,ierr); 01008 } 01009 } 01010 01011 01012 01013 template <typename T> 01014 inline 01015 AutoPtr<NumericVector<T> > PetscVector<T>::zero_clone () const 01016 { 01017 AutoPtr<NumericVector<T> > cloned_vector (new PetscVector<T>); 01018 01019 cloned_vector->init(*this); 01020 01021 return cloned_vector; 01022 } 01023 01024 01025 01026 template <typename T> 01027 inline 01028 AutoPtr<NumericVector<T> > PetscVector<T>::clone () const 01029 { 01030 AutoPtr<NumericVector<T> > cloned_vector (new PetscVector<T>); 01031 01032 cloned_vector->init(*this, true); 01033 01034 *cloned_vector = *this; 01035 01036 return cloned_vector; 01037 } 01038 01039 01040 01041 template <typename T> 01042 inline 01043 numeric_index_type PetscVector<T>::size () const 01044 { 01045 libmesh_assert (this->initialized()); 01046 01047 PetscErrorCode ierr=0, petsc_size=0; 01048 01049 if (!this->initialized()) 01050 return 0; 01051 01052 ierr = VecGetSize(_vec, &petsc_size); 01053 CHKERRABORT(libMesh::COMM_WORLD,ierr); 01054 01055 return static_cast<numeric_index_type>(petsc_size); 01056 } 01057 01058 01059 01060 template <typename T> 01061 inline 01062 numeric_index_type PetscVector<T>::local_size () const 01063 { 01064 libmesh_assert (this->initialized()); 01065 01066 PetscErrorCode ierr=0, petsc_size=0; 01067 01068 ierr = VecGetLocalSize(_vec, &petsc_size); 01069 CHKERRABORT(libMesh::COMM_WORLD,ierr); 01070 01071 return static_cast<numeric_index_type>(petsc_size); 01072 } 01073 01074 01075 01076 template <typename T> 01077 inline 01078 numeric_index_type PetscVector<T>::first_local_index () const 01079 { 01080 libmesh_assert (this->initialized()); 01081 01082 PetscErrorCode ierr=0, petsc_first=0, petsc_last=0; 01083 01084 ierr = VecGetOwnershipRange (_vec, &petsc_first, &petsc_last); 01085 CHKERRABORT(libMesh::COMM_WORLD,ierr); 01086 01087 return static_cast<numeric_index_type>(petsc_first); 01088 } 01089 01090 01091 01092 template <typename T> 01093 inline 01094 numeric_index_type PetscVector<T>::last_local_index () const 01095 { 01096 libmesh_assert (this->initialized()); 01097 01098 PetscErrorCode ierr=0, petsc_first=0, petsc_last=0; 01099 01100 ierr = VecGetOwnershipRange (_vec, &petsc_first, &petsc_last); 01101 CHKERRABORT(libMesh::COMM_WORLD,ierr); 01102 01103 return static_cast<numeric_index_type>(petsc_last); 01104 } 01105 01106 01107 01108 template <typename T> 01109 inline 01110 numeric_index_type PetscVector<T>::map_global_to_local_index (const numeric_index_type i) const 01111 { 01112 libmesh_assert (this->initialized()); 01113 01114 PetscErrorCode ierr=0, petsc_first=0, petsc_last=0; 01115 ierr = VecGetOwnershipRange (_vec, &petsc_first, &petsc_last); 01116 CHKERRABORT(libMesh::COMM_WORLD,ierr); 01117 const numeric_index_type first = static_cast<numeric_index_type>(petsc_first); 01118 const numeric_index_type last = static_cast<numeric_index_type>(petsc_last); 01119 01120 if((i>=first) && (i<last)) 01121 { 01122 return i-first; 01123 } 01124 01125 GlobalToLocalMap::const_iterator it = _global_to_local_map.find(i); 01126 #ifndef NDEBUG 01127 const GlobalToLocalMap::const_iterator end = _global_to_local_map.end(); 01128 if (it == end) 01129 { 01130 std::ostringstream error_message; 01131 error_message << "No index " << i << " in ghosted vector.\n" 01132 << "Vector contains [" << first << ',' << last << ")\n"; 01133 GlobalToLocalMap::const_iterator b = _global_to_local_map.begin(); 01134 if (b == end) 01135 { 01136 error_message << "And empty ghost array.\n"; 01137 } 01138 else 01139 { 01140 error_message << "And ghost array {" << b->first; 01141 for (b++; b != end; b++) 01142 error_message << ',' << b->first; 01143 error_message << "}\n"; 01144 } 01145 01146 std::cerr << error_message.str(); 01147 01148 libmesh_error(); 01149 } 01150 libmesh_assert (it != _global_to_local_map.end()); 01151 #endif 01152 return it->second+last-first; 01153 } 01154 01155 01156 01157 template <typename T> 01158 inline 01159 T PetscVector<T>::operator() (const numeric_index_type i) const 01160 { 01161 this->_get_array(); 01162 01163 const numeric_index_type local_index = this->map_global_to_local_index(i); 01164 01165 #ifndef NDEBUG 01166 if(this->type() == GHOSTED) 01167 { 01168 libmesh_assert_less (local_index, _local_size); 01169 } 01170 #endif 01171 01172 return static_cast<T>(_values[local_index]); 01173 } 01174 01175 01176 01177 template <typename T> 01178 inline 01179 void PetscVector<T>::get(const std::vector<numeric_index_type>& index, std::vector<T>& values) const 01180 { 01181 this->_get_array(); 01182 01183 const std::size_t num = index.size(); 01184 values.resize(num); 01185 01186 for(std::size_t i=0; i<num; i++) 01187 { 01188 const numeric_index_type local_index = this->map_global_to_local_index(index[i]); 01189 #ifndef NDEBUG 01190 if(this->type() == GHOSTED) 01191 { 01192 libmesh_assert_less (local_index, _local_size); 01193 } 01194 #endif 01195 values[i] = static_cast<T>(_values[local_index]); 01196 } 01197 } 01198 01199 01200 01201 template <typename T> 01202 inline 01203 Real PetscVector<T>::min () const 01204 { 01205 this->_restore_array(); 01206 01207 PetscErrorCode ierr=0; 01208 PetscInt index=0; 01209 PetscReal returnval=0.; 01210 01211 ierr = VecMin (_vec, &index, &returnval); 01212 CHKERRABORT(libMesh::COMM_WORLD,ierr); 01213 01214 // this return value is correct: VecMin returns a PetscReal 01215 return static_cast<Real>(returnval); 01216 } 01217 01218 01219 01220 template <typename T> 01221 inline 01222 Real PetscVector<T>::max() const 01223 { 01224 this->_restore_array(); 01225 01226 PetscErrorCode ierr=0; 01227 PetscInt index=0; 01228 PetscReal returnval=0.; 01229 01230 ierr = VecMax (_vec, &index, &returnval); 01231 CHKERRABORT(libMesh::COMM_WORLD,ierr); 01232 01233 // this return value is correct: VecMax returns a PetscReal 01234 return static_cast<Real>(returnval); 01235 } 01236 01237 01238 01239 template <typename T> 01240 inline 01241 void PetscVector<T>::swap (NumericVector<T> &other) 01242 { 01243 NumericVector<T>::swap(other); 01244 01245 PetscVector<T>& v = libmesh_cast_ref<PetscVector<T>&>(other); 01246 01247 std::swap(_vec, v._vec); 01248 std::swap(_destroy_vec_on_exit, v._destroy_vec_on_exit); 01249 std::swap(_global_to_local_map, v._global_to_local_map); 01250 std::swap(_array_is_present, v._array_is_present); 01251 std::swap(_local_form, v._local_form); 01252 std::swap(_values, v._values); 01253 } 01254 01255 01256 01257 template <typename T> 01258 inline 01259 void PetscVector<T>::_get_array(void) const 01260 { 01261 libmesh_assert (this->initialized()); 01262 if(!_array_is_present) 01263 { 01264 PetscErrorCode ierr=0; 01265 if(this->type() != GHOSTED) 01266 { 01267 ierr = VecGetArray(_vec, &_values); 01268 CHKERRABORT(libMesh::COMM_WORLD,ierr); 01269 } 01270 else 01271 { 01272 ierr = VecGhostGetLocalForm (_vec,&_local_form); 01273 CHKERRABORT(libMesh::COMM_WORLD,ierr); 01274 ierr = VecGetArray(_local_form, &_values); 01275 CHKERRABORT(libMesh::COMM_WORLD,ierr); 01276 #ifndef NDEBUG 01277 PetscInt my_local_size = 0; 01278 ierr = VecGetLocalSize(_local_form, &my_local_size); 01279 CHKERRABORT(libMesh::COMM_WORLD,ierr); 01280 _local_size = static_cast<numeric_index_type>(my_local_size); 01281 #endif 01282 } 01283 _array_is_present = true; 01284 } 01285 } 01286 01287 01288 01289 template <typename T> 01290 inline 01291 void PetscVector<T>::_restore_array(void) const 01292 { 01293 libmesh_assert (this->initialized()); 01294 if(_array_is_present) 01295 { 01296 PetscErrorCode ierr=0; 01297 if(this->type() != GHOSTED) 01298 { 01299 ierr = VecRestoreArray (_vec, &_values); 01300 CHKERRABORT(libMesh::COMM_WORLD,ierr); 01301 _values = NULL; 01302 } 01303 else 01304 { 01305 ierr = VecRestoreArray (_local_form, &_values); 01306 CHKERRABORT(libMesh::COMM_WORLD,ierr); 01307 _values = NULL; 01308 ierr = VecGhostRestoreLocalForm (_vec,&_local_form); 01309 CHKERRABORT(libMesh::COMM_WORLD,ierr); 01310 _local_form = NULL; 01311 #ifndef NDEBUG 01312 _local_size = 0; 01313 #endif 01314 } 01315 _array_is_present = false; 01316 } 01317 } 01318 01319 01320 } // namespace libMesh 01321 01322 01323 #endif // #ifdef LIBMESH_HAVE_PETSC 01324 #endif // LIBMESH_PETSC_VECTOR_H 01325 01326 01327 01328 01329 01330 01331 01332
Site Created By: libMesh Developers
Last modified: February 05 2013 19:54:48 UTC
Hosted By: