NewMatMatrix.h

Go to the documentation of this file.
00001 /******************************************************************************
00002 *       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 3      *
00003 *                (c) 2006-2008 MGH, INRIA, USTL, UJF, CNRS                    *
00004 *                                                                             *
00005 * This library is free software; you can redistribute it and/or modify it     *
00006 * under the terms of the GNU Lesser General Public License as published by    *
00007 * the Free Software Foundation; either version 2.1 of the License, or (at     *
00008 * your option) any later version.                                             *
00009 *                                                                             *
00010 * This library is distributed in the hope that it will be useful, but WITHOUT *
00011 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
00012 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
00013 * for more details.                                                           *
00014 *                                                                             *
00015 * You should have received a copy of the GNU Lesser General Public License    *
00016 * along with this library; if not, write to the Free Software Foundation,     *
00017 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
00018 *******************************************************************************
00019 *                               SOFA :: Modules                               *
00020 *                                                                             *
00021 * Authors: The SOFA Team and external contributors (see Authors.txt)          *
00022 *                                                                             *
00023 * Contact information: contact@sofa-framework.org                             *
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 //#define NEWMAT_CHECK
00042 //#define NEWMAT_VERBOSE
00043 
00044 template<class Mat>
00045 class TNewMatMatrix : public Mat, public defaulttype::BaseMatrix
00046 {
00047 public:
00048     typedef Mat M;
00049     //typedef NewMAT::Matrix SubMatrixType;
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 << /* this->Name()  <<  */": 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 "<</* this->Name() <<*/" 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 << /* this->Name()  <<  */"("<<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 "<</* this->Name() <<*/" 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 << /* this->Name()  <<  */"("<<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 "<</* this->Name() <<*/" 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 << /* this->Name()  <<  */"("<<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 "<</* this->Name() <<*/" 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 << /* this->Name()  <<  */"("<<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 "<</* this->Name() <<*/" 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 << /* this->Name()  <<  */"("<<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 "<</* this->Name() <<*/" 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 << /* this->Name()  <<  */"("<<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 "<</* this->Name() <<*/" 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 << /* this->Name()  <<  */"("<<rowSize()<<","<<colSize()<<"): solve("<<*ov<<") = "<<std::endl;
00201 #endif
00202         *rv = this->i() * *ov;
00203 #ifdef NEWMAT_VERBOSE
00204         std::cout << /* this->Name()  <<  */"("<<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 << /* this->Name()  <<  */"("<<rowSize()<<","<<colSize()<<"): solve("<<*ov<<") = "<<std::endl;
00226 #endif
00227         *rv = solver->i() * *ov;
00228 #ifdef NEWMAT_VERBOSE
00229         std::cout << /* this->Name()  <<  */"("<<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 << /* this->Name()  <<  */"("<<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 "<</* this->Name() <<*/" 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 << /* this->Name()  <<  */"("<<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 "<</* this->Name() <<*/" 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 "<</* this->Name() <<*/" 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 << /* this->Name()  <<  */"("<<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 "<</* this->Name() <<*/" 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 << /* this->Name()  <<  */"("<<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 "<</* this->Name() <<*/" 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 "<</* this->Name() <<*/" 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 << /* this->Name()  <<  */"("<<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 "<</* this->Name() <<*/" 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 << /* this->Name()  <<  */"("<<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 "<</* this->Name() <<*/" 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 } // namespace linearsolver
00456 
00457 } // namespace component
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 } // namespace simulation
00496             
00497 } // namespace sofa
00498 
00499 #endif

Generated on Sun Nov 23 03:25:11 2008 for Sofa by  doxygen 1.5.7.1