$extrastylesheet
petsc_vector.C
Go to the documentation of this file.
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 
00019 
00020 // C++ includes
00021 
00022 // Local Includes
00023 #include "libmesh/petsc_vector.h"
00024 #include "libmesh/petsc_matrix.h"
00025 
00026 #ifdef LIBMESH_HAVE_PETSC
00027 
00028 #include "libmesh/dense_subvector.h"
00029 #include "libmesh/dense_vector.h"
00030 #include "libmesh/parallel.h"
00031 #include "libmesh/petsc_macro.h"
00032 #include "libmesh/utility.h"
00033 
00034 namespace libMesh
00035 {
00036 
00037 
00038 
00039 //-----------------------------------------------------------------------
00040 // PetscVector members
00041 
00042 template <typename T>
00043 T PetscVector<T>::sum () const
00044 {
00045   this->_restore_array();
00046   libmesh_assert(this->closed());
00047 
00048   PetscErrorCode ierr=0;
00049   PetscScalar value=0.;
00050 
00051   ierr = VecSum (_vec, &value);
00052   LIBMESH_CHKERRABORT(ierr);
00053 
00054   return static_cast<T>(value);
00055 }
00056 
00057 
00058 template <typename T>
00059 Real PetscVector<T>::l1_norm () const
00060 {
00061   this->_restore_array();
00062   libmesh_assert(this->closed());
00063 
00064   PetscErrorCode ierr=0;
00065   PetscReal value=0.;
00066 
00067   ierr = VecNorm (_vec, NORM_1, &value);
00068   LIBMESH_CHKERRABORT(ierr);
00069 
00070   return static_cast<Real>(value);
00071 }
00072 
00073 
00074 
00075 template <typename T>
00076 Real PetscVector<T>::l2_norm () const
00077 {
00078   this->_restore_array();
00079   libmesh_assert(this->closed());
00080 
00081   PetscErrorCode ierr=0;
00082   PetscReal value=0.;
00083 
00084   ierr = VecNorm (_vec, NORM_2, &value);
00085   LIBMESH_CHKERRABORT(ierr);
00086 
00087   return static_cast<Real>(value);
00088 }
00089 
00090 
00091 
00092 
00093 template <typename T>
00094 Real PetscVector<T>::linfty_norm () const
00095 {
00096   this->_restore_array();
00097   libmesh_assert(this->closed());
00098 
00099   PetscErrorCode ierr=0;
00100   PetscReal value=0.;
00101 
00102   ierr = VecNorm (_vec, NORM_INFINITY, &value);
00103   LIBMESH_CHKERRABORT(ierr);
00104 
00105   return static_cast<Real>(value);
00106 }
00107 
00108 
00109 
00110 
00111 template <typename T>
00112 NumericVector<T>&
00113 PetscVector<T>::operator += (const NumericVector<T>& v)
00114 {
00115   this->_restore_array();
00116   libmesh_assert(this->closed());
00117 
00118   this->add(1., v);
00119 
00120   return *this;
00121 }
00122 
00123 
00124 
00125 template <typename T>
00126 NumericVector<T>&
00127 PetscVector<T>::operator -= (const NumericVector<T>& v)
00128 {
00129   this->_restore_array();
00130   libmesh_assert(this->closed());
00131 
00132   this->add(-1., v);
00133 
00134   return *this;
00135 }
00136 
00137 
00138 
00139 template <typename T>
00140 void PetscVector<T>::set (const numeric_index_type i, const T value)
00141 {
00142   this->_restore_array();
00143   libmesh_assert_less (i, size());
00144 
00145   PetscErrorCode ierr=0;
00146   PetscInt i_val = static_cast<PetscInt>(i);
00147   PetscScalar petsc_value = static_cast<PetscScalar>(value);
00148 
00149   ierr = VecSetValues (_vec, 1, &i_val, &petsc_value, INSERT_VALUES);
00150   LIBMESH_CHKERRABORT(ierr);
00151 
00152   this->_is_closed = false;
00153 }
00154 
00155 
00156 
00157 template <typename T>
00158 void PetscVector<T>::reciprocal()
00159 {
00160   PetscErrorCode ierr = 0;
00161 
00162   // VecReciprocal has been in PETSc since at least 2.3.3 days
00163   ierr = VecReciprocal(_vec);
00164   LIBMESH_CHKERRABORT(ierr);
00165 }
00166 
00167 
00168 
00169 template <typename T>
00170 void PetscVector<T>::conjugate()
00171 {
00172   PetscErrorCode ierr = 0;
00173 
00174   // We just call the PETSc VecConjugate
00175   ierr = VecConjugate(_vec);
00176   LIBMESH_CHKERRABORT(ierr);
00177 }
00178 
00179 
00180 
00181 template <typename T>
00182 void PetscVector<T>::add (const numeric_index_type i, const T value)
00183 {
00184   this->_restore_array();
00185   libmesh_assert_less (i, size());
00186 
00187   PetscErrorCode ierr=0;
00188   PetscInt i_val = static_cast<PetscInt>(i);
00189   PetscScalar petsc_value = static_cast<PetscScalar>(value);
00190 
00191   ierr = VecSetValues (_vec, 1, &i_val, &petsc_value, ADD_VALUES);
00192   LIBMESH_CHKERRABORT(ierr);
00193 
00194   this->_is_closed = false;
00195 }
00196 
00197 
00198 
00199 template <typename T>
00200 void PetscVector<T>::add_vector (const T* v,
00201                                  const std::vector<numeric_index_type>& dof_indices)
00202 {
00203   // If we aren't adding anything just return
00204   if(dof_indices.empty())
00205     return;
00206 
00207   this->_restore_array();
00208 
00209   PetscErrorCode ierr=0;
00210   const PetscInt * i_val = reinterpret_cast<const PetscInt*>(&dof_indices[0]);
00211   const PetscScalar * petsc_value = static_cast<const PetscScalar*>(v);
00212 
00213   ierr = VecSetValues (_vec, cast_int<PetscInt>(dof_indices.size()),
00214                        i_val, petsc_value, ADD_VALUES);
00215   LIBMESH_CHKERRABORT(ierr);
00216 
00217   this->_is_closed = false;
00218 }
00219 
00220 
00221 
00222 template <typename T>
00223 void PetscVector<T>::add_vector (const NumericVector<T>& V_in,
00224                                  const SparseMatrix<T>& A_in)
00225 {
00226   this->_restore_array();
00227   // Make sure the data passed in are really of Petsc types
00228   const PetscVector<T>* V = cast_ptr<const PetscVector<T>*>(&V_in);
00229   const PetscMatrix<T>* A = cast_ptr<const PetscMatrix<T>*>(&A_in);
00230 
00231   PetscErrorCode ierr=0;
00232 
00233   A->close();
00234 
00235   // The const_cast<> is not elegant, but it is required since PETSc
00236   // is not const-correct.
00237   ierr = MatMultAdd(const_cast<PetscMatrix<T>*>(A)->mat(), V->_vec, _vec, _vec);
00238   LIBMESH_CHKERRABORT(ierr);
00239 }
00240 
00241 
00242 
00243 template <typename T>
00244 void PetscVector<T>::add_vector_transpose (const NumericVector<T>& V_in,
00245                                            const SparseMatrix<T>& A_in)
00246 {
00247   this->_restore_array();
00248   // Make sure the data passed in are really of Petsc types
00249   const PetscVector<T>* V = cast_ptr<const PetscVector<T>*>(&V_in);
00250   const PetscMatrix<T>* A = cast_ptr<const PetscMatrix<T>*>(&A_in);
00251 
00252   PetscErrorCode ierr=0;
00253 
00254   A->close();
00255 
00256   // The const_cast<> is not elegant, but it is required since PETSc
00257   // is not const-correct.
00258   ierr = MatMultTransposeAdd(const_cast<PetscMatrix<T>*>(A)->mat(), V->_vec, _vec, _vec);
00259   LIBMESH_CHKERRABORT(ierr);
00260 }
00261 
00262 
00263 #if PETSC_VERSION_LESS_THAN(3,1,0)
00264 template <typename T>
00265 void PetscVector<T>::add_vector_conjugate_transpose (const NumericVector<T>&,
00266                                                      const SparseMatrix<T>&)
00267 {
00268   libmesh_error_msg("MatMultHermitianTranspose was introduced in PETSc 3.1.0," \
00269                     << "No one has made it backwards compatible with older " \
00270                     << "versions of PETSc so far.");
00271 }
00272 
00273 #else
00274 
00275 template <typename T>
00276 void PetscVector<T>::add_vector_conjugate_transpose (const NumericVector<T>& V_in,
00277                                                      const SparseMatrix<T>& A_in)
00278 {
00279   this->_restore_array();
00280   // Make sure the data passed in are really of Petsc types
00281   const PetscVector<T>* V = cast_ptr<const PetscVector<T>*>(&V_in);
00282   const PetscMatrix<T>* A = cast_ptr<const PetscMatrix<T>*>(&A_in);
00283 
00284   A->close();
00285 
00286   // Store a temporary copy since MatMultHermitianTransposeAdd doesn't seem to work
00287   // TODO: Find out why MatMultHermitianTransposeAdd doesn't work, might be a PETSc bug?
00288   UniquePtr< NumericVector<Number> > this_clone = this->clone();
00289 
00290   // The const_cast<> is not elegant, but it is required since PETSc
00291   // is not const-correct.
00292   PetscErrorCode ierr = MatMultHermitianTranspose(const_cast<PetscMatrix<T>*>(A)->mat(), V->_vec, _vec);
00293   LIBMESH_CHKERRABORT(ierr);
00294 
00295   // Add the temporary copy to the matvec result
00296   this->add(1., *this_clone);
00297 }
00298 #endif
00299 
00300 
00301 template <typename T>
00302 void PetscVector<T>::add (const T v_in)
00303 {
00304   this->_restore_array();
00305 
00306   PetscErrorCode ierr=0;
00307   PetscScalar* values;
00308   const PetscScalar v = static_cast<PetscScalar>(v_in);
00309 
00310   if(this->type() != GHOSTED)
00311     {
00312       const PetscInt n   = static_cast<PetscInt>(this->local_size());
00313       const PetscInt fli = static_cast<PetscInt>(this->first_local_index());
00314 
00315       for (PetscInt i=0; i<n; i++)
00316         {
00317           ierr = VecGetArray (_vec, &values);
00318           LIBMESH_CHKERRABORT(ierr);
00319 
00320           PetscInt ig = fli + i;
00321 
00322           PetscScalar value = (values[i] + v);
00323 
00324           ierr = VecRestoreArray (_vec, &values);
00325           LIBMESH_CHKERRABORT(ierr);
00326 
00327           ierr = VecSetValues (_vec, 1, &ig, &value, INSERT_VALUES);
00328           LIBMESH_CHKERRABORT(ierr);
00329         }
00330     }
00331   else
00332     {
00333       /* Vectors that include ghost values require a special
00334          handling.  */
00335       Vec loc_vec;
00336       ierr = VecGhostGetLocalForm (_vec,&loc_vec);
00337       LIBMESH_CHKERRABORT(ierr);
00338 
00339       PetscInt n=0;
00340       ierr = VecGetSize(loc_vec, &n);
00341       LIBMESH_CHKERRABORT(ierr);
00342 
00343       for (PetscInt i=0; i<n; i++)
00344         {
00345           ierr = VecGetArray (loc_vec, &values);
00346           LIBMESH_CHKERRABORT(ierr);
00347 
00348           PetscScalar value = (values[i] + v);
00349 
00350           ierr = VecRestoreArray (loc_vec, &values);
00351           LIBMESH_CHKERRABORT(ierr);
00352 
00353           ierr = VecSetValues (loc_vec, 1, &i, &value, INSERT_VALUES);
00354           LIBMESH_CHKERRABORT(ierr);
00355         }
00356 
00357       ierr = VecGhostRestoreLocalForm (_vec,&loc_vec);
00358       LIBMESH_CHKERRABORT(ierr);
00359     }
00360 
00361   this->_is_closed = false;
00362 }
00363 
00364 
00365 
00366 template <typename T>
00367 void PetscVector<T>::add (const NumericVector<T>& v)
00368 {
00369   this->add (1., v);
00370 }
00371 
00372 
00373 
00374 template <typename T>
00375 void PetscVector<T>::add (const T a_in, const NumericVector<T>& v_in)
00376 {
00377   this->_restore_array();
00378 
00379   PetscErrorCode ierr = 0;
00380   PetscScalar a = static_cast<PetscScalar>(a_in);
00381 
00382   // Make sure the NumericVector passed in is really a PetscVector
00383   const PetscVector<T>* v = cast_ptr<const PetscVector<T>*>(&v_in);
00384   v->_restore_array();
00385 
00386   libmesh_assert_equal_to (this->size(), v->size());
00387 
00388   if(this->type() != GHOSTED)
00389     {
00390 #if PETSC_VERSION_LESS_THAN(2,3,0)
00391       // 2.2.x & earlier style
00392       ierr = VecAXPY(&a, v->_vec, _vec);
00393       LIBMESH_CHKERRABORT(ierr);
00394 #else
00395       // 2.3.x & later style
00396       ierr = VecAXPY(_vec, a, v->_vec);
00397       LIBMESH_CHKERRABORT(ierr);
00398 #endif
00399     }
00400   else
00401     {
00402       Vec loc_vec;
00403       Vec v_loc_vec;
00404       ierr = VecGhostGetLocalForm (_vec,&loc_vec);
00405       LIBMESH_CHKERRABORT(ierr);
00406       ierr = VecGhostGetLocalForm (v->_vec,&v_loc_vec);
00407       LIBMESH_CHKERRABORT(ierr);
00408 
00409 #if PETSC_VERSION_LESS_THAN(2,3,0)
00410       // 2.2.x & earlier style
00411       ierr = VecAXPY(&a, v_loc_vec, loc_vec);
00412       LIBMESH_CHKERRABORT(ierr);
00413 #else
00414       // 2.3.x & later style
00415       ierr = VecAXPY(loc_vec, a, v_loc_vec);
00416       LIBMESH_CHKERRABORT(ierr);
00417 #endif
00418 
00419       ierr = VecGhostRestoreLocalForm (v->_vec,&v_loc_vec);
00420       LIBMESH_CHKERRABORT(ierr);
00421       ierr = VecGhostRestoreLocalForm (_vec,&loc_vec);
00422       LIBMESH_CHKERRABORT(ierr);
00423     }
00424 }
00425 
00426 
00427 
00428 template <typename T>
00429 void PetscVector<T>::insert (const T* v,
00430                              const std::vector<numeric_index_type>& dof_indices)
00431 {
00432   if (dof_indices.empty())
00433     return;
00434 
00435   this->_restore_array();
00436 
00437   PetscErrorCode ierr=0;
00438   PetscInt *idx_values = numeric_petsc_cast(&dof_indices[0]);
00439   ierr = VecSetValues (_vec, dof_indices.size(), idx_values, v, INSERT_VALUES);
00440   LIBMESH_CHKERRABORT(ierr);
00441 
00442   this->_is_closed = false;
00443 }
00444 
00445 
00446 
00447 template <typename T>
00448 void PetscVector<T>::scale (const T factor_in)
00449 {
00450   this->_restore_array();
00451 
00452   PetscErrorCode ierr = 0;
00453   PetscScalar factor = static_cast<PetscScalar>(factor_in);
00454 
00455   if(this->type() != GHOSTED)
00456     {
00457 #if PETSC_VERSION_LESS_THAN(2,3,0)
00458       // 2.2.x & earlier style
00459       ierr = VecScale(&factor, _vec);
00460       LIBMESH_CHKERRABORT(ierr);
00461 #else
00462       // 2.3.x & later style
00463       ierr = VecScale(_vec, factor);
00464       LIBMESH_CHKERRABORT(ierr);
00465 #endif
00466     }
00467   else
00468     {
00469       Vec loc_vec;
00470       ierr = VecGhostGetLocalForm (_vec,&loc_vec);
00471       LIBMESH_CHKERRABORT(ierr);
00472 
00473 #if PETSC_VERSION_LESS_THAN(2,3,0)
00474       // 2.2.x & earlier style
00475       ierr = VecScale(&factor, loc_vec);
00476       LIBMESH_CHKERRABORT(ierr);
00477 #else
00478       // 2.3.x & later style
00479       ierr = VecScale(loc_vec, factor);
00480       LIBMESH_CHKERRABORT(ierr);
00481 #endif
00482 
00483       ierr = VecGhostRestoreLocalForm (_vec,&loc_vec);
00484       LIBMESH_CHKERRABORT(ierr);
00485     }
00486 }
00487 
00488 template <typename T>
00489 NumericVector<T> & PetscVector<T>::operator /= (NumericVector<T> & v)
00490 {
00491   PetscErrorCode ierr = 0;
00492 
00493   const PetscVector<T>* v_vec = cast_ptr<const PetscVector<T>*>(&v);
00494 
00495   ierr = VecPointwiseDivide(_vec, _vec, v_vec->_vec);
00496   LIBMESH_CHKERRABORT(ierr);
00497 
00498   return *this;
00499 }
00500 
00501 template <typename T>
00502 void PetscVector<T>::abs()
00503 {
00504   this->_restore_array();
00505 
00506   PetscErrorCode ierr = 0;
00507 
00508   if(this->type() != GHOSTED)
00509     {
00510       ierr = VecAbs(_vec);
00511       LIBMESH_CHKERRABORT(ierr);
00512     }
00513   else
00514     {
00515       Vec loc_vec;
00516       ierr = VecGhostGetLocalForm (_vec,&loc_vec);
00517       LIBMESH_CHKERRABORT(ierr);
00518 
00519       ierr = VecAbs(loc_vec);
00520       LIBMESH_CHKERRABORT(ierr);
00521 
00522       ierr = VecGhostRestoreLocalForm (_vec,&loc_vec);
00523       LIBMESH_CHKERRABORT(ierr);
00524     }
00525 }
00526 
00527 template <typename T>
00528 T PetscVector<T>::dot (const NumericVector<T>& V) const
00529 {
00530   this->_restore_array();
00531 
00532   // Error flag
00533   PetscErrorCode ierr = 0;
00534 
00535   // Return value
00536   PetscScalar value=0.;
00537 
00538   // Make sure the NumericVector passed in is really a PetscVector
00539   const PetscVector<T>* v = cast_ptr<const PetscVector<T>*>(&V);
00540 
00541   // 2.3.x (at least) style.  Untested for previous versions.
00542   ierr = VecDot(this->_vec, v->_vec, &value);
00543   LIBMESH_CHKERRABORT(ierr);
00544 
00545   return static_cast<T>(value);
00546 }
00547 
00548 template <typename T>
00549 T PetscVector<T>::indefinite_dot (const NumericVector<T>& V) const
00550 {
00551   this->_restore_array();
00552 
00553   // Error flag
00554   PetscErrorCode ierr = 0;
00555 
00556   // Return value
00557   PetscScalar value=0.;
00558 
00559   // Make sure the NumericVector passed in is really a PetscVector
00560   const PetscVector<T>* v = cast_ptr<const PetscVector<T>*>(&V);
00561 
00562   // 2.3.x (at least) style.  Untested for previous versions.
00563   ierr = VecTDot(this->_vec, v->_vec, &value);
00564   LIBMESH_CHKERRABORT(ierr);
00565 
00566   return static_cast<T>(value);
00567 }
00568 
00569 
00570 template <typename T>
00571 NumericVector<T>&
00572 PetscVector<T>::operator = (const T s_in)
00573 {
00574   this->_restore_array();
00575   libmesh_assert(this->closed());
00576 
00577   PetscErrorCode ierr = 0;
00578   PetscScalar s = static_cast<PetscScalar>(s_in);
00579 
00580   if (this->size() != 0)
00581     {
00582       if(this->type() != GHOSTED)
00583         {
00584 #if PETSC_VERSION_LESS_THAN(2,3,0)
00585           // 2.2.x & earlier style
00586           ierr = VecSet(&s, _vec);
00587           LIBMESH_CHKERRABORT(ierr);
00588 #else
00589           // 2.3.x & later style
00590           ierr = VecSet(_vec, s);
00591           LIBMESH_CHKERRABORT(ierr);
00592 #endif
00593         }
00594       else
00595         {
00596           Vec loc_vec;
00597           ierr = VecGhostGetLocalForm (_vec,&loc_vec);
00598           LIBMESH_CHKERRABORT(ierr);
00599 
00600 #if PETSC_VERSION_LESS_THAN(2,3,0)
00601           // 2.2.x & earlier style
00602           ierr = VecSet(&s, loc_vec);
00603           LIBMESH_CHKERRABORT(ierr);
00604 #else
00605           // 2.3.x & later style
00606           ierr = VecSet(loc_vec, s);
00607           LIBMESH_CHKERRABORT(ierr);
00608 #endif
00609 
00610           ierr = VecGhostRestoreLocalForm (_vec,&loc_vec);
00611           LIBMESH_CHKERRABORT(ierr);
00612         }
00613     }
00614 
00615   return *this;
00616 }
00617 
00618 
00619 
00620 template <typename T>
00621 NumericVector<T>&
00622 PetscVector<T>::operator = (const NumericVector<T>& v_in)
00623 {
00624   // Make sure the NumericVector passed in is really a PetscVector
00625   const PetscVector<T>* v = cast_ptr<const PetscVector<T>*>(&v_in);
00626 
00627   *this = *v;
00628 
00629   return *this;
00630 }
00631 
00632 
00633 
00634 template <typename T>
00635 PetscVector<T>&
00636 PetscVector<T>::operator = (const PetscVector<T>& v)
00637 {
00638   this->_restore_array();
00639   v._restore_array();
00640 
00641   libmesh_assert_equal_to (this->size(), v.size());
00642   libmesh_assert_equal_to (this->local_size(), v.local_size());
00643   libmesh_assert (v.closed());
00644 
00645   PetscErrorCode ierr = 0;
00646 
00647   if (((this->type()==PARALLEL) && (v.type()==GHOSTED)) ||
00648       ((this->type()==GHOSTED) && (v.type()==PARALLEL)) ||
00649       ((this->type()==GHOSTED) && (v.type()==SERIAL))   ||
00650       ((this->type()==SERIAL) && (v.type()==GHOSTED)))
00651     {
00652       /* Allow assignment of a ghosted to a parallel vector since this
00653          causes no difficulty.  See discussion in libmesh-devel of
00654          June 24, 2010.  */
00655       ierr = VecCopy (v._vec, this->_vec);
00656       LIBMESH_CHKERRABORT(ierr);
00657     }
00658   else
00659     {
00660       /* In all other cases, we assert that both vectors are of equal
00661          type.  */
00662       libmesh_assert_equal_to (this->_type, v._type);
00663 
00664       if (v.size() != 0)
00665         {
00666           if(this->type() != GHOSTED)
00667             {
00668               ierr = VecCopy (v._vec, this->_vec);
00669               LIBMESH_CHKERRABORT(ierr);
00670             }
00671           else
00672             {
00673               Vec loc_vec;
00674               Vec v_loc_vec;
00675               ierr = VecGhostGetLocalForm (_vec,&loc_vec);
00676               LIBMESH_CHKERRABORT(ierr);
00677               ierr = VecGhostGetLocalForm (v._vec,&v_loc_vec);
00678               LIBMESH_CHKERRABORT(ierr);
00679 
00680               ierr = VecCopy (v_loc_vec, loc_vec);
00681               LIBMESH_CHKERRABORT(ierr);
00682 
00683               ierr = VecGhostRestoreLocalForm (v._vec,&v_loc_vec);
00684               LIBMESH_CHKERRABORT(ierr);
00685               ierr = VecGhostRestoreLocalForm (_vec,&loc_vec);
00686               LIBMESH_CHKERRABORT(ierr);
00687             }
00688         }
00689     }
00690 
00691   close();
00692 
00693   return *this;
00694 }
00695 
00696 
00697 
00698 template <typename T>
00699 NumericVector<T>&
00700 PetscVector<T>::operator = (const std::vector<T>& v)
00701 {
00702   this->_restore_array();
00703 
00704   const numeric_index_type nl   = this->local_size();
00705   const numeric_index_type ioff = this->first_local_index();
00706   PetscErrorCode ierr=0;
00707   PetscScalar* values;
00708 
00713   if (this->size() == v.size())
00714     {
00715       ierr = VecGetArray (_vec, &values);
00716       LIBMESH_CHKERRABORT(ierr);
00717 
00718       for (numeric_index_type i=0; i<nl; i++)
00719         values[i] =  static_cast<PetscScalar>(v[i+ioff]);
00720 
00721       ierr = VecRestoreArray (_vec, &values);
00722       LIBMESH_CHKERRABORT(ierr);
00723     }
00724 
00729   else
00730     {
00731       libmesh_assert_equal_to (this->local_size(), v.size());
00732 
00733       ierr = VecGetArray (_vec, &values);
00734       LIBMESH_CHKERRABORT(ierr);
00735 
00736       for (numeric_index_type i=0; i<nl; i++)
00737         values[i] = static_cast<PetscScalar>(v[i]);
00738 
00739       ierr = VecRestoreArray (_vec, &values);
00740       LIBMESH_CHKERRABORT(ierr);
00741     }
00742 
00743   // Make sure ghost dofs are up to date
00744   if (this->type() == GHOSTED)
00745     this->close();
00746 
00747   return *this;
00748 }
00749 
00750 
00751 
00752 template <typename T>
00753 void PetscVector<T>::localize (NumericVector<T>& v_local_in) const
00754 {
00755   this->_restore_array();
00756 
00757   // Make sure the NumericVector passed in is really a PetscVector
00758   PetscVector<T>* v_local = cast_ptr<PetscVector<T>*>(&v_local_in);
00759 
00760   libmesh_assert(v_local);
00761   libmesh_assert_equal_to (v_local->size(), this->size());
00762 
00763   PetscErrorCode ierr = 0;
00764   const PetscInt n = this->size();
00765 
00766   IS is;
00767   VecScatter scatter;
00768 
00769   // Create idx, idx[i] = i;
00770   std::vector<PetscInt> idx(n); Utility::iota (idx.begin(), idx.end(), 0);
00771 
00772   // Create the index set & scatter object
00773   ierr = ISCreateLibMesh(this->comm().get(), n, &idx[0], PETSC_USE_POINTER, &is);
00774   LIBMESH_CHKERRABORT(ierr);
00775 
00776   ierr = VecScatterCreate(_vec,          is,
00777                           v_local->_vec, is,
00778                           &scatter);
00779   LIBMESH_CHKERRABORT(ierr);
00780 
00781   // Perform the scatter
00782 #if PETSC_VERSION_LESS_THAN(2,3,3)
00783 
00784   ierr = VecScatterBegin(_vec, v_local->_vec, INSERT_VALUES,
00785                          SCATTER_FORWARD, scatter);
00786   LIBMESH_CHKERRABORT(ierr);
00787 
00788   ierr = VecScatterEnd  (_vec, v_local->_vec, INSERT_VALUES,
00789                          SCATTER_FORWARD, scatter);
00790   LIBMESH_CHKERRABORT(ierr);
00791 #else
00792   // API argument order change in PETSc 2.3.3
00793   ierr = VecScatterBegin(scatter, _vec, v_local->_vec,
00794                          INSERT_VALUES, SCATTER_FORWARD);
00795   LIBMESH_CHKERRABORT(ierr);
00796 
00797   ierr = VecScatterEnd  (scatter, _vec, v_local->_vec,
00798                          INSERT_VALUES, SCATTER_FORWARD);
00799   LIBMESH_CHKERRABORT(ierr);
00800 #endif
00801 
00802   // Clean up
00803   ierr = LibMeshISDestroy (&is);
00804   LIBMESH_CHKERRABORT(ierr);
00805 
00806   ierr = LibMeshVecScatterDestroy(&scatter);
00807   LIBMESH_CHKERRABORT(ierr);
00808 
00809   // Make sure ghost dofs are up to date
00810   if (v_local->type() == GHOSTED)
00811     v_local->close();
00812 }
00813 
00814 
00815 
00816 template <typename T>
00817 void PetscVector<T>::localize (NumericVector<T>& v_local_in,
00818                                const std::vector<numeric_index_type>& send_list) const
00819 {
00820   // FIXME: Workaround for a strange bug at large-scale.
00821   // If we have ghosting, PETSc lets us just copy the solution, and
00822   // doing so avoids a segfault?
00823   if (v_local_in.type() == GHOSTED &&
00824       this->type() == PARALLEL)
00825     {
00826       v_local_in = *this;
00827       return;
00828     }
00829 
00830   // Normal code path begins here
00831 
00832   this->_restore_array();
00833 
00834   // Make sure the NumericVector passed in is really a PetscVector
00835   PetscVector<T>* v_local = cast_ptr<PetscVector<T>*>(&v_local_in);
00836 
00837   libmesh_assert(v_local);
00838   libmesh_assert_equal_to (v_local->size(), this->size());
00839   libmesh_assert_less_equal (send_list.size(), v_local->size());
00840 
00841   PetscErrorCode ierr=0;
00842   const numeric_index_type n_sl =
00843     cast_int<numeric_index_type>(send_list.size());
00844 
00845   IS is;
00846   VecScatter scatter;
00847 
00848   std::vector<PetscInt> idx(n_sl + this->local_size());
00849 
00850   for (numeric_index_type i=0; i<n_sl; i++)
00851     idx[i] = static_cast<PetscInt>(send_list[i]);
00852   for (numeric_index_type i = 0; i != this->local_size(); ++i)
00853     idx[n_sl+i] = i + this->first_local_index();
00854 
00855   // Create the index set & scatter object
00856   if (idx.empty())
00857     ierr = ISCreateLibMesh(this->comm().get(),
00858                            n_sl+this->local_size(), PETSC_NULL, PETSC_USE_POINTER, &is);
00859   else
00860     ierr = ISCreateLibMesh(this->comm().get(),
00861                            n_sl+this->local_size(), &idx[0], PETSC_USE_POINTER, &is);
00862   LIBMESH_CHKERRABORT(ierr);
00863 
00864   ierr = VecScatterCreate(_vec,          is,
00865                           v_local->_vec, is,
00866                           &scatter);
00867   LIBMESH_CHKERRABORT(ierr);
00868 
00869 
00870   // Perform the scatter
00871 #if PETSC_VERSION_LESS_THAN(2,3,3)
00872 
00873   ierr = VecScatterBegin(_vec, v_local->_vec, INSERT_VALUES,
00874                          SCATTER_FORWARD, scatter);
00875   LIBMESH_CHKERRABORT(ierr);
00876 
00877   ierr = VecScatterEnd  (_vec, v_local->_vec, INSERT_VALUES,
00878                          SCATTER_FORWARD, scatter);
00879   LIBMESH_CHKERRABORT(ierr);
00880 
00881 #else
00882 
00883   // API argument order change in PETSc 2.3.3
00884   ierr = VecScatterBegin(scatter, _vec, v_local->_vec,
00885                          INSERT_VALUES, SCATTER_FORWARD);
00886   LIBMESH_CHKERRABORT(ierr);
00887 
00888   ierr = VecScatterEnd  (scatter, _vec, v_local->_vec,
00889                          INSERT_VALUES, SCATTER_FORWARD);
00890   LIBMESH_CHKERRABORT(ierr);
00891 
00892 #endif
00893 
00894 
00895   // Clean up
00896   ierr = LibMeshISDestroy (&is);
00897   LIBMESH_CHKERRABORT(ierr);
00898 
00899   ierr = LibMeshVecScatterDestroy(&scatter);
00900   LIBMESH_CHKERRABORT(ierr);
00901 
00902   // Make sure ghost dofs are up to date
00903   if (v_local->type() == GHOSTED)
00904     v_local->close();
00905 }
00906 
00907 
00908 template <typename T>
00909 void PetscVector<T>::localize (const numeric_index_type first_local_idx,
00910                                const numeric_index_type last_local_idx,
00911                                const std::vector<numeric_index_type>& send_list)
00912 {
00913   this->_restore_array();
00914 
00915   libmesh_assert_less_equal (send_list.size(), this->size());
00916   libmesh_assert_less_equal (last_local_idx+1, this->size());
00917 
00918   const numeric_index_type my_size       = this->size();
00919   const numeric_index_type my_local_size = (last_local_idx - first_local_idx + 1);
00920   PetscErrorCode ierr=0;
00921 
00922   // Don't bother for serial cases
00923   //  if ((first_local_idx == 0) &&
00924   //      (my_local_size == my_size))
00925   // But we do need to stay in sync for degenerate cases
00926   if (this->n_processors() == 1)
00927     return;
00928 
00929 
00930   // Build a parallel vector, initialize it with the local
00931   // parts of (*this)
00932   PetscVector<T> parallel_vec(this->comm(), PARALLEL);
00933 
00934   parallel_vec.init (my_size, my_local_size, true, PARALLEL);
00935 
00936 
00937   // Copy part of *this into the parallel_vec
00938   {
00939     IS is;
00940     VecScatter scatter;
00941 
00942     // Create idx, idx[i] = i+first_local_idx;
00943     std::vector<PetscInt> idx(my_local_size);
00944     Utility::iota (idx.begin(), idx.end(), first_local_idx);
00945 
00946     // Create the index set & scatter object
00947     ierr = ISCreateLibMesh(this->comm().get(), my_local_size,
00948                            my_local_size ? &idx[0] : NULL, PETSC_USE_POINTER, &is);
00949     LIBMESH_CHKERRABORT(ierr);
00950 
00951     ierr = VecScatterCreate(_vec,              is,
00952                             parallel_vec._vec, is,
00953                             &scatter);
00954     LIBMESH_CHKERRABORT(ierr);
00955 
00956     // Perform the scatter
00957 #if PETSC_VERSION_LESS_THAN(2,3,3)
00958 
00959     ierr = VecScatterBegin(_vec, parallel_vec._vec, INSERT_VALUES,
00960                            SCATTER_FORWARD, scatter);
00961     LIBMESH_CHKERRABORT(ierr);
00962 
00963     ierr = VecScatterEnd  (_vec, parallel_vec._vec, INSERT_VALUES,
00964                            SCATTER_FORWARD, scatter);
00965     LIBMESH_CHKERRABORT(ierr);
00966 
00967 #else
00968 
00969     // API argument order change in PETSc 2.3.3
00970     ierr = VecScatterBegin(scatter, _vec, parallel_vec._vec,
00971                            INSERT_VALUES, SCATTER_FORWARD);
00972     LIBMESH_CHKERRABORT(ierr);
00973 
00974     ierr = VecScatterEnd  (scatter, _vec, parallel_vec._vec,
00975                            INSERT_VALUES, SCATTER_FORWARD);
00976     LIBMESH_CHKERRABORT(ierr);
00977 
00978 #endif
00979 
00980     // Clean up
00981     ierr = LibMeshISDestroy (&is);
00982     LIBMESH_CHKERRABORT(ierr);
00983 
00984     ierr = LibMeshVecScatterDestroy(&scatter);
00985     LIBMESH_CHKERRABORT(ierr);
00986   }
00987 
00988   // localize like normal
00989   parallel_vec.close();
00990   parallel_vec.localize (*this, send_list);
00991   this->close();
00992 }
00993 
00994 
00995 
00996 template <typename T>
00997 void PetscVector<T>::localize (std::vector<T>& v_local) const
00998 {
00999   this->_restore_array();
01000 
01001   // This function must be run on all processors at once
01002   parallel_object_only();
01003 
01004   PetscErrorCode ierr=0;
01005   const PetscInt n = this->size();
01006   const PetscInt nl = this->local_size();
01007   PetscScalar *values;
01008 
01009   v_local.clear();
01010   v_local.resize(n, 0.);
01011 
01012   ierr = VecGetArray (_vec, &values);
01013   LIBMESH_CHKERRABORT(ierr);
01014 
01015   numeric_index_type ioff = first_local_index();
01016 
01017   for (PetscInt i=0; i<nl; i++)
01018     v_local[i+ioff] = static_cast<T>(values[i]);
01019 
01020   ierr = VecRestoreArray (_vec, &values);
01021   LIBMESH_CHKERRABORT(ierr);
01022 
01023   this->comm().sum(v_local);
01024 }
01025 
01026 
01027 
01028 // Full specialization for Real datatypes
01029 #ifdef LIBMESH_USE_REAL_NUMBERS
01030 
01031 template <>
01032 void PetscVector<Real>::localize_to_one (std::vector<Real>& v_local,
01033                                          const processor_id_type pid) const
01034 {
01035   this->_restore_array();
01036 
01037   PetscErrorCode ierr=0;
01038   const PetscInt n  = size();
01039   const PetscInt nl = local_size();
01040   PetscScalar *values;
01041 
01042 
01043   // only one processor
01044   if (n_processors() == 1)
01045     {
01046       v_local.resize(n);
01047 
01048       ierr = VecGetArray (_vec, &values);
01049       LIBMESH_CHKERRABORT(ierr);
01050 
01051       for (PetscInt i=0; i<n; i++)
01052         v_local[i] = static_cast<Real>(values[i]);
01053 
01054       ierr = VecRestoreArray (_vec, &values);
01055       LIBMESH_CHKERRABORT(ierr);
01056     }
01057 
01058   // otherwise multiple processors
01059   else
01060     {
01061       if(pid == 0) // optimized version for localizing to 0
01062         {
01063           Vec vout;
01064           VecScatter ctx;
01065 
01066           ierr = VecScatterCreateToZero(_vec, &ctx, &vout);
01067           LIBMESH_CHKERRABORT(ierr);
01068 
01069           ierr = VecScatterBegin(ctx, _vec, vout, INSERT_VALUES, SCATTER_FORWARD);
01070           LIBMESH_CHKERRABORT(ierr);
01071           ierr = VecScatterEnd(ctx, _vec, vout, INSERT_VALUES, SCATTER_FORWARD);
01072           LIBMESH_CHKERRABORT(ierr);
01073 
01074           if(processor_id() == 0)
01075             {
01076               v_local.resize(n);
01077 
01078               ierr = VecGetArray (vout, &values);
01079               LIBMESH_CHKERRABORT(ierr);
01080 
01081               for (PetscInt i=0; i<n; i++)
01082                 v_local[i] = static_cast<Real>(values[i]);
01083 
01084               ierr = VecRestoreArray (vout, &values);
01085               LIBMESH_CHKERRABORT(ierr);
01086             }
01087 
01088           ierr = LibMeshVecScatterDestroy(&ctx);
01089           LIBMESH_CHKERRABORT(ierr);
01090           ierr = LibMeshVecDestroy(&vout);
01091           LIBMESH_CHKERRABORT(ierr);
01092 
01093         }
01094       else
01095         {
01096           v_local.resize(n);
01097 
01098           numeric_index_type ioff = this->first_local_index();
01099           std::vector<Real> local_values (n, 0.);
01100 
01101           {
01102             ierr = VecGetArray (_vec, &values);
01103             LIBMESH_CHKERRABORT(ierr);
01104 
01105             for (PetscInt i=0; i<nl; i++)
01106               local_values[i+ioff] = static_cast<Real>(values[i]);
01107 
01108             ierr = VecRestoreArray (_vec, &values);
01109             LIBMESH_CHKERRABORT(ierr);
01110           }
01111 
01112 
01113           MPI_Reduce (&local_values[0], &v_local[0], n, MPI_REAL, MPI_SUM,
01114                       pid, this->comm().get());
01115         }
01116     }
01117 }
01118 
01119 #endif
01120 
01121 
01122 // Full specialization for Complex datatypes
01123 #ifdef LIBMESH_USE_COMPLEX_NUMBERS
01124 
01125 template <>
01126 void PetscVector<Complex>::localize_to_one (std::vector<Complex>& v_local,
01127                                             const processor_id_type pid) const
01128 {
01129   this->_restore_array();
01130 
01131   PetscErrorCode ierr=0;
01132   const PetscInt n  = size();
01133   const PetscInt nl = local_size();
01134   PetscScalar *values;
01135 
01136 
01137   v_local.resize(n);
01138 
01139 
01140   for (PetscInt i=0; i<n; i++)
01141     v_local[i] = 0.;
01142 
01143   // only one processor
01144   if (n == nl)
01145     {
01146       ierr = VecGetArray (_vec, &values);
01147       LIBMESH_CHKERRABORT(ierr);
01148 
01149       for (PetscInt i=0; i<n; i++)
01150         v_local[i] = static_cast<Complex>(values[i]);
01151 
01152       ierr = VecRestoreArray (_vec, &values);
01153       LIBMESH_CHKERRABORT(ierr);
01154     }
01155 
01156   // otherwise multiple processors
01157   else
01158     {
01159       numeric_index_type ioff = this->first_local_index();
01160 
01161       /* in here the local values are stored, acting as send buffer for MPI
01162        * initialize to zero, since we collect using MPI_SUM
01163        */
01164       std::vector<Real> real_local_values(n, 0.);
01165       std::vector<Real> imag_local_values(n, 0.);
01166 
01167       {
01168         ierr = VecGetArray (_vec, &values);
01169         LIBMESH_CHKERRABORT(ierr);
01170 
01171         // provide my local share to the real and imag buffers
01172         for (PetscInt i=0; i<nl; i++)
01173           {
01174             real_local_values[i+ioff] = static_cast<Complex>(values[i]).real();
01175             imag_local_values[i+ioff] = static_cast<Complex>(values[i]).imag();
01176           }
01177 
01178         ierr = VecRestoreArray (_vec, &values);
01179         LIBMESH_CHKERRABORT(ierr);
01180       }
01181 
01182       /* have buffers of the real and imaginary part of v_local.
01183        * Once MPI_Reduce() collected all the real and imaginary
01184        * parts in these std::vector<Real>, the values can be
01185        * copied to v_local
01186        */
01187       std::vector<Real> real_v_local(n);
01188       std::vector<Real> imag_v_local(n);
01189 
01190       // collect entries from other proc's in real_v_local, imag_v_local
01191       MPI_Reduce (&real_local_values[0], &real_v_local[0], n,
01192                   MPI_REAL, MPI_SUM,
01193                   pid, this->comm().get());
01194 
01195       MPI_Reduce (&imag_local_values[0], &imag_v_local[0], n,
01196                   MPI_REAL, MPI_SUM,
01197                   pid, this->comm().get());
01198 
01199       // copy real_v_local and imag_v_local to v_local
01200       for (PetscInt i=0; i<n; i++)
01201         v_local[i] = Complex(real_v_local[i], imag_v_local[i]);
01202     }
01203 }
01204 
01205 #endif
01206 
01207 
01208 
01209 template <typename T>
01210 void PetscVector<T>::pointwise_mult (const NumericVector<T>& vec1,
01211                                      const NumericVector<T>& vec2)
01212 {
01213   this->_restore_array();
01214 
01215   PetscErrorCode ierr = 0;
01216 
01217   // Convert arguments to PetscVector*.
01218   const PetscVector<T>* vec1_petsc = cast_ptr<const PetscVector<T>*>(&vec1);
01219   const PetscVector<T>* vec2_petsc = cast_ptr<const PetscVector<T>*>(&vec2);
01220 
01221   // Call PETSc function.
01222 
01223 #if PETSC_VERSION_LESS_THAN(2,3,1)
01224 
01225   libmesh_error_msg("This method has been developed with PETSc 2.3.1.  " \
01226                     << "No one has made it backwards compatible with older " \
01227                     << "versions of PETSc so far; however, it might work " \
01228                     << "without any change with some older version.");
01229 
01230 #else
01231 
01232   if(this->type() != GHOSTED)
01233     {
01234       ierr = VecPointwiseMult(this->vec(),
01235                               const_cast<PetscVector<T>*>(vec1_petsc)->vec(),
01236                               const_cast<PetscVector<T>*>(vec2_petsc)->vec());
01237       LIBMESH_CHKERRABORT(ierr);
01238     }
01239   else
01240     {
01241       Vec loc_vec;
01242       Vec v1_loc_vec;
01243       Vec v2_loc_vec;
01244       ierr = VecGhostGetLocalForm (_vec,&loc_vec);
01245       LIBMESH_CHKERRABORT(ierr);
01246       ierr = VecGhostGetLocalForm (const_cast<PetscVector<T>*>(vec1_petsc)->vec(),&v1_loc_vec);
01247       LIBMESH_CHKERRABORT(ierr);
01248       ierr = VecGhostGetLocalForm (const_cast<PetscVector<T>*>(vec2_petsc)->vec(),&v2_loc_vec);
01249       LIBMESH_CHKERRABORT(ierr);
01250 
01251       ierr = VecPointwiseMult(loc_vec,v1_loc_vec,v2_loc_vec);
01252       LIBMESH_CHKERRABORT(ierr);
01253 
01254       ierr = VecGhostRestoreLocalForm (const_cast<PetscVector<T>*>(vec1_petsc)->vec(),&v1_loc_vec);
01255       LIBMESH_CHKERRABORT(ierr);
01256       ierr = VecGhostRestoreLocalForm (const_cast<PetscVector<T>*>(vec2_petsc)->vec(),&v2_loc_vec);
01257       LIBMESH_CHKERRABORT(ierr);
01258       ierr = VecGhostRestoreLocalForm (_vec,&loc_vec);
01259       LIBMESH_CHKERRABORT(ierr);
01260     }
01261 
01262 #endif
01263 
01264 }
01265 
01266 
01267 
01268 template <typename T>
01269 void PetscVector<T>::print_matlab (const std::string& name) const
01270 {
01271   this->_restore_array();
01272   libmesh_assert (this->closed());
01273 
01274   PetscErrorCode ierr=0;
01275   PetscViewer petsc_viewer;
01276 
01277 
01278   ierr = PetscViewerCreate (this->comm().get(),
01279                             &petsc_viewer);
01280   LIBMESH_CHKERRABORT(ierr);
01281 
01286   if (name != "")
01287     {
01288       ierr = PetscViewerASCIIOpen( this->comm().get(),
01289                                    name.c_str(),
01290                                    &petsc_viewer);
01291       LIBMESH_CHKERRABORT(ierr);
01292 
01293       ierr = PetscViewerSetFormat (petsc_viewer,
01294                                    PETSC_VIEWER_ASCII_MATLAB);
01295       LIBMESH_CHKERRABORT(ierr);
01296 
01297       ierr = VecView (_vec, petsc_viewer);
01298       LIBMESH_CHKERRABORT(ierr);
01299     }
01300 
01304   else
01305     {
01306       ierr = PetscViewerSetFormat (PETSC_VIEWER_STDOUT_WORLD,
01307                                    PETSC_VIEWER_ASCII_MATLAB);
01308       LIBMESH_CHKERRABORT(ierr);
01309 
01310       ierr = VecView (_vec, PETSC_VIEWER_STDOUT_WORLD);
01311       LIBMESH_CHKERRABORT(ierr);
01312     }
01313 
01314 
01318   ierr = LibMeshPetscViewerDestroy (&petsc_viewer);
01319   LIBMESH_CHKERRABORT(ierr);
01320 }
01321 
01322 
01323 
01324 
01325 
01326 template <typename T>
01327 void PetscVector<T>::create_subvector(NumericVector<T>& subvector,
01328                                       const std::vector<numeric_index_type>& rows) const
01329 {
01330   this->_restore_array();
01331 
01332   // PETSc data structures
01333   IS parent_is, subvector_is;
01334   VecScatter scatter;
01335   PetscErrorCode ierr = 0;
01336 
01337   // Make sure the passed in subvector is really a PetscVector
01338   PetscVector<T>* petsc_subvector = cast_ptr<PetscVector<T>*>(&subvector);
01339 
01340   // If the petsc_subvector is already initialized, we assume that the
01341   // user has already allocated the *correct* amount of space for it.
01342   // If not, we use the appropriate PETSc routines to initialize it.
01343   if (!petsc_subvector->initialized())
01344     {
01345       // Initialize the petsc_subvector to have enough space to hold
01346       // the entries which will be scattered into it.  Note: such an
01347       // init() function (where we let PETSc decide the number of local
01348       // entries) is not currently offered by the PetscVector
01349       // class.  Should we differentiate here between sequential and
01350       // parallel vector creation based on this->n_processors() ?
01351       ierr = VecCreateMPI(this->comm().get(),
01352                           PETSC_DECIDE,                    // n_local
01353                           cast_int<PetscInt>(rows.size()), // n_global
01354                           &(petsc_subvector->_vec));
01355       LIBMESH_CHKERRABORT(ierr);
01356 
01357       ierr = VecSetFromOptions (petsc_subvector->_vec);
01358       LIBMESH_CHKERRABORT(ierr);
01359 
01360       // Mark the subvector as initialized
01361       petsc_subvector->_is_initialized = true;
01362     }
01363   else
01364     {
01365       petsc_subvector->_restore_array();
01366     }
01367 
01368   // Use iota to fill an array with entries [0,1,2,3,4,...rows.size()]
01369   std::vector<PetscInt> idx(rows.size());
01370   Utility::iota (idx.begin(), idx.end(), 0);
01371 
01372   // Construct index sets
01373   ierr = ISCreateLibMesh(this->comm().get(),
01374                          rows.size(),
01375                          numeric_petsc_cast(&rows[0]),
01376                          PETSC_USE_POINTER,
01377                          &parent_is);
01378   LIBMESH_CHKERRABORT(ierr);
01379 
01380   ierr = ISCreateLibMesh(this->comm().get(),
01381                          rows.size(),
01382                          &idx[0],
01383                          PETSC_USE_POINTER,
01384                          &subvector_is);
01385   LIBMESH_CHKERRABORT(ierr);
01386 
01387   // Construct the scatter object
01388   ierr = VecScatterCreate(this->_vec,
01389                           parent_is,
01390                           petsc_subvector->_vec,
01391                           subvector_is,
01392                           &scatter); LIBMESH_CHKERRABORT(ierr);
01393 
01394   // Actually perform the scatter
01395 #if PETSC_VERSION_LESS_THAN(2,3,3)
01396   ierr = VecScatterBegin(this->_vec,
01397                          petsc_subvector->_vec,
01398                          INSERT_VALUES,
01399                          SCATTER_FORWARD,
01400                          scatter); LIBMESH_CHKERRABORT(ierr);
01401 
01402   ierr = VecScatterEnd(this->_vec,
01403                        petsc_subvector->_vec,
01404                        INSERT_VALUES,
01405                        SCATTER_FORWARD,
01406                        scatter); LIBMESH_CHKERRABORT(ierr);
01407 #else
01408   // API argument order change in PETSc 2.3.3
01409   ierr = VecScatterBegin(scatter,
01410                          this->_vec,
01411                          petsc_subvector->_vec,
01412                          INSERT_VALUES,
01413                          SCATTER_FORWARD); LIBMESH_CHKERRABORT(ierr);
01414 
01415   ierr = VecScatterEnd(scatter,
01416                        this->_vec,
01417                        petsc_subvector->_vec,
01418                        INSERT_VALUES,
01419                        SCATTER_FORWARD); LIBMESH_CHKERRABORT(ierr);
01420 #endif
01421 
01422   // Clean up
01423   ierr = LibMeshISDestroy(&parent_is);       LIBMESH_CHKERRABORT(ierr);
01424   ierr = LibMeshISDestroy(&subvector_is);    LIBMESH_CHKERRABORT(ierr);
01425   ierr = LibMeshVecScatterDestroy(&scatter); LIBMESH_CHKERRABORT(ierr);
01426 
01427 }
01428 
01429 
01430 
01431 
01432 //------------------------------------------------------------------
01433 // Explicit instantiations
01434 template class PetscVector<Number>;
01435 
01436 } // namespace libMesh
01437 
01438 
01439 
01440 #endif // #ifdef LIBMESH_HAVE_PETSC