00001 00003 // 00004 // -= ODE solver using the RungeKutta method =- 00005 // 00006 // Definition: "a 4th order ordinary differential equation solver" 00007 // 00009 // 00010 // $RCSfile: RungeKuttaODEsolver.h,v $ 00011 // $Date: 2002/01/10 03:10:47 $ 00012 // $Revision: 1.4 $ 00013 // Copyright (C) 1998, 1999, 2000 Kevin Meinert, kevin@vrsource.org 00014 // 00015 // This library is free software; you can redistribute it and/or 00016 // modify it under the terms of the GNU Library General Public 00017 // License as published by the Free Software Foundation; either 00018 // version 2 of the License, or (at your option) any later version. 00019 // 00020 // This library is distributed in the hope that it will be useful, 00021 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00022 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00023 // Library General Public License for more details. 00024 // 00025 // You should have received a copy of the GNU Library General Public 00026 // License along with this library; if not, write to the Free 00027 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00028 // 00030 #ifndef RUNGEKUTTA_METHOD 00031 #define RUNGEKUTTA_METHOD 00032 00033 #include "ani/Dynamics/ODEsolver.h" 00034 00035 namespace ani 00036 { 00037 //: the fourth-order Runge-Kutta method is generally considered to provide an 00038 // excellent balance of power, precision [O(h^5)], and simplicity to program. 00039 // Here there are four gradient or ``k'' terms which provide a better approximation 00040 // to the behavior of f(t,y) near the midpoint... 00041 template <class _item> 00042 class RungeKuttaODEsolver : public ODEsolver<_item> 00043 { 00044 public: 00045 RungeKuttaODEsolver() {} 00046 virtual ~RungeKuttaODEsolver() {} 00047 00048 //: the fourth-order Runge-Kutta method 00049 // 00050 // give: 00051 // currentState = current state of the item 00052 // currentTime = current time of the item 00053 // timeDelta = current stepsize (t(n) - t(n+1)) == time delta 00054 // returns: 00055 // currentState = x(t0 + h) == the next state of the item after taking this step... 00056 virtual void exec( _item& currentState, float timeDelta ) 00057 { 00058 static const float oneOverSix = (1.0f/6.0f); 00059 00060 // compute next state. 00061 00062 // any particle that is put into f() needs to have its mass and force accums set 00063 // to equal the current _item, since all the operations only act on the phase space 00064 // (pos, vel), this is needed: 00065 _item temp( currentState ); 00066 00067 00068 // k1 = h * func( x0, t0 ); 00069 // f = func(..., ...) 00070 f.computeDerivative( currentState, timeDelta * 0.0f ); 00071 // k1 = h * f 00072 k1.multiplyPhase( f, timeDelta ); 00073 00074 00075 //: k2 = h * func( x0 + k1*0.5f, t0 + h*0.5f ); 00076 // f = func(..., ...) 00077 temp.multiplyPhase( k1, 0.5f ); 00078 temp.addPhase( currentState, temp ); 00079 f.computeDerivative( temp, timeDelta * 0.5f ); 00080 // k2 = h * f 00081 k2.multiplyPhase( f, timeDelta ); 00082 00083 //: k3 = h * func( x0 + k2*0.5f, t0 + h*0.5f ); 00084 // f = func(..., ...) 00085 temp.multiplyPhase( k2, 0.5f ); 00086 temp.addPhase( currentState, temp ); 00087 f.computeDerivative( temp, timeDelta * 0.5f ); 00088 // k3 = h * f 00089 k3.multiplyPhase( f, timeDelta ); 00090 00091 //: k4 = h * func( x0 + k3, t0 + h ); 00092 // f = func(..., ...) 00093 temp.addPhase( currentState, k3 ); 00094 f.computeDerivative( temp, timeDelta * 1.0f ); 00095 // k4 = h * f 00096 k4.multiplyPhase( f, timeDelta ); 00097 00098 // xt0h = x0 + 1/6 * k1 + 1/3 * k2 + 1/3 * k3 + 1/6 * k4; 00099 //currentState = currentState + (oneOverSix * (k1 + 2.0f * (k2 + k3) + k4)); 00100 changeInState.addPhase( k2, k3 ); 00101 changeInState.multiplyPhase( 2.0f ); 00102 changeInState.addPhase( k1 ); 00103 changeInState.addPhase( k4 ); 00104 changeInState.multiplyPhase( oneOverSix ); 00105 00106 currentState.addPhase( currentState, changeInState ); 00107 currentState.normalize(); 00108 } 00109 00110 // the four gradient or ``k'' terms 00111 _item k1, k2, k3, k4; 00112 _item changeInState, f; 00113 }; 00114 }; // end namespace 00115 00116 #endif