/* * fosd.java - revised 7 Apr 05 - width 481, height 381 * @author jackord@kw.igs.net * the driven damped oscillator (initially at rest at origin) * - sine or square wave driving force * - f/fo equals 1/6, 1/2, 1, 2 * - Q equals 1/3, 1, 3, inf * - sine wave analytic solution superposition option (except f=fo, Q=inf) */ import java.applet.Applet; import java.awt.*; import java.awt.event.ActionListener; import java.awt.event.ActionEvent; public class fosd extends Applet implements ActionListener { int kk=0; // Declarations String b1s="Sine"; Button b1=new Button(b1s); String b2s="Square"; Button b2=new Button(b2s); Choice cho1=new Choice(); Choice cho2=new Choice(); Checkbox ch1= new Checkbox("Anal"); public void init() { setLayout(new FlowLayout(FlowLayout.LEFT)); cho1.addItem("f=1/6"); cho1.addItem("f=1/2"); cho1.addItem("f=1"); cho1.addItem("f=2"); cho2.addItem("Q=1/3"); cho2.addItem("Q=1"); cho2.addItem("Q=3"); cho2.addItem("Q=inf"); add(b1); add(b2); add(cho1); add(cho2); add(ch1); b1.addActionListener(this); b2.addActionListener(this); setBackground(new Color(211, 211, 211)); // Light Gray Background ch1.setBackground(getBackground()); cho1.setBackground(getBackground()); cho2.setBackground(getBackground()); } public void paint(Graphics g) { // Paint int x1, y1, x2, y2, nf; int n=480; double b, c, d, w, wo, w2, wa, wb, rq, dt, t, x, v, dv, r, s, a, a1, a2; double [] bs=new double[5]; int [] fs=new int[5]; fs[0]=240; fs[1]=80; fs[2]=40; fs[3]=20; bs[0]=3; bs[1]=1; bs[2]=1./3.; bs[3]=0; wo=Math.PI/40; w2=wo*wo; c=45; d=w2*c; dt=1; if (kk==0) { b1.setBounds(5, 5, 55, 20); b2.setBounds(65, 5, 55, 20); cho1.setBounds(5, 30, 55, 20); cho2.setBounds(65, 30, 55, 20); ch1.setBounds(125, 5, 55, 20); cho1.select(2); cho2.select(1); } nf=fs[cho1.getSelectedIndex()]; rq=bs[cho2.getSelectedIndex()]; b=wo*rq; w=40*wo/nf; g.setColor(Color.black); g.drawRect(0, 0, 480, 380); g.drawLine(0, 200, 480, 200); if (kk==1) { // Sine Wave x1=0; y1=200; g.setColor(Color.red); // Driving Force for (int i=1; i<=n; i=i+1) { y2=200-(int)(c*Math.sin(w*i*dt)); g.drawLine(x1, y1, i, y2); x1=i; y1=y2; } t=0; x=0; v=0; dv=0; // Feynman algorithm g.setColor(Color.blue); x1=0; y1=200; for (int i=1; i<=n; i=i+1) { // No Half-Step (a=0) x=x+v*dt; dv=(d*Math.sin(w*i*dt)-b*(v+dv/2)-w2*x)*dt; v=v+dv; y2=200-(int)(x); g.drawLine(i-1, y1, i, y2); y1=y2; } if ((ch1.getState()==true)&&((b>0)||(nf!=40))) { // Analytic solution... g.setColor(Color.magenta); y1=200; r=w/wo; s=1/r; if (nf==40) { a=Math.PI/2; } else { a=Math.atan2(rq,(s-r)); } c=c*s/Math.sqrt((s-r)*(s-r)+rq*rq); if (rq>2) { // ...overdamped... wa=-wo*(rq/2+Math.sqrt(rq*rq/4-1)); wb=-wo*(rq/2-Math.sqrt(rq*rq/4-1)); a2=c*(wa*Math.sin(a)+w*Math.cos(a))/(wa-wb); a1=c*Math.sin(a)-a2; for (int i=1; i<=n; i=i+1) { y2=200-(int)(a1*Math.exp(wa*i*dt)+a2*Math.exp(wb*i*dt)+c*Math.sin(w*i*dt-a)); g.drawLine(i-1, y1, i, y2); y1=y2; } } else { // ...underdamped wa=wo*Math.sqrt(1-rq*rq/4); a1=c*Math.sin(a); a2=(a1*b/2-w*c*Math.cos(a))/wa; for (int i=1; i<=n; i=i+1) { y2=200-(int)(Math.exp(-b*i*dt/2)*(a1*Math.cos(wa*i*dt)+a2*Math.sin(wa*i*dt))+c*Math.sin(w*i*dt-a)); g.drawLine(i-1, y1, i, y2); y1=y2; } } } } if (kk==2) { // Square Wave g.setColor(Color.red); // Driving Force g.drawLine(0, 200, 0, 155); g.drawLine(480, 245, 480, 200); for (int i=1; i<=n/nf-1; i=i+1) { g.drawLine(i*nf, 155, i*nf, 245); } for (int i=0; i<=n/2/nf-1; i=i+1) { x1=i*2*nf; g.drawLine(x1, 155, x1+nf, 155); g.drawLine(x1+nf, 245, x1+2*nf, 245); } g.drawLine(480, 245, 480, 200); t=0; x=0; v=0; // Feynman algorithm dv=d*dt; v=v+dv/2; // Half-Step g.setColor(Color.blue); x1=0; y1=200; for (int i=0; i<=n/nf-1; i=i+1) { for (int j=1; j<=nf; j=j+1) { x=x+v*dt; dv=(d-b*(v+dv/2)-w2*x)*dt; v=v+dv; x2=j+i*nf; y2=200-(int)(x); g.drawLine(x1, y1, x2, y2); x1=x2; y1=y2; } v=v-d*dt; dv=dv-d*dt; // Discontinuity corrn d=-d; } } } public void actionPerformed(ActionEvent e) { String tst; tst=e.getActionCommand(); if (b1s.equals(tst)) { kk=1; } if (b2s.equals(tst)) { kk=2; } repaint(); } }