00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
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
00060
00061
00062
00063
00064
00065
00066 }
00067
00068
00069
00070
00071
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
00083
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);
00091
00092
00093
00094
00095 computeForce(b);
00096
00097
00098
00099 computeDfV(f);
00100 b.peq(f,h+f_rayleighStiffness.getValue());
00101
00102 if (f_rayleighMass.getValue() != 0.0)
00103 {
00104
00105
00106
00107
00108 addMdx(b,vel,-f_rayleighMass.getValue());
00109 }
00110
00111 b.teq(h);
00112
00113 if( verbose )
00114 cerr<<"CGImplicitSolver, f0 = "<< b <<endl;
00115
00116 projectResponse(b);
00117
00118 double normb2 = b.dot(b);
00119 double normb = sqrt(normb2);
00120
00121
00122
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
00130 MultiVector& r = b;
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
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
00147
00148
00149
00150 rho = (nb_iter==1) ? normb2 : r.dot(r);
00151
00152 if (nb_iter>1)
00153 {
00154 double normr = sqrt(rho);
00155 if (normr/normb <= f_tolerance.getValue())
00156 {
00157 endcond = "tolerance";
00158 break;
00159 }
00160 }
00161
00162 if( nb_iter==1 )
00163 p = r;
00164 else
00165 {
00166 beta = rho / rho_1;
00167
00168
00169 v_op(p,r,p,beta);
00170 }
00171
00172 if( verbose )
00173 {
00174 cerr<<"p : "<<p<<endl;
00175 }
00176
00177
00178 propagateDx(p);
00179 computeDf(q);
00180
00181 if( verbose )
00182 {
00183 cerr<<"q = df/dx p : "<<q<<endl;
00184 }
00185
00186 q *= -h*(h+f_rayleighStiffness.getValue());
00187
00188 if( verbose )
00189 {
00190 cerr<<"q = -h(h+rs) df/dx p : "<<q<<endl;
00191 }
00192
00193
00194
00195
00196
00197 if (f_rayleighMass.getValue()==0.0)
00198 {
00199
00200 addMdx(q);
00201 }
00202 else
00203 {
00204
00205
00206
00207 addMdx(q,VecId(),(1+h*f_rayleighMass.getValue()));
00208 }
00209 if( verbose )
00210 {
00211 cerr<<"q = Mp -h(h+rs) df/dx p +hr Mp = "<<q<<endl;
00212 }
00213
00214
00215
00216 projectResponse(q);
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);
00237 r.peq(q,-alpha);
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
00260
00261
00262 #ifdef SOFA_NO_VMULTIOP // unoptimized version
00263 vel.peq( x );
00264 pos.peq( vel, h );
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 }
00301
00302 }
00303
00304 }
00305