CGLinearSolver.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_CGLINEARSOLVER_H
00026 #define SOFA_COMPONENT_LINEARSOLVER_CGLINEARSOLVER_H
00027 
00028 #include <sofa/core/componentmodel/behavior/LinearSolver.h>
00029 #include <sofa/simulation/common/MatrixLinearSolver.h>
00030 #include <sofa/simulation/common/MechanicalVisitor.h>
00031 #include <math.h>
00032 
00033 namespace sofa
00034 {
00035 
00036 namespace component
00037 {
00038 
00039 namespace linearsolver
00040 {
00041 
00043 template<class TMatrix, class TVector>
00044 class CGLinearSolver : public sofa::simulation::MatrixLinearSolver<TMatrix,TVector>, public virtual sofa::core::objectmodel::BaseObject
00045 {
00046 public:
00047     typedef TMatrix Matrix;
00048     typedef TVector Vector;
00049     Data<unsigned> f_maxIter;
00050     Data<double> f_tolerance;
00051     Data<double> f_smallDenominatorThreshold;
00052     Data<bool> f_verbose;
00053 
00054     CGLinearSolver()
00055     : f_maxIter( initData(&f_maxIter,(unsigned)25,"iterations","maximum number of iterations of the Conjugate Gradient solution") )
00056     , f_tolerance( initData(&f_tolerance,1e-5,"tolerance","desired precision of the Conjugate Gradient Solution (ratio of current residual norm over initial residual norm)") )
00057     , f_smallDenominatorThreshold( initData(&f_smallDenominatorThreshold,1e-5,"threshold","minimum value of the denominator in the conjugate Gradient solution") )
00058     , f_verbose( initData(&f_verbose,false,"verbose","Dump system state at each iteration") )
00059     {
00060     }
00061 protected:
00064     inline void cgstep_beta(Vector& p, Vector& r, double beta);
00067     inline void cgstep_alpha(Vector& x, Vector& r, Vector& p, Vector& q, double alpha);
00068     
00069 public:
00071     void solve (Matrix& M, Vector& x, Vector& b)
00072     {
00073         using std::cerr;
00074         using std::endl;
00075 
00076         Vector& p = *this->createVector();
00077         Vector& q = *this->createVector();
00078         Vector& r = *this->createVector();
00079         
00080         const bool printLog = f_printLog.getValue();
00081         const bool verbose  = f_verbose.getValue();
00082         
00083         // -- solve the system using a conjugate gradient solution
00084         double rho, rho_1=0, alpha, beta;
00085         
00086         if( verbose )
00087             cerr<<"CGLinearSolver, b = "<< b <<endl;
00088         
00089         x.clear();
00090         r = b; // initial residual
00091         
00092         double normb2 = b.dot(b);
00093         double normb = sqrt(normb2);
00094         
00095         unsigned nb_iter;
00096         const char* endcond = "iterations";
00097         for( nb_iter=1; nb_iter<=f_maxIter.getValue(); nb_iter++ )
00098         {
00099         
00100             //      printWithElapsedTime( x, helper::system::thread::CTime::getTime()-time0,std::cout );
00101             
00102             //z = r; // no precond
00103             //rho = r.dot(z);
00104             rho = (nb_iter==1) ? normb2 : r.dot(r);
00105             
00106             if (nb_iter>1)
00107             {
00108                 double normr = sqrt(rho); //sqrt(r.dot(r));
00109                 if (normr/normb <= f_tolerance.getValue())
00110                 {
00111                     endcond = "tolerance";
00112                     break;
00113                 }
00114             }
00115             
00116             if( nb_iter==1 )
00117                 p = r; //z;
00118             else
00119             {
00120                 beta = rho / rho_1;
00121                 //p = p*beta + r; //z;
00122                 cgstep_beta(p,r,beta);
00123             }
00124             
00125             if( verbose )
00126             {
00127                 cerr<<"p : "<<p<<endl;
00128             }
00129             
00130             // matrix-vector product
00131             q = M*p;
00132             
00133             if( verbose )
00134             {
00135                 cerr<<"q = M p : "<<q<<endl;
00136             }
00137             
00138             double den = p.dot(q);
00139             
00140             
00141             if( fabs(den)<f_smallDenominatorThreshold.getValue() )
00142             {
00143                 endcond = "threshold";
00144                 if( verbose )
00145                 {
00146                     cerr<<"CGLinearSolver, den = "<<den<<", smallDenominatorThreshold = "<<f_smallDenominatorThreshold.getValue()<<endl;
00147                 }
00148                 break;
00149             }
00150             alpha = rho/den;
00151             //x.peq(p,alpha);                 // x = x + alpha p
00152             //r.peq(q,-alpha);                // r = r - alpha q
00153             cgstep_alpha(x,r,p,q,alpha);
00154             if( verbose ){
00155                 cerr<<"den = "<<den<<", alpha = "<<alpha<<endl;
00156                 cerr<<"x : "<<x<<endl;
00157                 cerr<<"r : "<<r<<endl;
00158             }
00159             
00160             rho_1 = rho;
00161         }
00162         // x is the solution of the system
00163         if( printLog )
00164         {
00165             cerr<<"CGLinearSolver::solve, nbiter = "<<nb_iter<<" stop because of "<<endcond<<endl;
00166         }
00167         if( verbose )
00168         {
00169             cerr<<"CGLinearSolver::solve, solution = "<<x<<endl;
00170         }
00171         this->deleteVector(&p);
00172         this->deleteVector(&q);
00173         this->deleteVector(&r);
00174     }
00175 };
00176 
00177 template<class TMatrix, class TVector>
00178 inline void CGLinearSolver<TMatrix,TVector>::cgstep_beta(Vector& p, Vector& r, double beta)
00179 {
00180     p *= beta;
00181     p += r; //z;
00182 }
00183 
00184 template<class TMatrix, class TVector>
00185 inline void CGLinearSolver<TMatrix,TVector>::cgstep_alpha(Vector& x, Vector& r, Vector& p, Vector& q, double alpha)
00186 {
00187     x.peq(p,alpha);                 // x = x + alpha p
00188     r.peq(q,-alpha);                // r = r - alpha q
00189 }
00190 
00191 template<>
00192 inline void CGLinearSolver<simulation::GraphScatteredMatrix,simulation::GraphScatteredVector>::cgstep_beta(Vector& p, Vector& r, double beta)
00193 {
00194     this->v_op(p,r,p,beta); // p = p*beta + r
00195 }
00196 
00197 template<>
00198 inline void CGLinearSolver<simulation::GraphScatteredMatrix,simulation::GraphScatteredVector>::cgstep_alpha(Vector& x, Vector& r, Vector& p, Vector& q, double alpha)
00199 {
00200 #if 1 //SOFA_NO_VMULTIOP // unoptimized version
00201     x.peq(p,alpha);                 // x = x + alpha p
00202     r.peq(q,-alpha);                // r = r - alpha q
00203 #else // single-operation optimization
00204     simulation::tree::MechanicalVMultiOpVisitor vmop;
00205     vmop.ops.resize(2);
00206     vmop.ops[0].first = (VecId)x;
00207     vmop.ops[0].second.push_back(std::make_pair((VecId)x,1.0));
00208     vmop.ops[0].second.push_back(std::make_pair((VecId)p,alpha));
00209     vmop.ops[1].first = (VecId)r;
00210     vmop.ops[1].second.push_back(std::make_pair((VecId)r,1.0));
00211     vmop.ops[1].second.push_back(std::make_pair((VecId)q,-alpha));
00212     vmop.execute(this->getContext());
00213 #endif
00214 }
00215 
00216 } // namespace linearsolver
00217 
00218 } // namespace component
00219 
00220 } // namespace sofa
00221 
00222 #endif

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