LULinearSolver.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_LULINEARSOLVER_H
00026 #define SOFA_COMPONENT_LINEARSOLVER_LULINEARSOLVER_H
00027 
00028 #include <sofa/core/componentmodel/behavior/LinearSolver.h>
00029 #include <sofa/simulation/common/MatrixLinearSolver.h>
00030 #include <sofa/component/linearsolver/SparseMatrix.h>
00031 #include <sofa/component/linearsolver/FullMatrix.h>
00032 #include <math.h>
00033 
00034 namespace sofa
00035 {
00036 
00037 namespace component
00038 {
00039 
00040 namespace linearsolver
00041 {
00042 
00044 template<class Matrix, class Vector>
00045 class LULinearSolver : public sofa::simulation::MatrixLinearSolver<Matrix,Vector>, public virtual sofa::core::objectmodel::BaseObject
00046 {
00047 public:
00048     Data<bool> f_verbose;
00049     typename Matrix::LUSolver* solver;
00050     typename Matrix::InvMatrixType Minv;
00051     bool computedMinv;
00052     
00053     LULinearSolver()
00054     : f_verbose( initData(&f_verbose,false,"verbose","Dump system state at each iteration") )
00055     , solver(NULL), computedMinv(false)
00056     {
00057     }
00058     
00059     ~LULinearSolver()
00060     {
00061         if (solver != NULL)
00062             delete solver;
00063     }
00064     
00066     void invert (Matrix& M)
00067     {
00068         if (solver != NULL)
00069             delete solver;
00070         solver = M.makeLUSolver();
00071         computedMinv = false;
00072     }
00073     
00075     void solve (Matrix& M, Vector& x, Vector& b)
00076     {
00077         using std::cerr;
00078         using std::endl;
00079         
00080         const bool verbose  = f_verbose.getValue();
00081         
00082         if( verbose )
00083         {
00084             cerr<<"LULinearSolver, b = "<< b <<endl;
00085             cerr<<"LULinearSolver, M = "<< M <<endl;
00086         }
00087         if (solver)
00088             M.solve(&x,&b, solver);
00089         else
00090             M.solve(&x,&b);
00091         
00092         // x is the solution of the system
00093         if( verbose )
00094         {
00095             cerr<<"LULinearSolver::solve, solution = "<<x<<endl;
00096         }
00097     }
00098     
00099     void computeMinv()
00100     {
00101         if (!computedMinv)
00102         {
00103             if (solver)
00104                 Minv = solver->i();
00105             else
00106                 Minv = this->systemMatrix->i();
00107             computedMinv = true;
00108         }
00109         /*typename Matrix::InvMatrixType I;
00110         I = ((*this->systemMatrix)*Minv);
00111         for (int i=0;i<I.rowSize();++i)
00112             for (int j=0;j<I.rowSize();++j)
00113             {
00114                 double err = I.element(i,j)-((i==j)?1.0:0.0);
00115                 if (fabs(err) > 1.0e-6)
00116                     std::cerr << "ERROR: I("<<i<<","<<j<<") error "<<err<<std::endl;
00117             }*/
00118     }
00119     
00120     double getMinvElement(int i, int j)
00121     {
00122         return Minv.element(i,j);
00123     }
00124     
00125     template<class RMatrix, class JMatrix>
00126     bool addJMInvJt(RMatrix& result, JMatrix& J, double fact)
00127     {
00128         const int Jrows = J.rowSize();
00129         const int Jcols = J.colSize();
00130         if (Jcols != this->systemMatrix->rowSize())
00131         {
00132             std::cerr << "LULinearSolver::addJMInvJt ERROR: incompatible J matrix size." << std::endl;
00133             return false;
00134         }
00135         
00136         if (!Jrows) return false;
00137         computeMinv();
00138         
00139         const typename JMatrix::LineConstIterator jitend = J.end();
00140         for (typename JMatrix::LineConstIterator jit1 = J.begin(); jit1 != jitend; ++jit1)
00141         {
00142             int row1 = jit1->first;
00143             for (typename JMatrix::LineConstIterator jit2 = jit1; jit2 != jitend; ++jit2)
00144             {
00145                 int row2 = jit2->first;
00146                 double acc = 0.0;
00147                 for (typename JMatrix::LElementConstIterator i1 = jit1->second.begin(), i1end = jit1->second.end(); i1 != i1end; ++i1)
00148                 {
00149                     int col1 = i1->first;
00150                     double val1 = i1->second;
00151                     for (typename JMatrix::LElementConstIterator i2 = jit2->second.begin(), i2end = jit2->second.end(); i2 != i2end; ++i2)
00152                     {
00153                         int col2 = i2->first;
00154                         double val2 = i2->second;
00155                         acc += val1 * getMinvElement(col1,col2) * val2;
00156                     }
00157                 }
00158                 acc *= fact;
00159                 //std::cout << "W("<<row1<<","<<row2<<") += "<<acc<<" * "<<fact<<std::endl;
00160                 result.add(row1,row2,acc);
00161                 if (row1!=row2)
00162                     result.add(row2,row1,acc);
00163             }
00164         }
00165         return true;
00166     }
00167     
00173     bool addJMInvJt(defaulttype::BaseMatrix* result, defaulttype::BaseMatrix* J, double fact)
00174     {
00175         if (FullMatrix<double>* r = dynamic_cast<FullMatrix<double>*>(result))
00176         {
00177             if (SparseMatrix<double>* j = dynamic_cast<SparseMatrix<double>*>(J))
00178             {
00179                 return addJMInvJt(*r,*j,fact);
00180             }
00181             else if (SparseMatrix<float>* j = dynamic_cast<SparseMatrix<float>*>(J))
00182             {
00183                 return addJMInvJt(*r,*j,fact);
00184             }
00185         }
00186         else if (FullMatrix<double>* r = dynamic_cast<FullMatrix<double>*>(result))
00187         {
00188             if (SparseMatrix<double>* j = dynamic_cast<SparseMatrix<double>*>(J))
00189             {
00190                 return addJMInvJt(*r,*j,fact);
00191             }
00192             else if (SparseMatrix<float>* j = dynamic_cast<SparseMatrix<float>*>(J))
00193             {
00194                 return addJMInvJt(*r,*j,fact);
00195             }
00196         }
00197         else if (defaulttype::BaseMatrix* r = result)
00198         {
00199             if (SparseMatrix<double>* j = dynamic_cast<SparseMatrix<double>*>(J))
00200             {
00201                 return addJMInvJt(*r,*j,fact);
00202             }
00203             else if (SparseMatrix<float>* j = dynamic_cast<SparseMatrix<float>*>(J))
00204             {
00205                 return addJMInvJt(*r,*j,fact);
00206             }
00207         }
00208         return false;
00209     }
00210     
00211 };
00212 
00213 } // namespace linearsolver
00214 
00215 } // namespace component
00216 
00217 } // namespace sofa
00218 
00219 #endif

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