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