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