$extrastylesheet
numeric_vector.C
Go to the documentation of this file.
00001 // The libMesh Finite Element Library.
00002 // Copyright (C) 2002-2014 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
00003 
00004 // This library is free software; you can redistribute it and/or
00005 // modify it under the terms of the GNU Lesser General Public
00006 // License as published by the Free Software Foundation; either
00007 // version 2.1 of the License, or (at your option) any later version.
00008 
00009 // This library is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012 // Lesser General Public License for more details.
00013 
00014 // You should have received a copy of the GNU Lesser General Public
00015 // License along with this library; if not, write to the Free Software
00016 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017 
00018 
00019 
00020 // C++ includes
00021 #include <cstdlib> // *must* precede <cmath> for proper std:abs() on PGI, Sun Studio CC
00022 #include <cmath> // for std::abs
00023 #include <limits>
00024 
00025 // Local Includes
00026 #include "libmesh/numeric_vector.h"
00027 #include "libmesh/distributed_vector.h"
00028 #include "libmesh/laspack_vector.h"
00029 #include "libmesh/eigen_sparse_vector.h"
00030 #include "libmesh/petsc_vector.h"
00031 #include "libmesh/trilinos_epetra_vector.h"
00032 #include "libmesh/shell_matrix.h"
00033 #include "libmesh/tensor_tools.h"
00034 
00035 namespace libMesh
00036 {
00037 
00038 
00039 
00040 //------------------------------------------------------------------
00041 // NumericVector methods
00042 
00043 // Full specialization for Real datatypes
00044 template <typename T>
00045 UniquePtr<NumericVector<T> >
00046 NumericVector<T>::build(const Parallel::Communicator &comm, const SolverPackage solver_package)
00047 {
00048   // Build the appropriate vector
00049   switch (solver_package)
00050     {
00051 
00052 #ifdef LIBMESH_HAVE_LASPACK
00053     case LASPACK_SOLVERS:
00054       return UniquePtr<NumericVector<T> >(new LaspackVector<T>(comm, AUTOMATIC));
00055 #endif
00056 
00057 #ifdef LIBMESH_HAVE_PETSC
00058     case PETSC_SOLVERS:
00059       return UniquePtr<NumericVector<T> >(new PetscVector<T>(comm, AUTOMATIC));
00060 #endif
00061 
00062 #ifdef LIBMESH_HAVE_TRILINOS
00063     case TRILINOS_SOLVERS:
00064       return UniquePtr<NumericVector<T> >(new EpetraVector<T>(comm, AUTOMATIC));
00065 #endif
00066 
00067 #ifdef LIBMESH_HAVE_EIGEN
00068     case EIGEN_SOLVERS:
00069       return UniquePtr<NumericVector<T> >(new EigenSparseVector<T>(comm, AUTOMATIC));
00070 #endif
00071 
00072     default:
00073       return UniquePtr<NumericVector<T> >(new DistributedVector<T>(comm, AUTOMATIC));
00074     }
00075 
00076   libmesh_error_msg("We'll never get here!");
00077   return UniquePtr<NumericVector<T> >();
00078 }
00079 
00080 
00081 #ifndef LIBMESH_DISABLE_COMMWORLD
00082 template <typename T>
00083 UniquePtr<NumericVector<T> >
00084 NumericVector<T>::build(const SolverPackage solver_package)
00085 {
00086   libmesh_deprecated();
00087   return NumericVector<T>::build(CommWorld, solver_package);
00088 }
00089 #endif
00090 
00091 
00092 
00093 template <typename T>
00094 void NumericVector<T>::insert (const T* v,
00095                                const std::vector<numeric_index_type>& dof_indices)
00096 {
00097   for (numeric_index_type i=0; i<dof_indices.size(); i++)
00098     this->set (dof_indices[i], v[i]);
00099 }
00100 
00101 
00102 
00103 template <typename T>
00104 void NumericVector<T>::insert (const NumericVector<T>& V,
00105                                const std::vector<numeric_index_type>& dof_indices)
00106 {
00107   libmesh_assert_equal_to (V.size(), dof_indices.size());
00108 
00109   for (numeric_index_type i=0; i<dof_indices.size(); i++)
00110     this->set (dof_indices[i], V(i));
00111 }
00112 
00113 
00114 
00115 template <typename T>
00116 int NumericVector<T>::compare (const NumericVector<T> &other_vector,
00117                                const Real threshold) const
00118 {
00119   libmesh_assert (this->initialized());
00120   libmesh_assert (other_vector.initialized());
00121   libmesh_assert_equal_to (this->first_local_index(), other_vector.first_local_index());
00122   libmesh_assert_equal_to (this->last_local_index(), other_vector.last_local_index());
00123 
00124   int first_different_i = std::numeric_limits<int>::max();
00125   numeric_index_type i = first_local_index();
00126 
00127   do
00128     {
00129       if ( std::abs( (*this)(i) - other_vector(i) ) > threshold )
00130         first_different_i = i;
00131       else
00132         i++;
00133     }
00134   while (first_different_i==std::numeric_limits<int>::max()
00135          && i<last_local_index());
00136 
00137   // Find the correct first differing index in parallel
00138   this->comm().min(first_different_i);
00139 
00140   if (first_different_i == std::numeric_limits<int>::max())
00141     return -1;
00142 
00143   return first_different_i;
00144 }
00145 
00146 
00147 template <typename T>
00148 int NumericVector<T>::local_relative_compare (const NumericVector<T> &other_vector,
00149                                               const Real threshold) const
00150 {
00151   libmesh_assert (this->initialized());
00152   libmesh_assert (other_vector.initialized());
00153   libmesh_assert_equal_to (this->first_local_index(), other_vector.first_local_index());
00154   libmesh_assert_equal_to (this->last_local_index(), other_vector.last_local_index());
00155 
00156   int first_different_i = std::numeric_limits<int>::max();
00157   numeric_index_type i = first_local_index();
00158 
00159   do
00160     {
00161       if ( std::abs( (*this)(i) - other_vector(i) ) > threshold *
00162            std::max(std::abs((*this)(i)), std::abs(other_vector(i))))
00163         first_different_i = i;
00164       else
00165         i++;
00166     }
00167   while (first_different_i==std::numeric_limits<int>::max()
00168          && i<last_local_index());
00169 
00170   // Find the correct first differing index in parallel
00171   this->comm().min(first_different_i);
00172 
00173   if (first_different_i == std::numeric_limits<int>::max())
00174     return -1;
00175 
00176   return first_different_i;
00177 }
00178 
00179 
00180 template <typename T>
00181 int NumericVector<T>::global_relative_compare (const NumericVector<T> &other_vector,
00182                                                const Real threshold) const
00183 {
00184   libmesh_assert (this->initialized());
00185   libmesh_assert (other_vector.initialized());
00186   libmesh_assert_equal_to (this->first_local_index(), other_vector.first_local_index());
00187   libmesh_assert_equal_to (this->last_local_index(), other_vector.last_local_index());
00188 
00189   int first_different_i = std::numeric_limits<int>::max();
00190   numeric_index_type i = first_local_index();
00191 
00192   const Real my_norm = this->linfty_norm();
00193   const Real other_norm = other_vector.linfty_norm();
00194   const Real abs_threshold = std::max(my_norm, other_norm) * threshold;
00195 
00196   do
00197     {
00198       if ( std::abs( (*this)(i) - other_vector(i) ) > abs_threshold )
00199         first_different_i = i;
00200       else
00201         i++;
00202     }
00203   while (first_different_i==std::numeric_limits<int>::max()
00204          && i<last_local_index());
00205 
00206   // Find the correct first differing index in parallel
00207   this->comm().min(first_different_i);
00208 
00209   if (first_different_i == std::numeric_limits<int>::max())
00210     return -1;
00211 
00212   return first_different_i;
00213 }
00214 
00215 /*
00216 // Full specialization for float datatypes (DistributedVector wants this)
00217 
00218 template <>
00219 int NumericVector<float>::compare (const NumericVector<float> &other_vector,
00220 const Real threshold) const
00221 {
00222 libmesh_assert (this->initialized());
00223 libmesh_assert (other_vector.initialized());
00224 libmesh_assert_equal_to (this->first_local_index(), other_vector.first_local_index());
00225 libmesh_assert_equal_to (this->last_local_index(), other_vector.last_local_index());
00226 
00227 int rvalue     = -1;
00228 numeric_index_type i = first_local_index();
00229 
00230 do
00231 {
00232 if ( std::abs( (*this)(i) - other_vector(i) ) > threshold )
00233 rvalue = i;
00234 else
00235 i++;
00236 }
00237 while (rvalue==-1 && i<last_local_index());
00238 
00239 return rvalue;
00240 }
00241 
00242 // Full specialization for double datatypes
00243 template <>
00244 int NumericVector<double>::compare (const NumericVector<double> &other_vector,
00245 const Real threshold) const
00246 {
00247 libmesh_assert (this->initialized());
00248 libmesh_assert (other_vector.initialized());
00249 libmesh_assert_equal_to (this->first_local_index(), other_vector.first_local_index());
00250 libmesh_assert_equal_to (this->last_local_index(), other_vector.last_local_index());
00251 
00252 int rvalue     = -1;
00253 numeric_index_type i = first_local_index();
00254 
00255 do
00256 {
00257 if ( std::abs( (*this)(i) - other_vector(i) ) > threshold )
00258 rvalue = i;
00259 else
00260 i++;
00261 }
00262 while (rvalue==-1 && i<last_local_index());
00263 
00264 return rvalue;
00265 }
00266 
00267 #ifdef LIBMESH_DEFAULT_TRIPLE_PRECISION
00268 // Full specialization for long double datatypes
00269 template <>
00270 int NumericVector<long double>::compare (const NumericVector<long double> &other_vector,
00271 const Real threshold) const
00272 {
00273 libmesh_assert (this->initialized());
00274 libmesh_assert (other_vector.initialized());
00275 libmesh_assert_equal_to (this->first_local_index(), other_vector.first_local_index());
00276 libmesh_assert_equal_to (this->last_local_index(), other_vector.last_local_index());
00277 
00278 int rvalue     = -1;
00279 numeric_index_type i = first_local_index();
00280 
00281 do
00282 {
00283 if ( std::abs( (*this)(i) - other_vector(i) ) > threshold )
00284 rvalue = i;
00285 else
00286 i++;
00287 }
00288 while (rvalue==-1 && i<last_local_index());
00289 
00290 return rvalue;
00291 }
00292 #endif
00293 
00294 
00295 // Full specialization for Complex datatypes
00296 template <>
00297 int NumericVector<Complex>::compare (const NumericVector<Complex> &other_vector,
00298 const Real threshold) const
00299 {
00300 libmesh_assert (this->initialized());
00301 libmesh_assert (other_vector.initialized());
00302 libmesh_assert_equal_to (this->first_local_index(), other_vector.first_local_index());
00303 libmesh_assert_equal_to (this->last_local_index(), other_vector.last_local_index());
00304 
00305 int rvalue     = -1;
00306 numeric_index_type i = first_local_index();
00307 
00308 do
00309 {
00310 if (( std::abs( (*this)(i).real() - other_vector(i).real() ) > threshold ) ||
00311 ( std::abs( (*this)(i).imag() - other_vector(i).imag() ) > threshold ))
00312 rvalue = i;
00313 else
00314 i++;
00315 }
00316 while (rvalue==-1 && i<this->last_local_index());
00317 
00318 return rvalue;
00319 }
00320 */
00321 
00322 
00323 template <class T>
00324 Real NumericVector<T>::subset_l1_norm (const std::set<numeric_index_type> & indices) const
00325 {
00326   const NumericVector<T> & v = *this;
00327 
00328   std::set<numeric_index_type>::const_iterator it = indices.begin();
00329   const std::set<numeric_index_type>::const_iterator it_end = indices.end();
00330 
00331   Real norm = 0;
00332 
00333   for(; it!=it_end; ++it)
00334     norm += std::abs(v(*it));
00335 
00336   this->comm().sum(norm);
00337 
00338   return norm;
00339 }
00340 
00341 template <class T>
00342 Real NumericVector<T>::subset_l2_norm (const std::set<numeric_index_type> & indices) const
00343 {
00344   const NumericVector<T> & v = *this;
00345 
00346   std::set<numeric_index_type>::const_iterator it = indices.begin();
00347   const std::set<numeric_index_type>::const_iterator it_end = indices.end();
00348 
00349   Real norm = 0;
00350 
00351   for(; it!=it_end; ++it)
00352     norm += TensorTools::norm_sq(v(*it));
00353 
00354   this->comm().sum(norm);
00355 
00356   return std::sqrt(norm);
00357 }
00358 
00359 template <class T>
00360 Real NumericVector<T>::subset_linfty_norm (const std::set<numeric_index_type> & indices) const
00361 {
00362   const NumericVector<T> & v = *this;
00363 
00364   std::set<numeric_index_type>::const_iterator it = indices.begin();
00365   const std::set<numeric_index_type>::const_iterator it_end = indices.end();
00366 
00367   Real norm = 0;
00368 
00369   for(; it!=it_end; ++it)
00370     {
00371       Real value = std::abs(v(*it));
00372       if(value > norm)
00373         norm = value;
00374     }
00375 
00376   this->comm().max(norm);
00377 
00378   return norm;
00379 }
00380 
00381 
00382 
00383 template <typename T>
00384 void NumericVector<T>::add_vector (const T* v,
00385                                    const std::vector<numeric_index_type>& dof_indices)
00386 {
00387   int n = dof_indices.size();
00388   for (int i=0; i<n; i++)
00389     this->add (dof_indices[i], v[i]);
00390 }
00391 
00392 
00393 
00394 template <typename T>
00395 void NumericVector<T>::add_vector (const NumericVector<T>& v,
00396                                    const std::vector<numeric_index_type>& dof_indices)
00397 {
00398   int n = dof_indices.size();
00399   libmesh_assert_equal_to(v.size(), static_cast<unsigned>(n));
00400   for (int i=0; i<n; i++)
00401     this->add (dof_indices[i], v(i));
00402 }
00403 
00404 
00405 
00406 template <typename T>
00407 void NumericVector<T>::add_vector (const NumericVector<T>& v,
00408                                    const ShellMatrix<T>& a)
00409 {
00410   a.vector_mult_add(*this,v);
00411 }
00412 
00413 
00414 
00415 //------------------------------------------------------------------
00416 // Explicit instantiations
00417 template class NumericVector<Number>;
00418 
00419 } // namespace libMesh