/**
 * <code>Tests</code> - A class for testing ODE Integration code.  The test below illustrates the simulation of simple pendulum behavior.
 *
 * @author <a href="mailto:tneller@triton">Todd W. Neller</a>
 * @version 1.0
 * @since 1.0
 * @see ODEIntegratable
 */

public class Tests implements ODEIntegratable {
    private int evalCount = 0;
    
    /**
     * 
     * @param args java.lang.String[]
     * @exception odeint.ODEIntException The exception description.
     */
    public static void main(String args[]) throws ODEIntException {
	Tests t = new Tests();
	t.rk45test();
    }
    
    /* <code>ode</code> - simple pendulum ODEs
     *
     * @param x a <code>double</code> value
     * @param y a <code>double[]</code> value
     * @param dydx a <code>double[]</code> value
     */
    public void ode(double x, double[] y, double[] dydx) {
	final double length = 1.0, g = 9.8; 
	evalCount++;
	dydx[0] = y[1];
	dydx[1] = -g*Math.sin(y[0])/length;
    }
    
    /**
     * Describe <code>rk45test</code> method here.
     *
     * @exception ODEIntException if an error occurs
     */
    public void rk45test() throws ODEIntException {
	// Number of variables, and maximum number of intermediate
	// steps to store.
	int nvar = 2, kmax = 100;
	// Start and end times.
	double x1 = 0.0;
	double x2 = 10.0;
	// Starting angular displacement and velocity.
	double[] ystart = {1.0, 0.0};
	// Create new RK45 integrator with this class providing ode
	// method, nvar as the number of variables, and kmax as the
	// maximum number of stored steps.
	RK45ODEInt rk45 = new RK45ODEInt(this, nvar, kmax); 
	
	// Desired numerical integration accuracy (per step)
	rk45.eps = 1.0e-4;
	// Initial guess at appropriate stepsize for integration
	rk45.h1 = 0.1;
	// Minimum stepsize allowed (careful - value of 0 can lead to
	// underflow)
	rk45.hmin = 0.0;
	// approximate dx interval for which intermediate values are stored 
	rk45.dxsav = (x2-x1)/(kmax-1);
	evalCount = 0;

	// DO NUMERICAL INTEGRATION
	rk45.integrate(ystart,x1,x2);
	
	// Copy integration results to minimal size arrays
	int steps = rk45.kount;
	double[] xOut = new double[steps];
	double[][] yOut = new double[nvar][steps];
	System.arraycopy(rk45.xp, 0, xOut, 0, steps);
	for (int i=0; i<nvar; i++)
	    System.arraycopy(rk45.yp[i], 0, yOut[i], 0, steps);

	// Report simulation results.
	System.out.println("Step\tTime\tAngular Displacement\tAngular Velocity");
	for (int i=0; i<steps; i++) {
	    System.out.print(i + "\t" + xOut[i]);
	    for (int j=0; j<nvar; j++)
		System.out.print("\t" + yOut[j][i]);
	    System.out.println();
	}
	
    }
}








