![]() |
MechSys
1.0
Computing library for simulations in continuum and discrete mechanics
|
00001 /************************************************************************ 00002 * MechSys - Open Library for Mechanical Systems * 00003 * Copyright (C) 2005 Dorival M. Pedroso, Raul Durand * 00004 * Copyright (C) 2009 Sergio Galindo * 00005 * * 00006 * This program is free software: you can redistribute it and/or modify * 00007 * it under the terms of the GNU General Public License as published by * 00008 * the Free Software Foundation, either version 3 of the License, or * 00009 * any later version. * 00010 * * 00011 * This program is distributed in the hope that it will be useful, * 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00014 * GNU General Public License for more details. * 00015 * * 00016 * You should have received a copy of the GNU General Public License * 00017 * along with this program. If not, see <http://www.gnu.org/licenses/> * 00018 ************************************************************************/ 00019 00020 #ifndef MECHSYS_SPARSE_TRIPLET_H 00021 #define MECHSYS_SPARSE_TRIPLET_H 00022 00023 // STL 00024 #include <iostream> 00025 #include <fstream> 00026 00027 // MechSys 00028 #include <mechsys/util/numstreams.h> 00029 00030 namespace Sparse 00031 { 00032 00057 template<typename Value_T, typename Index_T> 00058 class Triplet 00059 { 00060 public: 00062 Triplet(); 00063 00065 Triplet(Triplet<Value_T,Index_T> const & A, Triplet<Value_T,Index_T> const & B, Triplet<Value_T,Index_T> const & C, Triplet<Value_T,Index_T> const & D); 00066 00068 ~Triplet(); 00069 00070 // Methods 00071 Index_T Rows () const { return _nrows; } 00072 Index_T Cols () const { return _ncols; } 00073 Index_T Size () const { return _size; } 00074 Index_T Top () const { return _top; } 00075 void AllocSpace (Index_T nRows, Index_T nCols, Index_T Size); 00076 void PushEntry (Index_T i, Index_T j, Value_T x); 00077 void ResetTop (Index_T NewTop=0) { _top = NewTop; } 00078 00079 // Access methods 00080 Index_T Ai (Index_T k) const; 00081 Index_T Aj (Index_T k) const; 00082 Value_T Ax (Index_T k) const; 00083 Index_T * GetAiPtr (); 00084 Index_T * GetAjPtr (); 00085 Value_T * GetAxPtr (); 00086 Index_T const * GetAiPtr () const; 00087 Index_T const * GetAjPtr () const; 00088 Value_T const * GetAxPtr () const; 00089 00090 // Auxiliar methods 00091 void SetNS (Util::NumStream & NS) { _ns = &NS; } 00092 Util::NumStream const & NS () const { return (*_ns); } 00093 void WriteSMAT (char const * FileKey, double Tol=1.0e-14) const; 00094 void IncIndices (Index_T Delta); 00095 00096 private: 00097 // Data 00098 Index_T _nrows; 00099 Index_T _ncols; 00100 Index_T _size; 00101 Index_T _top; 00102 Index_T * _Ai; 00103 Index_T * _Aj; 00104 Value_T * _Ax; 00105 Util::NumStream * _ns; 00106 00107 }; // class Triplet 00108 00109 00111 template<typename Value_T, typename Index_T> 00112 void AddMult (Sparse::Triplet<Value_T,Index_T> const & M, Vec_t const & X, Vec_t & Y) 00113 { 00114 for (int k=0; k<M.Top(); ++k) 00115 Y(M.Ai(k)) += M.Ax(k) * X(M.Aj(k)); // Y += M*X 00116 } 00117 00119 template<typename Value_T, typename Index_T> 00120 void SubMult (Sparse::Triplet<Value_T,Index_T> const & M, Vec_t const & X, Vec_t & Y) 00121 { 00122 for (int k=0; k<M.Top(); ++k) 00123 Y(M.Ai(k)) -= M.Ax(k) * X(M.Aj(k)); // Y -= M*X 00124 } 00125 00127 template<typename Value_T, typename Index_T> 00128 void SubMult (double s, Sparse::Triplet<Value_T,Index_T> const & M, Vec_t const & X, Vec_t & Y) 00129 { 00130 for (int k=0; k<M.Top(); ++k) 00131 Y(M.Ai(k)) -= s * M.Ax(k) * X(M.Aj(k)); // Y -= M*X 00132 } 00133 00134 00136 00137 00138 // Constructor & Destructor 00139 00140 template<typename Value_T, typename Index_T> 00141 inline Triplet<Value_T,Index_T>::Triplet() 00142 : _nrows (0), 00143 _ncols (0), 00144 _size (0), 00145 _top (0), 00146 _Ai (NULL), 00147 _Aj (NULL), 00148 _Ax (NULL), 00149 _ns (&Util::_8s) 00150 {} 00151 00152 template<typename Value_T, typename Index_T> 00153 inline Triplet<Value_T,Index_T>::~Triplet() 00154 { 00155 if (_Ai!=NULL) delete [] _Ai; 00156 if (_Aj!=NULL) delete [] _Aj; 00157 if (_Ax!=NULL) delete [] _Ax; 00158 } 00159 00160 template<typename Value_T, typename Index_T> 00161 inline Triplet<Value_T,Index_T>::Triplet(Triplet<Value_T,Index_T> const & A, Triplet<Value_T,Index_T> const & B, Triplet<Value_T,Index_T> const & C, Triplet<Value_T,Index_T> const & D) 00162 : _nrows (0), 00163 _ncols (0), 00164 _size (0), 00165 _top (0), 00166 _Ai (NULL), 00167 _Aj (NULL), 00168 _Ax (NULL), 00169 _ns (&Util::_8s) 00170 { 00171 /* 00172 std::cout << A.Rows() << " " << B.Rows() << " " << C.Rows() << " " << D.Rows() << " " << std::endl; 00173 std::cout << A.Cols() << " " << B.Cols() << " " << C.Cols() << " " << D.Cols() << " " << std::endl; 00174 */ 00175 00176 // check 00177 int m = A.Rows(); 00178 int n = A.Cols(); 00179 if (B.Rows()!=m || B.Cols()!=n || 00180 C.Rows()!=m || C.Cols()!=n || 00181 D.Rows()!=m || D.Cols()!=n) throw new Fatal("Sparse::Triplet: When construction with other 4 triplets, all triplets must have the same number of rows and columns"); 00182 00183 // set 00184 AllocSpace (m, n, A.Top()+B.Top()+C.Top()+D.Top()); 00185 for (int k=0; k<A.Top(); ++k) PushEntry (A.Ai(k), A.Aj(k), A.Ax(k)); 00186 for (int k=0; k<B.Top(); ++k) PushEntry (B.Ai(k), B.Aj(k), B.Ax(k)); 00187 for (int k=0; k<C.Top(); ++k) PushEntry (C.Ai(k), C.Aj(k), C.Ax(k)); 00188 for (int k=0; k<D.Top(); ++k) PushEntry (D.Ai(k), D.Aj(k), D.Ax(k)); 00189 } 00190 00191 // Methods 00192 00193 template<typename Value_T, typename Index_T> 00194 inline void Triplet<Value_T,Index_T>::AllocSpace(Index_T nRows, Index_T nCols, Index_T Size) 00195 { 00196 if (_Ai!=NULL) delete [] _Ai; 00197 if (_Aj!=NULL) delete [] _Aj; 00198 if (_Ax!=NULL) delete [] _Ax; 00199 _nrows = nRows; 00200 _ncols = nCols; 00201 _size = Size; 00202 _top = 0; 00203 _Ai = new Index_T [_size]; 00204 _Aj = new Index_T [_size]; 00205 _Ax = new Value_T [_size]; 00206 } 00207 00208 template<typename Value_T, typename Index_T> 00209 inline void Triplet<Value_T,Index_T>::PushEntry(Index_T i, Index_T j, Value_T x) 00210 { 00211 if (_top>=_size) throw new Fatal("Sparse::Triplet::PushEntry: _top (%d) must be smaller than _size (%d)",_top,_size); 00212 _Ai[_top] = i; 00213 _Aj[_top] = j; 00214 _Ax[_top] = x; 00215 _top++; 00216 } 00217 00218 // Access methods 00219 00220 template<typename Value_T, typename Index_T> 00221 inline Index_T Triplet<Value_T,Index_T>::Ai(Index_T k) const 00222 { 00223 #ifndef DNDEBUG 00224 if ((k<0) || (k>=_top)) throw new Fatal("Sparse::Triplet::Ai: Index (k=%d) for a row index must be greater than/equal to zero and smaller than/ equal to top(=%d)",k,_top); 00225 //if ((k<0) || (k>_top)) throw new Fatal("Sparse::Triplet::Ai: Index (k=%d) for a row index must be greater than/equal to zero and smaller than top(=%d)",k,_top); 00226 #endif 00227 return _Ai[k]; 00228 } 00229 00230 template<typename Value_T, typename Index_T> 00231 inline Index_T Triplet<Value_T,Index_T>::Aj(Index_T k) const 00232 { 00233 #ifndef DNDEBUG 00234 if ((k<0) || (k>_top)) throw new Fatal("Sparse::Triplet::Aj: Index (k=%d) for a column index must be greater than/equal to zero and smaller than top(=%d)",k,_top); 00235 #endif 00236 return _Aj[k]; 00237 } 00238 00239 template<typename Value_T, typename Index_T> 00240 inline Value_T Triplet<Value_T,Index_T>::Ax(Index_T k) const 00241 { 00242 #ifndef DNDEBUG 00243 if ((k<0) || (k>=_top)) throw new Fatal("Sparse::Triplet::Ax: Index (k=%d) for a non-zero value must be greater than/or equal to zero and smaller than/equal to top(=%d)",k,_top); 00244 //if ((k<0) || (k>_top)) throw new Fatal("Sparse::Triplet::Ax: Index (k=%d) for a non-zero value must be greater than/or equal to zero and smaller than top(=%d)",k,_top); 00245 #endif 00246 return _Ax[k]; 00247 } 00248 00249 template<typename Value_T, typename Index_T> 00250 inline Index_T * Triplet<Value_T,Index_T>::GetAiPtr() 00251 { 00252 #ifndef DNDEBUG 00253 if (_Ai==NULL) throw new Fatal("Sparse::Triplet::GetAiPtr: The matrix must be allocated prior to get the pointer to Ai (row indexes)."); 00254 #endif 00255 return _Ai; 00256 } 00257 00258 template<typename Value_T, typename Index_T> 00259 inline Index_T * Triplet<Value_T,Index_T>::GetAjPtr() 00260 { 00261 #ifndef DNDEBUG 00262 if (_Aj==NULL) throw new Fatal("Sparse::Triplet::GetAjPtr: The matrix must be allocated prior to get the pointer to Aj (column indexes)."); 00263 #endif 00264 return _Aj; 00265 } 00266 00267 template<typename Value_T, typename Index_T> 00268 inline Value_T * Triplet<Value_T,Index_T>::GetAxPtr() 00269 { 00270 #ifndef DNDEBUG 00271 if (_Ax==NULL) throw new Fatal("Sparse::Triplet::GetAxPtr: The matrix must be allocated prior to get the pointer to Ax (non-zero values, including duplicates)."); 00272 #endif 00273 return _Ax; 00274 } 00275 00276 template<typename Value_T, typename Index_T> 00277 inline Index_T const * Triplet<Value_T,Index_T>::GetAiPtr() const 00278 { 00279 #ifndef DNDEBUG 00280 if (_Ai==NULL) throw new Fatal("Sparse::Triplet::GetAiPtr: The matrix must be allocated prior to get the pointer to Ai (row indexes)."); 00281 #endif 00282 return _Ai; 00283 } 00284 00285 template<typename Value_T, typename Index_T> 00286 inline Index_T const * Triplet<Value_T,Index_T>::GetAjPtr() const 00287 { 00288 #ifndef DNDEBUG 00289 if (_Aj==NULL) throw new Fatal("Sparse::Triplet::GetAjPtr: The matrix must be allocated prior to get the pointer to Aj (column indexes)."); 00290 #endif 00291 return _Aj; 00292 } 00293 00294 template<typename Value_T, typename Index_T> 00295 inline Value_T const * Triplet<Value_T,Index_T>::GetAxPtr() const 00296 { 00297 #ifndef DNDEBUG 00298 if (_Ax==NULL) throw new Fatal("Sparse::Triplet::GetAxPtr: The matrix must be allocated prior to get the pointer to Ax (non-zero values, including duplicates)."); 00299 #endif 00300 return _Ax; 00301 } 00302 00303 template<typename Value_T, typename Index_T> 00304 inline void Triplet<Value_T,Index_T>::WriteSMAT (char const * FileKey, double Tol) const 00305 { 00306 // find the number of really non-zero values 00307 size_t nz = 0; 00308 for (int k=0; k<Top(); ++k) 00309 { 00310 if (fabs(Ax(k))>Tol) nz++; 00311 } 00312 00313 // output 00314 std::ostringstream oss; 00315 char buf[256]; 00316 sprintf(buf, "%d %d %zd\n", Rows(), Cols(), nz); 00317 oss << buf; 00318 for (int k=0; k<Top(); ++k) 00319 { 00320 if (fabs(Ax(k))>Tol) 00321 { 00322 sprintf(buf, " %d %d %g\n", Ai(k), Aj(k), Ax(k)); 00323 oss << buf; 00324 } 00325 } 00326 00327 // write to file 00328 String fn(FileKey); fn.append(".smat"); 00329 std::ofstream of(fn.CStr(), std::ios::out); 00330 of << oss.str(); 00331 of.close(); 00332 } 00333 00334 template<typename Value_T, typename Index_T> 00335 inline void Triplet<Value_T,Index_T>::IncIndices (Index_T Delta) 00336 { 00337 for (int k=0; k<Top(); ++k) 00338 { 00339 _Ai[k] += Delta; 00340 _Aj[k] += Delta; 00341 } 00342 } 00343 00345 template<typename Value_T, typename Index_T> 00346 std::ostream & operator<< (std::ostream & os, const Sparse::Triplet<Value_T,Index_T> & T) 00347 { 00348 os << "Rows=" << Util::_3<<T.Rows() << ", Cols=" << Util::_3<<T.Cols() << ", Top=" << Util::_3<<T.Top() << ", Size=" << Util::_3<<T.Size() << std::endl; 00349 for (Index_T k=0; k<T.Top(); ++k) 00350 os << Util::_3<< k << " # i= " << Util::_3<<T.Ai(k) << ", j= " << Util::_3<<T.Aj(k) << ", value=" << T.NS()<< T.Ax(k) << std::endl; 00351 return os; 00352 } 00353 00354 00355 }; // namespace Sparse 00356 00357 #endif // MECHSYS_SPARSE_TRIPLET_H