Original Post
Hi, I am a bit confused now. Should RK4 or Euler actually calculates the new positions first and then the new velocity or the other way around? Thanks.
// Runge-Kutta 4 integration, GRinline void proceed_RK4(const double &dt){ // Performance is increased on some architectures when division is avoided static const double one_sixth = 1.0/6.0; vector_3 k1_velocity = mercury.velocity; vector_3 k1_acceleration = acceleration(mercury.position, k1_velocity); vector_3 k2_velocity = mercury.velocity + k1_acceleration*dt*0.5; vector_3 k2_acceleration = acceleration(mercury.position + k1_velocity*dt*0.5, k2_velocity); vector_3 k3_velocity = mercury.velocity + k2_acceleration*dt*0.5; vector_3 k3_acceleration = acceleration(mercury.position + k2_velocity*dt*0.5, k3_velocity); vector_3 k4_velocity = mercury.velocity + k3_acceleration*dt; vector_3 k4_acceleration = acceleration(mercury.position + k3_velocity*dt, k4_velocity); mercury.velocity += (k1_acceleration + k2_acceleration*2.0 + k3_acceleration*2.0 + k4_acceleration)*dt*one_sixth; mercury.position += (k1_velocity + k2_velocity*2.0 + k3_velocity*2.0 + k4_velocity)*dt*one_sixth;}// Euler integration, GRinline void proceed_E(const double &dt){ mercury.velocity += acceleration(mercury.position, mercury.velocity)*dt; mercury.position += mercury.velocity*dt;}a = initial value of x;b = final value of x;n = number of steps;h = (b - a) / n; // step sizeu[0] = u0; // initial condition for u at av[0] = v0; // initial condition for v at afor i = 0 to n-1 x = a + h * i; u[i+1] = u + h * f(x, u, v); v[i+1] = v + h * g(x, u, v);next ireturn u, v; // arrays of approximate valuesQuote:
Original post by chronos
Ah... I misunderstood the question.
Tabby,
What is your source for the claim that one should obtain the new velocity before the new position? According to the book "Numerical Methods" by Fausett, the way to solve higher order ODE's is as follows:
If y'''' = g(x,y,y') is your second-order ODE, then
v = y'
u = y
v' = g(x,u,v)
u' = v = f(x,u,v).
By Euler's method:
*** Source Snippet Removed ***
So, both the new position and the new velocity are obtained at the same time.
proceedEuler(float dt){ nextPos = initPos + initVel * dt; nextVel = initVel + acc * dt;}Quote:
Original post by juxie
Should I then do Euler as:
*** Source Snippet Removed ***
Quote:
Original post by MrRowl Quote:
Original post by juxie
Should I then do Euler as:
*** Source Snippet Removed ***
Yes - this is the standard Euler formulation.
There's a slight variation, called either Euler–Cromer or Symplectic Euler, where you use your predicted velocity as an estimate that is used in the position update:
nextVel = initVel + acc * dt;
nextPos = initPos + nextVel * dt;
This is generally considered to be better, and is a trivial change to make.
Higher order methods don't allow you to seperate out the steps into a simple "do velocity" and "do position" update - the two things are tied together as one operation (calculate the new state form the old state, where state means position and velocity).
Higher order integration methods differ in their details - but also in one important respect: If you have a system of N bodies, some of which are connected by forces that depend on the relative position between bodies, you can perform an Euler integration on each one independantly, using forces calculated at the start of the integration. This means it's OK to write a Body::integrate(dt) function, for example.
When implementing RK4 (for example), the system needs to be integrated as a whole, since the inter-object forces change "during" the integration. This means you can't implement RK4 for individual bodies - you need to write a solver that integrates the whole system at once. If you expect you need to use RK4 (or similar) eventually, its worth bearing this in mind so that you don't write a lot of code that assumes each body can be integrated independantly.
Quote:
Original post by taby
Good question. Always add acceleration to obtain the new velocity first, then add the new velocity to obtain the new position. If you do it the other way around, things will get wonky.
Here are source snippets of both RK4 and Euler doing the same thing:
*** Source Snippet Removed ***
mercury.velocity += (k1_acceleration + k1_acceleration*2.0 + k1_acceleration*2.0 + k1_acceleration)*dt*one_sixth; mercury.position += (k1_velocity + k1_velocity*2.0 + k1_velocity*2.0 + k1_velocity)*dt*one_sixth;This topic has been locked by a moderator. New replies are not allowed.
With your permission, GameDev.net uses analytics cookies to understand how people use the platform. You can accept analytics or continue with necessary cookies only. Learn more