00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifndef SOFA_COMPONENT_LINEARSOLVER_SPARSEMATRIX_H
00026 #define SOFA_COMPONENT_LINEARSOLVER_SPARSEMATRIX_H
00027
00028 #include <sofa/defaulttype/BaseMatrix.h>
00029 #include <sofa/simulation/common/MatrixLinearSolver.h>
00030 #include "FullVector.h"
00031
00032 #include <map>
00033
00034 namespace sofa
00035 {
00036
00037 namespace component
00038 {
00039
00040 namespace linearsolver
00041 {
00042
00043
00044
00045
00046 template<typename T>
00047 class SparseMatrix : public defaulttype::BaseMatrix
00048 {
00049 public:
00050 typedef T Real;
00051 typedef int Index;
00052 typedef std::map<Index,Real> Line;
00053 typedef std::map<Index,Line> Data;
00054 typedef typename Line::iterator LElementIterator;
00055 typedef typename Line::const_iterator LElementConstIterator;
00056 typedef typename Data::iterator LineIterator;
00057 typedef typename Data::const_iterator LineConstIterator;
00058
00059 protected:
00060 Data data;
00061 Index nRow,nCol;
00062
00063 public:
00064
00065 SparseMatrix()
00066 : nRow(0), nCol(0)
00067 {
00068 }
00069
00070 SparseMatrix(int nbRow, int nbCol)
00071 : nRow(nbRow), nCol(nbCol)
00072 {
00073 }
00074
00075 LineIterator begin() { return data.begin(); }
00076 LineIterator end() { return data.end(); }
00077 LineConstIterator begin() const { return data.begin(); }
00078 LineConstIterator end() const { return data.end(); }
00079
00080 Line& operator[](Index i)
00081 {
00082 return data[i];
00083 }
00084
00085 const Line& operator[](Index i) const
00086 {
00087 static const Line empty;
00088 LineConstIterator it = data.find(i);
00089 if (it==data.end())
00090 return empty;
00091 else
00092 return it->second;
00093 }
00094
00095 void resize(int nbRow, int nbCol)
00096 {
00097 #ifdef SPARSEMATRIX_VERBOSE
00098 if (nbRow != rowSize() || nbCol != colSize())
00099 std::cout << ": resize("<<nbRow<<","<<nbCol<<")"<<std::endl;
00100 #endif
00101 data.clear();
00102 nRow = nbRow;
00103 nCol = nbCol;
00104 }
00105
00106 int rowSize(void) const
00107 {
00108 return nRow;
00109 }
00110
00111 int colSize(void) const
00112 {
00113 return nCol;
00114 }
00115
00116 SReal element(int i, int j) const
00117 {
00118 #ifdef SPARSEMATRIX_CHECK
00119 if ((unsigned)i >= (unsigned)rowSize() || (unsigned)j >= (unsigned)colSize())
00120 {
00121 std::cerr << "ERROR: invalid read access to element ("<<i<<","<<j<<") in "<<" of size ("<<rowSize()<<","<<colSize()<<")"<<std::endl;
00122 return 0.0;
00123 }
00124 #endif
00125 LineConstIterator it = data.find(i);
00126 if (it==data.end())
00127 return 0.0;
00128 LElementConstIterator ite = it->second.find(j);
00129 if (ite == it->second.end())
00130 return 0.0;
00131 return ite->second;
00132 }
00133
00134 void set(int i, int j, double v)
00135 {
00136 #ifdef SPARSEMATRIX_VERBOSE
00137 std::cout << "("<<rowSize()<<","<<colSize()<<"): element("<<i<<","<<j<<") = "<<v<<std::endl;
00138 #endif
00139 #ifdef SPARSEMATRIX_CHECK
00140 if ((unsigned)i >= (unsigned)rowSize() || (unsigned)j >= (unsigned)colSize())
00141 {
00142 std::cerr << "ERROR: invalid write access to element ("<<i<<","<<j<<") in "<<" of size ("<<rowSize()<<","<<colSize()<<")"<<std::endl;
00143 return;
00144 }
00145 #endif
00146 data[i][j] = (Real)v;
00147 }
00148
00149 void add(int i, int j, double v)
00150 {
00151 #ifdef SPARSEMATRIX_VERBOSE
00152 std::cout << "("<<rowSize()<<","<<colSize()<<"): element("<<i<<","<<j<<") += "<<v<<std::endl;
00153 #endif
00154 #ifdef SPARSEMATRIX_CHECK
00155 if ((unsigned)i >= (unsigned)rowSize() || (unsigned)j >= (unsigned)colSize())
00156 {
00157 std::cerr << "ERROR: invalid write access to element ("<<i<<","<<j<<") in "<<" of size ("<<rowSize()<<","<<colSize()<<")"<<std::endl;
00158 return;
00159 }
00160 #endif
00161 data[i][j] += (Real)v;
00162 }
00163
00164 void clear(int i, int j)
00165 {
00166 #ifdef SPARSEMATRIX_VERBOSE
00167 std::cout << "("<<rowSize()<<","<<colSize()<<"): element("<<i<<","<<j<<") = 0"<<std::endl;
00168 #endif
00169 #ifdef SPARSEMATRIX_CHECK
00170 if ((unsigned)i >= (unsigned)rowSize() || (unsigned)j >= (unsigned)colSize())
00171 {
00172 std::cerr << "ERROR: invalid write access to element ("<<i<<","<<j<<") in "<<" of size ("<<rowSize()<<","<<colSize()<<")"<<std::endl;
00173 return;
00174 }
00175 #endif
00176 LineIterator it = data.find(i);
00177 if (it==data.end())
00178 return;
00179 LElementIterator ite = it->second.find(j);
00180 if (ite == it->second.end())
00181 return;
00182 it->second.erase(ite);
00183 if (it->second.empty())
00184 data.erase(it);
00185 }
00186
00187 void clearRow(int i)
00188 {
00189 #ifdef SPARSEMATRIX_VERBOSE
00190 std::cout << "("<<rowSize()<<","<<colSize()<<"): row("<<i<<") = 0"<<std::endl;
00191 #endif
00192 #ifdef SPARSEMATRIX_CHECK
00193 if ((unsigned)i >= (unsigned)rowSize())
00194 {
00195 std::cerr << "ERROR: invalid write access to row "<<i<<" in "<<" of size ("<<rowSize()<<","<<colSize()<<")"<<std::endl;
00196 return;
00197 }
00198 #endif
00199 LineIterator it = data.find(i);
00200 if (it==data.end())
00201 return;
00202 data.erase(it);
00203 }
00204
00205 void clearCol(int j)
00206 {
00207 #ifdef SPARSEMATRIX_VERBOSE
00208 std::cout << "("<<rowSize()<<","<<colSize()<<"): col("<<j<<") = 0"<<std::endl;
00209 #endif
00210 #ifdef SPARSEMATRIX_CHECK
00211 if ((unsigned)j >= (unsigned)colSize())
00212 {
00213 std::cerr << "ERROR: invalid write access to column "<<j<<" in "<<" of size ("<<rowSize()<<","<<colSize()<<")"<<std::endl;
00214 return;
00215 }
00216 #endif
00217 for(LineIterator it=data.begin(),itend=data.end();it!=itend;++it)
00218 {
00219 LElementIterator ite = it->second.find(j);
00220 if (ite != it->second.end())
00221 it->second.erase(ite);
00222 }
00223 }
00224
00225 void clearRowCol(int i)
00226 {
00227 #ifdef SPARSEMATRIX_VERBOSE
00228 std::cout << "("<<rowSize()<<","<<colSize()<<"): row("<<i<<") = 0 and col("<<i<<") = 0"<<std::endl;
00229 #endif
00230 #ifdef SPARSEMATRIX_CHECK
00231 if ((unsigned)i >= (unsigned)rowSize() || (unsigned)i >= (unsigned)colSize())
00232 {
00233 std::cerr << "ERROR: invalid write access to row and column "<<i<<" in "<<" of size ("<<rowSize()<<","<<colSize()<<")"<<std::endl;
00234 return;
00235 }
00236 #endif
00237 clearRow(i);
00238 clearCol(i);
00239 }
00240
00241 void clear() { data.clear(); }
00242
00243 template<class Real2>
00244 void mul(FullVector<Real2>& res, const FullVector<Real2>& v) const
00245 {
00246 res.resize(rowSize());
00247 for (LineConstIterator itl = begin(), itlend=end(); itl!=itlend; ++itl)
00248 {
00249 Real2 r = 0;
00250 for (LElementConstIterator ite = itl->second.begin(), iteend=itl->second.end(); ite!=iteend; ++ite)
00251 r += (Real2)ite->second * v[ite->first];
00252 res[itl->first] = r;
00253 }
00254 }
00255
00256 template<class Real2>
00257 void mulTranspose(FullVector<Real2>& res, const FullVector<Real2>& v) const
00258 {
00259 res.resize(colSize());
00260 for (LineConstIterator itl = begin(), itlend=end(); itl!=itlend; ++itl)
00261 {
00262 Real2 vi = v[itl->first];
00263 for (LElementConstIterator ite = itl->second.begin(), iteend=itl->second.end(); ite!=iteend; ++ite)
00264 res[ite->first] += (Real2)ite->second * vi;
00265 }
00266 }
00267
00268 template<class Real2>
00269 void mul(FullVector<Real2>& res, const defaulttype::BaseVector* v) const
00270 {
00271 res.resize(rowSize());
00272 for (LineConstIterator itl = begin(), itlend=end(); itl!=itlend; ++itl)
00273 {
00274 Real2 r = 0;
00275 for (LElementConstIterator ite = itl->second.begin(), iteend=itl->second.end(); ite!=iteend; ++ite)
00276 r += (Real2)ite->second * (Real2)v->element(ite->first);
00277 res[itl->first] = r;
00278 }
00279 }
00280
00281 template<class Real2>
00282 void mulTranspose(FullVector<Real2>& res, const defaulttype::BaseVector* v) const
00283 {
00284 res.resize(colSize());
00285 for (LineConstIterator itl = begin(), itlend=end(); itl!=itlend; ++itl)
00286 {
00287 Real2 vi = v->element(itl->first);
00288 for (LElementConstIterator ite = itl->second.begin(), iteend=itl->second.end(); ite!=iteend; ++ite)
00289 res[ite->first] += (Real2)ite->second * vi;
00290 }
00291 }
00292
00293 template<class Real2>
00294 void mul(defaulttype::BaseVector* res, const FullVector<Real2>& v) const
00295 {
00296 res->resize(rowSize());
00297 for (LineConstIterator itl = begin(), itlend=end(); itl!=itlend; ++itl)
00298 {
00299 Real2 r = 0;
00300 for (LElementConstIterator ite = itl->second.begin(), iteend=itl->second.end(); ite!=iteend; ++ite)
00301 r += (Real2)ite->second * v[ite->first];
00302 res->set(itl->first, r);
00303 }
00304 }
00305
00306 template<class Real2>
00307 void mulTranspose(defaulttype::BaseVector* res, const FullVector<Real2>& v) const
00308 {
00309 res->resize(colSize());
00310 for (LineConstIterator itl = begin(), itlend=end(); itl!=itlend; ++itl)
00311 {
00312 Real2 vi = v[itl->first];
00313 for (LElementConstIterator ite = itl->second.begin(), iteend=itl->second.end(); ite!=iteend; ++ite)
00314 res->add(ite->first, ite->second * vi);
00315 }
00316 }
00317
00318 void mul(defaulttype::BaseVector* res, const defaulttype::BaseVector* v) const
00319 {
00320 res->resize(rowSize());
00321 for (LineConstIterator itl = begin(), itlend=end(); itl!=itlend; ++itl)
00322 {
00323 Real r = 0;
00324 for (LElementConstIterator ite = itl->second.begin(), iteend=itl->second.end(); ite!=iteend; ++ite)
00325 r += ite->second * (Real)v->element(ite->first);
00326 res->set(itl->first, r);
00327 }
00328 }
00329
00330 void mulTranspose(defaulttype::BaseVector* res, const defaulttype::BaseVector* v) const
00331 {
00332 res->resize(colSize());
00333 for (LineConstIterator itl = begin(), itlend=end(); itl!=itlend; ++itl)
00334 {
00335 Real vi = (Real)v->element(itl->first);
00336 for (LElementConstIterator ite = itl->second.begin(), iteend=itl->second.end(); ite!=iteend; ++ite)
00337 res->add(ite->first, ite->second * vi);
00338 }
00339 }
00340
00341 template<class Real2>
00342 FullVector<Real2> operator*(const FullVector<Real2>& v) const
00343 {
00344 FullVector<Real2> res;
00345 mul(res,v);
00346 return res;
00347 }
00348
00349 friend std::ostream& operator << (std::ostream& out, const SparseMatrix<T>& v )
00350 {
00351 int nx = v.Ncols();
00352 int ny = v.Nrows();
00353 out << "[";
00354 for (int y=0;y<ny;++y)
00355 {
00356 out << "\n[";
00357 for (int x=0;x<nx;++x)
00358 {
00359 out << " " << v.element(y,x);
00360 }
00361 out << " ]";
00362 }
00363 out << " ]";
00364 return out;
00365 }
00366
00367 static const char* Name() { return "SparseMatrix"; }
00368 };
00369
00370 }
00371
00372 }
00373
00374 }
00375
00376 #endif