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_NEWMATMATRIX_H
00026 #define SOFA_COMPONENT_LINEARSOLVER_NEWMATMATRIX_H
00027
00028 #include <sofa/defaulttype/BaseMatrix.h>
00029 #include <sofa/simulation/common/MatrixLinearSolver.h>
00030 #include "NewMatVector.h"
00031
00032 namespace sofa
00033 {
00034
00035 namespace component
00036 {
00037
00038 namespace linearsolver
00039 {
00040
00041
00042
00043
00044 template<class Mat>
00045 class TNewMatMatrix : public Mat, public defaulttype::BaseMatrix
00046 {
00047 public:
00048 typedef Mat M;
00049
00050 typedef TNewMatMatrix<NEWMAT::Matrix> SubMatrixType;
00051 typedef TNewMatMatrix<NEWMAT::Matrix> InvMatrixType;
00052 typedef NEWMAT::LinearEquationSolver LUSolver;
00053 explicit TNewMatMatrix(int defaultBandWidth = 11)
00054 : bandWidth(defaultBandWidth)
00055 {
00056 }
00057
00058 void resize(int nbRow, int nbCol)
00059 {
00060 #ifdef NEWMAT_VERBOSE
00061 std::cout << ": resize("<<nbRow<<","<<nbCol<<")"<<std::endl;
00062 #endif
00063 M::ReSize(nbRow, nbCol);
00064 (*this) = 0.0;
00065 }
00066
00067 int rowSize(void) const
00068 {
00069 return M::Nrows();
00070 }
00071
00072 int colSize(void) const
00073 {
00074 return M::Ncols();
00075 }
00076
00077 SReal element(int i, int j) const
00078 {
00079 #ifdef NEWMAT_CHECK
00080 if ((unsigned)i >= (unsigned)rowSize() || (unsigned)j >= (unsigned)colSize())
00081 {
00082 std::cerr << "ERROR: invalid read access to element ("<<i<<","<<j<<") in "<<" of size ("<<rowSize()<<","<<colSize()<<")"<<std::endl;
00083 return 0.0;
00084 }
00085 #endif
00086 return M::element(i,j);
00087 }
00088
00089 void set(int i, int j, double v)
00090 {
00091 #ifdef NEWMAT_VERBOSE
00092 std::cout << "("<<rowSize()<<","<<colSize()<<"): element("<<i<<","<<j<<") = "<<v<<std::endl;
00093 #endif
00094 #ifdef NEWMAT_CHECK
00095 if ((unsigned)i >= (unsigned)rowSize() || (unsigned)j >= (unsigned)colSize())
00096 {
00097 std::cerr << "ERROR: invalid write access to element ("<<i<<","<<j<<") in "<<" of size ("<<rowSize()<<","<<colSize()<<")"<<std::endl;
00098 return;
00099 }
00100 #endif
00101 M::element(i,j) = v;
00102 }
00103
00104 void add(int i, int j, double v)
00105 {
00106 #ifdef NEWMAT_VERBOSE
00107 std::cout << "("<<rowSize()<<","<<colSize()<<"): element("<<i<<","<<j<<") += "<<v<<std::endl;
00108 #endif
00109 #ifdef NEWMAT_CHECK
00110 if ((unsigned)i >= (unsigned)rowSize() || (unsigned)j >= (unsigned)colSize())
00111 {
00112 std::cerr << "ERROR: invalid write access to element ("<<i<<","<<j<<") in "<<" of size ("<<rowSize()<<","<<colSize()<<")"<<std::endl;
00113 return;
00114 }
00115 #endif
00116 M::element(i,j) += v;
00117 }
00118
00119 void clear(int i, int j)
00120 {
00121 #ifdef NEWMAT_VERBOSE
00122 std::cout << "("<<rowSize()<<","<<colSize()<<"): element("<<i<<","<<j<<") = 0"<<std::endl;
00123 #endif
00124 #ifdef NEWMAT_CHECK
00125 if ((unsigned)i >= (unsigned)rowSize() || (unsigned)j >= (unsigned)colSize())
00126 {
00127 std::cerr << "ERROR: invalid write access to element ("<<i<<","<<j<<") in "<<" of size ("<<rowSize()<<","<<colSize()<<")"<<std::endl;
00128 return;
00129 }
00130 #endif
00131 M::element(i,j) = 0.0;
00132 }
00133
00134 void clearRow(int i)
00135 {
00136 #ifdef NEWMAT_VERBOSE
00137 std::cout << "("<<rowSize()<<","<<colSize()<<"): row("<<i<<") = 0"<<std::endl;
00138 #endif
00139 #ifdef NEWMAT_CHECK
00140 if ((unsigned)i >= (unsigned)rowSize())
00141 {
00142 std::cerr << "ERROR: invalid write access to row "<<i<<" in "<<" of size ("<<rowSize()<<","<<colSize()<<")"<<std::endl;
00143 return;
00144 }
00145 #endif
00146 M::Row(1+i) = 0.0;
00147 }
00148
00149 void clearCol(int j)
00150 {
00151 #ifdef NEWMAT_VERBOSE
00152 std::cout << "("<<rowSize()<<","<<colSize()<<"): col("<<j<<") = 0"<<std::endl;
00153 #endif
00154 #ifdef NEWMAT_CHECK
00155 if ((unsigned)j >= (unsigned)colSize())
00156 {
00157 std::cerr << "ERROR: invalid write access to column "<<j<<" in "<<" of size ("<<rowSize()<<","<<colSize()<<")"<<std::endl;
00158 return;
00159 }
00160 #endif
00161 M::Column(1+j) = 0.0;
00162 }
00163
00164 void clearRowCol(int i)
00165 {
00166 #ifdef NEWMAT_VERBOSE
00167 std::cout << "("<<rowSize()<<","<<colSize()<<"): row("<<i<<") = 0 and col("<<i<<") = 0"<<std::endl;
00168 #endif
00169 #ifdef NEWMAT_CHECK
00170 if ((unsigned)i >= (unsigned)rowSize() || (unsigned)i >= (unsigned)colSize())
00171 {
00172 std::cerr << "ERROR: invalid write access to row and column "<<i<<" in "<<" of size ("<<rowSize()<<","<<colSize()<<")"<<std::endl;
00173 return;
00174 }
00175 #endif
00176 M::Row(1+i) = 0.0;
00177 M::Column(1+i) = 0.0;
00178 }
00179
00180 NEWMAT::GetSubMatrix sub(int i, int j, int nrow, int ncol)
00181 {
00182 return M::SubMatrix(i+1,i+nrow,j+1,j+ncol);
00183 }
00184
00185 template<class T>
00186 void getSubMatrix(int i, int j, int nrow, int ncol, T& m)
00187 {
00188 m = M::SubMatrix(i+1,i+nrow,j+1,j+ncol);
00189 }
00190
00191 template<class T>
00192 void setSubMatrix(int i, int j, int nrow, int ncol, const T& m)
00193 {
00194 M::SubMatrix(i+1,i+nrow,j+1,j+ncol) = m;
00195 }
00196
00197 void solve(NewMatVector *rv, NewMatVector *ov)
00198 {
00199 #ifdef NEWMAT_VERBOSE
00200 std::cout << "("<<rowSize()<<","<<colSize()<<"): solve("<<*ov<<") = "<<std::endl;
00201 #endif
00202 *rv = this->i() * *ov;
00203 #ifdef NEWMAT_VERBOSE
00204 std::cout << "("<<rowSize()<<","<<colSize()<<"): solve("<<*ov<<") = "<<*rv<<std::endl;
00205 #endif
00206 }
00207
00208 virtual void solve(defaulttype::BaseVector *op, defaulttype::BaseVector *res)
00209 {
00210 NewMatVector *rv = dynamic_cast<NewMatVector *>(res);
00211 NewMatVector *ov = dynamic_cast<NewMatVector *>(op);
00212
00213 assert((ov!=NULL) && (rv!=NULL));
00214 solve(rv,ov);
00215 }
00216
00217 LUSolver* makeLUSolver()
00218 {
00219 return new LUSolver(*this);
00220 }
00221
00222 void solve(NewMatVector *rv, NewMatVector *ov, LUSolver* solver)
00223 {
00224 #ifdef NEWMAT_VERBOSE
00225 std::cout << "("<<rowSize()<<","<<colSize()<<"): solve("<<*ov<<") = "<<std::endl;
00226 #endif
00227 *rv = solver->i() * *ov;
00228 #ifdef NEWMAT_VERBOSE
00229 std::cout << "("<<rowSize()<<","<<colSize()<<"): solve("<<*ov<<") = "<<*rv<<std::endl;
00230 #endif
00231 }
00232
00233 template<class T>
00234 void operator=(const T& m) { M::operator=(m); }
00235
00236 void clear() { (*this) = 0.0; }
00237
00238 friend std::ostream& operator << (std::ostream& out, const TNewMatMatrix& v )
00239 {
00240 int nx = v.Ncols();
00241 int ny = v.Nrows();
00242 out << "[";
00243 for (int y=0;y<ny;++y)
00244 {
00245 out << "\n[";
00246 for (int x=0;x<nx;++x)
00247 {
00248 out << " " << v.element(y,x);
00249 }
00250 out << " ]";
00251 }
00252 out << " ]";
00253 return out;
00254 }
00255
00256 static const char* Name();
00257
00258 int bandWidth;
00259 };
00260
00261 typedef TNewMatMatrix<NEWMAT::Matrix> NewMatMatrix;
00262 typedef TNewMatMatrix<NEWMAT::SymmetricMatrix> NewMatSymmetricMatrix;
00263 typedef TNewMatMatrix<NEWMAT::BandMatrix> NewMatBandMatrix;
00264 typedef TNewMatMatrix<NEWMAT::SymmetricBandMatrix> NewMatSymmetricBandMatrix;
00265
00266 template<>
00267 inline const char* TNewMatMatrix<NEWMAT::Matrix>::Name() { return "NewMat"; }
00268
00269 template<>
00270 inline const char* TNewMatMatrix<NEWMAT::SymmetricMatrix>::Name() { return "NewMatSymmetric"; }
00271
00272 template<>
00273 inline const char* TNewMatMatrix<NEWMAT::BandMatrix>::Name() { return "NewMatBand"; }
00274
00275 template<>
00276 inline const char* TNewMatMatrix<NEWMAT::SymmetricBandMatrix>::Name() { return "NewMatSymmetricBand"; }
00277
00278 template<>
00279 inline void TNewMatMatrix<NEWMAT::SymmetricMatrix>::resize(int nbRow, int nbCol)
00280 {
00281 if (nbCol != nbRow)
00282 std::cerr << "ERROR: NEWMAT::SymmetricMatrix must be square, size "<<nbRow<<"x"<<nbCol<<" not supported."<<std::endl;
00283 M::ReSize(nbRow);
00284 }
00285
00286 template<>
00287 inline void TNewMatMatrix<NEWMAT::BandMatrix>::resize(int nbRow, int nbCol)
00288 {
00289 if (nbCol != nbRow)
00290 std::cerr << "ERROR: NewMAT::BandMatrix must be square, size "<<nbRow<<"x"<<nbCol<<" not supported."<<std::endl;
00291 M::ReSize(nbRow, bandWidth, bandWidth);
00292 }
00293
00294 template<>
00295 inline void TNewMatMatrix<NEWMAT::SymmetricBandMatrix>::resize(int nbRow, int nbCol)
00296 {
00297 if (nbCol != nbRow)
00298 std::cerr << "ERROR: NEWMAT::SymmetricBandMatrix must be square, size "<<nbRow<<"x"<<nbCol<<" not supported."<<std::endl;
00299 M::ReSize(nbRow, bandWidth);
00300 }
00301
00302 template<>
00303 inline void TNewMatMatrix<NEWMAT::SymmetricMatrix>::set(int i, int j, double v)
00304 {
00305 #ifdef NEWMAT_VERBOSE
00306 std::cout << "("<<rowSize()<<","<<colSize()<<"): element("<<i<<","<<j<<") = "<<v<<std::endl;
00307 #endif
00308 #ifdef NEWMAT_CHECK
00309 if ((unsigned)i >= (unsigned)rowSize() || (unsigned)j >= (unsigned)colSize())
00310 {
00311 std::cerr << "ERROR: invalid write access to element ("<<i<<","<<j<<") in "<<" of size ("<<rowSize()<<","<<colSize()<<")"<<std::endl;
00312 return;
00313 }
00314 #endif
00315 if (j <= i)
00316 M::element(i,j) = v;
00317 }
00318
00319 template<>
00320 inline void TNewMatMatrix<NEWMAT::SymmetricMatrix>::add(int i, int j, double v)
00321 {
00322 #ifdef NEWMAT_VERBOSE
00323 std::cout << "("<<rowSize()<<","<<colSize()<<"): element("<<i<<","<<j<<") += "<<v<<std::endl;
00324 #endif
00325 #ifdef NEWMAT_CHECK
00326 if ((unsigned)i >= (unsigned)rowSize() || (unsigned)j >= (unsigned)colSize())
00327 {
00328 std::cerr << "ERROR: invalid write access to element ("<<i<<","<<j<<") in "<<" of size ("<<rowSize()<<","<<colSize()<<")"<<std::endl;
00329 return;
00330 }
00331 #endif
00332 if (j <= i)
00333 M::element(i,j) += v;
00334 }
00335
00336 template<>
00337 inline SReal TNewMatMatrix<NEWMAT::BandMatrix>::element(int i, int j) const
00338 {
00339 #ifdef NEWMAT_CHECK
00340 if ((unsigned)i >= (unsigned)rowSize() || (unsigned)j >= (unsigned)colSize())
00341 {
00342 std::cerr << "ERROR: invalid read access to element ("<<i<<","<<j<<") in "<<" of size ("<<rowSize()<<","<<colSize()<<")"<<std::endl;
00343 return 0.0;
00344 }
00345 #endif
00346 if (j < i-bandWidth || j > i+bandWidth)
00347 return 0.0;
00348 else
00349 return M::element(i,j);
00350 }
00351
00352
00353 template<>
00354 inline void TNewMatMatrix<NEWMAT::BandMatrix>::set(int i, int j, double v)
00355 {
00356 #ifdef NEWMAT_VERBOSE
00357 std::cout << "("<<rowSize()<<","<<colSize()<<"): element("<<i<<","<<j<<") = "<<v<<std::endl;
00358 #endif
00359 #ifdef NEWMAT_CHECK
00360 if ((unsigned)i >= (unsigned)rowSize() || (unsigned)j >= (unsigned)colSize())
00361 {
00362 std::cerr << "ERROR: invalid write access to element ("<<i<<","<<j<<") in "<<" of size ("<<rowSize()<<","<<colSize()<<")"<<std::endl;
00363 return;
00364 }
00365 #endif
00366 if (j < i-bandWidth || j > i+bandWidth)
00367 {
00368 std::cerr << "ERROR: trying to set "<<v<<" to element ("<<i<<","<<j<<") in NewMAT::BandMatrix of bandwidth "<<bandWidth<<std::endl;
00369 return;
00370 }
00371 M::element(i,j) = v;
00372 }
00373
00374 template<>
00375 inline void TNewMatMatrix<NEWMAT::BandMatrix>::add(int i, int j, double v)
00376 {
00377 #ifdef NEWMAT_VERBOSE
00378 std::cout << "("<<rowSize()<<","<<colSize()<<"): element("<<i<<","<<j<<") += "<<v<<std::endl;
00379 #endif
00380 #ifdef NEWMAT_CHECK
00381 if ((unsigned)i >= (unsigned)rowSize() || (unsigned)j >= (unsigned)colSize())
00382 {
00383 std::cerr << "ERROR: invalid write access to element ("<<i<<","<<j<<") in "<<" of size ("<<rowSize()<<","<<colSize()<<")"<<std::endl;
00384 return;
00385 }
00386 #endif
00387 if (j < i-bandWidth || j > i+bandWidth)
00388 {
00389 std::cerr << "ERROR: trying to set "<<v<<" to element ("<<i<<","<<j<<") in NewMAT::BandMatrix of bandwidth "<<bandWidth<<std::endl;
00390 return;
00391 }
00392 M::element(i,j) += v;
00393 }
00394
00395 template<>
00396 inline SReal TNewMatMatrix<NEWMAT::SymmetricBandMatrix>::element(int i, int j) const
00397 {
00398 #ifdef NEWMAT_CHECK
00399 if ((unsigned)i >= (unsigned)rowSize() || (unsigned)j >= (unsigned)colSize())
00400 {
00401 std::cerr << "ERROR: invalid read access to element ("<<i<<","<<j<<") in "<<" of size ("<<rowSize()<<","<<colSize()<<")"<<std::endl;
00402 return 0.0;
00403 }
00404 #endif
00405 if (j < i-bandWidth || j > i+bandWidth)
00406 return 0.0;
00407 else
00408 return M::element(i,j);
00409 }
00410
00411 template<>
00412 inline void TNewMatMatrix<NEWMAT::SymmetricBandMatrix>::set(int i, int j, double v)
00413 {
00414 #ifdef NEWMAT_VERBOSE
00415 std::cout << "("<<rowSize()<<","<<colSize()<<"): element("<<i<<","<<j<<") = "<<v<<std::endl;
00416 #endif
00417 #ifdef NEWMAT_CHECK
00418 if ((unsigned)i >= (unsigned)rowSize() || (unsigned)j >= (unsigned)colSize())
00419 {
00420 std::cerr << "ERROR: invalid write access to element ("<<i<<","<<j<<") in "<<" of size ("<<rowSize()<<","<<colSize()<<")"<<std::endl;
00421 return;
00422 }
00423 #endif
00424 if (j < i-bandWidth || j > i+bandWidth)
00425 {
00426 std::cerr << "ERROR: trying to set "<<v<<" to element ("<<i<<","<<j<<") in NewMAT::SymmetricBandMatrix of bandwidth "<<bandWidth<<std::endl;
00427 return;
00428 }
00429 if (j <= i)
00430 M::element(i,j) = v;
00431 }
00432
00433 template<>
00434 inline void TNewMatMatrix<NEWMAT::SymmetricBandMatrix>::add(int i, int j, double v)
00435 {
00436 #ifdef NEWMAT_VERBOSE
00437 std::cout << "("<<rowSize()<<","<<colSize()<<"): element("<<i<<","<<j<<") += "<<v<<std::endl;
00438 #endif
00439 #ifdef NEWMAT_CHECK
00440 if ((unsigned)i >= (unsigned)rowSize() || (unsigned)j >= (unsigned)colSize())
00441 {
00442 std::cerr << "ERROR: invalid write access to element ("<<i<<","<<j<<") in "<<" of size ("<<rowSize()<<","<<colSize()<<")"<<std::endl;
00443 return;
00444 }
00445 #endif
00446 if (j < i-bandWidth || j > i+bandWidth)
00447 {
00448 std::cerr << "ERROR: trying to set "<<v<<" to element ("<<i<<","<<j<<") in NewMAT::SymmetricBandMatrix of bandwidth "<<bandWidth<<std::endl;
00449 return;
00450 }
00451 if (j <= i)
00452 M::element(i,j) += v;
00453 }
00454
00455 }
00456
00457 }
00458
00459 namespace simulation
00460 {
00461
00462 template<>
00463 class MatrixLinearSolverInternalData< component::linearsolver::TNewMatMatrix<NEWMAT::SymmetricBandMatrix> , component::linearsolver::NewMatVector >
00464 {
00465 public:
00466 Data<int> bandWidth;
00467 MatrixLinearSolverInternalData(core::objectmodel::BaseObject* o)
00468 : bandWidth( o->initData(&bandWidth, 11, "bandWidth", "width of the band on each side of the diagonal (i.e. total values per lines is 2*bandWidth+1)"))
00469 {}
00470 };
00471
00472 template<>
00473 inline component::linearsolver::TNewMatMatrix<NEWMAT::SymmetricBandMatrix>* MatrixLinearSolver< component::linearsolver::TNewMatMatrix<NEWMAT::SymmetricBandMatrix> , component::linearsolver::NewMatVector >::createMatrix()
00474 {
00475 return new component::linearsolver::TNewMatMatrix<NEWMAT::SymmetricBandMatrix>(this->data->bandWidth.getValue());
00476 }
00477
00478 template<>
00479 class MatrixLinearSolverInternalData< component::linearsolver::TNewMatMatrix<NEWMAT::BandMatrix> , component::linearsolver::NewMatVector >
00480 {
00481 public:
00482 Data<int> bandWidth;
00483 MatrixLinearSolverInternalData(core::objectmodel::BaseObject* o)
00484 : bandWidth( o->initData(&bandWidth, 11, "bandWidth", "width of the band on each side of the diagonal (i.e. total values per lines is 2*bandWidth+1)"))
00485 {}
00486 };
00487
00488 template<>
00489 inline component::linearsolver::TNewMatMatrix<NEWMAT::BandMatrix>* MatrixLinearSolver< component::linearsolver::TNewMatMatrix<NEWMAT::BandMatrix> , component::linearsolver::NewMatVector >::createMatrix()
00490 {
00491 return new component::linearsolver::TNewMatMatrix<NEWMAT::BandMatrix>(this->data->bandWidth.getValue());
00492 }
00493
00494
00495 }
00496
00497 }
00498
00499 #endif