/* From: "COMPUTATIONAL PHYSICS, 2nd Ed" by RH Landau, MJ Paez, and CC Bordeianu Copyright Wiley-VCH, 2007. Electronic Materials copyright: R Landau, Oregon State Univ, 2007; MJ Paez, Univ Antioquia, 2007; and CC Bordeianu, Univ Bucharest, 2007. Support by National Science Foundation */ // rk45: Runge-Kutta-Fehlberg adaptive step size ODE solver import java.io.*; public class Rk45 { public static void main(String[] argv) throws IOException, FileNotFoundException { PrintWriter w = new PrintWriter(new FileOutputStream("rk45_rhl.dat"), true); PrintWriter q = // File output new PrintWriter(new FileOutputStream("rk45_exact.dat"), true); double h, t, s, s1, hmin, hmax, E, Eexact, error; double y[] = new double[2]; double fReturn[] = new double[2]; double ydumb[] = new double[2]; double err[] = new double[2]; double k1[] = new double[2]; double k2[] = new double[2]; double k3[] = new double[2]; double k4[] = new double[2]; double k5[] = new double[2]; double k6[] = new double[2]; double Tol = 1.0E-8; // Error tolerance double a = 0., b = 10. ; // Endpoints int i, j, flops, n = 20; y[0] = 1. ; y[1] = 0. ; // Initialize h = (b-a)/n; // Temp number of steps hmin = h/64; hmax = h*64; // Min and max step sizes t = a; j = 0; long timeStart = System.nanoTime(); System.out.println("" + timeStart + ""); flops = 0; Eexact = 0. ; error = 0. ; double sum = 0. ; // Loop over time while (t < b) { if ( (t + h) > b ) h = b - t; // Last step f(t, y, fReturn); // evaluate both RHS's, return in fReturn k1[0] = h*fReturn[0]; k1[1] = h*fReturn[1]; for ( i=0; i <= 1; i++ ) ydumb[i] = y[i] + k1[i]/4; f(t + h/4, ydumb, fReturn); k2[0] = h*fReturn[0]; k2[1] = h*fReturn[1]; for (i=0; i <= 1; i++) ydumb[i] = y[i]+3*k1[i]/32 + 9*k2[i]/32; f(t + 3*h/8, ydumb, fReturn); k3[0] = h*fReturn[0]; k3[1] = h*fReturn[1]; for ( i=0; i <= 1; i++ ) ydumb[i] = y[i] + 1932*k1[i]/2197 -7200*k2[i]/2197. + 7296*k3[i]/2197; f(t + 12*h/13, ydumb, fReturn); k4[0] = h*fReturn[0]; k4[1] = h*fReturn[1]; for ( i=0; i <= 1; i++ ) ydumb[i] = y[i]+439*k1[i]/216 -8*k2[i] + 3680*k3[i]/513 -845*k4[i]/4104; f(t + h, ydumb, fReturn); k5[0] = h*fReturn[0]; k5[1] = h*fReturn[1]; for ( i=0; i <= 1; i++ ) ydumb[i] = y[i] -8*k1[i]/27 + 2*k2[i] -3544*k3[i]/2565 + 1859*k4[i]/4104 -11*k5[i]/40; f(t + h/2, ydumb, fReturn); k6[0] = h*fReturn[0]; k6[1] = h*fReturn[1]; for ( i=0; i <= 1; i++ ) err[i] = Math.abs( k1[i]/360 - 128*k3[i]/4275 - 2197*k4[i]/75240 + k5[i]/50. +2*k6[i]/55); // Accept step size if ( err[0] < Tol || err[1] < Tol || h <= 2*hmin ) { for ( i=0; i <= 1; i++ ) y[i] = y[i] + 25*k1[i]/216. + 1408*k3[i]/2565. + 2197*k4[i]/4104. - k5[i]/5.; t = t + h; j++ ; } if ( err[0]==0 || err[1]==0 ) s = 0; // Trap division by 0 else s = 0.84*Math.pow(Tol*h/err[0], 0.25); // Reduce step if ( s < 0.75 && h > 2*hmin ) h /= 2.; // Increase step else if ( s > 1.5 && 2* h < hmax ) h *= 2.; flops++ ; E = Math.pow(y[0], 6.) + 0.5*y[1]*y[1]; Eexact = 1. ; error = Math.abs((E-Eexact)/Eexact); sum += error; } System.out.println(" < error> = " + sum/flops); System.out.println("flops = " + flops + ""); long timeFinal = System.nanoTime(); System.out.println("" + timeFinal + ""); System.out.println("Nanoseconds = " + (timeFinal-timeStart)); } // Enter your own RHS here! public static void f(double t, double y[], double fReturn[]) { fReturn[0] = y[1]; fReturn[1] = -6.*Math.pow(y[0], 5.); return; } }