/*
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);
}
}