$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 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