// Runge-Kutta Method, coded by David Protas, c.2006 // Any corrections or suggestions for improvement of this code will be // appreciated and should be sent to david.protas@csun.edu // Latest revision: October 2, 2006 /********************* * Document: RK.java *********************/ import java.applet.*; import java.awt.*; import expr.*; public class RK extends Applet { final int MaxN = 100; //Maximum number of subintervals double x_0D, y_0D, bD, ymin, ymax, h, a, b, k1, k2, k3, k4, xtemp, ytemp; int nI, counter = -1, last; double[] xArray = new double[MaxN+1]; double[] yArray = new double[MaxN+1]; Panel top, pan1, pan2, pan3, bottom, pan4, pan5; Label functionLabel, inputLabelX ,inputLabelY, inputLabelB, inputLabelN, message; TextField functionField, inputFieldX, inputFieldY, inputFieldB, inputFieldN; TextArea results; Button calculate; RK_G graph; Color babyBlue; public void init() { setLayout(new BorderLayout(4,0)); top = new Panel(); top.setLayout(new GridLayout(3,1)); bottom = new Panel(); bottom.setLayout(new GridLayout(3,1)); pan1 = new Panel(); pan2 = new Panel(); pan3 = new Panel(); pan4 = new Panel(); pan5 = new Panel(); functionLabel = new Label("f(x,y) = "); functionField = new TextField(20); inputLabelX = new Label(" x_0 ="); inputLabelY = new Label(" y_0 ="); inputLabelB = new Label(" b ="); inputLabelN = new Label(" n ="); inputFieldX = new TextField(5); inputFieldY = new TextField(5); inputFieldB = new TextField(5); inputFieldN = new TextField(5); calculate = new Button("Calculate"); results = new TextArea(" x_n y_n ", 10, 30); results.setEditable(false); message = new Label(" " + " "); graph = new RK_G(); babyBlue = new Color(204,255,255); pan1.add(functionLabel); pan1.add(functionField); top.add(pan1); pan2.add(inputLabelX); pan2.add(inputFieldX); pan2.add(inputLabelY); pan2.add(inputFieldY); top.add(pan2); pan3.add(inputLabelB); pan3.add(inputFieldB); pan3.add(inputLabelN); pan3.add(inputFieldN); pan3.add(calculate); top.add(pan3); add("North",top); add("Center",graph); add("East",results); pan5.add(message); bottom.add(pan5); add("South",bottom); setBackground(babyBlue); pan1.setBackground(babyBlue); pan2.setBackground(babyBlue); pan3.setBackground(babyBlue); pan4.setBackground(babyBlue); pan5.setBackground(babyBlue); message.setForeground(Color.red); message.setBackground(babyBlue); results.setFont(new Font("Courier",Font.PLAIN,10)); } public boolean action(Event evt, Object arg) { Variable x = null; Variable y = null; Expr function = null, inputX = null, inputY = null, inputB = null; if (evt.target instanceof Button) { counter = 0; graph.counter = counter; message.setText(""); try { x = Variable.make ("x"); y = Variable.make ("y"); function = Parser.parse (functionField.getText()); inputX = Parser.parse(inputFieldX.getText()); inputY = Parser.parse(inputFieldY.getText()); inputB = Parser.parse(inputFieldB.getText()); } catch (Syntax_error e) { message.setText("" + e); } Variable.make ("pi").set_value (Math.PI); Variable.make ("e").set_value (Math.E); x_0D = inputX.value(); y_0D = inputY.value(); bD = inputB.value(); if (entryValid(inputFieldN.getText()) == false) message.setText("n needs to be an integer. Try again."); else { nI = intFromString(inputFieldN.getText()); last = nI; if((nI < 1) || (nI > MaxN)) message.setText("Applet requires n to be a positive integer <= " + MaxN); else if (x_0D < bD) { h = (bD - x_0D)/nI; graph.h = h; graph.nI = nI; results.setText(" x_n y_n " + "\n" + rndOff(x_0D) + " " + rndOff(y_0D)); graph.x_0D = x_0D; graph.y_0D = y_0D; graph.bD = bD; xArray[0] = x_0D; yArray[0] = y_0D; graph.xArray[0] = xArray[0]; graph.yArray[0] = yArray[0]; ymin = Math.min(y_0D,-.5); ymax = Math.max(y_0D,.2); for (int i = 1; i <= nI; i++) { x.set_value(xArray[i-1]); y.set_value(yArray[i-1]); k1 = function.value(); if (k1 != k1) { //tests whether k1 is a number message.setText("y'(" + rndOff(xArray[i-1]).trim() + ") is undefined. Computation ends there."); last = i-1; break; } xtemp = xArray[i-1] + h/2; x.set_value(xtemp); ytemp = yArray[i-1] + h*k1/2; y.set_value(ytemp); k2 = function.value(); if (k2 != k2) { //tests whether k2 is a number message.setText("y'(" + rndOff(xArray[i-1]).trim() + ") is undefined. Computation ends there."); last = i-1; break; } ytemp = yArray[i-1] + h*k2/2; y.set_value(ytemp); k3 = function.value(); if (k3 != k3) { //tests whether k3 is a number message.setText("y'(" + rndOff(xArray[i-1]).trim() + ") is undefined. Computation ends there."); last = i-1; break; } xtemp = xArray[i-1] + h; x.set_value(xtemp); ytemp = yArray[i-1] + h*k3; y.set_value(ytemp); k4 = function.value(); if (k4 != k4) { //tests whether k4 is a number message.setText("y'(" + rndOff(xArray[i-1]).trim() + ") is undefined. Computation ends there."); last = i-1; break; } yArray[i] = yArray[i-1] + h*(k1 + 2*k2 + 2*k3 + k4)/6; //Array of y values xArray[i] = x_0D + i*h; //Array of x values if (yArray[i] < ymin) ymin = yArray[i]; //find min value of y if (yArray[i] > ymax) ymax = yArray[i]; //find max value of y } graph.ymin = ymin; graph.ymax = ymax; graph.repaint(); } //end of else if x_0D < bD else message.setText("Need x_0 < b. Try again."); } //end of else entry valid graph.counter = last; for (int i = 1; i <= last; i++) { graph.xArray[i] = xArray[i]; graph.yArray[i] = yArray[i]; results.appendText("\n" + rndOff(xArray[i]) + " " + rndOff(yArray[i])); graph.repaint(); } return true; } //end of evt.target return false; } //end of action public static int intFromString(String str) { Integer intObj = new Integer(str); return intObj.intValue(); } private boolean entryValid(String entry) { boolean status; try { double number = intFromString(entry); status = true; } catch(NumberFormatException e) { status =false; } return status; } public static String rndOff(double number) //to 5 places past the decimal { String strnum, bigstrnum, substrnum = " 0.00000"; int period, lngth; long longnum; if ((number >= 0.001) || (number <= -0.001) || (number != number)) { number = Math.pow(0.1,5)*Math.round(Math.pow(10,5)*number); strnum = String.valueOf(number); bigstrnum = " " + strnum + " "; period = bigstrnum.indexOf('.'); substrnum = bigstrnum.substring(period -6, period + 6); if ((number >= 1000000) || (number <= -100000) || (number != number)) substrnum = "big magnitude"; } else { longnum = Math.round(Math.pow(10,5)*number); if (longnum == 0) substrnum = " 0.00000"; else { strnum = String.valueOf(longnum); if (longnum < 0) strnum = strnum.substring(1); lngth = strnum.length(); switch (lngth) { case 1: substrnum = " 0.0000" + strnum; break; case 2: substrnum = " 0.000" + strnum; break; default: substrnum = " error"; } if (longnum < 0) substrnum = " -" + substrnum.substring(5); } } return substrnum; } } //end of RK