trilinos_epetra_vector.C
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 // C++ includes 00019 #include <limits> 00020 00021 // Local Includes 00022 #include "libmesh/trilinos_epetra_vector.h" 00023 00024 #ifdef LIBMESH_HAVE_TRILINOS 00025 00026 #include "libmesh/dense_subvector.h" 00027 #include "libmesh/dense_vector.h" 00028 #include "libmesh/parallel.h" 00029 #include "libmesh/trilinos_epetra_matrix.h" 00030 #include "libmesh/utility.h" 00031 00032 // Trilinos Includes 00033 #include <Epetra_LocalMap.h> 00034 #include <Epetra_Comm.h> 00035 #include <Epetra_Map.h> 00036 #include <Epetra_BlockMap.h> 00037 #include <Epetra_Import.h> 00038 #include <Epetra_Export.h> 00039 #include <Epetra_Util.h> 00040 #include <Epetra_IntSerialDenseVector.h> 00041 #include <Epetra_SerialDenseVector.h> 00042 #include <Epetra_Vector.h> 00043 00044 namespace libMesh 00045 { 00046 00047 template <typename T> 00048 T EpetraVector<T>::sum () const 00049 { 00050 libmesh_assert(this->closed()); 00051 00052 const unsigned int nl = _vec->MyLength(); 00053 00054 T sum=0.0; 00055 00056 T * values = _vec->Values(); 00057 00058 for (unsigned int i=0; i<nl; i++) 00059 sum += values[i]; 00060 00061 CommWorld.sum<T>(sum); 00062 00063 return sum; 00064 } 00065 00066 template <typename T> 00067 Real EpetraVector<T>::l1_norm () const 00068 { 00069 libmesh_assert(this->closed()); 00070 00071 Real value; 00072 00073 _vec->Norm1(&value); 00074 00075 return value; 00076 } 00077 00078 template <typename T> 00079 Real EpetraVector<T>::l2_norm () const 00080 { 00081 libmesh_assert(this->closed()); 00082 00083 Real value; 00084 00085 _vec->Norm2(&value); 00086 00087 return value; 00088 } 00089 00090 template <typename T> 00091 Real EpetraVector<T>::linfty_norm () const 00092 { 00093 libmesh_assert(this->closed()); 00094 00095 Real value; 00096 00097 _vec->NormInf(&value); 00098 00099 return value; 00100 } 00101 00102 template <typename T> 00103 NumericVector<T>& 00104 EpetraVector<T>::operator += (const NumericVector<T>& v) 00105 { 00106 libmesh_assert(this->closed()); 00107 00108 this->add(1., v); 00109 00110 return *this; 00111 } 00112 00113 00114 00115 template <typename T> 00116 NumericVector<T>& 00117 EpetraVector<T>::operator -= (const NumericVector<T>& v) 00118 { 00119 libmesh_assert(this->closed()); 00120 00121 this->add(-1., v); 00122 00123 return *this; 00124 } 00125 00126 00127 00128 template <typename T> 00129 void EpetraVector<T>::set (const unsigned int i_in, const T value_in) 00130 { 00131 int i = static_cast<int> (i_in); 00132 T value = value_in; 00133 00134 libmesh_assert_less (i_in, this->size()); 00135 00136 ReplaceGlobalValues(1, &i, &value); 00137 00138 this->_is_closed = false; 00139 } 00140 00141 00142 00143 template <typename T> 00144 void EpetraVector<T>::reciprocal() 00145 { 00146 // The Epetra::reciprocal() function takes a constant reference to *another* vector, 00147 // and fills _vec with its reciprocal. Does that mean we can't pass *_vec as the 00148 // argument? 00149 // _vec->reciprocal( *_vec ); 00150 00151 // Alternatively, compute the reciprocal by hand... see also the add(T) member that does this... 00152 const unsigned int nl = _vec->MyLength(); 00153 00154 T* values = _vec->Values(); 00155 00156 for (unsigned int i=0; i<nl; i++) 00157 { 00158 // Don't divide by zero (maybe only check this in debug mode?) 00159 if (std::abs(values[i]) < std::numeric_limits<T>::min()) 00160 { 00161 libMesh::err << "Error, divide by zero in DistributedVector<T>::reciprocal()!" << std::endl; 00162 libmesh_error(); 00163 } 00164 00165 values[i] = 1. / values[i]; 00166 } 00167 00168 // Leave the vector in a closed state... 00169 this->close(); 00170 } 00171 00172 00173 00174 template <typename T> 00175 void EpetraVector<T>::add (const unsigned int i_in, const T value_in) 00176 { 00177 int i = static_cast<int> (i_in); 00178 T value = value_in; 00179 00180 libmesh_assert_less (i_in, this->size()); 00181 00182 SumIntoGlobalValues(1, &i, &value); 00183 00184 this->_is_closed = false; 00185 } 00186 00187 00188 00189 template <typename T> 00190 void EpetraVector<T>::add_vector (const std::vector<T>& v, 00191 const std::vector<unsigned int>& dof_indices) 00192 { 00193 libmesh_assert_equal_to (v.size(), dof_indices.size()); 00194 00195 SumIntoGlobalValues (v.size(), 00196 (int*) &dof_indices[0], 00197 const_cast<T*>(&v[0])); 00198 } 00199 00200 00201 00202 template <typename T> 00203 void EpetraVector<T>::add_vector (const NumericVector<T>& V, 00204 const std::vector<unsigned int>& dof_indices) 00205 { 00206 libmesh_assert_equal_to (V.size(), dof_indices.size()); 00207 00208 for (unsigned int i=0; i<V.size(); i++) 00209 this->add (dof_indices[i], V(i)); 00210 } 00211 00212 00213 00214 // TODO: fill this in after creating an EpetraMatrix 00215 template <typename T> 00216 void EpetraVector<T>::add_vector (const NumericVector<T>& V_in, 00217 const SparseMatrix<T>& A_in) 00218 { 00219 const EpetraVector<T>* V = libmesh_cast_ptr<const EpetraVector<T>*>(&V_in); 00220 const EpetraMatrix<T>* A = libmesh_cast_ptr<const EpetraMatrix<T>*>(&A_in); 00221 00222 // FIXME - does Trilinos let us do this *without* memory allocation? 00223 AutoPtr<NumericVector<T> > temp = V->zero_clone(); 00224 EpetraVector<T>* tempV = libmesh_cast_ptr<EpetraVector<T>*>(temp.get()); 00225 A->mat()->Multiply(false, *V->_vec, *tempV->_vec); 00226 *this += *temp; 00227 } 00228 00229 00230 00231 template <typename T> 00232 void EpetraVector<T>::add_vector (const DenseVector<T>& V_in, 00233 const std::vector<unsigned int>& dof_indices) 00234 { 00235 libmesh_assert_equal_to (V_in.size(), dof_indices.size()); 00236 00237 SumIntoGlobalValues(dof_indices.size(), 00238 (int *)&dof_indices[0], 00239 &const_cast<DenseVector<T> *>(&V_in)->get_values()[0]); 00240 } 00241 00242 00243 // TODO: fill this in after creating an EpetraMatrix 00244 template <typename T> 00245 void EpetraVector<T>::add_vector_transpose (const NumericVector<T>& /* V_in */, 00246 const SparseMatrix<T>& /* A_in */) 00247 { 00248 libmesh_not_implemented(); 00249 } 00250 00251 00252 00253 template <typename T> 00254 void EpetraVector<T>::add (const T v_in) 00255 { 00256 const unsigned int nl = _vec->MyLength(); 00257 00258 T * values = _vec->Values(); 00259 00260 for (unsigned int i=0; i<nl; i++) 00261 values[i]+=v_in; 00262 00263 this->_is_closed = false; 00264 } 00265 00266 00267 template <typename T> 00268 void EpetraVector<T>::add (const NumericVector<T>& v) 00269 { 00270 this->add (1., v); 00271 } 00272 00273 00274 template <typename T> 00275 void EpetraVector<T>::add (const T a_in, const NumericVector<T>& v_in) 00276 { 00277 const EpetraVector<T>* v = libmesh_cast_ptr<const EpetraVector<T>*>(&v_in); 00278 00279 libmesh_assert_equal_to (this->size(), v->size()); 00280 00281 _vec->Update(a_in,*v->_vec, 1.); 00282 } 00283 00284 00285 00286 template <typename T> 00287 void EpetraVector<T>::insert (const std::vector<T>& v, 00288 const std::vector<unsigned int>& dof_indices) 00289 { 00290 libmesh_assert_equal_to (v.size(), dof_indices.size()); 00291 00292 ReplaceGlobalValues (v.size(), 00293 (int*) &dof_indices[0], 00294 const_cast<T*>(&v[0])); 00295 } 00296 00297 00298 00299 template <typename T> 00300 void EpetraVector<T>::insert (const NumericVector<T>& V, 00301 const std::vector<unsigned int>& dof_indices) 00302 { 00303 libmesh_assert_equal_to (V.size(), dof_indices.size()); 00304 00305 // TODO: If V is an EpetraVector this can be optimized 00306 for (unsigned int i=0; i<V.size(); i++) 00307 this->set (dof_indices[i], V(i)); 00308 } 00309 00310 00311 00312 template <typename T> 00313 void EpetraVector<T>::insert (const DenseVector<T>& v, 00314 const std::vector<unsigned int>& dof_indices) 00315 { 00316 libmesh_assert_equal_to (v.size(), dof_indices.size()); 00317 00318 std::vector<T> &vals = const_cast<DenseVector<T>&>(v).get_values(); 00319 00320 ReplaceGlobalValues (v.size(), 00321 (int*) &dof_indices[0], 00322 &vals[0]); 00323 } 00324 00325 00326 00327 template <typename T> 00328 void EpetraVector<T>::insert (const DenseSubVector<T>& v, 00329 const std::vector<unsigned int>& dof_indices) 00330 { 00331 libmesh_assert_equal_to (v.size(), dof_indices.size()); 00332 00333 for (unsigned int i=0; i < v.size(); ++i) 00334 this->set (dof_indices[i], v(i)); 00335 } 00336 00337 00338 00339 template <typename T> 00340 void EpetraVector<T>::scale (const T factor_in) 00341 { 00342 _vec->Scale(factor_in); 00343 } 00344 00345 template <typename T> 00346 void EpetraVector<T>::abs() 00347 { 00348 _vec->Abs(*_vec); 00349 } 00350 00351 00352 template <typename T> 00353 T EpetraVector<T>::dot (const NumericVector<T>& V_in) const 00354 { 00355 const EpetraVector<T>* V = libmesh_cast_ptr<const EpetraVector<T>*>(&V_in); 00356 00357 T result=0.0; 00358 00359 _vec->Dot(*V->_vec, &result); 00360 00361 return result; 00362 } 00363 00364 00365 template <typename T> 00366 void EpetraVector<T>::pointwise_mult (const NumericVector<T>& vec1, 00367 const NumericVector<T>& vec2) 00368 { 00369 const EpetraVector<T>* V1 = libmesh_cast_ptr<const EpetraVector<T>*>(&vec1); 00370 const EpetraVector<T>* V2 = libmesh_cast_ptr<const EpetraVector<T>*>(&vec2); 00371 00372 _vec->Multiply(1.0, *V1->_vec, *V2->_vec, 0.0); 00373 } 00374 00375 00376 template <typename T> 00377 NumericVector<T>& 00378 EpetraVector<T>::operator = (const T s_in) 00379 { 00380 _vec->PutScalar(s_in); 00381 00382 return *this; 00383 } 00384 00385 00386 00387 template <typename T> 00388 NumericVector<T>& 00389 EpetraVector<T>::operator = (const NumericVector<T>& v_in) 00390 { 00391 const EpetraVector<T>* v = libmesh_cast_ptr<const EpetraVector<T>*>(&v_in); 00392 00393 *this = *v; 00394 00395 return *this; 00396 } 00397 00398 00399 00400 template <typename T> 00401 EpetraVector<T>& 00402 EpetraVector<T>::operator = (const EpetraVector<T>& v) 00403 { 00404 (*_vec) = *v._vec; 00405 00406 return *this; 00407 } 00408 00409 00410 00411 template <typename T> 00412 NumericVector<T>& 00413 EpetraVector<T>::operator = (const std::vector<T>& v) 00414 { 00415 T * values = _vec->Values(); 00416 00421 if(this->size() == v.size()) 00422 { 00423 const unsigned int nl=this->local_size(); 00424 const unsigned int fli=this->first_local_index(); 00425 00426 for(unsigned int i=0;i<nl;i++) 00427 values[i]=v[fli+i]; 00428 } 00429 00434 else 00435 { 00436 libmesh_assert_equal_to (v.size(), this->local_size()); 00437 00438 const unsigned int nl=this->local_size(); 00439 00440 for(unsigned int i=0;i<nl;i++) 00441 values[i]=v[i]; 00442 } 00443 00444 return *this; 00445 } 00446 00447 00448 00449 template <typename T> 00450 void EpetraVector<T>::localize (NumericVector<T>& v_local_in) const 00451 { 00452 EpetraVector<T>* v_local = libmesh_cast_ptr<EpetraVector<T>*>(&v_local_in); 00453 00454 Epetra_Map rootMap = Epetra_Util::Create_Root_Map( *_map, -1); 00455 v_local->_vec->ReplaceMap(rootMap); 00456 00457 Epetra_Import importer(v_local->_vec->Map(), *_map); 00458 v_local->_vec->Import(*_vec, importer, Insert); 00459 } 00460 00461 00462 00463 template <typename T> 00464 void EpetraVector<T>::localize (NumericVector<T>& v_local_in, 00465 const std::vector<unsigned int>& /* send_list */) const 00466 { 00467 // TODO: optimize to sync only the send list values 00468 this->localize(v_local_in); 00469 00470 // EpetraVector<T>* v_local = 00471 // libmesh_cast_ptr<EpetraVector<T>*>(&v_local_in); 00472 00473 // libmesh_assert(this->_map.get()); 00474 // libmesh_assert(v_local->_map.get()); 00475 // libmesh_assert_equal_to (v_local->local_size(), this->size()); 00476 // libmesh_assert_less_equal (send_list.size(), v_local->size()); 00477 00478 // Epetra_Import importer (*v_local->_map, *this->_map); 00479 00480 // v_local->_vec->Import (*this->_vec, importer, Insert); 00481 } 00482 00483 00484 template <typename T> 00485 void EpetraVector<T>::localize (const unsigned int /* first_local_idx */, 00486 const unsigned int /* last_local_idx */, 00487 const std::vector<unsigned int>& /* send_list */) 00488 { 00489 libmesh_not_implemented(); 00490 00491 // // Only good for serial vectors. 00492 // libmesh_assert_equal_to (this->size(), this->local_size()); 00493 // libmesh_assert_greater (last_local_idx, first_local_idx); 00494 // libmesh_assert_less_equal (send_list.size(), this->size()); 00495 // libmesh_assert_less (last_local_idx, this->size()); 00496 00497 // const unsigned int size = this->size(); 00498 // const unsigned int local_size = (last_local_idx - first_local_idx + 1); 00499 // int ierr=0; 00500 00501 // // Don't bother for serial cases 00502 // if ((first_local_idx == 0) && 00503 // (local_size == size)) 00504 // return; 00505 00506 00507 // // Build a parallel vector, initialize it with the local 00508 // // parts of (*this) 00509 // EpetraVector<T> parallel_vec; 00510 00511 // parallel_vec.init (size, local_size, true, PARALLEL); 00512 00513 00514 // // Copy part of *this into the parallel_vec 00515 // { 00516 // IS is; 00517 // VecScatter scatter; 00518 00519 // // Create idx, idx[i] = i+first_local_idx; 00520 // std::vector<int> idx(local_size); 00521 // Utility::iota (idx.begin(), idx.end(), first_local_idx); 00522 00523 // // Create the index set & scatter object 00524 // ierr = ISCreateGeneral(libMesh::COMM_WORLD, local_size, &idx[0], &is); 00525 // CHKERRABORT(libMesh::COMM_WORLD,ierr); 00526 00527 // ierr = VecScatterCreate(_vec, is, 00528 // parallel_vec._vec, is, 00529 // &scatter); 00530 // CHKERRABORT(libMesh::COMM_WORLD,ierr); 00531 00532 // // Perform the scatter 00533 // #if EPETRA_VERSION_LESS_THAN(2,3,3) 00534 00535 // ierr = VecScatterBegin(_vec, parallel_vec._vec, INSERT_VALUES, 00536 // SCATTER_FORWARD, scatter); 00537 // CHKERRABORT(libMesh::COMM_WORLD,ierr); 00538 00539 // ierr = VecScatterEnd (_vec, parallel_vec._vec, INSERT_VALUES, 00540 // SCATTER_FORWARD, scatter); 00541 // CHKERRABORT(libMesh::COMM_WORLD,ierr); 00542 00543 // #else 00544 00545 // // API argument order change in Epetra 2.3.3 00546 // ierr = VecScatterBegin(scatter, _vec, parallel_vec._vec, 00547 // INSERT_VALUES, SCATTER_FORWARD); 00548 // CHKERRABORT(libMesh::COMM_WORLD,ierr); 00549 00550 // ierr = VecScatterEnd (scatter, _vec, parallel_vec._vec, 00551 // INSERT_VALUES, SCATTER_FORWARD); 00552 // CHKERRABORT(libMesh::COMM_WORLD,ierr); 00553 00554 // #endif 00555 00556 // // Clean up 00557 // ierr = LibMeshISDestroy (is); 00558 // CHKERRABORT(libMesh::COMM_WORLD,ierr); 00559 00560 // ierr = LibMeshVecScatterDestroy(scatter); 00561 // CHKERRABORT(libMesh::COMM_WORLD,ierr); 00562 // } 00563 00564 // // localize like normal 00565 // parallel_vec.close(); 00566 // parallel_vec.localize (*this, send_list); 00567 // this->close(); 00568 } 00569 00570 00571 00572 template <typename T> 00573 void EpetraVector<T>::localize (std::vector<T>& v_local) const 00574 { 00575 // This function must be run on all processors at once 00576 parallel_only(); 00577 00578 const unsigned int n = this->size(); 00579 const unsigned int nl = this->local_size(); 00580 00581 libmesh_assert(this->_vec); 00582 00583 v_local.clear(); 00584 v_local.reserve(n); 00585 00586 // build up my local part 00587 for (unsigned int i=0; i<nl; i++) 00588 v_local.push_back((*this->_vec)[i]); 00589 00590 CommWorld.allgather (v_local); 00591 } 00592 00593 00594 00595 template <typename T> 00596 void EpetraVector<T>::localize_to_one (std::vector<T>& v_local, 00597 const processor_id_type pid) const 00598 { 00599 // This function must be run on all processors at once 00600 parallel_only(); 00601 00602 const unsigned int n = this->size(); 00603 const unsigned int nl = this->local_size(); 00604 00605 libmesh_assert_less (pid, libMesh::n_processors()); 00606 libmesh_assert(this->_vec); 00607 00608 v_local.clear(); 00609 v_local.reserve(n); 00610 00611 00612 // build up my local part 00613 for (unsigned int i=0; i<nl; i++) 00614 v_local.push_back((*this->_vec)[i]); 00615 00616 CommWorld.gather (pid, v_local); 00617 } 00618 00619 00620 00621 template <typename T> 00622 void EpetraVector<T>::print_matlab (const std::string /* name */) const 00623 { 00624 libmesh_not_implemented(); 00625 00626 // libmesh_assert (this->initialized()); 00627 // libmesh_assert (this->closed()); 00628 00629 // int ierr=0; 00630 // EpetraViewer epetra_viewer; 00631 00632 00633 // ierr = EpetraViewerCreate (libMesh::COMM_WORLD, 00634 // &epetra_viewer); 00635 // CHKERRABORT(libMesh::COMM_WORLD,ierr); 00636 00637 // /** 00638 // * Create an ASCII file containing the matrix 00639 // * if a filename was provided. 00640 // */ 00641 // if (name != "NULL") 00642 // { 00643 // ierr = EpetraViewerASCIIOpen( libMesh::COMM_WORLD, 00644 // name.c_str(), 00645 // &epetra_viewer); 00646 // CHKERRABORT(libMesh::COMM_WORLD,ierr); 00647 00648 // ierr = EpetraViewerSetFormat (epetra_viewer, 00649 // EPETRA_VIEWER_ASCII_MATLAB); 00650 // CHKERRABORT(libMesh::COMM_WORLD,ierr); 00651 00652 // ierr = VecView (_vec, epetra_viewer); 00653 // CHKERRABORT(libMesh::COMM_WORLD,ierr); 00654 // } 00655 00656 // /** 00657 // * Otherwise the matrix will be dumped to the screen. 00658 // */ 00659 // else 00660 // { 00661 // ierr = EpetraViewerSetFormat (EPETRA_VIEWER_STDOUT_WORLD, 00662 // EPETRA_VIEWER_ASCII_MATLAB); 00663 // CHKERRABORT(libMesh::COMM_WORLD,ierr); 00664 00665 // ierr = VecView (_vec, EPETRA_VIEWER_STDOUT_WORLD); 00666 // CHKERRABORT(libMesh::COMM_WORLD,ierr); 00667 // } 00668 00669 00670 // /** 00671 // * Destroy the viewer. 00672 // */ 00673 // ierr = EpetraViewerDestroy (epetra_viewer); 00674 // CHKERRABORT(libMesh::COMM_WORLD,ierr); 00675 } 00676 00677 00678 00679 00680 00681 template <typename T> 00682 void EpetraVector<T>::create_subvector(NumericVector<T>& /* subvector */, 00683 const std::vector<unsigned int>& /* rows */) const 00684 { 00685 libmesh_not_implemented(); 00686 00687 // // Epetra data structures 00688 // IS parent_is, subvector_is; 00689 // VecScatter scatter; 00690 // int ierr = 0; 00691 00692 // // Make sure the passed int subvector is really a EpetraVector 00693 // EpetraVector<T>* epetra_subvector = libmesh_cast_ptr<EpetraVector<T>*>(&subvector); 00694 // libmesh_assert(epetra_subvector); 00695 00696 // // If the epetra_subvector is already initialized, we assume that the 00697 // // user has already allocated the *correct* amount of space for it. 00698 // // If not, we use the appropriate Epetra routines to initialize it. 00699 // if (!epetra_subvector->initialized()) 00700 // { 00701 // // Initialize the epetra_subvector to have enough space to hold 00702 // // the entries which will be scattered into it. Note: such an 00703 // // init() function (where we let Epetra decide the number of local 00704 // // entries) is not currently offered by the EpetraVector 00705 // // class. Should we differentiate here between sequential and 00706 // // parallel vector creation based on libMesh::n_processors() ? 00707 // ierr = VecCreateMPI(libMesh::COMM_WORLD, 00708 // EPETRA_DECIDE, // n_local 00709 // rows.size(), // n_global 00710 // &(epetra_subvector->_vec)); CHKERRABORT(libMesh::COMM_WORLD,ierr); 00711 00712 // ierr = VecSetFromOptions (epetra_subvector->_vec); CHKERRABORT(libMesh::COMM_WORLD,ierr); 00713 00714 // // Mark the subvector as initialized 00715 // epetra_subvector->_is_initialized = true; 00716 // } 00717 00718 // // Use iota to fill an array with entries [0,1,2,3,4,...rows.size()] 00719 // std::vector<int> idx(rows.size()); 00720 // Utility::iota (idx.begin(), idx.end(), 0); 00721 00722 // // Construct index sets 00723 // ierr = ISCreateGeneral(libMesh::COMM_WORLD, 00724 // rows.size(), 00725 // (int*) &rows[0], 00726 // &parent_is); CHKERRABORT(libMesh::COMM_WORLD,ierr); 00727 00728 // ierr = ISCreateGeneral(libMesh::COMM_WORLD, 00729 // rows.size(), 00730 // (int*) &idx[0], 00731 // &subvector_is); CHKERRABORT(libMesh::COMM_WORLD,ierr); 00732 00733 // // Construct the scatter object 00734 // ierr = VecScatterCreate(this->_vec, 00735 // parent_is, 00736 // epetra_subvector->_vec, 00737 // subvector_is, 00738 // &scatter); CHKERRABORT(libMesh::COMM_WORLD,ierr); 00739 00740 // // Actually perform the scatter 00741 // #if EPETRA_VERSION_LESS_THAN(2,3,3) 00742 // ierr = VecScatterBegin(this->_vec, 00743 // epetra_subvector->_vec, 00744 // INSERT_VALUES, 00745 // SCATTER_FORWARD, 00746 // scatter); CHKERRABORT(libMesh::COMM_WORLD,ierr); 00747 00748 // ierr = VecScatterEnd(this->_vec, 00749 // epetra_subvector->_vec, 00750 // INSERT_VALUES, 00751 // SCATTER_FORWARD, 00752 // scatter); CHKERRABORT(libMesh::COMM_WORLD,ierr); 00753 // #else 00754 // // API argument order change in Epetra 2.3.3 00755 // ierr = VecScatterBegin(scatter, 00756 // this->_vec, 00757 // epetra_subvector->_vec, 00758 // INSERT_VALUES, 00759 // SCATTER_FORWARD); CHKERRABORT(libMesh::COMM_WORLD,ierr); 00760 00761 // ierr = VecScatterEnd(scatter, 00762 // this->_vec, 00763 // epetra_subvector->_vec, 00764 // INSERT_VALUES, 00765 // SCATTER_FORWARD); CHKERRABORT(libMesh::COMM_WORLD,ierr); 00766 // #endif 00767 00768 // // Clean up 00769 // ierr = LibMeshISDestroy(parent_is); CHKERRABORT(libMesh::COMM_WORLD,ierr); 00770 // ierr = LibMeshISDestroy(subvector_is); CHKERRABORT(libMesh::COMM_WORLD,ierr); 00771 // ierr = LibMeshVecScatterDestroy(scatter); CHKERRABORT(libMesh::COMM_WORLD,ierr); 00772 } 00773 00774 00775 /********************************************************************* 00776 * The following were copied (and slightly modified) from 00777 * Epetra_FEVector.h in order to allow us to use a standard 00778 * Epetra_Vector... which is more compatible with other Trilinos 00779 * packages such as NOX. All of this code is originally under LGPL 00780 *********************************************************************/ 00781 00782 //---------------------------------------------------------------------------- 00783 template <typename T> 00784 int EpetraVector<T>::SumIntoGlobalValues(int numIDs, const int* GIDs, 00785 const double* values) 00786 { 00787 return( inputValues( numIDs, GIDs, values, true) ); 00788 } 00789 00790 //---------------------------------------------------------------------------- 00791 template <typename T> 00792 int EpetraVector<T>::SumIntoGlobalValues(const Epetra_IntSerialDenseVector& GIDs, 00793 const Epetra_SerialDenseVector& values) 00794 { 00795 if (GIDs.Length() != values.Length()) { 00796 return(-1); 00797 } 00798 00799 return( inputValues( GIDs.Length(), GIDs.Values(), values.Values(), true) ); 00800 } 00801 00802 //---------------------------------------------------------------------------- 00803 template <typename T> 00804 int EpetraVector<T>::SumIntoGlobalValues(int numIDs, const int* GIDs, 00805 const int* numValuesPerID, 00806 const double* values) 00807 { 00808 return( inputValues( numIDs, GIDs, numValuesPerID, values, true) ); 00809 } 00810 00811 //---------------------------------------------------------------------------- 00812 template <typename T> 00813 int EpetraVector<T>::ReplaceGlobalValues(int numIDs, const int* GIDs, 00814 const double* values) 00815 { 00816 return( inputValues( numIDs, GIDs, values, false) ); 00817 } 00818 00819 //---------------------------------------------------------------------------- 00820 template <typename T> 00821 int EpetraVector<T>::ReplaceGlobalValues(const Epetra_IntSerialDenseVector& GIDs, 00822 const Epetra_SerialDenseVector& values) 00823 { 00824 if (GIDs.Length() != values.Length()) { 00825 return(-1); 00826 } 00827 00828 return( inputValues( GIDs.Length(), GIDs.Values(), values.Values(), false) ); 00829 } 00830 00831 //---------------------------------------------------------------------------- 00832 template <typename T> 00833 int EpetraVector<T>::ReplaceGlobalValues(int numIDs, const int* GIDs, 00834 const int* numValuesPerID, 00835 const double* values) 00836 { 00837 return( inputValues( numIDs, GIDs, numValuesPerID, values, false) ); 00838 } 00839 00840 //---------------------------------------------------------------------------- 00841 template <typename T> 00842 int EpetraVector<T>::inputValues(int numIDs, 00843 const int* GIDs, 00844 const double* values, 00845 bool accumulate) 00846 { 00847 //Important note!! This method assumes that there is only 1 point 00848 //associated with each element. 00849 00850 for(int i=0; i<numIDs; ++i) { 00851 if (_vec->Map().MyGID(GIDs[i])) { 00852 if (accumulate) { 00853 _vec->SumIntoGlobalValue(GIDs[i], 0, 0, values[i]); 00854 } 00855 else { 00856 _vec->ReplaceGlobalValue(GIDs[i], 0, 0, values[i]); 00857 } 00858 } 00859 else { 00860 if (!ignoreNonLocalEntries_) { 00861 EPETRA_CHK_ERR( inputNonlocalValue(GIDs[i], values[i], accumulate) ); 00862 } 00863 } 00864 } 00865 00866 return(0); 00867 } 00868 00869 //---------------------------------------------------------------------------- 00870 template <typename T> 00871 int EpetraVector<T>::inputValues(int numIDs, 00872 const int* GIDs, 00873 const int* numValuesPerID, 00874 const double* values, 00875 bool accumulate) 00876 { 00877 int offset=0; 00878 for(int i=0; i<numIDs; ++i) { 00879 int numValues = numValuesPerID[i]; 00880 if (_vec->Map().MyGID(GIDs[i])) { 00881 if (accumulate) { 00882 for(int j=0; j<numValues; ++j) { 00883 _vec->SumIntoGlobalValue(GIDs[i], j, 0, values[offset+j]); 00884 } 00885 } 00886 else { 00887 for(int j=0; j<numValues; ++j) { 00888 _vec->ReplaceGlobalValue(GIDs[i], j, 0, values[offset+j]); 00889 } 00890 } 00891 } 00892 else { 00893 if (!ignoreNonLocalEntries_) { 00894 EPETRA_CHK_ERR( inputNonlocalValues(GIDs[i], numValues, 00895 &(values[offset]), accumulate) ); 00896 } 00897 } 00898 offset += numValues; 00899 } 00900 00901 return(0); 00902 } 00903 00904 //---------------------------------------------------------------------------- 00905 template <typename T> 00906 int EpetraVector<T>::inputNonlocalValue(int GID, double value, bool accumulate) 00907 { 00908 int insertPoint = -1; 00909 00910 //find offset of GID in nonlocalIDs_ 00911 int offset = Epetra_Util_binary_search(GID, nonlocalIDs_, numNonlocalIDs_, 00912 insertPoint); 00913 if (offset >= 0) { 00914 //if offset >= 0 00915 // put value in nonlocalCoefs_[offset][0] 00916 00917 if (accumulate) { 00918 nonlocalCoefs_[offset][0] += value; 00919 } 00920 else { 00921 nonlocalCoefs_[offset][0] = value; 00922 } 00923 } 00924 else { 00925 //else 00926 // insert GID in nonlocalIDs_ 00927 // insert 1 in nonlocalElementSize_ 00928 // insert value in nonlocalCoefs_ 00929 00930 int tmp1 = numNonlocalIDs_; 00931 int tmp2 = allocatedNonlocalLength_; 00932 int tmp3 = allocatedNonlocalLength_; 00933 EPETRA_CHK_ERR( Epetra_Util_insert(GID, insertPoint, nonlocalIDs_, 00934 tmp1, tmp2) ); 00935 --tmp1; 00936 EPETRA_CHK_ERR( Epetra_Util_insert(1, insertPoint, nonlocalElementSize_, 00937 tmp1, tmp3) ); 00938 double* values = new double[1]; 00939 values[0] = value; 00940 EPETRA_CHK_ERR( Epetra_Util_insert(values, insertPoint, nonlocalCoefs_, 00941 numNonlocalIDs_, allocatedNonlocalLength_) ); 00942 } 00943 00944 return(0); 00945 } 00946 00947 //---------------------------------------------------------------------------- 00948 template <typename T> 00949 int EpetraVector<T>::inputNonlocalValues(int GID, int numValues, 00950 const double* values, bool accumulate) 00951 { 00952 int insertPoint = -1; 00953 00954 //find offset of GID in nonlocalIDs_ 00955 int offset = Epetra_Util_binary_search(GID, nonlocalIDs_, numNonlocalIDs_, 00956 insertPoint); 00957 if (offset >= 0) { 00958 //if offset >= 0 00959 // put value in nonlocalCoefs_[offset][0] 00960 00961 if (numValues != nonlocalElementSize_[offset]) { 00962 cerr << "Epetra_FEVector ERROR: block-size for GID " << GID << " is " 00963 << numValues<<" which doesn't match previously set block-size of " 00964 << nonlocalElementSize_[offset] << endl; 00965 return(-1); 00966 } 00967 00968 if (accumulate) { 00969 for(int j=0; j<numValues; ++j) { 00970 nonlocalCoefs_[offset][j] += values[j]; 00971 } 00972 } 00973 else { 00974 for(int j=0; j<numValues; ++j) { 00975 nonlocalCoefs_[offset][j] = values[j]; 00976 } 00977 } 00978 } 00979 else { 00980 //else 00981 // insert GID in nonlocalIDs_ 00982 // insert numValues in nonlocalElementSize_ 00983 // insert values in nonlocalCoefs_ 00984 00985 int tmp1 = numNonlocalIDs_; 00986 int tmp2 = allocatedNonlocalLength_; 00987 int tmp3 = allocatedNonlocalLength_; 00988 EPETRA_CHK_ERR( Epetra_Util_insert(GID, insertPoint, nonlocalIDs_, 00989 tmp1, tmp2) ); 00990 --tmp1; 00991 EPETRA_CHK_ERR( Epetra_Util_insert(numValues, insertPoint, nonlocalElementSize_, 00992 tmp1, tmp3) ); 00993 double* newvalues = new double[numValues]; 00994 for(int j=0; j<numValues; ++j) { 00995 newvalues[j] = values[j]; 00996 } 00997 EPETRA_CHK_ERR( Epetra_Util_insert(newvalues, insertPoint, nonlocalCoefs_, 00998 numNonlocalIDs_, allocatedNonlocalLength_) ); 00999 } 01000 01001 return(0); 01002 } 01003 01004 //---------------------------------------------------------------------------- 01005 template <typename T> 01006 int EpetraVector<T>::GlobalAssemble(Epetra_CombineMode mode) 01007 { 01008 //In this method we need to gather all the non-local (overlapping) data 01009 //that's been input on each processor, into the (probably) non-overlapping 01010 //distribution defined by the map that 'this' vector was constructed with. 01011 01012 //We don't need to do anything if there's only one processor or if 01013 //ignoreNonLocalEntries_ is true. 01014 if (_vec->Map().Comm().NumProc() < 2 || ignoreNonLocalEntries_) { 01015 return(0); 01016 } 01017 01018 01019 01020 //First build a map that describes the data in nonlocalIDs_/nonlocalCoefs_. 01021 //We'll use the arbitrary distribution constructor of Map. 01022 01023 Epetra_BlockMap sourceMap(-1, numNonlocalIDs_, 01024 nonlocalIDs_, nonlocalElementSize_, 01025 _vec->Map().IndexBase(), _vec->Map().Comm()); 01026 01027 //Now build a vector to hold our nonlocalCoefs_, and to act as the source- 01028 //vector for our import operation. 01029 Epetra_MultiVector nonlocalVector(sourceMap, 1); 01030 01031 int i,j; 01032 for(i=0; i<numNonlocalIDs_; ++i) { 01033 for(j=0; j<nonlocalElementSize_[i]; ++j) { 01034 nonlocalVector.ReplaceGlobalValue(nonlocalIDs_[i], j, 0, 01035 nonlocalCoefs_[i][j]); 01036 } 01037 } 01038 01039 Epetra_Export exporter(sourceMap, _vec->Map()); 01040 01041 EPETRA_CHK_ERR( _vec->Export(nonlocalVector, exporter, mode) ); 01042 01043 destroyNonlocalData(); 01044 01045 return(0); 01046 } 01047 01048 01049 //---------------------------------------------------------------------------- 01050 template <typename T> 01051 void EpetraVector<T>::FEoperatorequals(const EpetraVector& source) 01052 { 01053 (*_vec) = *(source._vec); 01054 01055 destroyNonlocalData(); 01056 01057 if (source.allocatedNonlocalLength_ > 0) { 01058 allocatedNonlocalLength_ = source.allocatedNonlocalLength_; 01059 numNonlocalIDs_ = source.numNonlocalIDs_; 01060 nonlocalIDs_ = new int[allocatedNonlocalLength_]; 01061 nonlocalElementSize_ = new int[allocatedNonlocalLength_]; 01062 nonlocalCoefs_ = new double*[allocatedNonlocalLength_]; 01063 for(int i=0; i<numNonlocalIDs_; ++i) { 01064 int elemSize = source.nonlocalElementSize_[i]; 01065 nonlocalCoefs_[i] = new double[elemSize]; 01066 nonlocalIDs_[i] = source.nonlocalIDs_[i]; 01067 nonlocalElementSize_[i] = elemSize; 01068 for(int j=0; j<elemSize; ++j) { 01069 nonlocalCoefs_[i][j] = source.nonlocalCoefs_[i][j]; 01070 } 01071 } 01072 } 01073 } 01074 01075 01076 //---------------------------------------------------------------------------- 01077 template <typename T> 01078 void EpetraVector<T>::destroyNonlocalData() 01079 { 01080 if (allocatedNonlocalLength_ > 0) { 01081 delete [] nonlocalIDs_; 01082 delete [] nonlocalElementSize_; 01083 nonlocalIDs_ = NULL; 01084 nonlocalElementSize_ = NULL; 01085 for(int i=0; i<numNonlocalIDs_; ++i) { 01086 delete [] nonlocalCoefs_[i]; 01087 } 01088 delete [] nonlocalCoefs_; 01089 nonlocalCoefs_ = NULL; 01090 numNonlocalIDs_ = 0; 01091 allocatedNonlocalLength_ = 0; 01092 } 01093 return; 01094 } 01095 01096 01097 //------------------------------------------------------------------ 01098 // Explicit instantiations 01099 template class EpetraVector<Number>; 01100 01101 } // namespace libMesh 01102 01103 #endif // #ifdef HAVE_EPETRA
Site Created By: libMesh Developers
Last modified: February 05 2013 19:54:49 UTC
Hosted By: