$extrastylesheet
trilinos_epetra_vector.C
Go to the documentation of this file.
00001 // The libMesh Finite Element Library.
00002 // Copyright (C) 2002-2014 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
00003 
00004 // This library is free software; you can redistribute it and/or
00005 // modify it under the terms of the GNU Lesser General Public
00006 // License as published by the Free Software Foundation; either
00007 // version 2.1 of the License, or (at your option) any later version.
00008 
00009 // This library is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012 // Lesser General Public License for more details.
00013 
00014 // You should have received a copy of the GNU Lesser General Public
00015 // License along with this library; if not, write to the Free Software
00016 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017 
00018 // 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