| The 2nd Order Runge-Kutta formula 
              shown above is for a single variable x, which would suffice for 
              determining the motion of a falling object or for an object on spring. 
              For projectile motion, though, we deal with two coordinates.  We thus need formulas for both vertical (y) 
              and horizontal (x) 
              variables:       and 
              then       Below we show the code for a second order Runge-Kutta
               class that generalizes the above formulas to  multiple variables.
              Array arguments 
              carry the variables and their derivative. Here we use the name vel,
               as in velocity, for the derivatives but these could be derivatives
              
              with respect to a non-time related variable.  The derivative of the velocity comes from an interface 
              method called Derivable, 
              shown below. The method modifier static 
              eliminates the need to create an instance of the class.  
              
                 
                  | RungeKutta2nd.java |   
                  | /** 
                    Carry out the Runge-Kutta 2nd order algorithm. **/ public class RungeKutta2nd
 {
 /** Calculate as step in the Runge-Kutta 2nd order. 
                    **/
 public static void step (double t, double dt,
 double 
                    [] var,
 double 
                    [] vel,
 Derivable 
                    func )  {
 
 double k1_var, k1_vel;
 double k2_var, k2_vel;
 
 for (int i=0; i < var.length; i++) 
                    {
 k1_var = vel[i] * dt;
 k1_vel = func.deriv (i,var[i],vel[i],t)*dt;
 
 k2_var =  (vel[i] 
                    + 0.5*k1_vel)*dt;
 k2_vel = func.deriv (i,
 var[i] 
                    + 0.5*k1_var,
 vel[i] 
                    + 0.5 * k1_vel,
 t+0.5 
                    * dt) * dt;
 
 var[i] = var[i] + k2_var;
 vel[i] = vel[i] + k2_vel;
 }
 
 t += dt;
 } // step
 
 } // RungeKutta2nd
 |   
                  | Derivable.java |   
                  | public 
                      interface Derivable{
 public double deriv (int i, double pos, 
                      double v,
 double 
                      t, double t);
 } // Derivable
 |    The program below uses the second order Runge-Kutta code above 
              to solve for the intercept of a projectile with the horizontal plane. 
              Ignoring air drag (see the exercises), 
              the horizontal force is zero and the vertical force is a constant. 
             Note how the class implements the interface and overrides 
              its method. 
              
                 
                  | RK2ndApplet.java (Output goes to browser's Java 
                    console.)
 |   
                  | /** * This applet uses the second order Runge-Kutta 
                    method
 * to solve for the landing point of a projectile.
 **/
 public class RK2ndApplet extends java.applet.Applet
 implements Derivable
 {
 // Constants
 double g  = 9.80;// meter per sec**2
 double x0 = 0.0;
 double y0 = 0.0;
 double v0 = 100.0;// initial vel, m/s
 double angle = Math.PI/4.0;
 
 // Instance variables
 double [] pos = new double[2];
 double [] vel = new double[2];
 
 /** Initialize the algorithm. **/
 public void init () {
 
 double t;
 double total_t;
 int n;
 
 double dt =  0.01;
 int n_steps = 100000;
 
 pos[0] = x0;
 pos[1] = y0;
 vel[0] = v0 * Math.cos (angle);
 vel[1] = v0 * Math.sin (angle);
 t = 0.0;
 
 for (n=0; n < n_steps; n++) {
 RungeKutta2nd.step (t,dt,pos,vel,this);
 if (pos[1] <= 0.0) break;
 }
 System.out.println ("After steps =" 
                    + n);
 System.out.println (" x = " + pos[0]);
 
 } // init
 
 /** Implement the interfact method for the derivative
 * of the variables. **/
 public double deriv (int i, double newVar, double 
                    newVel, double t) {
 if (i == 0) {// x variable
 return 0.0;
 } else { // y variable
 return -g;
 }
 
 } // deriv
 
 /** Paint message in Applet window. **/
 public void paint (java.awt.Graphics g) {
 g.drawString ("RK2ndApplet",20,20);
 } // pain
 
 /** Run optionally as an application. **/
 public static void main (String [] args) {
 RK2ndApplet obj = new RK2ndApplet 
                    ();
 obj.init ();
 } // main
 
 } // RK2ndApplet
 |    The output shows 
              
                 
                  | After steps 
                    =1443 x = 1021.0621920333822
 |    This compares to a value of 1020.4 for the analytical 
              solution. Exercise : Try 
              a finer dt 
              value to see if the intercept makes a better match to the analytical 
              value. Exercise : The 
              program checks if the projectile vertical coordinate has become 
              negative to indicate that the object has reached the surface. However, 
              this can overestimate the horizontal intercept. Add code to do an 
              interpolation to obtain a more accurate intercept.   Most recent update: Oct. 21, 2005 |