$extrastylesheet
00001 // The libMesh Finite Element Library. 00002 // Copyright (C) 2002-2014 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 #ifndef LIBMESH_TRILINOS_EPETRA_VECTOR_H 00019 #define LIBMESH_TRILINOS_EPETRA_VECTOR_H 00020 00021 00022 #include "libmesh/libmesh_common.h" 00023 00024 00025 #ifdef LIBMESH_HAVE_TRILINOS 00026 00027 // Local includes 00028 #include "libmesh/numeric_vector.h" 00029 #include "libmesh/parallel.h" 00030 00031 // Trilinos includes 00032 #include <Epetra_CombineMode.h> 00033 #include <Epetra_Map.h> 00034 #include <Epetra_MultiVector.h> 00035 #include <Epetra_Vector.h> 00036 #include <Epetra_MpiComm.h> 00037 00038 // C++ includes 00039 #include <cstddef> 00040 #include <vector> 00041 00042 // Forward declarations 00043 class Epetra_IntSerialDenseVector; 00044 class Epetra_SerialDenseVector; 00045 00046 namespace libMesh 00047 { 00048 00049 // forward declarations 00050 template <typename T> class SparseMatrix; 00051 00059 template <typename T> 00060 class EpetraVector : public NumericVector<T> 00061 { 00062 public: 00063 00067 explicit 00068 EpetraVector (const Parallel::Communicator &comm, 00069 const ParallelType type = AUTOMATIC); 00070 00074 explicit 00075 EpetraVector (const Parallel::Communicator &comm, 00076 const numeric_index_type n, 00077 const ParallelType type = AUTOMATIC); 00078 00083 EpetraVector (const Parallel::Communicator &comm, 00084 const numeric_index_type n, 00085 const numeric_index_type n_local, 00086 const ParallelType type = AUTOMATIC); 00087 00093 EpetraVector (const Parallel::Communicator &comm, 00094 const numeric_index_type N, 00095 const numeric_index_type n_local, 00096 const std::vector<numeric_index_type>& ghost, 00097 const ParallelType type = AUTOMATIC); 00098 00106 EpetraVector(Epetra_Vector & v, 00107 const Parallel::Communicator &comm 00108 LIBMESH_CAN_DEFAULT_TO_COMMWORLD); 00109 00114 ~EpetraVector (); 00115 00119 void close (); 00120 00124 void clear (); 00125 00130 void zero (); 00131 00137 virtual UniquePtr<NumericVector<T> > zero_clone () const; 00138 00142 UniquePtr<NumericVector<T> > clone () const; 00143 00157 void init (const numeric_index_type N, 00158 const numeric_index_type n_local, 00159 const bool fast=false, 00160 const ParallelType type=AUTOMATIC); 00161 00165 void init (const numeric_index_type N, 00166 const bool fast=false, 00167 const ParallelType type=AUTOMATIC); 00168 00173 void init (const numeric_index_type /*N*/, 00174 const numeric_index_type /*n_local*/, 00175 const std::vector<numeric_index_type>& /*ghost*/, 00176 const bool /*fast*/ = false, 00177 const ParallelType = AUTOMATIC); 00178 00183 virtual void init (const NumericVector<T>& other, 00184 const bool fast = false); 00185 00186 // /** 00187 // * Change the dimension to that of the 00188 // * vector \p V. The same applies as for 00189 // * the other \p init function. 00190 // * 00191 // * The elements of \p V are not copied, i.e. 00192 // * this function is the same as calling 00193 // * \p init(V.size(),fast). 00194 // */ 00195 // void init (const NumericVector<T>& V, 00196 // const bool fast=false); 00197 00201 NumericVector<T> & operator= (const T s); 00202 00206 NumericVector<T> & operator= (const NumericVector<T> &V); 00207 00211 EpetraVector<T> & operator= (const EpetraVector<T> &V); 00212 00216 NumericVector<T> & operator= (const std::vector<T> &v); 00217 00223 Real min () const; 00224 00230 Real max () const; 00231 00235 T sum () const; 00236 00241 Real l1_norm () const; 00242 00248 Real l2_norm () const; 00249 00255 Real linfty_norm () const; 00256 00264 numeric_index_type size () const; 00265 00270 numeric_index_type local_size() const; 00271 00276 numeric_index_type first_local_index() const; 00277 00282 numeric_index_type last_local_index() const; 00283 00287 T operator() (const numeric_index_type i) const; 00288 00293 NumericVector<T> & operator += (const NumericVector<T> &V); 00294 00299 NumericVector<T> & operator -= (const NumericVector<T> &V); 00300 00304 virtual NumericVector<T> & operator /= (NumericVector<T> & v); 00305 00309 virtual void reciprocal(); 00310 00316 virtual void conjugate(); 00317 00321 void set (const numeric_index_type i, const T value); 00322 00326 void add (const numeric_index_type i, const T value); 00327 00333 void add (const T s); 00334 00340 void add (const NumericVector<T>& V); 00341 00347 void add (const T a, const NumericVector<T>& v); 00348 00353 using NumericVector<T>::add_vector; 00354 00359 void add_vector (const T* v, 00360 const std::vector<numeric_index_type>& dof_indices); 00361 00366 void add_vector (const NumericVector<T> &V, 00367 const SparseMatrix<T> &A); 00368 00373 void add_vector_transpose (const NumericVector<T> &V, 00374 const SparseMatrix<T> &A_trans); 00375 00380 using NumericVector<T>::insert; 00381 00386 virtual void insert (const T* v, 00387 const std::vector<numeric_index_type>& dof_indices); 00388 00393 void scale (const T factor); 00394 00399 virtual void abs(); 00400 00401 00405 virtual T dot(const NumericVector<T>& V) const; 00406 00411 void localize (std::vector<T>& v_local) const; 00412 00417 void localize (NumericVector<T>& v_local) const; 00418 00424 void localize (NumericVector<T>& v_local, 00425 const std::vector<numeric_index_type>& send_list) const; 00426 00431 void localize (const numeric_index_type first_local_idx, 00432 const numeric_index_type last_local_idx, 00433 const std::vector<numeric_index_type>& send_list); 00434 00441 void localize_to_one (std::vector<T>& v_local, 00442 const processor_id_type proc_id=0) const; 00443 00448 virtual void pointwise_mult (const NumericVector<T>& vec1, 00449 const NumericVector<T>& vec2); 00450 00455 virtual void create_subvector (NumericVector<T>& subvector, 00456 const std::vector<numeric_index_type>& rows) const; 00457 00461 virtual void swap (NumericVector<T> &v); 00462 00468 Epetra_Vector * vec () { libmesh_assert(_vec); return _vec; } 00469 00470 private: 00471 00476 Epetra_Vector * _vec; 00477 00481 Epetra_Map * _map; 00482 00487 bool _destroy_vec_on_exit; 00488 00489 00490 00491 /********************************************************************* 00492 * The following were copied (and slightly modified) from 00493 * Epetra_FEVector.h in order to allow us to use a standard 00494 * Epetra_Vector... which is more compatible with other Trilinos 00495 * packages such as NOX. All of this code is originally under LGPL 00496 *********************************************************************/ 00497 00501 int SumIntoGlobalValues(int numIDs, const int* GIDs, const double* values); 00502 00512 int SumIntoGlobalValues(const Epetra_IntSerialDenseVector& GIDs, 00513 const Epetra_SerialDenseVector& values); 00514 00518 int ReplaceGlobalValues(int numIDs, const int* GIDs, const double* values); 00519 00529 int ReplaceGlobalValues(const Epetra_IntSerialDenseVector& GIDs, 00530 const Epetra_SerialDenseVector& values); 00531 00532 int SumIntoGlobalValues(int numIDs, const int* GIDs, 00533 const int* numValuesPerID, 00534 const double* values); 00535 00536 int ReplaceGlobalValues(int numIDs, const int* GIDs, 00537 const int* numValuesPerID, 00538 const double* values); 00539 00547 int GlobalAssemble(Epetra_CombineMode mode = Add); 00548 00551 void setIgnoreNonLocalEntries(bool flag) { 00552 ignoreNonLocalEntries_ = flag; 00553 } 00554 00555 void FEoperatorequals(const EpetraVector& source); 00556 00557 int inputValues(int numIDs, 00558 const int* GIDs, const double* values, 00559 bool accumulate); 00560 00561 int inputValues(int numIDs, 00562 const int* GIDs, const int* numValuesPerID, 00563 const double* values, 00564 bool accumulate); 00565 00566 int inputNonlocalValue(int GID, double value, bool accumulate); 00567 00568 int inputNonlocalValues(int GID, int numValues, const double* values, 00569 bool accumulate); 00570 00571 void destroyNonlocalData(); 00572 00573 int myFirstID_; 00574 int myNumIDs_; 00575 double* myCoefs_; 00576 00577 int* nonlocalIDs_; 00578 int* nonlocalElementSize_; 00579 int numNonlocalIDs_; 00580 int allocatedNonlocalLength_; 00581 double** nonlocalCoefs_; 00582 00588 unsigned char last_edit; 00589 00590 bool ignoreNonLocalEntries_; 00591 }; 00592 00593 00594 /*----------------------- Inline functions ----------------------------------*/ 00595 00596 00597 00598 template <typename T> 00599 inline 00600 EpetraVector<T>::EpetraVector (const Parallel::Communicator &comm, 00601 const ParallelType type) 00602 : NumericVector<T>(comm, type), 00603 _destroy_vec_on_exit(true), 00604 myFirstID_(0), 00605 myNumIDs_(0), 00606 myCoefs_(NULL), 00607 nonlocalIDs_(NULL), 00608 nonlocalElementSize_(NULL), 00609 numNonlocalIDs_(0), 00610 allocatedNonlocalLength_(0), 00611 nonlocalCoefs_(NULL), 00612 last_edit(0), 00613 ignoreNonLocalEntries_(false) 00614 { 00615 this->_type = type; 00616 } 00617 00618 00619 00620 template <typename T> 00621 inline 00622 EpetraVector<T>::EpetraVector (const Parallel::Communicator &comm, 00623 const numeric_index_type n, 00624 const ParallelType type) 00625 : NumericVector<T>(comm, type), 00626 _destroy_vec_on_exit(true), 00627 myFirstID_(0), 00628 myNumIDs_(0), 00629 myCoefs_(NULL), 00630 nonlocalIDs_(NULL), 00631 nonlocalElementSize_(NULL), 00632 numNonlocalIDs_(0), 00633 allocatedNonlocalLength_(0), 00634 nonlocalCoefs_(NULL), 00635 last_edit(0), 00636 ignoreNonLocalEntries_(false) 00637 00638 { 00639 this->init(n, n, false, type); 00640 } 00641 00642 00643 00644 template <typename T> 00645 inline 00646 EpetraVector<T>::EpetraVector (const Parallel::Communicator &comm, 00647 const numeric_index_type n, 00648 const numeric_index_type n_local, 00649 const ParallelType type) 00650 : NumericVector<T>(comm, type), 00651 _destroy_vec_on_exit(true), 00652 myFirstID_(0), 00653 myNumIDs_(0), 00654 myCoefs_(NULL), 00655 nonlocalIDs_(NULL), 00656 nonlocalElementSize_(NULL), 00657 numNonlocalIDs_(0), 00658 allocatedNonlocalLength_(0), 00659 nonlocalCoefs_(NULL), 00660 last_edit(0), 00661 ignoreNonLocalEntries_(false) 00662 { 00663 this->init(n, n_local, false, type); 00664 } 00665 00666 00667 00668 00669 template <typename T> 00670 inline 00671 EpetraVector<T>::EpetraVector(Epetra_Vector & v, 00672 const Parallel::Communicator &comm) 00673 : NumericVector<T>(comm, AUTOMATIC), 00674 _destroy_vec_on_exit(false), 00675 myFirstID_(0), 00676 myNumIDs_(0), 00677 myCoefs_(NULL), 00678 nonlocalIDs_(NULL), 00679 nonlocalElementSize_(NULL), 00680 numNonlocalIDs_(0), 00681 allocatedNonlocalLength_(0), 00682 nonlocalCoefs_(NULL), 00683 last_edit(0), 00684 ignoreNonLocalEntries_(false) 00685 { 00686 _vec = &v; 00687 00688 this->_type = PARALLEL; // FIXME - need to determine this from v! 00689 00690 myFirstID_ = _vec->Map().MinMyGID(); 00691 myNumIDs_ = _vec->Map().NumMyElements(); 00692 00693 _map = new Epetra_Map(_vec->GlobalLength(), 00694 _vec->MyLength(), 00695 0, 00696 Epetra_MpiComm (this->comm().get())); 00697 00698 //Currently we impose the restriction that NumVectors==1, so we won't 00699 //need the LDA argument when calling ExtractView. Hence the "dummy" arg. 00700 int dummy; 00701 _vec->ExtractView(&myCoefs_, &dummy); 00702 00703 this->_is_closed = true; 00704 this->_is_initialized = true; 00705 } 00706 00707 00708 00709 template <typename T> 00710 inline 00711 EpetraVector<T>::EpetraVector (const Parallel::Communicator &comm, 00712 const numeric_index_type n, 00713 const numeric_index_type n_local, 00714 const std::vector<numeric_index_type>& ghost, 00715 const ParallelType type) 00716 : NumericVector<T>(comm, AUTOMATIC), 00717 _destroy_vec_on_exit(true), 00718 myFirstID_(0), 00719 myNumIDs_(0), 00720 myCoefs_(NULL), 00721 nonlocalIDs_(NULL), 00722 nonlocalElementSize_(NULL), 00723 numNonlocalIDs_(0), 00724 allocatedNonlocalLength_(0), 00725 nonlocalCoefs_(NULL), 00726 last_edit(0), 00727 ignoreNonLocalEntries_(false) 00728 { 00729 this->init(n, n_local, ghost, false, type); 00730 } 00731 00732 00733 00734 /* Default implementation for solver packages for which ghosted 00735 vectors are not yet implemented. */ 00736 template <class T> 00737 void EpetraVector<T>::init (const NumericVector<T>& other, 00738 const bool fast) 00739 { 00740 this->init(other.size(),other.local_size(),fast,other.type()); 00741 } 00742 00743 00744 00745 template <typename T> 00746 inline 00747 EpetraVector<T>::~EpetraVector () 00748 { 00749 this->clear (); 00750 } 00751 00752 00753 00754 template <typename T> 00755 inline 00756 void EpetraVector<T>::init (const numeric_index_type n, 00757 const numeric_index_type n_local, 00758 const bool fast, 00759 const ParallelType type) 00760 { 00761 // We default to allocating n_local local storage 00762 numeric_index_type my_n_local = n_local; 00763 00764 if (type == AUTOMATIC) 00765 { 00766 if (n == n_local) 00767 this->_type = SERIAL; 00768 else 00769 this->_type = PARALLEL; 00770 } 00771 else if (type == GHOSTED) 00772 { 00773 // We don't yet support GHOSTED Epetra vectors, so to get the 00774 // same functionality we need a SERIAL vector with local 00775 // storage allocated for every entry. 00776 this->_type = SERIAL; 00777 my_n_local = n; 00778 } 00779 else 00780 this->_type = type; 00781 00782 libmesh_assert ((this->_type==SERIAL && n==my_n_local) || 00783 this->_type==PARALLEL); 00784 00785 _map = new Epetra_Map(static_cast<int>(n), 00786 my_n_local, 00787 0, 00788 Epetra_MpiComm (this->comm().get())); 00789 00790 _vec = new Epetra_Vector(*_map); 00791 00792 myFirstID_ = _vec->Map().MinMyGID(); 00793 myNumIDs_ = _vec->Map().NumMyElements(); 00794 00795 //Currently we impose the restriction that NumVectors==1, so we won't 00796 //need the LDA argument when calling ExtractView. Hence the "dummy" arg. 00797 int dummy; 00798 _vec->ExtractView(&myCoefs_, &dummy); 00799 00800 this->_is_initialized = true; 00801 this->_is_closed = true; 00802 this->last_edit = 0; 00803 00804 if (fast == false) 00805 this->zero (); 00806 } 00807 00808 00809 template <typename T> 00810 inline 00811 void EpetraVector<T>::init (const numeric_index_type n, 00812 const numeric_index_type n_local, 00813 const std::vector<numeric_index_type>& /*ghost*/, 00814 const bool fast, 00815 const ParallelType type) 00816 { 00817 // TODO: we shouldn't ignore the ghost sparsity pattern 00818 this->init(n, n_local, fast, type); 00819 } 00820 00821 00822 00823 template <typename T> 00824 inline 00825 void EpetraVector<T>::init (const numeric_index_type n, 00826 const bool fast, 00827 const ParallelType type) 00828 { 00829 this->init(n,n,fast,type); 00830 } 00831 00832 00833 00834 template <typename T> 00835 inline 00836 void EpetraVector<T>::close () 00837 { 00838 libmesh_assert (this->initialized()); 00839 00840 // Are we adding or inserting? 00841 unsigned char global_last_edit = last_edit; 00842 this->comm().max(global_last_edit); 00843 libmesh_assert(!last_edit || last_edit == global_last_edit); 00844 00845 if (global_last_edit == 1) 00846 this->GlobalAssemble(Insert); 00847 else if (global_last_edit == 2) 00848 this->GlobalAssemble(Add); 00849 else 00850 libmesh_assert(!global_last_edit); 00851 00852 this->_is_closed = true; 00853 this->last_edit = 0; 00854 } 00855 00856 00857 00858 template <typename T> 00859 inline 00860 void EpetraVector<T>::clear () 00861 { 00862 if (this->initialized()) 00863 { 00864 // We might just be an interface to a user-provided _vec 00865 if (this->_destroy_vec_on_exit) 00866 { 00867 delete _vec; 00868 _vec = NULL; 00869 } 00870 00871 // But we currently always own our own _map 00872 delete _map; 00873 _map = NULL; 00874 } 00875 00876 this->_is_closed = this->_is_initialized = false; 00877 } 00878 00879 00880 00881 template <typename T> 00882 inline 00883 void EpetraVector<T>::zero () 00884 { 00885 libmesh_assert (this->initialized()); 00886 libmesh_assert (this->closed()); 00887 00888 _vec->PutScalar(0.0); 00889 } 00890 00891 00892 00893 template <typename T> 00894 inline 00895 UniquePtr<NumericVector<T> > EpetraVector<T>::zero_clone () const 00896 { 00897 UniquePtr<NumericVector<T> > cloned_vector 00898 (new EpetraVector<T>(this->comm(), AUTOMATIC)); 00899 00900 cloned_vector->init(*this); 00901 00902 return cloned_vector; 00903 } 00904 00905 00906 00907 template <typename T> 00908 inline 00909 UniquePtr<NumericVector<T> > EpetraVector<T>::clone () const 00910 { 00911 UniquePtr<NumericVector<T> > cloned_vector 00912 (new EpetraVector<T>(this->comm(), AUTOMATIC)); 00913 00914 cloned_vector->init(*this, true); 00915 00916 *cloned_vector = *this; 00917 00918 return cloned_vector; 00919 } 00920 00921 00922 00923 template <typename T> 00924 inline 00925 numeric_index_type EpetraVector<T>::size () const 00926 { 00927 libmesh_assert (this->initialized()); 00928 00929 return _vec->GlobalLength(); 00930 } 00931 00932 00933 00934 template <typename T> 00935 inline 00936 numeric_index_type EpetraVector<T>::local_size () const 00937 { 00938 libmesh_assert (this->initialized()); 00939 00940 return _vec->MyLength(); 00941 } 00942 00943 template <typename T> 00944 inline 00945 numeric_index_type EpetraVector<T>::first_local_index () const 00946 { 00947 libmesh_assert (this->initialized()); 00948 00949 return _vec->Map().MinMyGID(); 00950 } 00951 00952 00953 00954 template <typename T> 00955 inline 00956 numeric_index_type EpetraVector<T>::last_local_index () const 00957 { 00958 libmesh_assert (this->initialized()); 00959 00960 return _vec->Map().MaxMyGID()+1; 00961 } 00962 00963 00964 template <typename T> 00965 inline 00966 T EpetraVector<T>::operator() (const numeric_index_type i) const 00967 { 00968 libmesh_assert (this->initialized()); 00969 libmesh_assert ( ((i >= this->first_local_index()) && 00970 (i < this->last_local_index())) ); 00971 00972 return (*_vec)[i-this->first_local_index()]; 00973 } 00974 00975 00976 00977 template <typename T> 00978 inline 00979 Real EpetraVector<T>::min () const 00980 { 00981 libmesh_assert (this->initialized()); 00982 00983 T value; 00984 00985 _vec->MinValue(&value); 00986 00987 return value; 00988 } 00989 00990 00991 00992 template <typename T> 00993 inline 00994 Real EpetraVector<T>::max() const 00995 { 00996 libmesh_assert (this->initialized()); 00997 00998 T value; 00999 01000 _vec->MaxValue(&value); 01001 01002 return value; 01003 } 01004 01005 01006 01007 template <typename T> 01008 inline 01009 void EpetraVector<T>::swap (NumericVector<T> &other) 01010 { 01011 NumericVector<T>::swap(other); 01012 01013 EpetraVector<T>& v = cast_ref<EpetraVector<T>&>(other); 01014 01015 std::swap(_vec, v._vec); 01016 std::swap(_map, v._map); 01017 std::swap(_destroy_vec_on_exit, v._destroy_vec_on_exit); 01018 std::swap(myFirstID_, v.myFirstID_); 01019 std::swap(myNumIDs_, v.myNumIDs_); 01020 std::swap(myCoefs_, v.myCoefs_); 01021 std::swap(nonlocalIDs_, v.nonlocalIDs_); 01022 std::swap(nonlocalElementSize_, v.nonlocalElementSize_); 01023 std::swap(numNonlocalIDs_, v.numNonlocalIDs_); 01024 std::swap(allocatedNonlocalLength_, v.allocatedNonlocalLength_); 01025 std::swap(nonlocalCoefs_, v.nonlocalCoefs_); 01026 std::swap(last_edit, v.last_edit); 01027 std::swap(ignoreNonLocalEntries_, v.ignoreNonLocalEntries_); 01028 } 01029 01030 } // namespace libMesh 01031 01032 01033 #endif // #ifdef HAVE_EPETRA 01034 #endif // LIBMESH_TRILINOS_EPETRA_VECTOR_H