CGImplicitSolver.cpp

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 // Author: François Faure, INRIA-UJF, (C) 2006
00026 //
00027 // Copyright: See COPYING file that comes with this distribution
00028 #include <sofa/component/odesolver/CGImplicitSolver.h>
00029 #include <sofa/simulation/common/MechanicalVisitor.h>
00030 #include <sofa/core/ObjectFactory.h>
00031 #include <math.h>
00032 #include <iostream>
00033 #include "sofa/helper/system/thread/CTime.h"
00034 
00035 using std::cerr;
00036 using std::endl;
00037 
00038 namespace sofa
00039 {
00040 
00041 namespace component
00042 {
00043 
00044 namespace odesolver
00045 {
00046 
00047 using namespace sofa::defaulttype;
00048 using namespace core::componentmodel::behavior;
00049 
00050 CGImplicitSolver::CGImplicitSolver()
00051         : f_maxIter( initData(&f_maxIter,(unsigned)25,"iterations","maximum number of iterations of the Conjugate Gradient solution") )
00052         , f_tolerance( initData(&f_tolerance,1e-5,"tolerance","desired precision of the Conjugate Gradient Solution (ratio of current residual norm over initial residual norm)") )
00053         , f_smallDenominatorThreshold( initData(&f_smallDenominatorThreshold,1e-5,"threshold","minimum value of the denominator in the conjugate Gradient solution") )
00054         , f_rayleighStiffness( initData(&f_rayleighStiffness,0.1,"rayleighStiffness","Rayleigh damping coefficient related to stiffness") )
00055         , f_rayleighMass( initData(&f_rayleighMass,0.1,"rayleighMass","Rayleigh damping coefficient related to mass"))
00056         , f_velocityDamping( initData(&f_velocityDamping,0.,"vdamping","Velocity decay coefficient (no decay if null)") )
00057         , f_verbose( initData(&f_verbose,false,"verbose","Dump system state at each iteration") )
00058 {
00059     //     maxCGIter = 25;
00060     //     smallDenominatorThreshold = 1e-5;
00061     //     tolerance = 1e-5;
00062     //     rayleighStiffness = 0.1;
00063     //     rayleighMass = 0.1;
00064     //     velocityDamping = 0;
00065 
00066 }
00067 
00068 // CGImplicitSolver* CGImplicitSolver::setMaxIter( int n )
00069 // {
00070 //     maxCGIter = n;
00071 //     return this;
00072 // }
00073 
00074 void CGImplicitSolver::solve(double dt)
00075 {
00076     MultiVector pos(this, VecId::position());
00077     MultiVector vel(this, VecId::velocity());
00078     MultiVector f(this, VecId::force());
00079     MultiVector b(this, VecId::V_DERIV);
00080     MultiVector p(this, VecId::V_DERIV);
00081     MultiVector q(this, VecId::V_DERIV);
00082     //MultiVector q2(this, VecId::V_DERIV);
00083     //MultiVector r(this, VecId::V_DERIV);
00084     MultiVector x(this, VecId::V_DERIV);
00085 
00086     double h = dt;
00087     const bool printLog = f_printLog.getValue();
00088     const bool verbose  = f_verbose.getValue();
00089 
00090     addSeparateGravity(dt); // v += dt*g . Used if mass wants to added G separately from the other forces to v.
00091 
00092     //projectResponse(vel);          // initial velocities are projected to the constrained space
00093 
00094     // compute the right-hand term of the equation system
00095     computeForce(b);             // b = f0
00096 
00097     //propagateDx(vel);            // dx = v
00098     //computeDf(f);                // f = df/dx v
00099     computeDfV(f);                // f = df/dx v
00100     b.peq(f,h+f_rayleighStiffness.getValue());      // b = f0 + (h+rs)df/dx v
00101 
00102     if (f_rayleighMass.getValue() != 0.0)
00103     {
00104         //f.clear();
00105         //addMdx(f,vel);
00106         //b.peq(f,-f_rayleighMass.getValue());     // b = f0 + (h+rs)df/dx v - rd M v
00107         //addMdx(b,VecId(),-f_rayleighMass.getValue()); // no need to propagate vel as dx again
00108         addMdx(b,vel,-f_rayleighMass.getValue()); // no need to propagate vel as dx again
00109     }
00110 
00111     b.teq(h);                           // b = h(f0 + (h+rs)df/dx v - rd M v)
00112 
00113     if( verbose )
00114     cerr<<"CGImplicitSolver, f0 = "<< b <<endl;
00115 
00116     projectResponse(b);          // b is projected to the constrained space
00117 
00118     double normb2 = b.dot(b);
00119     double normb = sqrt(normb2);
00120 
00121 
00122     // -- solve the system using a conjugate gradient solution
00123     double rho, rho_1=0, alpha, beta;
00124 
00125     if( verbose )
00126     cerr<<"CGImplicitSolver, projected f0 = "<< b <<endl;
00127 
00128     v_clear( x );
00129     //v_eq(r,b); // initial residual
00130     MultiVector& r = b; // b is never used after this point
00131 
00132     if( verbose )
00133     {
00134         cerr<<"CGImplicitSolver, dt = "<< dt <<endl;
00135         cerr<<"CGImplicitSolver, initial x = "<< pos <<endl;
00136         cerr<<"CGImplicitSolver, initial v = "<< vel <<endl;
00137         cerr<<"CGImplicitSolver, r0 = f0 = "<< b <<endl;
00138         //cerr<<"CGImplicitSolver, r0 = "<< r <<endl;
00139     }
00140 
00141     unsigned nb_iter;
00142     const char* endcond = "iterations";
00143     for( nb_iter=1; nb_iter<=f_maxIter.getValue(); nb_iter++ )
00144     {
00145         
00146 //      printWithElapsedTime( x, helper::system::thread::CTime::getTime()-time0,std::cout );
00147         
00148         //z = r; // no precond
00149         //rho = r.dot(z);
00150         rho = (nb_iter==1) ? normb2 : r.dot(r);
00151 
00152         if (nb_iter>1)
00153         {
00154             double normr = sqrt(rho); //sqrt(r.dot(r));
00155             if (normr/normb <= f_tolerance.getValue())
00156             {
00157                 endcond = "tolerance";
00158                 break;
00159             }
00160         }
00161 
00162         if( nb_iter==1 )
00163             p = r; //z;
00164         else
00165         {
00166             beta = rho / rho_1;
00167             //p *= beta;
00168             //p += r; //z;
00169             v_op(p,r,p,beta); // p = p*beta + r
00170         }
00171 
00172         if( verbose )
00173         {
00174             cerr<<"p : "<<p<<endl;
00175         }
00176         
00177         // matrix-vector product
00178         propagateDx(p);          // dx = p
00179         computeDf(q);            // q = df/dx p
00180         
00181         if( verbose )
00182         {
00183             cerr<<"q = df/dx p : "<<q<<endl;
00184         }
00185         
00186         q *= -h*(h+f_rayleighStiffness.getValue());  // q = -h(h+rs) df/dx p
00187         
00188         if( verbose )
00189         {
00190             cerr<<"q = -h(h+rs) df/dx p : "<<q<<endl;
00191         }
00192         //
00193         //      cerr<<"-h(h+rs) df/dx p : "<<q<<endl;
00194         //      cerr<<"f_rayleighMass.getValue() : "<<f_rayleighMass.getValue()<<endl;
00195 
00196         // apply global Rayleigh damping 
00197         if (f_rayleighMass.getValue()==0.0)
00198         {
00199             //addMdx( q, p);           // q = Mp -h(h+rs) df/dx p
00200             addMdx(q); // no need to propagate p as dx again
00201         }
00202         else
00203         {
00204             //q2.clear();
00205             //addMdx( q2, p);
00206             //q.peq(q2,(1+h*f_rayleighMass.getValue())); // q = Mp -h(h+rs) df/dx p +hr Mp  =  (M + dt(rd M + rs K) + dt2 K) dx
00207             addMdx(q,VecId(),(1+h*f_rayleighMass.getValue())); // no need to propagate p as dx again
00208         }
00209         if( verbose )
00210         {
00211             cerr<<"q = Mp -h(h+rs) df/dx p +hr Mp  =  "<<q<<endl;
00212         }
00213 
00214         // filter the product to take the constraints into account
00215         //
00216         projectResponse(q);     // q is projected to the constrained space
00217         if( verbose )
00218         {
00219             cerr<<"q after constraint projection : "<<q<<endl;
00220         }
00221 
00222         double den = p.dot(q);
00223 
00224 
00225         if( fabs(den)<f_smallDenominatorThreshold.getValue() )
00226         {
00227             endcond = "threshold";
00228             if( verbose )
00229             {
00230                 cerr<<"CGImplicitSolver, den = "<<den<<", smallDenominatorThreshold = "<<f_smallDenominatorThreshold.getValue()<<endl;
00231             }
00232             break;
00233         }
00234         alpha = rho/den;
00235 #ifdef SOFA_NO_VMULTIOP // unoptimized version
00236         x.peq(p,alpha);                 // x = x + alpha p
00237         r.peq(q,-alpha);                // r = r - alpha q
00238 #else // single-operation optimization
00239         {
00240             simulation::MechanicalVMultiOpVisitor vmop;
00241             vmop.ops.resize(2);
00242             vmop.ops[0].first = (VecId)x;
00243             vmop.ops[0].second.push_back(std::make_pair((VecId)x,1.0));
00244             vmop.ops[0].second.push_back(std::make_pair((VecId)p,alpha));
00245             vmop.ops[1].first = (VecId)r;
00246             vmop.ops[1].second.push_back(std::make_pair((VecId)r,1.0));
00247             vmop.ops[1].second.push_back(std::make_pair((VecId)q,-alpha));
00248             vmop.execute(this->getContext());
00249         }
00250 #endif
00251         if( verbose ){
00252             cerr<<"den = "<<den<<", alpha = "<<alpha<<endl;
00253             cerr<<"x : "<<x<<endl;
00254             cerr<<"r : "<<r<<endl;
00255         }
00256 
00257         rho_1 = rho;
00258     }
00259     // x is the solution of the system
00260 
00261     // apply the solution
00262 #ifdef SOFA_NO_VMULTIOP // unoptimized version
00263     vel.peq( x );                       // vel = vel + x
00264     pos.peq( vel, h );                  // pos = pos + h vel
00265 #else // single-operation optimization
00266     {
00267         simulation::MechanicalVMultiOpVisitor vmop;
00268         vmop.ops.resize(2);
00269         vmop.ops[0].first = (VecId)vel;
00270         vmop.ops[0].second.push_back(std::make_pair((VecId)vel,1.0));
00271         vmop.ops[0].second.push_back(std::make_pair((VecId)x,1.0));
00272         vmop.ops[1].first = (VecId)pos;
00273         vmop.ops[1].second.push_back(std::make_pair((VecId)pos,1.0));
00274         vmop.ops[1].second.push_back(std::make_pair((VecId)vel,h));
00275         vmop.execute(this->getContext());
00276     }
00277 #endif
00278     if (f_velocityDamping.getValue()!=0.0)
00279         vel *= exp(-h*f_velocityDamping.getValue());
00280     
00281     if( printLog )
00282     {
00283         cerr<<"CGImplicitSolver::solve, nbiter = "<<nb_iter<<" stop because of "<<endcond<<endl;
00284     }
00285     if( verbose )
00286     {
00287         cerr<<"CGImplicitSolver::solve, solution = "<<x<<endl;
00288         cerr<<"CGImplicitSolver, final x = "<< pos <<endl;
00289         cerr<<"CGImplicitSolver, final v = "<< vel <<endl;
00290     }
00291 }
00292 
00293 SOFA_DECL_CLASS(CGImplicit)
00294 
00295 int CGImplicitSolverClass = core::RegisterObject("Implicit time integration using the filtered conjugate gradient")
00296 .add< CGImplicitSolver >()
00297 .addAlias("CGImplicit");
00298 ;
00299 
00300 } // namespace odesolver
00301 
00302 } // namespace component
00303 
00304 } // namespace sofa
00305 

Generated on Sun Nov 23 03:42:46 2008 for Sofa by  doxygen 1.5.7.1