// KAMTori.java // This applet implements a nearly integrable system in action-angle // variables and does a polar plot of theta_1 vs omega_1/omega_2 in the // section of omega_2==0. import java.awt.*; import java.applet.*; public class KAMTori extends Applet implements Runnable { public void init() { Panel tmp_panel; this.setLayout(new BorderLayout()); bottom_panel=new Panel(); bottom_panel.setLayout(new GridLayout(2,4)); method_choice=new Choice(); method_choice.addItem("Euler"); method_choice.addItem("RK2"); method_choice.addItem("RK4"); method_choice.addItem("Symplectic Order 1"); method_choice.addItem("Symplectic Order 2"); method_choice.addItem("Symplectic Order 4"); bottom_panel.add(method_choice); clear_button=new Button("Clear"); bottom_panel.add(clear_button); tmp_panel=new Panel(); tmp_panel.add(new Label("Epsilon: ")); epsilon_text=new TextField("0.000"); tmp_panel.add(epsilon_text); bottom_panel.add(tmp_panel); tmp_panel=new Panel(); tmp_panel.add(new Label("dt: ")); dt_text=new TextField("0.03"); tmp_panel.add(dt_text); bottom_panel.add(tmp_panel); point_count=0; tmp_panel=new Panel(); point_label=new Label("Points: 00000"); tmp_panel.add(point_label); bottom_panel.add(tmp_panel); tmp_panel=new Panel(); energy_label=new Label("Energy: 0.000"); tmp_panel.add(energy_label); bottom_panel.add(tmp_panel); this.add("South",bottom_panel); top_panel=new Panel(); this.add("Center",top_panel); this.layout(); top_image=createImage(top_panel.size().width,top_panel.size().height); rule=new KAMSystem(); action=1.0; angle=0.0; InitSystem(); } public void run() { try { while(true) { sys.Advance(); energy_label.setText("Energy: "+Double.toString(rule.Energy(sys.GetStateVector()))); DrawSection(); repaint(); Thread.sleep(10); } } catch(InterruptedException e) { java.lang.System.out.println("Thread interrupted!"); } } public void start() { if(thread==null) { thread=new Thread(this); thread.start(); } } public void stop() { if(thread!=null) { thread.stop(); thread=null; } } public void paint(Graphics g) { top_panel.getGraphics().drawImage(top_image,0,0,this); } public void update(Graphics g) { paint(g); } public boolean mouseDown(Event evt,int x,int y) { double dx,dy; int min_dim; // If in the top panel then set the action values. if(y<=top_panel.size().height) { min_dim=Math.min(top_panel.size().width,top_panel.size().height); dx=Math.abs(x-top_panel.size().width/2); dy=Math.abs(y-top_panel.size().height/2); action=Math.sqrt(dx*dx+dy*dy)*4.0/min_dim; angle=Math.atan2(dy,dx); point_count=0; InitSystem(); return(true); } return(false); } public boolean action(Event evt,Object what) { Graphics g; if(evt.target==clear_button) { g=top_image.getGraphics(); g.setColor(Color.white); g.fillRect(0,0,top_image.getWidth(this),top_image.getHeight(this)); point_count=0; return(true); } else if(evt.target==method_choice) { InitSystem(); return(true); } return(false); } public boolean lostFocus(Event evt,Object what) { if((evt.target==dt_text) || (evt.target==epsilon_text)) { InitSystem(); return(true); } return(false); } // This function plots when sv[3] mod 2PI==0. It plots a section of // the torus. private void DrawSection() { if(top_image==null) return; Graphics g=top_image.getGraphics(); int x,y; int min_dim; double ef_sv0,ef_sv2; try { if(sys.Get(1)>=Math.PI) { min_dim=Math.min(top_image.getWidth(this),top_image.getHeight(this)); ef_sv0=sv0+(sys.Get(0)-sv0)*(Math.PI-sv1)/(sys.Get(1)-sv1); ef_sv2=sv2+(sys.Get(2)-sv2)*(Math.PI-sv1)/(sys.Get(1)-sv1); x=(top_image.getWidth(this)>>1)+(int)(ef_sv2*Math.cos(ef_sv0)*min_dim/4.0); y=(top_image.getHeight(this)>>1)+(int)(ef_sv2*Math.sin(ef_sv0)*min_dim/4.0); g.setColor(Color.black); g.drawLine(x,y,x,y); point_count++; point_label.setText("Points: "+Integer.toString(point_count)); sys.Set(1,sys.Get(1)-2.0*Math.PI); } while(sys.Get(0)>=Math.PI) sys.Set(0,sys.Get(0)-2.0*Math.PI); sv0=sys.Get(0); sv1=sys.Get(1); sv2=sys.Get(2); } catch(System.OutOfRangeException e) {} } private void InitSystem() { double dt,epsilon; switch(method_choice.getSelectedIndex()) { case 0: sys=new Euler(rule); break; case 1: sys=new Trapazoid(rule); break; case 2: sys=new RK4(rule); break; case 3: sys=new SimMap1(rule); break; case 4: sys=new SimMap2(rule); break; case 5: sys=new SimMap4(rule); break; } try { dt=Double.valueOf(dt_text.getText()).doubleValue(); } catch(NumberFormatException ex) { dt=0.03; dt_text.setText("0.03"); } try { epsilon=Double.valueOf(epsilon_text.getText()).doubleValue(); } catch(NumberFormatException ex) { epsilon=0.0; epsilon_text.setText("0.0"); } rule.epsilon=epsilon; sys.SetTimeStep(dt); try { sys.Set(0,angle); sys.Set(1,0.0); sys.Set(2,action); sys.Set(3,1.0); } catch(System.OutOfRangeException e) {} } private System sys; private KAMSystem rule; private Thread thread; private Panel bottom_panel; private Choice method_choice; private TextField epsilon_text; private TextField dt_text; private Button clear_button; private Panel top_panel; private Image top_image; private double action,angle; private Label point_label; private int point_count; private Label energy_label; private double sv0,sv1,sv2; }