sparse_matrix.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 00019 00020 // C++ includes 00021 00022 // Local Includes 00023 #include "libmesh/dof_map.h" 00024 #include "libmesh/laspack_matrix.h" 00025 #include "libmesh/parallel.h" 00026 #include "libmesh/petsc_matrix.h" 00027 #include "libmesh/sparse_matrix.h" 00028 #include "libmesh/trilinos_epetra_matrix.h" 00029 #include "libmesh/numeric_vector.h" 00030 00031 namespace libMesh 00032 { 00033 00034 00035 //------------------------------------------------------------------ 00036 // SparseMatrix Methods 00037 00038 00039 // Constructor 00040 template <typename T> 00041 SparseMatrix<T>::SparseMatrix () : 00042 _dof_map(NULL), 00043 _is_initialized(false) 00044 {} 00045 00046 00047 00048 // Destructor 00049 template <typename T> 00050 SparseMatrix<T>::~SparseMatrix () 00051 {} 00052 00053 00054 00055 // Full specialization of print method for Complex datatypes 00056 template <> 00057 void SparseMatrix<Complex>::print(std::ostream& os, const bool sparse) const 00058 { 00059 // std::complex<>::operator<<() is defined, but use this form 00060 00061 if(sparse) 00062 { 00063 libmesh_not_implemented(); 00064 } 00065 00066 os << "Real part:" << std::endl; 00067 for (numeric_index_type i=0; i<this->m(); i++) 00068 { 00069 for (numeric_index_type j=0; j<this->n(); j++) 00070 os << std::setw(8) << (*this)(i,j).real() << " "; 00071 os << std::endl; 00072 } 00073 00074 os << std::endl << "Imaginary part:" << std::endl; 00075 for (numeric_index_type i=0; i<this->m(); i++) 00076 { 00077 for (numeric_index_type j=0; j<this->n(); j++) 00078 os << std::setw(8) << (*this)(i,j).imag() << " "; 00079 os << std::endl; 00080 } 00081 } 00082 00083 00084 00085 00086 00087 00088 // Full specialization for Real datatypes 00089 template <typename T> 00090 AutoPtr<SparseMatrix<T> > 00091 SparseMatrix<T>::build(const SolverPackage solver_package) 00092 { 00093 // Build the appropriate vector 00094 switch (solver_package) 00095 { 00096 00097 00098 #ifdef LIBMESH_HAVE_LASPACK 00099 case LASPACK_SOLVERS: 00100 { 00101 AutoPtr<SparseMatrix<T> > ap(new LaspackMatrix<T>); 00102 return ap; 00103 } 00104 #endif 00105 00106 00107 #ifdef LIBMESH_HAVE_PETSC 00108 case PETSC_SOLVERS: 00109 { 00110 AutoPtr<SparseMatrix<T> > ap(new PetscMatrix<T>); 00111 return ap; 00112 } 00113 #endif 00114 00115 00116 #ifdef LIBMESH_HAVE_TRILINOS 00117 case TRILINOS_SOLVERS: 00118 { 00119 AutoPtr<SparseMatrix<T> > ap(new EpetraMatrix<T>); 00120 return ap; 00121 } 00122 #endif 00123 00124 00125 default: 00126 libMesh::err << "ERROR: Unrecognized solver package: " 00127 << solver_package 00128 << std::endl; 00129 libmesh_error(); 00130 } 00131 00132 AutoPtr<SparseMatrix<T> > ap(NULL); 00133 return ap; 00134 } 00135 00136 00137 template <typename T> 00138 void SparseMatrix<T>::vector_mult (NumericVector<T>& dest, 00139 const NumericVector<T>& arg) const 00140 { 00141 dest.zero(); 00142 this->vector_mult_add(dest,arg); 00143 } 00144 00145 00146 00147 template <typename T> 00148 void SparseMatrix<T>::vector_mult_add (NumericVector<T>& dest, 00149 const NumericVector<T>& arg) const 00150 { 00151 /* This functionality is actually implemented in the \p 00152 NumericVector class. */ 00153 dest.add_vector(arg,*this); 00154 } 00155 00156 00157 00158 template <typename T> 00159 void SparseMatrix<T>::zero_rows (std::vector<numeric_index_type> &, T) 00160 { 00161 /* This functionality isn't implemented or stubbed in every subclass yet */ 00162 libmesh_not_implemented(); 00163 } 00164 00165 00166 00167 template <typename T> 00168 void SparseMatrix<T>::print(std::ostream& os, const bool sparse) const 00169 { 00170 parallel_only(); 00171 00172 libmesh_assert (this->initialized()); 00173 00174 if(!this->_dof_map) 00175 { 00176 os << std::endl << "Error! Trying to print a matrix with no dof_map set!" << std::endl << std::endl; 00177 libmesh_error(); 00178 } 00179 00180 // We'll print the matrix from processor 0 to make sure 00181 // it's serialized properly 00182 if (libMesh::processor_id() == 0) 00183 { 00184 libmesh_assert_equal_to (this->_dof_map->first_dof(), 0); 00185 for (numeric_index_type i=this->_dof_map->first_dof(); 00186 i!=this->_dof_map->end_dof(); ++i) 00187 { 00188 if(sparse) 00189 { 00190 for (numeric_index_type j=0; j<this->n(); j++) 00191 { 00192 T c = (*this)(i,j); 00193 if (c != static_cast<T>(0.0)) 00194 { 00195 os << i << " " << j << " " << c << std::endl; 00196 } 00197 } 00198 } 00199 else 00200 { 00201 for (numeric_index_type j=0; j<this->n(); j++) 00202 os << (*this)(i,j) << " "; 00203 os << std::endl; 00204 } 00205 } 00206 00207 std::vector<numeric_index_type> ibuf, jbuf; 00208 std::vector<T> cbuf; 00209 numeric_index_type currenti = this->_dof_map->end_dof(); 00210 for (processor_id_type p=1; p < libMesh::n_processors(); ++p) 00211 { 00212 CommWorld.receive(p, ibuf); 00213 CommWorld.receive(p, jbuf); 00214 CommWorld.receive(p, cbuf); 00215 libmesh_assert_equal_to (ibuf.size(), jbuf.size()); 00216 libmesh_assert_equal_to (ibuf.size(), cbuf.size()); 00217 00218 if (ibuf.empty()) 00219 continue; 00220 libmesh_assert_greater_equal (ibuf.front(), currenti); 00221 libmesh_assert_greater_equal (ibuf.back(), ibuf.front()); 00222 00223 std::size_t currentb = 0; 00224 for (;currenti <= ibuf.back(); ++currenti) 00225 { 00226 if(sparse) 00227 { 00228 for (numeric_index_type j=0; j<this->n(); j++) 00229 { 00230 if (currentb < ibuf.size() && 00231 ibuf[currentb] == currenti && 00232 jbuf[currentb] == j) 00233 { 00234 os << currenti << " " << j << " " << cbuf[currentb] << std::endl; 00235 currentb++; 00236 } 00237 } 00238 } 00239 else 00240 { 00241 for (numeric_index_type j=0; j<this->n(); j++) 00242 { 00243 if (currentb < ibuf.size() && 00244 ibuf[currentb] == currenti && 00245 jbuf[currentb] == j) 00246 { 00247 os << cbuf[currentb] << " "; 00248 currentb++; 00249 } 00250 else 00251 os << static_cast<T>(0.0) << " "; 00252 } 00253 os << std::endl; 00254 } 00255 } 00256 } 00257 if(!sparse) 00258 { 00259 for (; currenti != this->m(); ++currenti) 00260 { 00261 for (numeric_index_type j=0; j<this->n(); j++) 00262 os << static_cast<T>(0.0) << " "; 00263 os << std::endl; 00264 } 00265 } 00266 } 00267 else 00268 { 00269 std::vector<numeric_index_type> ibuf, jbuf; 00270 std::vector<T> cbuf; 00271 00272 // We'll assume each processor has access to entire 00273 // matrix rows, so (*this)(i,j) is valid if i is a local index. 00274 for (numeric_index_type i=this->_dof_map->first_dof(); 00275 i!=this->_dof_map->end_dof(); ++i) 00276 { 00277 for (numeric_index_type j=0; j<this->n(); j++) 00278 { 00279 T c = (*this)(i,j); 00280 if (c != static_cast<T>(0.0)) 00281 { 00282 ibuf.push_back(i); 00283 jbuf.push_back(j); 00284 cbuf.push_back(c); 00285 } 00286 } 00287 } 00288 CommWorld.send(0,ibuf); 00289 CommWorld.send(0,jbuf); 00290 CommWorld.send(0,cbuf); 00291 } 00292 } 00293 00294 00295 00296 //------------------------------------------------------------------ 00297 // Explicit instantiations 00298 template class SparseMatrix<Number>; 00299 00300 } // namespace libMesh
Site Created By: libMesh Developers
Last modified: February 05 2013 19:54:48 UTC
Hosted By: