distributed_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 #include "libmesh/libmesh_common.h" 00021 00022 00023 00024 #ifndef LIBMESH_DISTRIBUTED_VECTOR_H 00025 #define LIBMESH_DISTRIBUTED_VECTOR_H 00026 00027 // Local includes 00028 #include "libmesh/numeric_vector.h" 00029 #include "libmesh/parallel.h" 00030 00031 // C++ includes 00032 #include <vector> 00033 #include <algorithm> 00034 #include <limits> 00035 00036 namespace libMesh 00037 { 00038 00039 00040 00051 template <typename T> 00052 class DistributedVector : public NumericVector<T> 00053 { 00054 public: 00055 00059 explicit 00060 DistributedVector (const ParallelType = AUTOMATIC); 00061 00065 explicit 00066 DistributedVector (const numeric_index_type n, 00067 const ParallelType ptype = AUTOMATIC); 00068 00073 DistributedVector (const numeric_index_type n, 00074 const numeric_index_type n_local, 00075 const ParallelType ptype = AUTOMATIC); 00076 00082 DistributedVector (const numeric_index_type N, 00083 const numeric_index_type n_local, 00084 const std::vector<numeric_index_type>& ghost, 00085 const ParallelType ptype = AUTOMATIC); 00086 00091 ~DistributedVector (); 00092 00096 void close (); 00097 00101 void clear (); 00102 00107 void zero (); 00108 00114 virtual AutoPtr<NumericVector<T> > zero_clone () const; 00115 00119 AutoPtr<NumericVector<T> > clone () const; 00120 00133 void init (const numeric_index_type N, 00134 const numeric_index_type n_local, 00135 const bool fast=false, 00136 const ParallelType ptype=AUTOMATIC); 00137 00141 void init (const numeric_index_type N, 00142 const bool fast=false, 00143 const ParallelType ptype=AUTOMATIC); 00144 00149 virtual void init (const numeric_index_type /*N*/, 00150 const numeric_index_type /*n_local*/, 00151 const std::vector<numeric_index_type>& /*ghost*/, 00152 const bool /*fast*/ = false, 00153 const ParallelType = AUTOMATIC); 00154 00159 virtual void init (const NumericVector<T>& other, 00160 const bool fast = false); 00161 00165 NumericVector<T> & operator= (const T s); 00166 00170 NumericVector<T> & operator= (const NumericVector<T> &V); 00171 00175 DistributedVector<T> & operator= (const DistributedVector<T> &V); 00176 00180 NumericVector<T> & operator= (const std::vector<T> &v); 00181 00187 Real min () const; 00188 00194 Real max () const; 00195 00199 T sum() const; 00200 00205 Real l1_norm () const; 00206 00212 Real l2_norm () const; 00213 00219 Real linfty_norm () const; 00220 00228 numeric_index_type size () const; 00229 00234 numeric_index_type local_size() const; 00235 00240 numeric_index_type first_local_index() const; 00241 00246 numeric_index_type last_local_index() const; 00247 00251 T operator() (const numeric_index_type i) const; 00252 00257 NumericVector<T> & operator += (const NumericVector<T> &V); 00258 00263 NumericVector<T> & operator -= (const NumericVector<T> &V); 00264 00268 virtual void reciprocal(); 00269 00273 void set (const numeric_index_type i, const T value); 00274 00278 void add (const numeric_index_type i, const T value); 00279 00285 void add (const T s); 00286 00292 void add (const NumericVector<T>& V); 00293 00299 void add (const T a, const NumericVector<T>& v); 00300 00306 void add_vector (const std::vector<T>& v, 00307 const std::vector<numeric_index_type>& dof_indices); 00308 00315 void add_vector (const NumericVector<T>& V, 00316 const std::vector<numeric_index_type>& dof_indices); 00317 00324 void add_vector (const NumericVector<T>&, 00325 const SparseMatrix<T>&) 00326 { libmesh_error(); } 00327 00334 void add_vector (const DenseVector<T>& V, 00335 const std::vector<numeric_index_type>& dof_indices); 00336 00343 void add_vector_transpose (const NumericVector<T>&, 00344 const SparseMatrix<T>&) 00345 { libmesh_error(); } 00346 00351 virtual void insert (const std::vector<T>& v, 00352 const std::vector<numeric_index_type>& dof_indices); 00353 00360 virtual void insert (const NumericVector<T>& V, 00361 const std::vector<numeric_index_type>& dof_indices); 00362 00368 virtual void insert (const DenseVector<T>& V, 00369 const std::vector<numeric_index_type>& dof_indices); 00370 00376 virtual void insert (const DenseSubVector<T>& V, 00377 const std::vector<numeric_index_type>& dof_indices); 00378 00383 void scale (const T factor); 00384 00389 virtual void abs(); 00390 00394 virtual T dot(const NumericVector<T>& V) const; 00395 00400 void localize (std::vector<T>& v_local) const; 00401 00406 void localize (NumericVector<T>& v_local) const; 00407 00413 void localize (NumericVector<T>& v_local, 00414 const std::vector<numeric_index_type>& send_list) const; 00415 00420 void localize (const numeric_index_type first_local_idx, 00421 const numeric_index_type last_local_idx, 00422 const std::vector<numeric_index_type>& send_list); 00423 00430 void localize_to_one (std::vector<T>& v_local, 00431 const processor_id_type proc_id=0) const; 00432 00437 virtual void pointwise_mult (const NumericVector<T>& vec1, 00438 const NumericVector<T>& vec2); 00439 00443 virtual void swap (NumericVector<T> &v); 00444 00445 private: 00446 00451 std::vector<T> _values; 00452 00456 numeric_index_type _global_size; 00457 00461 numeric_index_type _local_size; 00462 00466 numeric_index_type _first_local_index; 00467 00471 numeric_index_type _last_local_index; 00472 }; 00473 00474 00475 //-------------------------------------------------------------------------- 00476 // DistributedVector inline methods 00477 template <typename T> 00478 inline 00479 DistributedVector<T>::DistributedVector (const ParallelType ptype) : 00480 _global_size (0), 00481 _local_size (0), 00482 _first_local_index(0), 00483 _last_local_index (0) 00484 { 00485 this->_type = ptype; 00486 } 00487 00488 00489 00490 template <typename T> 00491 inline 00492 DistributedVector<T>::DistributedVector (const numeric_index_type n, 00493 const ParallelType ptype) 00494 { 00495 this->init(n, n, false, ptype); 00496 } 00497 00498 00499 00500 template <typename T> 00501 inline 00502 DistributedVector<T>::DistributedVector (const numeric_index_type n, 00503 const numeric_index_type n_local, 00504 const ParallelType ptype) 00505 { 00506 this->init(n, n_local, false, ptype); 00507 } 00508 00509 00510 00511 template <typename T> 00512 inline 00513 DistributedVector<T>::DistributedVector (const numeric_index_type n, 00514 const numeric_index_type n_local, 00515 const std::vector<numeric_index_type>& ghost, 00516 const ParallelType ptype) 00517 { 00518 this->init(n, n_local, ghost, false, ptype); 00519 } 00520 00521 00522 00523 template <typename T> 00524 inline 00525 DistributedVector<T>::~DistributedVector () 00526 { 00527 this->clear (); 00528 } 00529 00530 00531 00532 template <typename T> 00533 inline 00534 void DistributedVector<T>::init (const numeric_index_type n, 00535 const numeric_index_type n_local, 00536 const bool fast, 00537 const ParallelType ptype) 00538 { 00539 // This function must be run on all processors at once 00540 parallel_only(); 00541 00542 libmesh_assert_less_equal (n_local, n); 00543 00544 if (ptype == AUTOMATIC) 00545 { 00546 if (n == n_local) 00547 this->_type = SERIAL; 00548 else 00549 this->_type = PARALLEL; 00550 } 00551 else 00552 this->_type = ptype; 00553 00554 libmesh_assert ((this->_type==SERIAL && n==n_local) || 00555 this->_type==PARALLEL); 00556 00557 // Clear the data structures if already initialized 00558 if (this->initialized()) 00559 this->clear(); 00560 00561 // Initialize data structures 00562 _values.resize(n_local); 00563 _local_size = n_local; 00564 _global_size = n; 00565 00566 _first_local_index = 0; 00567 00568 #ifdef LIBMESH_HAVE_MPI 00569 00570 std::vector<numeric_index_type> local_sizes (libMesh::n_processors(), 0); 00571 00572 local_sizes[libMesh::processor_id()] = n_local; 00573 00574 CommWorld.sum(local_sizes); 00575 00576 // _first_local_index is the sum of _local_size 00577 // for all processor ids less than ours 00578 for (processor_id_type p=0; p!=libMesh::processor_id(); p++) 00579 _first_local_index += local_sizes[p]; 00580 00581 00582 # ifdef DEBUG 00583 // Make sure all the local sizes sum up to the global 00584 // size, otherwise there is big trouble! 00585 numeric_index_type dbg_sum=0; 00586 00587 for (processor_id_type p=0; p!=libMesh::n_processors(); p++) 00588 dbg_sum += local_sizes[p]; 00589 00590 libmesh_assert_equal_to (dbg_sum, n); 00591 00592 # endif 00593 00594 #else 00595 00596 // No other options without MPI! 00597 if (n != n_local) 00598 { 00599 libMesh::err << "ERROR: MPI is required for n != n_local!" 00600 << std::endl; 00601 libmesh_error(); 00602 } 00603 00604 #endif 00605 00606 _last_local_index = _first_local_index + n_local; 00607 00608 // Set the initialized flag 00609 this->_is_initialized = true; 00610 00611 // Zero the components unless directed otherwise 00612 if (!fast) 00613 this->zero(); 00614 } 00615 00616 00617 template <typename T> 00618 inline 00619 void DistributedVector<T>::init (const numeric_index_type n, 00620 const numeric_index_type n_local, 00621 const std::vector<numeric_index_type>& /*ghost*/, 00622 const bool fast, 00623 const ParallelType ptype) 00624 { 00625 // TODO: we shouldn't ignore the ghost sparsity pattern 00626 this->init(n, n_local, fast, ptype); 00627 } 00628 00629 00630 00631 /* Default implementation for solver packages for which ghosted 00632 vectors are not yet implemented. */ 00633 template <class T> 00634 void DistributedVector<T>::init (const NumericVector<T>& other, 00635 const bool fast) 00636 { 00637 this->init(other.size(),other.local_size(),fast,other.type()); 00638 } 00639 00640 00641 00642 template <typename T> 00643 inline 00644 void DistributedVector<T>::init (const numeric_index_type n, 00645 const bool fast, 00646 const ParallelType ptype) 00647 { 00648 this->init(n,n,fast,ptype); 00649 } 00650 00651 00652 00653 template <typename T> 00654 inline 00655 void DistributedVector<T>::close () 00656 { 00657 libmesh_assert (this->initialized()); 00658 00659 this->_is_closed = true; 00660 } 00661 00662 00663 00664 template <typename T> 00665 inline 00666 void DistributedVector<T>::clear () 00667 { 00668 _values.clear(); 00669 00670 _global_size = 00671 _local_size = 00672 _first_local_index = 00673 _last_local_index = 0; 00674 00675 00676 this->_is_closed = this->_is_initialized = false; 00677 } 00678 00679 00680 00681 template <typename T> 00682 inline 00683 void DistributedVector<T>::zero () 00684 { 00685 libmesh_assert (this->initialized()); 00686 libmesh_assert_equal_to (_values.size(), _local_size); 00687 libmesh_assert_equal_to ((_last_local_index - _first_local_index), _local_size); 00688 00689 std::fill (_values.begin(), 00690 _values.end(), 00691 0.); 00692 } 00693 00694 00695 00696 template <typename T> 00697 inline 00698 AutoPtr<NumericVector<T> > DistributedVector<T>::zero_clone () const 00699 { 00700 AutoPtr<NumericVector<T> > cloned_vector (new DistributedVector<T>); 00701 00702 cloned_vector->init(*this); 00703 00704 return cloned_vector; 00705 } 00706 00707 00708 00709 template <typename T> 00710 inline 00711 AutoPtr<NumericVector<T> > DistributedVector<T>::clone () const 00712 { 00713 AutoPtr<NumericVector<T> > cloned_vector (new DistributedVector<T>); 00714 00715 cloned_vector->init(*this, true); 00716 00717 *cloned_vector = *this; 00718 00719 return cloned_vector; 00720 } 00721 00722 00723 00724 template <typename T> 00725 inline 00726 numeric_index_type DistributedVector<T>::size () const 00727 { 00728 libmesh_assert (this->initialized()); 00729 libmesh_assert_equal_to (_values.size(), _local_size); 00730 libmesh_assert_equal_to ((_last_local_index - _first_local_index), _local_size); 00731 00732 return _global_size; 00733 } 00734 00735 00736 00737 template <typename T> 00738 inline 00739 numeric_index_type DistributedVector<T>::local_size () const 00740 { 00741 libmesh_assert (this->initialized()); 00742 libmesh_assert_equal_to (_values.size(), _local_size); 00743 libmesh_assert_equal_to ((_last_local_index - _first_local_index), _local_size); 00744 00745 return _local_size; 00746 } 00747 00748 00749 00750 template <typename T> 00751 inline 00752 numeric_index_type DistributedVector<T>::first_local_index () const 00753 { 00754 libmesh_assert (this->initialized()); 00755 libmesh_assert_equal_to (_values.size(), _local_size); 00756 libmesh_assert_equal_to ((_last_local_index - _first_local_index), _local_size); 00757 00758 return _first_local_index; 00759 } 00760 00761 00762 00763 template <typename T> 00764 inline 00765 numeric_index_type DistributedVector<T>::last_local_index () const 00766 { 00767 libmesh_assert (this->initialized()); 00768 libmesh_assert_equal_to (_values.size(), _local_size); 00769 libmesh_assert_equal_to ((_last_local_index - _first_local_index), _local_size); 00770 00771 return _last_local_index; 00772 } 00773 00774 00775 00776 template <typename T> 00777 inline 00778 T DistributedVector<T>::operator() (const numeric_index_type i) const 00779 { 00780 libmesh_assert (this->initialized()); 00781 libmesh_assert_equal_to (_values.size(), _local_size); 00782 libmesh_assert_equal_to ((_last_local_index - _first_local_index), _local_size); 00783 libmesh_assert ( ((i >= first_local_index()) && 00784 (i < last_local_index())) ); 00785 00786 return _values[i - _first_local_index]; 00787 } 00788 00789 00790 00791 template <typename T> 00792 inline 00793 void DistributedVector<T>::set (const numeric_index_type i, const T value) 00794 { 00795 libmesh_assert (this->initialized()); 00796 libmesh_assert_equal_to (_values.size(), _local_size); 00797 libmesh_assert_equal_to ((_last_local_index - _first_local_index), _local_size); 00798 libmesh_assert_less (i, size()); 00799 libmesh_assert_less (i-first_local_index(), local_size()); 00800 00801 _values[i - _first_local_index] = value; 00802 } 00803 00804 00805 00806 template <typename T> 00807 inline 00808 void DistributedVector<T>::add (const numeric_index_type i, const T value) 00809 { 00810 libmesh_assert (this->initialized()); 00811 libmesh_assert_equal_to (_values.size(), _local_size); 00812 libmesh_assert_equal_to ((_last_local_index - _first_local_index), _local_size); 00813 libmesh_assert_less (i, size()); 00814 libmesh_assert_less (i-first_local_index(), local_size()); 00815 00816 _values[i - _first_local_index] += value; 00817 } 00818 00819 00820 00821 template <typename T> 00822 inline 00823 Real DistributedVector<T>::min () const 00824 { 00825 // This function must be run on all processors at once 00826 parallel_only(); 00827 00828 libmesh_assert (this->initialized()); 00829 libmesh_assert_equal_to (_values.size(), _local_size); 00830 libmesh_assert_equal_to ((_last_local_index - _first_local_index), _local_size); 00831 00832 Real local_min = _values.size() ? 00833 libmesh_real(_values[0]) : std::numeric_limits<Real>::max(); 00834 for (numeric_index_type i = 1; i < _values.size(); ++i) 00835 local_min = std::min(libmesh_real(_values[i]), local_min); 00836 00837 CommWorld.min(local_min); 00838 00839 return local_min; 00840 } 00841 00842 00843 00844 template <typename T> 00845 inline 00846 Real DistributedVector<T>::max() const 00847 { 00848 // This function must be run on all processors at once 00849 parallel_only(); 00850 00851 libmesh_assert (this->initialized()); 00852 libmesh_assert_equal_to (_values.size(), _local_size); 00853 libmesh_assert_equal_to ((_last_local_index - _first_local_index), _local_size); 00854 00855 Real local_max = _values.size() ? 00856 libmesh_real(_values[0]) : -std::numeric_limits<Real>::max(); 00857 for (numeric_index_type i = 1; i < _values.size(); ++i) 00858 local_max = std::max(libmesh_real(_values[i]), local_max); 00859 00860 CommWorld.max(local_max); 00861 00862 return local_max; 00863 } 00864 00865 00866 template <typename T> 00867 inline 00868 void DistributedVector<T>::swap (NumericVector<T> &other) 00869 { 00870 DistributedVector<T>& v = libmesh_cast_ref<DistributedVector<T>&>(other); 00871 00872 std::swap(_global_size, v._global_size); 00873 std::swap(_local_size, v._local_size); 00874 std::swap(_first_local_index, v._first_local_index); 00875 std::swap(_last_local_index, v._last_local_index); 00876 00877 // This should be O(1) with any reasonable STL implementation 00878 std::swap(_values, v._values); 00879 } 00880 00881 } // namespace libMesh 00882 00883 00884 #endif // LIBMESH_DISTRIBUTED_VECTOR_H
Site Created By: libMesh Developers
Last modified: February 05 2013 19:54:46 UTC
Hosted By: