Site hosted by Angelfire.com: Build your free website today!
/*
Java applet source code : sw1.java
April 1997 / Written by Michael J. Hurben

This applet provides a qualitative demonstration of spin wave
propagation on a two-dimensional lattice.  The user can choose
the magnitude and direction of the propagation wavevector by
clicking and dragging on an arrow. There is no damping - the
spins precess indefinitely. The frequency of the precession is,
of course, about 9 orders of less than in reality!  

The applet uses double buffering in an attempt to
eliminate (or reduce) the flicker in the animation.  
*/

import java.applet.Applet;
import java.awt.*;

public class sw1 extends Applet implements Runnable
{
   Dimension offDimension,d; // Variables used to create an 'offscreen'
   Image offImage;           // image via the update() method, to help 
   Graphics offGraphics;     // reduce flicker.

   int tipLength=8;          // Settings for the arrow tip size
   int tipWidth=4;           // 
   int xamp=10;              // x-amplitude for spins
   int yamp=6;               // y-amplitude for spins  
   int time=0;               // Start time
   int Hfield=0;             // Arbitrary measure of field H      
   int kx=350;               // Initial k tip x-coord
   int ky=160;               // Initial k tip y-coord
   int kxbase=260;           // Base of k-vector
   int kybase=160;           // Base of k-vector
   int dkx=kx-kxbase;        // x-component of k
   int dky=ky-kybase;        // y-component of k
   int ktip1x=kx-tipLength;  //
   int ktip2x=ktip1x;        // Initialize arrowhead
   int ktip1y=ky+tipWidth;   // for the k vector
   int ktip2y=ky-tipWidth;   //

   double dphix=dkx*0.031416/2;    // Phase shift for a single x-step
   double dphiy=dky*0.031416/2;    // Phase shift for a y-step
   double freq=(2*3.14/1200.);     // Period = 1200 'thread cycles'

   // Declare arrays - all are 6x6.

   int[][] xbases = new int[6][6];  // x-coords of spin-vector bottoms
   int[][] ybases = new int[6][6];  // y-coords of spin-vector bottoms
   int[][] a = new int[6][6];       // precession variable
   int[][] b = new int[6][6];       // precession variable
   int[][] mx = new int[6][6];      // x-coords of spin vector tips
   int[][] my = new int[6][6];      // y-coords of spin vector tips
   int[][] tip1x = new int[6][6];   //
   int[][] tip2x = new int[6][6];   // Used to draw arrowheads
   int[][] tip1y = new int[6][6];   //
   int[][] tip2y = new int[6][6];   //

   double[][] phase = new double[6][6];
   double[][] denom = new double[6][6];

   Button b1, b2, b3, b4, b5;

   Thread t;

   public void init()
   {                                   
    for(int row=0; row<6; row++)             //
      {                                      // Initialize the arrays
         for(int col=0; col<6; col++)        //
         {
           phase[row][col]=dphix*col-(5-row)*dphiy;  
           xbases[row][col]=30*(col+1);            
           ybases[row][col]=30*(row+1)+40;          
           mx[row][col]=xbases[row][col]; 
           my[row][col]=ybases[row][col]-20; 
           tip1x[row][col]=mx[row][col];

           tip2x[row][col]=mx[row][col];

           tip1y[row][col]=my[row][col];

           tip2y[row][col]=my[row][col];

         }
      }

      b1 = new Button("Increase H");      //
      b2 = new Button("Decrease H");      //
      b3 = new Button("Pause");           // setLayout(null)
      b4 = new Button("Resume");          // used to position 
      b5 = new Button("Finish");          // buttons at a specific
      add(b1);                            // x-y coord.
      add(b2);                            //
      add(b3);
      add(b4);
      add(b5);

      t=new Thread(this);
      t.start();      
   }
                                        
   public void paint(Graphics g)       // The guts of the painting
   {                                   // is done in the update()
      d=size();                        // method below.
      update(g);                        
   }

   public boolean mouseDrag(Event e, int mDx, int mDy)
   {
      if (mDx > kxbase && mDy > kybase-100 && mDx < kxbase

       + 100 && mDy < kybase &&
       Math.abs(mDx-kx) < 40 && Math.abs(mDy-ky) < 40)
      {
      kx=mDx;                  // Reposition the 
      ky=mDy;                  // k-vector tip.
      dkx=kx-kxbase;           // Calculate x-component.
      dky=ky-kybase;           // Calculate y-component.
      dphix=dkx*0.031416/2;    // Phase shift in x-direction.
      dphiy=dky*0.031416/2;    // Phase shift in y-direction.

      ktip1x=kx+(int)(((-dkx)*2*tipLength

      +(tipWidth)*(dky))/100);
      ktip2x=kx+(int)(((-dkx)*2*tipLength

      -(tipWidth)*(dky))/100);
      ktip1y=ky+(int)(((-dky)*2*tipLength

      -(tipWidth)*(dkx))/100);
      ktip2y=ky+(int)(((-dky)*2*tipLength

      +(tipWidth)*(dkx))/100);

      repaint();
      }
      return true;
   }

   public boolean action(Event e, Object o)
   {
      if (o.equals("Pause"))         //
      {                              //  Respond to button pushes.
         t.suspend();                //
      }
      else if (o.equals("Resume"))
      {
         t.resume();
      }
      else if (o.equals("Finish"))
      {
         t.stop();
      }
      else if (o.equals("Increase H"))
      {
         freq=freq*1.1;

         Hfield=Hfield+1;

      }
      else if (o.equals("Decrease H"))
      {
         freq=freq*0.9;

         Hfield=Hfield-1;

      }
      return true;
      }

      public void run()       // Run an infinite loop where the M vector
      {                       // position is calculated as a function of
         while(true)          // time.
         {
          for(int row=0; row<6; row++)
          {
          for(int col=0; col<6; col++)
           {
            phase[row][col]=-dphix*col+(5-row)*dphiy;  // Assign the phases

            a[row][col] = (int)                            //
             (xamp*(Math.cos(phase[row][col]+time*freq))); // Determine the
            b[row][col] = (int)                            // vector position
             (yamp*(Math.sin(phase[row][col]+time*freq))); // at [row][col]
            mx[row][col]= xbases[row][col]+a[row][col];    //
            my[row][col]= (int)(ybases[row][col]-20        //
            -b[row][col]);                                

            // Determine the coordinates for vector tips
       
            denom[row][col]=                           //

             Math.sqrt((xbases[row][col]-mx[row][col]) //  Instantaneous
             *(xbases[row][col]-mx[row][col])          //  vector length
             +(ybases[row][col]-my[row][col])          //  at [row][col].
             *(ybases[row][col]-my[row][col]));        //

            tip1x[row][col]=mx[row][col]               //
              +(int)(((xbases[row][col]-mx[row][col])  //
              *tipLength+(tipWidth/2)*(my[row][col]    //
              -ybases[row][col]))/denom[row][col]);    //
            tip2x[row][col]=mx[row][col]               //  Calculate the
              +(int)(((xbases[row][col]-mx[row][col])  //  vertices of the
              *tipLength-(tipWidth/2)*(my[row][col]    //  triangular tips
              -ybases[row][col]))/denom[row][col]);    //  of the spins
            tip1y[row][col]=my[row][col]               //  at [row][col].
              +(int)(((ybases[row][col]-my[row][col])  //
              *tipLength                               //
              -(tipWidth/2)*(mx[row][col]              //
              -xbases[row][col]))/denom[row][col]);    //
            tip2y[row][col]=my[row][col]               //
              +(int)(((ybases[row][col]-my[row][col])  //
              *tipLength+(tipWidth/2)*(mx[row][col]    //
              -xbases[row][col]))/denom[row][col]);    //

            repaint();
            time=time+1;       
            }
          }
       }
    }

    public void update(Graphics g)
    {                                         //
       if((offGraphics ==null)                // Setup an off-screen image
        ||(d.width !=offDimension.width)      // via the update() method.
        || (d.height != offDimension.height)) //
       {
       offDimension=d;

       offImage=createImage(d.width, d.height);
       offGraphics=offImage.getGraphics();

       }
       offGraphics.setColor(getBackground());
       offGraphics.fillRect(0,0, d.width, d.height);

       //Draw the H vector

       offGraphics.setColor(Color.blue);
       offGraphics.drawLine(kxbase, kybase, kxbase, kybase-90-Hfield);
       offGraphics.drawLine(kxbase, kybase-90-Hfield, kxbase+tipWidth,
        kybase-90-Hfield+2*tipLength);
       offGraphics.drawLine(kxbase, kybase-90-Hfield, kxbase-tipWidth,
        kybase-90-Hfield+2*tipLength);
       offGraphics.drawString("H", kxbase-5, kybase-95-Hfield);

       // Draw the wavevector k

       offGraphics.setColor(Color.cyan);
       offGraphics.drawLine(kxbase, kybase, kx, ky);
       offGraphics.drawLine(kx, ky, ktip1x, ktip1y);
       offGraphics.drawLine(kx, ky, ktip2x, ktip2y);
       offGraphics.drawString("k", kx+10, ky+10);

       // Draw the spins

       offGraphics.setColor(Color.red);
       for(int row=0; row<6; row++)
       {
         for(int col=0; col<6; col++)
         {
            offGraphics.drawLine(xbases[row][col],
             ybases[row][col], mx[row][col], my[row][col]);
            offGraphics.drawLine(mx[row][col], my[row][col],
             tip1x[row][col], tip1y[row][col]);
            offGraphics.drawLine(mx[row][col], my[row][col],
             tip2x[row][col], tip2y[row][col]);
         }
       }
      g.drawImage(offImage, 0, 0, this);               
   }
}