EulerImplicitSolver.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/EulerImplicitSolver.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 EulerImplicitSolver::EulerImplicitSolver()
00051 : f_rayleighStiffness( initData(&f_rayleighStiffness,0.1,"rayleighStiffness","Rayleigh damping coefficient related to stiffness") )
00052 , f_rayleighMass( initData(&f_rayleighMass,0.1,"rayleighMass","Rayleigh damping coefficient related to mass"))
00053 , f_velocityDamping( initData(&f_velocityDamping,0.,"vdamping","Velocity decay coefficient (no decay if null)") )
00054 , f_verbose( initData(&f_verbose,false,"verbose","Dump system state at each iteration") )
00055 {
00056 }
00057 
00058 void EulerImplicitSolver::solve(double dt)
00059 {
00060     MultiVector pos(this, VecId::position());
00061     MultiVector vel(this, VecId::velocity());
00062     MultiVector f(this, VecId::force());
00063     MultiVector b(this, VecId::V_DERIV);
00064     //MultiVector p(this, VecId::V_DERIV);
00065     //MultiVector q(this, VecId::V_DERIV);
00066     //MultiVector q2(this, VecId::V_DERIV);
00067     //MultiVector r(this, VecId::V_DERIV);
00068     MultiVector x(this, VecId::V_DERIV);
00069 
00070     double h = dt;
00071     //const bool printLog = f_printLog.getValue();
00072     const bool verbose  = f_verbose.getValue();
00073 
00074     addSeparateGravity(dt); // v += dt*g . Used if mass wants to added G separately from the other forces to v.
00075 
00076     //projectResponse(vel);          // initial velocities are projected to the constrained space
00077 
00078 #if 1
00079 
00080     // compute the right-hand term of the equation system
00081     // accumulation through mappings is disabled as it will be done by addMBKv after all factors are computed
00082     computeForce(b, true, false);             // b = f0
00083 
00084     //computeDfV(f);                // f = df/dx v
00085     //b.peq(f,h+f_rayleighStiffness.getValue());      // b = f0 + (h+rs)df/dx v
00086     //addMdx(b,vel,-f_rayleighMass.getValue()); // no need to propagate vel as dx again
00087     //f.teq(-1);
00088     //addMBKv(f, 0 /* (f_rayleighMass.getValue() == 0.0 ? 0.0 : -f_rayleighMass.getValue()) */, 0, 1);
00089     //cerr<<"EulerImplicitSolver, diff = "<< f <<endl;
00090     
00091     // new more powerful visitors
00092     // b += (h+rs)df/dx v - rd M v
00093     // values are not cleared so that contributions from computeForces are kept and accumulated through mappings once at the end
00094     addMBKv(b, (f_rayleighMass.getValue() == 0.0 ? 0.0 : -f_rayleighMass.getValue()), 0, h+f_rayleighStiffness.getValue(), false, true);
00095 
00096 #else
00097 
00098     // compute the right-hand term of the equation system
00099     computeForce(b);             // b = f0
00100 
00101     //propagateDx(vel);            // dx = v
00102     //computeDf(f);                // f = df/dx v
00103     computeDfV(f);                // f = df/dx v
00104     b.peq(f,h+f_rayleighStiffness.getValue());      // b = f0 + (h+rs)df/dx v
00105 
00106     if (f_rayleighMass.getValue() != 0.0)
00107     {
00108         //f.clear();
00109         //addMdx(f,vel);
00110         //b.peq(f,-f_rayleighMass.getValue());     // b = f0 + (h+rs)df/dx v - rd M v
00111         //addMdx(b,VecId(),-f_rayleighMass.getValue()); // no need to propagate vel as dx again
00112         addMdx(b,vel,-f_rayleighMass.getValue()); // no need to propagate vel as dx again
00113     }
00114 
00115 #endif
00116 
00117     b.teq(h);                           // b = h(f0 + (h+rs)df/dx v - rd M v)
00118 
00119     if( verbose )
00120     cerr<<"EulerImplicitSolver, f0 = "<< b <<endl;
00121 
00122     projectResponse(b);          // b is projected to the constrained space
00123     
00124     if( verbose )
00125     cerr<<"EulerImplicitSolver, projected f0 = "<< b <<endl;
00126     
00127     MultiMatrix matrix(this);
00128     matrix = MechanicalMatrix::K * (-h*(h+f_rayleighStiffness.getValue())) + MechanicalMatrix::M * (1+h*f_rayleighMass.getValue());
00129     
00130     //if( verbose )
00131 //  cerr<<"EulerImplicitSolver, matrix = "<< (MechanicalMatrix::K * (-h*(h+f_rayleighStiffness.getValue())) + MechanicalMatrix::M * (1+h*f_rayleighMass.getValue())) << " = " << matrix <<endl;
00132     
00133     matrix.solve(x, b);
00134     // projectResponse(x);
00135     // x is the solution of the system
00136 
00137     // apply the solution
00138 #ifdef SOFA_NO_VMULTIOP // unoptimized version
00139     vel.peq( x );                       // vel = vel + x
00140     pos.peq( vel, h );                  // pos = pos + h vel
00141 #else // single-operation optimization
00142     {
00143         simulation::MechanicalVMultiOpVisitor vmop;
00144         vmop.ops.resize(2);
00145         vmop.ops[0].first = (VecId)vel;
00146         vmop.ops[0].second.push_back(std::make_pair((VecId)vel,1.0));
00147         vmop.ops[0].second.push_back(std::make_pair((VecId)x,1.0));
00148         vmop.ops[1].first = (VecId)pos;
00149         vmop.ops[1].second.push_back(std::make_pair((VecId)pos,1.0));
00150         vmop.ops[1].second.push_back(std::make_pair((VecId)vel,h));
00151         vmop.execute(this->getContext());
00152     }
00153 #endif
00154     if (f_velocityDamping.getValue()!=0.0)
00155         vel *= exp(-h*f_velocityDamping.getValue());
00156 
00157     if( verbose )
00158     {
00159         cerr<<"EulerImplicitSolver, final x = "<< pos <<endl;
00160         cerr<<"EulerImplicitSolver, final v = "<< vel <<endl;
00161     }
00162 }
00163 
00164 SOFA_DECL_CLASS(EulerImplicitSolver)
00165 
00166 int EulerImplicitSolverClass = core::RegisterObject("Implicit time integrator using backward Euler scheme")
00167 .add< EulerImplicitSolver >()
00168 .addAlias("EulerImplicit");
00169 ;
00170 
00171 } // namespace odesolver
00172 
00173 } // namespace component
00174 
00175 } // namespace sofa
00176 

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