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