MechSys  1.0
Computing library for simulations in continuum and discrete mechanics
/home/dorival/mechsys/lib/linalg/sparse_triplet.h
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines