$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 // 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 this->comm().sum(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 template <typename T> 00128 NumericVector<T> & 00129 EpetraVector<T>::operator /= (NumericVector<T> & v) 00130 { 00131 libmesh_assert(this->closed()); 00132 libmesh_assert_equal_to(size(), v.size()); 00133 00134 EpetraVector<T> & v_vec = cast_ref<EpetraVector<T>&>(v); 00135 00136 _vec->ReciprocalMultiply(1.0, *v_vec._vec, *_vec, 0.0); 00137 } 00138 00139 00140 00141 00142 template <typename T> 00143 void EpetraVector<T>::set (const numeric_index_type i_in, const T value_in) 00144 { 00145 int i = static_cast<int> (i_in); 00146 T value = value_in; 00147 00148 libmesh_assert_less (i_in, this->size()); 00149 00150 ReplaceGlobalValues(1, &i, &value); 00151 00152 this->_is_closed = false; 00153 } 00154 00155 00156 00157 template <typename T> 00158 void EpetraVector<T>::reciprocal() 00159 { 00160 // The Epetra::reciprocal() function takes a constant reference to *another* vector, 00161 // and fills _vec with its reciprocal. Does that mean we can't pass *_vec as the 00162 // argument? 00163 // _vec->reciprocal( *_vec ); 00164 00165 // Alternatively, compute the reciprocal by hand... see also the add(T) member that does this... 00166 const unsigned int nl = _vec->MyLength(); 00167 00168 T* values = _vec->Values(); 00169 00170 for (unsigned int i=0; i<nl; i++) 00171 { 00172 // Don't divide by zero (maybe only check this in debug mode?) 00173 if (std::abs(values[i]) < std::numeric_limits<T>::min()) 00174 libmesh_error_msg("Error, divide by zero in DistributedVector<T>::reciprocal()!"); 00175 00176 values[i] = 1. / values[i]; 00177 } 00178 00179 // Leave the vector in a closed state... 00180 this->close(); 00181 } 00182 00183 00184 00185 template <typename T> 00186 void EpetraVector<T>::conjugate() 00187 { 00188 // EPetra is real, rendering this a no-op. 00189 } 00190 00191 00192 00193 template <typename T> 00194 void EpetraVector<T>::add (const numeric_index_type i_in, const T value_in) 00195 { 00196 int i = static_cast<int> (i_in); 00197 T value = value_in; 00198 00199 libmesh_assert_less (i_in, this->size()); 00200 00201 SumIntoGlobalValues(1, &i, &value); 00202 00203 this->_is_closed = false; 00204 } 00205 00206 00207 00208 template <typename T> 00209 void EpetraVector<T>::add_vector (const T* v, 00210 const std::vector<numeric_index_type>& dof_indices) 00211 { 00212 libmesh_assert_equal_to (sizeof(numeric_index_type), sizeof(int)); 00213 00214 SumIntoGlobalValues (dof_indices.size(), 00215 (int*) &dof_indices[0], 00216 const_cast<T*>(v)); 00217 } 00218 00219 00220 00221 // TODO: fill this in after creating an EpetraMatrix 00222 template <typename T> 00223 void EpetraVector<T>::add_vector (const NumericVector<T>& V_in, 00224 const SparseMatrix<T>& A_in) 00225 { 00226 const EpetraVector<T>* V = cast_ptr<const EpetraVector<T>*>(&V_in); 00227 const EpetraMatrix<T>* A = cast_ptr<const EpetraMatrix<T>*>(&A_in); 00228 00229 // FIXME - does Trilinos let us do this *without* memory allocation? 00230 UniquePtr<NumericVector<T> > temp = V->zero_clone(); 00231 EpetraVector<T>* tempV = cast_ptr<EpetraVector<T>*>(temp.get()); 00232 A->mat()->Multiply(false, *V->_vec, *tempV->_vec); 00233 *this += *temp; 00234 } 00235 00236 00237 00238 // TODO: fill this in after creating an EpetraMatrix 00239 template <typename T> 00240 void EpetraVector<T>::add_vector_transpose (const NumericVector<T>& /* V_in */, 00241 const SparseMatrix<T>& /* A_in */) 00242 { 00243 libmesh_not_implemented(); 00244 } 00245 00246 00247 00248 template <typename T> 00249 void EpetraVector<T>::add (const T v_in) 00250 { 00251 const unsigned int nl = _vec->MyLength(); 00252 00253 T * values = _vec->Values(); 00254 00255 for (unsigned int i=0; i<nl; i++) 00256 values[i]+=v_in; 00257 00258 this->_is_closed = false; 00259 } 00260 00261 00262 template <typename T> 00263 void EpetraVector<T>::add (const NumericVector<T>& v) 00264 { 00265 this->add (1., v); 00266 } 00267 00268 00269 template <typename T> 00270 void EpetraVector<T>::add (const T a_in, const NumericVector<T>& v_in) 00271 { 00272 const EpetraVector<T>* v = cast_ptr<const EpetraVector<T>*>(&v_in); 00273 00274 libmesh_assert_equal_to (this->size(), v->size()); 00275 00276 _vec->Update(a_in,*v->_vec, 1.); 00277 } 00278 00279 00280 00281 template <typename T> 00282 void EpetraVector<T>::insert (const T* v, 00283 const std::vector<numeric_index_type>& dof_indices) 00284 { 00285 libmesh_assert_equal_to (sizeof(numeric_index_type), sizeof(int)); 00286 00287 ReplaceGlobalValues (dof_indices.size(), 00288 (int*) &dof_indices[0], 00289 const_cast<T*>(v)); 00290 } 00291 00292 00293 00294 template <typename T> 00295 void EpetraVector<T>::scale (const T factor_in) 00296 { 00297 _vec->Scale(factor_in); 00298 } 00299 00300 template <typename T> 00301 void EpetraVector<T>::abs() 00302 { 00303 _vec->Abs(*_vec); 00304 } 00305 00306 00307 template <typename T> 00308 T EpetraVector<T>::dot (const NumericVector<T>& V_in) const 00309 { 00310 const EpetraVector<T>* V = cast_ptr<const EpetraVector<T>*>(&V_in); 00311 00312 T result=0.0; 00313 00314 _vec->Dot(*V->_vec, &result); 00315 00316 return result; 00317 } 00318 00319 00320 template <typename T> 00321 void EpetraVector<T>::pointwise_mult (const NumericVector<T>& vec1, 00322 const NumericVector<T>& vec2) 00323 { 00324 const EpetraVector<T>* V1 = cast_ptr<const EpetraVector<T>*>(&vec1); 00325 const EpetraVector<T>* V2 = cast_ptr<const EpetraVector<T>*>(&vec2); 00326 00327 _vec->Multiply(1.0, *V1->_vec, *V2->_vec, 0.0); 00328 } 00329 00330 00331 template <typename T> 00332 NumericVector<T>& 00333 EpetraVector<T>::operator = (const T s_in) 00334 { 00335 _vec->PutScalar(s_in); 00336 00337 return *this; 00338 } 00339 00340 00341 00342 template <typename T> 00343 NumericVector<T>& 00344 EpetraVector<T>::operator = (const NumericVector<T>& v_in) 00345 { 00346 const EpetraVector<T>* v = cast_ptr<const EpetraVector<T>*>(&v_in); 00347 00348 *this = *v; 00349 00350 return *this; 00351 } 00352 00353 00354 00355 template <typename T> 00356 EpetraVector<T>& 00357 EpetraVector<T>::operator = (const EpetraVector<T>& v) 00358 { 00359 (*_vec) = *v._vec; 00360 00361 // FIXME - what about our communications data? 00362 00363 return *this; 00364 } 00365 00366 00367 00368 template <typename T> 00369 NumericVector<T>& 00370 EpetraVector<T>::operator = (const std::vector<T>& v) 00371 { 00372 T * values = _vec->Values(); 00373 00378 if(this->size() == v.size()) 00379 { 00380 const unsigned int nl=this->local_size(); 00381 const unsigned int fli=this->first_local_index(); 00382 00383 for(unsigned int i=0;i<nl;i++) 00384 values[i]=v[fli+i]; 00385 } 00386 00391 else 00392 { 00393 libmesh_assert_equal_to (v.size(), this->local_size()); 00394 00395 const unsigned int nl=this->local_size(); 00396 00397 for(unsigned int i=0;i<nl;i++) 00398 values[i]=v[i]; 00399 } 00400 00401 return *this; 00402 } 00403 00404 00405 00406 template <typename T> 00407 void EpetraVector<T>::localize (NumericVector<T>& v_local_in) const 00408 { 00409 EpetraVector<T>* v_local = cast_ptr<EpetraVector<T>*>(&v_local_in); 00410 00411 Epetra_Map rootMap = Epetra_Util::Create_Root_Map( *_map, -1); 00412 v_local->_vec->ReplaceMap(rootMap); 00413 00414 Epetra_Import importer(v_local->_vec->Map(), *_map); 00415 v_local->_vec->Import(*_vec, importer, Insert); 00416 } 00417 00418 00419 00420 template <typename T> 00421 void EpetraVector<T>::localize (NumericVector<T>& v_local_in, 00422 const std::vector<numeric_index_type>& /* send_list */) const 00423 { 00424 // TODO: optimize to sync only the send list values 00425 this->localize(v_local_in); 00426 00427 // EpetraVector<T>* v_local = 00428 // cast_ptr<EpetraVector<T>*>(&v_local_in); 00429 00430 // libmesh_assert(this->_map.get()); 00431 // libmesh_assert(v_local->_map.get()); 00432 // libmesh_assert_equal_to (v_local->local_size(), this->size()); 00433 // libmesh_assert_less_equal (send_list.size(), v_local->size()); 00434 00435 // Epetra_Import importer (*v_local->_map, *this->_map); 00436 00437 // v_local->_vec->Import (*this->_vec, importer, Insert); 00438 } 00439 00440 00441 template <typename T> 00442 void EpetraVector<T>::localize (const numeric_index_type first_local_idx, 00443 const numeric_index_type last_local_idx, 00444 const std::vector<numeric_index_type>& send_list) 00445 { 00446 // Only good for serial vectors. 00447 libmesh_assert_equal_to (this->size(), this->local_size()); 00448 libmesh_assert_greater (last_local_idx, first_local_idx); 00449 libmesh_assert_less_equal (send_list.size(), this->size()); 00450 libmesh_assert_less (last_local_idx, this->size()); 00451 00452 const unsigned int my_size = this->size(); 00453 const unsigned int my_local_size = (last_local_idx - first_local_idx + 1); 00454 00455 // Don't bother for serial cases 00456 if ((first_local_idx == 0) && 00457 (my_local_size == my_size)) 00458 return; 00459 00460 // Build a parallel vector, initialize it with the local 00461 // parts of (*this) 00462 EpetraVector<T> parallel_vec(this->comm(), PARALLEL); 00463 00464 parallel_vec.init (my_size, my_local_size, true, PARALLEL); 00465 00466 // Copy part of *this into the parallel_vec 00467 for (numeric_index_type i=first_local_idx; i<=last_local_idx; i++) 00468 parallel_vec.set(i,this->el(i)); 00469 00470 // localize like normal 00471 parallel_vec.close(); 00472 parallel_vec.localize (*this, send_list); 00473 this->close(); 00474 } 00475 00476 00477 00478 template <typename T> 00479 void EpetraVector<T>::localize (std::vector<T>& v_local) const 00480 { 00481 // This function must be run on all processors at once 00482 parallel_object_only(); 00483 00484 const unsigned int n = this->size(); 00485 const unsigned int nl = this->local_size(); 00486 00487 libmesh_assert(this->_vec); 00488 00489 v_local.clear(); 00490 v_local.reserve(n); 00491 00492 // build up my local part 00493 for (unsigned int i=0; i<nl; i++) 00494 v_local.push_back((*this->_vec)[i]); 00495 00496 this->comm().allgather (v_local); 00497 } 00498 00499 00500 00501 template <typename T> 00502 void EpetraVector<T>::localize_to_one (std::vector<T>& v_local, 00503 const processor_id_type pid) const 00504 { 00505 // This function must be run on all processors at once 00506 parallel_object_only(); 00507 00508 const unsigned int n = this->size(); 00509 const unsigned int nl = this->local_size(); 00510 00511 libmesh_assert_less (pid, this->n_processors()); 00512 libmesh_assert(this->_vec); 00513 00514 v_local.clear(); 00515 v_local.reserve(n); 00516 00517 00518 // build up my local part 00519 for (unsigned int i=0; i<nl; i++) 00520 v_local.push_back((*this->_vec)[i]); 00521 00522 this->comm().gather (pid, v_local); 00523 } 00524 00525 00526 00527 template <typename T> 00528 void EpetraVector<T>::create_subvector(NumericVector<T>& /* subvector */, 00529 const std::vector<numeric_index_type>& /* rows */) const 00530 { 00531 libmesh_not_implemented(); 00532 } 00533 00534 00535 /********************************************************************* 00536 * The following were copied (and slightly modified) from 00537 * Epetra_FEVector.h in order to allow us to use a standard 00538 * Epetra_Vector... which is more compatible with other Trilinos 00539 * packages such as NOX. All of this code is originally under LGPL 00540 *********************************************************************/ 00541 00542 //---------------------------------------------------------------------------- 00543 template <typename T> 00544 int EpetraVector<T>::SumIntoGlobalValues(int numIDs, const int* GIDs, 00545 const double* values) 00546 { 00547 return( inputValues( numIDs, GIDs, values, true) ); 00548 } 00549 00550 //---------------------------------------------------------------------------- 00551 template <typename T> 00552 int EpetraVector<T>::SumIntoGlobalValues(const Epetra_IntSerialDenseVector& GIDs, 00553 const Epetra_SerialDenseVector& values) 00554 { 00555 if (GIDs.Length() != values.Length()) { 00556 return(-1); 00557 } 00558 00559 return( inputValues( GIDs.Length(), GIDs.Values(), values.Values(), true) ); 00560 } 00561 00562 //---------------------------------------------------------------------------- 00563 template <typename T> 00564 int EpetraVector<T>::SumIntoGlobalValues(int numIDs, const int* GIDs, 00565 const int* numValuesPerID, 00566 const double* values) 00567 { 00568 return( inputValues( numIDs, GIDs, numValuesPerID, values, true) ); 00569 } 00570 00571 //---------------------------------------------------------------------------- 00572 template <typename T> 00573 int EpetraVector<T>::ReplaceGlobalValues(int numIDs, const int* GIDs, 00574 const double* values) 00575 { 00576 return( inputValues( numIDs, GIDs, values, false) ); 00577 } 00578 00579 //---------------------------------------------------------------------------- 00580 template <typename T> 00581 int EpetraVector<T>::ReplaceGlobalValues(const Epetra_IntSerialDenseVector& GIDs, 00582 const Epetra_SerialDenseVector& values) 00583 { 00584 if (GIDs.Length() != values.Length()) { 00585 return(-1); 00586 } 00587 00588 return( inputValues( GIDs.Length(), GIDs.Values(), values.Values(), false) ); 00589 } 00590 00591 //---------------------------------------------------------------------------- 00592 template <typename T> 00593 int EpetraVector<T>::ReplaceGlobalValues(int numIDs, const int* GIDs, 00594 const int* numValuesPerID, 00595 const double* values) 00596 { 00597 return( inputValues( numIDs, GIDs, numValuesPerID, values, false) ); 00598 } 00599 00600 //---------------------------------------------------------------------------- 00601 template <typename T> 00602 int EpetraVector<T>::inputValues(int numIDs, 00603 const int* GIDs, 00604 const double* values, 00605 bool accumulate) 00606 { 00607 if (accumulate) { 00608 libmesh_assert(last_edit == 0 || last_edit == 2); 00609 last_edit = 2; 00610 } else { 00611 libmesh_assert(last_edit == 0 || last_edit == 1); 00612 last_edit = 1; 00613 } 00614 00615 //Important note!! This method assumes that there is only 1 point 00616 //associated with each element. 00617 00618 for(int i=0; i<numIDs; ++i) { 00619 if (_vec->Map().MyGID(GIDs[i])) { 00620 if (accumulate) { 00621 _vec->SumIntoGlobalValue(GIDs[i], 0, 0, values[i]); 00622 } 00623 else { 00624 _vec->ReplaceGlobalValue(GIDs[i], 0, 0, values[i]); 00625 } 00626 } 00627 else { 00628 if (!ignoreNonLocalEntries_) { 00629 EPETRA_CHK_ERR( inputNonlocalValue(GIDs[i], values[i], accumulate) ); 00630 } 00631 } 00632 } 00633 00634 return(0); 00635 } 00636 00637 //---------------------------------------------------------------------------- 00638 template <typename T> 00639 int EpetraVector<T>::inputValues(int numIDs, 00640 const int* GIDs, 00641 const int* numValuesPerID, 00642 const double* values, 00643 bool accumulate) 00644 { 00645 if (accumulate) { 00646 libmesh_assert(last_edit == 0 || last_edit == 2); 00647 last_edit = 2; 00648 } else { 00649 libmesh_assert(last_edit == 0 || last_edit == 1); 00650 last_edit = 1; 00651 } 00652 00653 int offset=0; 00654 for(int i=0; i<numIDs; ++i) { 00655 int numValues = numValuesPerID[i]; 00656 if (_vec->Map().MyGID(GIDs[i])) { 00657 if (accumulate) { 00658 for(int j=0; j<numValues; ++j) { 00659 _vec->SumIntoGlobalValue(GIDs[i], j, 0, values[offset+j]); 00660 } 00661 } 00662 else { 00663 for(int j=0; j<numValues; ++j) { 00664 _vec->ReplaceGlobalValue(GIDs[i], j, 0, values[offset+j]); 00665 } 00666 } 00667 } 00668 else { 00669 if (!ignoreNonLocalEntries_) { 00670 EPETRA_CHK_ERR( inputNonlocalValues(GIDs[i], numValues, 00671 &(values[offset]), accumulate) ); 00672 } 00673 } 00674 offset += numValues; 00675 } 00676 00677 return(0); 00678 } 00679 00680 //---------------------------------------------------------------------------- 00681 template <typename T> 00682 int EpetraVector<T>::inputNonlocalValue(int GID, double value, bool accumulate) 00683 { 00684 int insertPoint = -1; 00685 00686 //find offset of GID in nonlocalIDs_ 00687 int offset = Epetra_Util_binary_search(GID, nonlocalIDs_, numNonlocalIDs_, 00688 insertPoint); 00689 if (offset >= 0) { 00690 //if offset >= 0 00691 // put value in nonlocalCoefs_[offset][0] 00692 00693 if (accumulate) { 00694 nonlocalCoefs_[offset][0] += value; 00695 } 00696 else { 00697 nonlocalCoefs_[offset][0] = value; 00698 } 00699 } 00700 else { 00701 //else 00702 // insert GID in nonlocalIDs_ 00703 // insert 1 in nonlocalElementSize_ 00704 // insert value in nonlocalCoefs_ 00705 00706 int tmp1 = numNonlocalIDs_; 00707 int tmp2 = allocatedNonlocalLength_; 00708 int tmp3 = allocatedNonlocalLength_; 00709 EPETRA_CHK_ERR( Epetra_Util_insert(GID, insertPoint, nonlocalIDs_, 00710 tmp1, tmp2) ); 00711 --tmp1; 00712 EPETRA_CHK_ERR( Epetra_Util_insert(1, insertPoint, nonlocalElementSize_, 00713 tmp1, tmp3) ); 00714 double* values = new double[1]; 00715 values[0] = value; 00716 EPETRA_CHK_ERR( Epetra_Util_insert(values, insertPoint, nonlocalCoefs_, 00717 numNonlocalIDs_, allocatedNonlocalLength_) ); 00718 } 00719 00720 return(0); 00721 } 00722 00723 //---------------------------------------------------------------------------- 00724 template <typename T> 00725 int EpetraVector<T>::inputNonlocalValues(int GID, int numValues, 00726 const double* values, bool accumulate) 00727 { 00728 int insertPoint = -1; 00729 00730 //find offset of GID in nonlocalIDs_ 00731 int offset = Epetra_Util_binary_search(GID, nonlocalIDs_, numNonlocalIDs_, 00732 insertPoint); 00733 if (offset >= 0) { 00734 //if offset >= 0 00735 // put value in nonlocalCoefs_[offset][0] 00736 00737 if (numValues != nonlocalElementSize_[offset]) { 00738 libMesh::err << "Epetra_FEVector ERROR: block-size for GID " << GID << " is " 00739 << numValues<<" which doesn't match previously set block-size of " 00740 << nonlocalElementSize_[offset] << std::endl; 00741 return(-1); 00742 } 00743 00744 if (accumulate) { 00745 for(int j=0; j<numValues; ++j) { 00746 nonlocalCoefs_[offset][j] += values[j]; 00747 } 00748 } 00749 else { 00750 for(int j=0; j<numValues; ++j) { 00751 nonlocalCoefs_[offset][j] = values[j]; 00752 } 00753 } 00754 } 00755 else { 00756 //else 00757 // insert GID in nonlocalIDs_ 00758 // insert numValues in nonlocalElementSize_ 00759 // insert values in nonlocalCoefs_ 00760 00761 int tmp1 = numNonlocalIDs_; 00762 int tmp2 = allocatedNonlocalLength_; 00763 int tmp3 = allocatedNonlocalLength_; 00764 EPETRA_CHK_ERR( Epetra_Util_insert(GID, insertPoint, nonlocalIDs_, 00765 tmp1, tmp2) ); 00766 --tmp1; 00767 EPETRA_CHK_ERR( Epetra_Util_insert(numValues, insertPoint, nonlocalElementSize_, 00768 tmp1, tmp3) ); 00769 double* newvalues = new double[numValues]; 00770 for(int j=0; j<numValues; ++j) { 00771 newvalues[j] = values[j]; 00772 } 00773 EPETRA_CHK_ERR( Epetra_Util_insert(newvalues, insertPoint, nonlocalCoefs_, 00774 numNonlocalIDs_, allocatedNonlocalLength_) ); 00775 } 00776 00777 return(0); 00778 } 00779 00780 //---------------------------------------------------------------------------- 00781 template <typename T> 00782 int EpetraVector<T>::GlobalAssemble(Epetra_CombineMode mode) 00783 { 00784 //In this method we need to gather all the non-local (overlapping) data 00785 //that's been input on each processor, into the (probably) non-overlapping 00786 //distribution defined by the map that 'this' vector was constructed with. 00787 00788 //We don't need to do anything if there's only one processor or if 00789 //ignoreNonLocalEntries_ is true. 00790 if (_vec->Map().Comm().NumProc() < 2 || ignoreNonLocalEntries_) { 00791 return(0); 00792 } 00793 00794 00795 00796 //First build a map that describes the data in nonlocalIDs_/nonlocalCoefs_. 00797 //We'll use the arbitrary distribution constructor of Map. 00798 00799 Epetra_BlockMap sourceMap(-1, numNonlocalIDs_, 00800 nonlocalIDs_, nonlocalElementSize_, 00801 _vec->Map().IndexBase(), _vec->Map().Comm()); 00802 00803 //Now build a vector to hold our nonlocalCoefs_, and to act as the source- 00804 //vector for our import operation. 00805 Epetra_MultiVector nonlocalVector(sourceMap, 1); 00806 00807 int i,j; 00808 for(i=0; i<numNonlocalIDs_; ++i) { 00809 for(j=0; j<nonlocalElementSize_[i]; ++j) { 00810 nonlocalVector.ReplaceGlobalValue(nonlocalIDs_[i], j, 0, 00811 nonlocalCoefs_[i][j]); 00812 } 00813 } 00814 00815 Epetra_Export exporter(sourceMap, _vec->Map()); 00816 00817 EPETRA_CHK_ERR( _vec->Export(nonlocalVector, exporter, mode) ); 00818 00819 destroyNonlocalData(); 00820 00821 return(0); 00822 } 00823 00824 00825 //---------------------------------------------------------------------------- 00826 template <typename T> 00827 void EpetraVector<T>::FEoperatorequals(const EpetraVector& source) 00828 { 00829 (*_vec) = *(source._vec); 00830 00831 destroyNonlocalData(); 00832 00833 if (source.allocatedNonlocalLength_ > 0) { 00834 allocatedNonlocalLength_ = source.allocatedNonlocalLength_; 00835 numNonlocalIDs_ = source.numNonlocalIDs_; 00836 nonlocalIDs_ = new int[allocatedNonlocalLength_]; 00837 nonlocalElementSize_ = new int[allocatedNonlocalLength_]; 00838 nonlocalCoefs_ = new double*[allocatedNonlocalLength_]; 00839 for(int i=0; i<numNonlocalIDs_; ++i) { 00840 int elemSize = source.nonlocalElementSize_[i]; 00841 nonlocalCoefs_[i] = new double[elemSize]; 00842 nonlocalIDs_[i] = source.nonlocalIDs_[i]; 00843 nonlocalElementSize_[i] = elemSize; 00844 for(int j=0; j<elemSize; ++j) { 00845 nonlocalCoefs_[i][j] = source.nonlocalCoefs_[i][j]; 00846 } 00847 } 00848 } 00849 } 00850 00851 00852 //---------------------------------------------------------------------------- 00853 template <typename T> 00854 void EpetraVector<T>::destroyNonlocalData() 00855 { 00856 if (allocatedNonlocalLength_ > 0) { 00857 delete [] nonlocalIDs_; 00858 delete [] nonlocalElementSize_; 00859 nonlocalIDs_ = NULL; 00860 nonlocalElementSize_ = NULL; 00861 for(int i=0; i<numNonlocalIDs_; ++i) { 00862 delete [] nonlocalCoefs_[i]; 00863 } 00864 delete [] nonlocalCoefs_; 00865 nonlocalCoefs_ = NULL; 00866 numNonlocalIDs_ = 0; 00867 allocatedNonlocalLength_ = 0; 00868 } 00869 return; 00870 } 00871 00872 00873 //------------------------------------------------------------------ 00874 // Explicit instantiations 00875 template class EpetraVector<Number>; 00876 00877 } // namespace libMesh 00878 00879 #endif // #ifdef HAVE_EPETRA