/*
 * qm1.java - revised 27 Dec 07 - width 385, height 261
 * @author jack@ord.ca
 * quantum rectilinear pluck and pulse wavefunctions,
 *   and a standing (S) or travelling (A) localized sinusoidal pulse
 *   in a square well with time dependence calculated either directly
 *   from the Schrodinger Equation or from FFSS expansion
 * 320 frames (looping 600 times/frame), 192 elements (and FFSS terms)
 */

import java.applet.Applet;
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

public class qm1 extends Applet
                 implements ActionListener {
  int kk=0; int plt=0; int first=0;                    // Declarations
  String b1s="Pluck"; Button b1=new Button(b1s);
  String b2s="Pulse"; Button b2=new Button(b2s);
  String b3s="Pulse S"; Button b3=new Button(b3s);
  String b4s="Pulse A"; Button b4=new Button(b4s);
  String b5s="Motion"; Button b5=new Button(b5s);
  Checkbox ch1=new Checkbox("FFSS");
  Image bim;
  Graphics bgr;

  public void init() {
    setBackground(new Color(211, 211, 211));
    ch1.setBackground(getBackground());
    add(b1); add(b2); add(b3); add(b4); add(b5); add(ch1);
    b1.addActionListener(this);
    b2.addActionListener(this);
    b3.addActionListener(this);
    b4.addActionListener(this);
    b5.addActionListener(this);
  }

  public void paint(Graphics g) {
    int n, nf, c, jt, del, delt;                       // Declarations
    double [] yr=new double[193];
    double [] yrr=new double[193];
    double [] dyr=new double[193];
    double [] yi=new double[193];
    double [] yii=new double[193];
    double [] dyi=new double[193];
    double [] b=new double[193];
    double [] d=new double[193];
    double [] w=new double[193];
    int [] xx=new int[193];
    int [] yy=new int[193];
    double dt, pi, phi, sn, cs, energy, s, se;
    n=192; nf=320; c=600;                              // Loop constants
    pi=Math.PI; dt=n*n/4/pi/c/nf; s=0; se=0; energy=0; // d(t/T1) * constants
    g.setColor(Color.black);
    g.drawRect(0, 0, 384, 260);
    if (first==0) {
      bim=createImage(385, 261);                        // Animation buffer
      bgr=bim.getGraphics();
      first=1;
    }
    if (kk>0) {
      if (kk==1) {
        for (int i=0; i<=n/2; i=i+1) {                 // Init pluck
          yr[i]=30.*i/n; yr[n-i]=yr[i];
        }
        energy=12/pi/pi;
      }
      if (kk==2) {                                     // Init pulse
        for (int i=3*n/8; i<=n/2; i=i+1) {
          yr[i]=15.*8/n*(i-3*n/8); yr[n-i]=yr[i];
        }
        energy=16*12/pi/pi;
      }
      if (kk>2) {                                      // Init pulses A and B
        for (int i=3*n/8; i<=5*n/8; i=i+1) {
          phi=(i-3*n/8)*pi*8/n; yr[i]=7.5*(1-Math.cos(phi));
          if (kk==4) {
            yi[i]=-yr[i]*Math.sin(phi); yr[i]=yr[i]*Math.cos(phi);
          }
        }
        energy=21.333; if (kk==4) { energy=64+energy; }
      }
      if (ch1.getState()==true) {                      // FFSS
        for (int i=1; i<=n-1; i=i+1) {
          for (int j=1; j<=n-1; j=j+1) {
            sn=Math.sin(pi*i*j/n);
            b[i]=b[i]+yr[j]*2/n*sn; d[i]=d[i]+yi[j]*2/n*sn;
          }
          w[i]=i*i*2*pi/8/nf;
          s=s+b[i]*b[i]+d[i]*d[i];
          se=se+(b[i]*b[i]+d[i]*d[i])*i*i;
        }
        energy=se/s;                                   // Energy (FFSS)
      }
      else {
        for (int i=1; i<=n-1; i=i+1) {                 // Initialize dy step    
          dyr[i]=dt*(yi[i-1]+yi[i+1]-2*yi[i]);
          dyi[i]=-dt*(yr[i-1]+yr[i+1]-2*yr[i]);
        }
      }
      for (int i=0; i<=n; i=i+1) {
        xx[i]=2*i;
      }
      jt=0; yy[0]=260; yy[n]=260; energy=(int)(energy*1000)/1000.;
      long tt=System.currentTimeMillis(); del=60;      // Timing
      do {                                             // Frame loop
        for (int i=1; i<=n-1; i=i+1) {                 // To plot yy[i]...
          yy[i]=260-(int)(yr[i]*yr[i]+yi[i]*yi[i]+.5);
        }
        bgr.setColor(getBackground());                 // Set up plot buffer
        bgr.fillRect(0, 0, 384, 260);
        bgr.setColor(Color.black);
        bgr.drawRect(0, 0, 384, 260);
        bgr.setFont(new Font("TimesRoman", Font.PLAIN, 14));
        bgr.drawString("Frame "+jt+"/"+nf, 9, 50);
        bgr.drawString("E/gs = "+energy, 9, 70);
        bgr.setColor(Color.blue);
        bgr.fillPolygon(xx, yy, n+1);                  // Draw filled polygon
        g.drawImage(bim, 0, 0, null);                  // Show plot buffer
        jt=jt+1;
        if (ch1.getState()==true) {                    // FFSS
          for (int i=0; i<=n; i=i+1) {
            yr[i]=0; yi[i]=0;
            for (int k=1; k<=n-1; k=k+2) {
              sn=Math.sin(pi*i*k/n);
              yr[i]=yr[i]+sn*b[k]*Math.cos(w[k]*jt);
              yi[i]=yi[i]+sn*b[k]*Math.sin(w[k]*jt);
            }
            if (kk==4) {
              for (int k=2; k<=n-2; k=k+2) {
                sn=Math.sin(pi*i*k/n);
                yr[i]=yr[i]-sn*d[k]*Math.sin(w[k]*jt);
                yi[i]=yi[i]+sn*d[k]*Math.cos(w[k]*jt);
              }
            }
          }
        }
        else {                                         // Schroginger equation
          for (int jj=1; jj<=c; jj=jj+1) {             // Accuracy loop
            for (int i=1; i<=n-1; i=i+1) {             // Project ahead dy/2
              yrr[i]=yr[i]+dyr[i]/2; yii[i]=yi[i]+dyi[i]/2;
            }
            for (int i=1; i<=n-1; i=i+1) {             
              dyr[i]=dt*(yii[i-1]+yii[i+1]-2*yii[i]);
              yr[i]=yr[i]+dyr[i];
              dyi[i]=-dt*(yrr[i-1]+yrr[i+1]-2*yrr[i]);
              yi[i]=yi[i]+dyi[i];
            }
          }
        }
        while (tt>System.currentTimeMillis()) { }
        tt=tt+del; if (jt==nf+1) { kk=0; plt=0; }
      } while (plt==1);
    }
  } 

  public void actionPerformed(ActionEvent e) {         // Buttons
    String tst;
    tst=e.getActionCommand();
    if (b1s.equals(tst)) { kk=1; }
    if (b2s.equals(tst)) { kk=2; }
    if (b3s.equals(tst)) { kk=3; }
    if (b4s.equals(tst)) { kk=4; }
    if (b5s.equals(tst)) { if (kk>0) { plt=1;} }
    repaint();
  }
}
