00001 #ifndef animal_odesolver_inl___________________________
00002 #define animal_odesolver_inl___________________________
00003 
00004 
00005 #include "odeSolver.h"
00006 #include <iostream>
00007 
00008 
00009 
00010 namespace animal
00011 {
00012 
00013 template<class P,class V,class R>
00014 OdeSolver<P,V,R>::OdeSolver()
00015     : _method( EULER )
00016     , _MMIDsteps(3)
00017     , d1(dv1,da1)
00018     , d2(dv2,da2)
00019     , d3(dv3,da3)
00020     , d4(dv4,da4)
00021     , s1(sp1,sv1)
00022     , s2(sp2,sv2)
00023     , s3(sp3,sv3)
00024 {}
00025 
00026 template<class P,class V,class R>
00027 void OdeSolver<P,V,R>::solveODE(
00028     Positions& pos,
00029     Vector& vel,
00030     Real dt
00031 )
00032 {
00033     
00034     if( _method == EULER ){
00035         
00036         euler(pos,vel,dt);
00037     }
00038     else if( _method == RK2 ){
00039         
00040         rk2(pos,vel,dt);
00041     }
00042     else if( _method == RK4 ){
00043         
00044         rk4(pos,vel,dt);
00045     }
00046     else if( _method == MODMID ){
00047         
00048         modmid(pos,vel,dt,_MMIDsteps);
00049     }
00050     else if( _method == VVERLET ){
00051         
00052         velocityVerlet(pos,vel,dt);
00053     }
00054     else std::cerr <<"unknown integration method "<<_method<< std::endl;
00055 }
00056 
00057 
00058 
00059 template<class P,class V,class R>
00060 void OdeSolver<P,V,R>::setMethod( int m )
00061 {
00062     _method = m;
00063 }
00064 
00065 template<class P,class V,class R>
00066 int OdeSolver<P,V,R>::method() const
00067 {
00068     return _method;
00069 }
00070 
00071 
00072 
00073 
00074 
00075 
00076 
00077 
00078 
00079 
00080 
00081 
00082 
00083 template<class P,class V,class R>
00084 void OdeSolver<P,V,R>::computeDerivative(
00085     Der& d,
00086     const Sta& s,
00087     Real
00088 )
00089 {
00090             computeAccelerations( d.accelerations, s.positions, s.velocities );
00091             v_eq( d.velocities, s.velocities );
00092 
00093 }
00094 
00101 template<class P,class V,class R>
00102 void OdeSolver<P,V,R>::euler(Positions& pos, Vector& vel, Real h, Real t)
00103 {
00104     d1.resize( size(pos) );
00105     Sta states(pos,vel);
00106 
00107 
00108     integrate_euler(states,h,t,d1);
00109 }
00110 
00117 template<class P,class V,class R>
00118 void OdeSolver<P,V,R>::rk2(Positions& pos, Vector& vel, Real h, Real t)
00119 {
00120     d1.resize( size(pos) );
00121     s1.resize( size(pos) );
00122     States<P,V> states(pos,vel);
00123     integrate_rk2(states,h,t,d1,s1);
00124 }
00125 
00132 template<class P,class V,class R>
00133 void OdeSolver<P,V,R>::rk4(Positions& pos, Vector& vel, Real h, Real t)
00134 {
00135     d1.resize( size(pos) );
00136     d2.resize( size(pos) );
00137     d3.resize( size(pos) );
00138     d4.resize( size(pos) );
00139     s1.resize( size(pos) );
00140     States<P,V> states(pos,vel);
00141     integrate_rk4(states,h,t,d1,d2,d3,d4,s1);
00142 }
00143 
00151 template<class P,class V,class R>
00152 void OdeSolver<P,V,R>::modmid(Positions& pos, Vector& vel, Real h, int n, Real t)
00153 {
00154     d1.resize( size(pos) );
00155     s1.resize( size(pos) );
00156     s2.resize( size(pos) );
00157     s3.resize( size(pos) );
00158     States<P,V> states(pos,vel);
00159     integrate_modmid(states,h,t,n,d1,s1,s2,s3);
00160 }
00161 
00168 template<class P, class V, class R>
00169 void OdeSolver<P, V, R>::velocityVerlet(Positions& pos, Vector& vel, Real h)
00170 {
00171     
00172     velHalf.resize(size(vel));
00173 
00174     
00175     d1.resize(size(pos));
00176     States<P,V> states(pos, vel);
00177 
00178     integrate_VVerlet(states,h,d1);
00179 
00180 }
00181 
00182 template<class P,class V,class R>
00183 void OdeSolver<P,V,R>::integrate_euler
00184 (
00185     Sta& s,
00186     Real h,
00187     Real t,
00188     Der& d
00189 )
00190 {
00191     computeDerivative(d,s,t);
00192     v_eq_euler_step(s,s,h,d);
00193 }
00194 
00195 template<class P,class V,class R>
00196 void OdeSolver<P,V,R>::integrate_rk2
00197 ( 
00198     Sta& s, 
00199     Real h, 
00200     Real t, 
00201     Der& d, 
00202     Sta& s1 
00203 )
00204 {
00205     computeDerivative(d,s,t);
00206     v_eq_euler_step(s1,s,h/2,d);
00207     computeDerivative(d,s1,t+(h/2));
00208     v_eq_euler_step(s,s,h,d);
00209 }
00210 
00211 
00212 template<class P,class V,class R>
00213 void OdeSolver<P,V,R>::integrate_rk4
00214 (
00215     Sta& s, 
00216     Real h,
00217     Real t, 
00218     Der& d1, 
00219     Der& d2, 
00220     Der& d3, 
00221     Der& d4, 
00222     Sta& s1 
00223 )
00224 {
00225     computeDerivative(d1,s,t);
00226     v_eq_euler_step(s1,s,h/2,d1);
00227     computeDerivative(d2,s1,t+(h/2));
00228     v_eq_euler_step(s1,s,h/2,d2);
00229     computeDerivative(d3,s1,t+(h/2));
00230     v_eq_euler_step(s1,s,h,d3);
00231     computeDerivative(d4,s1,t+h);
00232     
00233     
00234     v_peq(d2,d3); 
00235     v_teq(d2,2.);  
00236     v_peq(d2,d1); 
00237     v_peq(d2,d4); 
00238     
00239     v_eq_euler_step(s,s,h/6,d2);
00240 }
00241 
00242 
00243 template<class P,class V,class R>
00244 void OdeSolver<P,V,R>::integrate_modmid
00245 ( 
00246     Sta& s, 
00247     Real h, 
00248     Real t, 
00249     int n, 
00250     Der& d1, 
00251     Sta& s1, 
00252     Sta& s2, 
00253     Sta& s3 
00254 )
00255 {
00256     Real hsub = h/n;       
00257     Real hhsub = 2.0*hsub; 
00258 
00259     v_eq(s1,s);
00260 
00261     computeDerivative(d1,s,t);
00262     v_eq_euler_step(s2,s,hsub,d1); 
00263     
00264     
00265     int i;
00266     for( i=0; i<n-1; ++i )
00267     {
00268         computeDerivative(d1,s2,t+i*hsub);
00269         v_eq_euler_step(s3,s1,hhsub,d1);
00270         v_eq(s1,s2);
00271         v_eq(s2,s3);
00272     }
00273     
00274     
00275     computeDerivative(d1,s2,t+i*hsub);
00276     v_eq_euler_step(s3,s1,hhsub,d1);
00277     
00278     
00279     computeDerivative(d1,s3,t+h);
00280     v_eq_euler_step(s3,s3,hsub,d1);
00281     
00282     
00283     v_peq(s2,s3);
00284     Real unDemi = 0.5;
00285     v_eq_ab( s,unDemi,s2 );
00286 }
00287 
00288 template<class P, class V, class R>
00289 void OdeSolver<P, V, R>::integrate_VVerlet(
00290     Sta& s,
00291     Real h,
00292     Der& d)
00293 {
00294     
00295     computeAccelerations(d.accelerations, s.positions, s.velocities);
00296 
00297     
00298     v_eq(velHalf, s.velocities, h/2, d.accelerations);
00299 
00300     
00301     v_eq(s.positions, s.positions, h, velHalf);
00302 
00303     
00304     
00305     computeAccelerations(d.accelerations, s.positions, velHalf);
00306 
00307     
00308     v_eq(s.velocities, velHalf, h/2, d.accelerations);
00309 
00310 }
00311 
00312 }
00313 
00314 #endif
00315