Fourth Order Runge Kutta


// This program uses the fourth-order Runge-Kutta method to solve a first order differential equation
// of the form dy/dx = f(x,y) over an interval of x. Here this is symbolized by (d/dx)y = der. 

// Import all classes needed for program
import java.util.Vector;
import java.lang.Double;
import java.lang.Math;
   
// Define class RungeKutta  
public class RungeKutta{
    
    // The method RK1 will step through the independent variable x to solve a first 
    // order differential equation over an interval xStart <= x <= End. The initial 
    // condition for Y is y = yStart. The method requires initial x and y values, 
    // stepsize h, and final x-value End. The variables xOutv and yOutv
    // are the output "arrays". These output "arrays" are called Vectors (java.util.Vector class). 
    // Vectors are act as arrays that can dynamically add elements through method *.addElement().  
    public Vector RK1 (double xStart, double yStart, double h, double End, Vector xOutv, Vector yOutv) {

        // Assign values. Recall that all variables must have an initial assignment
        double x = xStart;
        double y = yStart;
        double end = End;
        double yout = 0.0;
        
        // Place initial values in Vectors.
        // Add xStart and yStart values to Vectors xOutv and yOutv. Since the Vector
        // method addElement(Object) 
        // (i.e., the argument of addElement must be an object) is used, 
        // the double values x+h and yout must be made an instance 
        // (i.e., c and d) of the class Double. 
        // The Double class wraps a value of the primitive type double in an object. 
        // An object of type Double contains a single field whose type is double. 
        Double a = new Double(xStart);
        Double b = new Double(yStart);
        xOutv.addElement(a);
        yOutv.addElement(b);
       
        // Check for endpoint. Begin loop over values of indepedent variable x
        do {
     
            // Call Runge-Kutta integration method
            yout = fork(x, y, h, yout); 
            
            // Add x and y values to Vectors. Since the Vector method addElement(Object) (i.e.,
            // the argument of addElement must be an object) is used, the double values 
            // x+h and yout must be made an instance (i.e., c and d) of the class Double. 
            // The Double class wraps a value of the primitive type double in an object. 
            // An object of type Double contains a single field whose type is double. 
            Double c = new Double(x+h);
            Double d = new Double(yout);
            xOutv.addElement(c);
            yOutv.addElement(d);
                   
            // Prepare for next step
            x = x+h;
            y = yout;

        }
        while(x <= end);
            
        // Print to screen Vector xOutv
        System.out.println(xOutv);
        System.out.println(yOutv);
        
        // At or passed endpoint so exit loop and return
        System.out.println ("Integration is complete");
        
        // This statement is required even though we are not returning the value of xOutv to 
        // anywhere. Not sure why.
        return xOutv;
    }       
    
    // Takes one fourth-order Runge-Kutta step of stepsize h
    private double fork (double x, double y, double h, double yout){
 
        // Initialize and define local variables. Note: These values for k will be 
        // reassigned before they are used.  
        double k1 = 1.0000;
        double k2 = 1.0000;
        double k3 = 1.0000;
        double k4 = 1.0000;
        double der = y;
        
        // Perform calculations. The method deriv(x, y, der) is called and 
        // returns the value for der in its place in the equation.
        k1 = h*deriv(x,y,der);
        k2 = h*deriv(x+0.5*h,y+0.5*k1,der);
        k3 = h*deriv(x+0.5*h,y+0.5*k2,der);
        k4 = h*deriv(x+h,y+k3,der);
        
        // Set output
        double youtTerm =(k1+2*k2+2*k3+k4);
   
        // Calculate yout. Important: yout, y, and k1,...,k4 are of type double. If (1/6)*() 
        // was used we would get 0.0 in return, since 1/6 is int/int which equals int.
        yout = y+((k1+2*k2+2*k3+k4)/6);
        
        // Return value of yout to the "RK1" method
        return yout;
    } 
    // Method deriv: contains derivative of function to be integrated. The word "double"
    // comes before "deriv" since this is the data type being returned to the fork method.
    private double deriv (double x, double y, double der){
        
        // Derivative of differential equation (right-hand side) goes here
        // For this example, dy/dx = x + y + 2
        der = x + y + 2; 
        
        // Return the value of the derivative to the "fork" method
        return der;
    }
    
    // Main method
    public static void main (String args[]){
        
        // Vector() is a class so we must create a new instance of this class
        Vector xOutv = new Vector();
        Vector yOutv = new Vector();
        
        // Create a new instance of the class RungeKutta()
        RungeKutta integrate = new RungeKutta();
        
        System.out.println("Calling RungeKutta" );
        
        // The instance "integrate" calls the RK1 method
        // Initial x is 0.0, initial y is 0.0, intial stepsize is 1.0, last x is 5.0
        integrate.RK1(0.0, 0.0, 1.0, 5.0, xOutv, yOutv);        
    }  
}