import java.applet.*; import java.awt.*; import java.lang.*; public class MGXray extends Applet implements Runnable { // Display variables final int X0=10,Y0=320,H=256,W=256; final int KX0=10,KY0=450,KH=50,KW=250; final int KobjX0=10,KobjY0=380; final int MAXATOMS = 15,PathLength=23; final int HRange=5,KRange=5; final int nk=(2*HRange+1)*(2*KRange+1); // Frame PathDesign; Atom cur[] = new Atom[MAXATOMS+1]; Atom obj[] = new Atom[MAXATOMS+1]; Atom TestAtom = new Atom(); Grid mg[] = new Grid[PathLength+1]; int xfrom,yfrom,xto,yto; int xmill; int Range; double cost,newcost; // Frequency variables double h[] = new double[nk+1]; double k[] = new double[nk+1]; double vol[] = new double[nk+1]; double Prefactor[] = new double[nk+1]; double Ire[] = new double[nk+1]; double Iim[] = new double[nk+1]; double Itestre[] = new double[nk+1]; double Itestim[] = new double[nk+1]; double Intensity[] = new double[nk+1]; double testIntensity[] = new double[nk+1]; double objIntensity[] = new double[nk+1]; double ScaleK; //Temperature double TempInit,Temp; //Status variables boolean highlighted = false; boolean isTestAtom = false; boolean newDiffPattern = false; boolean showObj = false; boolean showMiller = false; // Dialog variables String msg,newmsg,millmsg,heldmsg; //int AcceptRatio[] = new int[PathLength+1]; int xAcc[] = new int[PathLength+1]; TextField message; Thread anneal; Label tempdis,pctdis; public void init() { //Display Layout setLayout(new FlowLayout() ); msg = String.valueOf((float)cost); message = new TextField("cost = "+msg,20); add(message); tempdis = new Label("Temp = "+String.valueOf(Temp)); add(tempdis); pctdis = new Label("% = "); add(pctdis); add(new Button("Anneal")); add(new Button("Pause")); add(new Button("Show")); add(new Button("Reset")); Choice trans = new Choice(); trans.addItem("Flip about X"); trans.addItem("Flip about Y"); trans.addItem("Flip about diagonal"); trans.addItem("Rotate 90 degrees"); add(trans); //Parameters for (int f=1;f<=nk;f++) { h[f] = (f-1)/(2*HRange+1) - HRange; k[f] = (f-1)%(2*KRange+1) - KRange; Intensity[f] = 0; } mg[1] = new Grid(5000,2000,200,32); mg[2] = new Grid(4000,2000,200,16); mg[3] = new Grid(3000,2000,200,32); mg[4] = new Grid(2000,2000,200,16); mg[5] = new Grid(1800,2000,200,8); mg[6] = new Grid(1600,2000,200,8); mg[7] = new Grid(1400,3000,200,8); mg[8] = new Grid(1200,2000,200,8); mg[9] = new Grid(1000,5000,200,4); mg[10] = new Grid(800,5000,100,4); mg[11] = new Grid(600,4000,100,4); mg[12] = new Grid(400,5000,100,4); mg[13] = new Grid(200,5000,100,4); mg[14] = new Grid(100,3000,100,4); mg[15] = new Grid(80,3000,100,2); mg[16] = new Grid(60,3000,100,2); mg[17] = new Grid(50,3000,100,2); mg[18] = new Grid(25,3000,100,2); mg[19] = new Grid(10,3000,100,2); mg[20] = new Grid(10,2000,75,1); mg[21] = new Grid(10,2000,50,1); mg[22] = new Grid(10,2000,25,1); mg[23] = new Grid(10,2000,10,1); setup(); for (int p=1;p<=PathLength;p++) { xAcc[p] = (int)(mg[1].Temp-mg[p].Temp)/100; } cost = findCost(Intensity,objIntensity); TempInit = (int)(cost/(MAXATOMS*2)); Temp = TempInit; tempdis.setText("Temp = "+String.valueOf(Temp)); msg = String.valueOf((float)cost); message.setText("cost = "+msg); }//end init void restart(){ highlighted = false; isTestAtom = false; newDiffPattern = false; showObj = false; setup(); // Temp = TempInit; cost = findCost(Intensity,objIntensity); TempInit = (int)(cost/(MAXATOMS*2)); Temp = TempInit; makeDisplay(0,0); repaint(); } void setup() { cur[1] = new Atom(0,0); obj[1] = new Atom(0,0); for (int n = 2;n<=MAXATOMS;n++) { cur[n] = new Atom(); } int cnn=0,xnn,ynn; for (int n=2;n<=MAXATOMS;n++) { //for (int n = 2;n<=(MAXATOMS+1)/2;n++) { //xnn = (int)(Math.floor(Grid.XMAX*Math.random())); //ynn = (int)(Math.floor(Grid.XMAX*Math.random())); cnn+=70; ynn = 63*(cnn/256); xnn = cnn%256; obj[n] = new Atom(xnn,ynn); //obj[n+(MAXATOMS-1)/2] = new Atom(Grid.XMAX-xnn,Grid.YMAX-ynn); } for (int f=1;f<=nk;f++) { Intensity[f] = 0; testIntensity[f] = 0; objIntensity[f] = 0; } for (int p=1;p<=PathLength;p++) { mg[p].InitAcceptRatio(0); mg[p].InitCost(1); } Temp = mg[1].Temp; //numSweeps = mg[p].numSweeps; Range = mg[1].Range; prepvol(h,k,vol); diffractObjective(); diffract(); } public void run() { int s,n,accepted=0,numSweeps=0; double deltaE,accumCost; for(int p=1;p<=PathLength;p++) { Temp = mg[p].Temp; numSweeps = mg[p].numSweeps; Range = mg[p].Range; accepted = 0; accumCost = 0; for (s=1;s<=numSweeps;s++) { for (n=2;n<=MAXATOMS;n++) { cur[n].nowTesting(); TestAtom.moveTowards(cur[n]); newDiffract(); cur[n].doneTesting(); newcost = findCost(testIntensity,objIntensity); deltaE = newcost-cost; if(metrop(deltaE,Temp) == true) { updateDiffractionPattern(); cur[n].moveTo(TestAtom); cost = newcost; accepted++; }//End (if) accumCost+=cost; }//End Atom loop }//End sweep loop //prepvol(h,k,vol); mg[p].InitCost((int)(accumCost)/(MAXATOMS*numSweeps)); mg[p].InitAcceptRatio((int)(100*accepted)/(MAXATOMS*numSweeps)); System.out.println("accepted = "+accepted+" numSweeps = "+numSweeps+ "Acceptance Ratio = "+mg[p].cost); makeDisplay(p,mg[p].AcceptRatio); repaint(); }//End path loop } void prepvol(double h[], double k[], double vol[]) { for(int f=1;f<=nk;f++) { if (h[f]!=0&&k[f]!=0) { vol[f]=(double)( (Grid.dx*Grid.dy/(Math.PI*Math.PI*h[f]*k[f]))* Math.sin(Math.PI*h[f]/Grid.dx)* Math.sin(Math.PI*k[f]/Grid.dy) ); } if (h[f]==0&&k[f]!=0) { vol[f] = (double)( (Grid.dy/(Math.PI*k[f]))*Math.sin(Math.PI*k[f]/Grid.dy) ); } if (h[f]!=0&&k[f]==0) { vol[f] = (double)( (Grid.dx/(Math.PI*h[f]))*Math.sin(Math.PI*h[f]/Grid.dx) ); } if (h[f]==0&&k[f]==0) { vol[f] = (double)(1); } } } boolean metrop(double dE, double T) { if (dE<0) return true; else if (Math.exp(-dE/T)>Math.random()) return true; else return false; } void makeDisplay(int p, int AcceptRatio) { tempdis.setText("Temp = "+String.valueOf(Temp)); msg = String.valueOf((float)cost); pctdis.setText("% = "+String.valueOf(AcceptRatio)); if (p==PathLength) msg += ": Done"; message.setText("cost = "+msg); } public boolean action(Event e, Object arg) { //Button commands if (e.target instanceof Button) { String command = (String)arg; if (command.equals("Reset")) { if (anneal !=null) { anneal.stop(); anneal = null; } restart(); } ///will this work correctly? if (command.equals("Pause")) { anneal.suspend(); } if (command.equals("Show")) { showObj = true; } if (command.equals("Anneal")) { if (anneal == null) { anneal = new Thread(this); anneal.start(); } else anneal.resume(); } // if (command.equals("Stop")) { // if (anneal !=null) { // anneal.stop(); // anneal = null; // } // } repaint(); } //Choice menu commands if(e.target instanceof Choice) { String command = (String)arg; if (command.equals("Flip about X")){ for (int n=1;n<=MAXATOMS;n++) cur[n].flipAboutX(); } if (command.equals("Flip about Y")){ for (int n=1;n<=MAXATOMS;n++) cur[n].flipAboutY(); } if (command.equals("Flip about diagonal")){ for (int n=1;n<=MAXATOMS;n++) cur[n].flipAboutDiagonal(); } if (command.equals("Rotate 90 degrees")){ for (int n=1;n<=MAXATOMS;n++) cur[n].rotate90(); } repaint(); } return true; }//End action public boolean mouseDown (Event e, int xin, int yin) { //Clicked on lattice if (clickedonBox(xin,yin)==true) { xfrom = xin-X0; yfrom = Y0-yin; cur[1].nowTesting(); } //Clicked on Frequency region //if (xin>=KX0&&xin<=KX0+KW&&yin>=KY0-120&&yin<=KY0) { if (clickedonFrequency(xin,yin)==true) { for(int f=0;f=(KX0+2*f)&&xin<(KX0+2*(f+1))) { xmill = (int)(KX0+2*f); millmsg = "(h,k) = ("+String.valueOf(h[f])+"," +String.valueOf(k[f])+")"; } } heldmsg = message.getText(); message.setText(millmsg); repaint(); showMiller = true; } repaint(); return true; }//End mouseDown public boolean mouseDrag(Event e, int xin, int yin) { if (xin>=X0&&xin<=X0+W&&yin>=Y0-H&&yin<=Y0) { xto = xin-X0; yto = Y0-yin; for (int n=1;n<=MAXATOMS;n++) { cur[n].moveBy(xto-xfrom,yto-yfrom); cur[n].keepInBox(); } xfrom = xto; yfrom = yto; } repaint(); return true; } public boolean mouseUp(Event e, int xin, int yin) { if (clickedonBox(xin,yin)==true) { xto = xin-X0; yto = Y0-yin; for (int n=1;n<=MAXATOMS;n++) { cur[n].moveBy(xto-xfrom,yto-yfrom); cur[n].keepInBox(); } cur[1].doneTesting(); } //Clicked on Frequency region if (clickedonFrequency(xin,yin)==true) { if (showMiller == true) { showMiller = false; message.setText(heldmsg); } } repaint(); return true; } public boolean keyDown(Event e, int key) { if (isTestAtom == true) { switch (key) { case Event.LEFT: TestAtom.x(TestAtom.x()-5); break; case Event.RIGHT: TestAtom.x(TestAtom.x()+5); break; case Event.UP: TestAtom.y(TestAtom.y()+5); break; case Event.DOWN: TestAtom.y(TestAtom.y()-5); break; } TestAtom.keepInBox(); newDiffract(); newcost = findCost(testIntensity,objIntensity); newmsg = String.valueOf((float)newcost); message.setText("cost = "+msg+"newcost= "+newmsg); repaint(); } return true; } // void addTestAtom(int xin , int yin) { // xtest=xin-X0; // ytest=Y0-yin; // for (int i=0;i<=W;i+=resx) // for (int j=0;j<=H;j+=resy) // if(xtest>=i-(resx/2)&&xtest=j-(resy/2)&&ytest=KX0&&xin<=KX0+KW&&yin>=KY0-120&&yin<=KY0) return true; else return false; } boolean clickedonBox(int xin, int yin) { if (xin>=X0&&xin<=X0+W&&yin>=Y0-H&&yin<=Y0) return true; else return false; } // // Diffraction Routines // void diffractObjective() { double re,im,arg; double xmid[] = new double[nk+1]; double ymid[] = new double[nk+1]; int n,f; for(n=1;n<=MAXATOMS;n++) { xmid[n] = (double)(obj[n].x())/W; ymid[n] = (double)(obj[n].y())/H; } for(f=1;f<=nk;f++) { re = im = 0; for(n=1;n<=MAXATOMS;n++) { arg = (double)( 2*Math.PI*( h[f]*xmid[n]+k[f]*ymid[n] ) ); // re += (double)(vol[f]*Math.cos(arg)); // im += (double)(vol[f]*Math.sin(arg)); re += (double)(Math.cos(arg)); im += (double)(Math.sin(arg)); objIntensity[f] = re*re+im*im; } } //Find largest intensity value to normalize the graphs ScaleK = 0.0; for(f=1;f<=nk;f++) if (ScaleK=Grid.XMAX) tempx-=Grid.XMAX; while(tempy<0) tempy+=Grid.YMAX; while(tempy>=Grid.YMAX) tempy-=Grid.YMAX; x(tempx); y(tempy); } void keepInBox() { while(x<0) x+=Grid.XMAX; while(x>=Grid.XMAX) x-=Grid.XMAX; while(y<0) y+=Grid.YMAX; while(y>=Grid.YMAX) y-=Grid.YMAX; } void moveTo(Atom rhs) { x=rhs.x(); y=rhs.y(); } void moveBy(int xin, int yin) { x +=xin; y +=yin; } void flipAboutY() {x = Grid.XMAX-x;} void flipAboutX() {y = Grid.YMAX-y;} void flipAboutDiagonal() { int temp; temp = y; y = x; x = temp; } void rotate90() { int temp; temp = y; y = x; x = Grid.YMAX-temp; } //static boolean locateAtom(int xin, int yin){ // int xspot = xin-X0; // int yspot = Y0-yin; // // for (int n=1; n<=MAXATOMS; n++) { // for (int ii=-resx/2;ii<=resx/2;ii++) // for (int jj=-resy/2;jj<=resy/2;jj++) // if(x+ii==xspot&&y+jj==yspot) { // highlight = true; // System.out.println("Spot #"+n+"x = "+xin+"y = "+yin); // return highlight; // } // } // return highlight; // } // } // // Design class // //class PathDesign extends Frame { // Label l // PathFrame (String title) { // super(title); // setLayout(new GridLayout