/* This code solves the Schroedinger equation for a wavepacket incident on a square potential barrier. The solution method is the simple Euler's method. This can be improved with, e.g., a Cranck-Nickolson method. But, it is good enough for teaching purposes. For the HTML code use: C.A. Bertulani, 08/23/2000 */ import java.awt.*; import java.applet.*; import java.awt.image.*; public class Potbar extends Applet implements Runnable { Thread runstring; // Creates a scrollbar with the specified orientation, value, extent, // mimimum, and maximum: value = initial position of scroll, extent = // width of scroll, minimum = minimun pixel number associated with position public Scrollbar leftRight; // A Canvas represents a blank rectangular area of the screen // onto which the application can draw or from which the application can // trap input events from the user. private MyCanvas canv; // A panel provides space in which an application can attach any other // component, including other panels. private MyPanel thePanel; // A border layout lays out a container, arranging and resizing its // components to fit in five regions: north, south, east, west, and center. BorderLayout MyLay; // global variables int Flag; public boolean stopped = false; public Potbar() // to initialize Flag { setFlag(0); } public void setFlag(int fl) { Flag = fl; // Flag 0 do not begin string motion, 1 yes } public void init() { setLayout(MyLay = new BorderLayout()); thePanel = new MyPanel(this,canv); leftRight = new Scrollbar(Scrollbar.HORIZONTAL,40,0,10,110); canv = new MyCanvas(this); canv.init(); thePanel.init(); add("Center",canv); // centering Canvas add("North",leftRight); // scrollbar at the top add("South", thePanel); // panel at the bottom } public void start() { if(! stopped) { if(Flag == 1){ canv.jj = 1; // initial condition canv.flag = 1; runstring = new Thread(this); runstring.start(); } } } public void stop() { if(runstring != null){ runstring = null; } } public void brk() //stops motion temporarily { stopped = false; setFlag(0); canv.jj = 1; // back to initial condition } public void run() { while(true){ try{ // during 380 miliseconds the thread does not run, even if the // processor becomes available. Thread.currentThread().sleep(380);} catch (InterruptedException e){ } canv.repaint(); // update of the applet's display area } } public void paint(Graphics g){ canv.repaint(); //called many times } public boolean handleEvent(Event ev){ // events sent by Mypanel and scrollbar interpreted here // scrollbar movements if(ev.target instanceof Scrollbar){ if(ev.target == leftRight)canv.setWidth(leftRight.getValue()); canv.repaint(); return true; } // mouse movements if((ev.id==ev.MOUSE_DRAG)){ canv.Xmos=ev.x; canv.Ymos=ev.y; canv.erase=true; // requests that the argument string be displayed in the "status window". showStatus("Cursor at position x = " + ev.x + " and y = " + ev.y); canv.repaint(); return true; } if(ev.id==ev.MOUSE_ENTER){ //to show black square at beginning //when mouse enters the applet canv.repaint(); return true; } return false; } } //class class MyCanvas extends Canvas implements ImageObserver{ // all the painting occurs here Potbar runstring; // run thread int ixmesh0, ixmeshN; double y0, yN; double myp,mxp,byp,bxp; double Stretchxx,Coefxx,Stretchyy,Coefyy,yypos,xxpos,pi,dx,dt; private Image offScreenImage; // to avoid flicker Graphics offScreenGraphics; int ypos,xpos,max,cor; int Xmos,Ymos,Xdef,Ydef; //mouse positions boolean erase=false; int first,incr,jj = 1; // jj=1 is for initial conditions int AppletHeight, AppletWidth, xleft,yupper,xsize,ysize; double margin; double psr[][], psi[][], v[], p2[]; int flag = 0; //do not draw equation public void init() { y0=0.0; yN=1.5; ixmesh0=0; ixmeshN=500; max=ixmeshN-ixmesh0; Dimension d = getSize(); AppletHeight = d.height; AppletWidth = d.width; margin = 0.1; // percent used in margin xleft = (int)(margin*AppletWidth); // x pixel-left point yupper = (int)(margin*AppletHeight); // y pixel-upper point xsize = (int)((AppletWidth-2.0*xleft)); ysize = (int)((AppletHeight-2.0*yupper)); psr=new double[max+1][2]; psi=new double[max+1][2]; p2=new double[max+1]; v=new double[max+1]; jj = 1; pi=3.14159265358979323846; dx=0.02; // coordinate-x step dt=0.9*dx*dx; // convenient time step size incr=10; cor=20; } public MyCanvas(Potbar runstring) //to initialize class and variables { this.runstring=runstring; setWidth(50); //initial position of the horizontal } public void update(Graphics g) { //To avoid screen flicker use double buffer technique Dimension d = getSize(); AppletHeight = d.height; AppletWidth = d.width; // copy image of screen offScreenImage=createImage(AppletWidth,AppletHeight); offScreenGraphics=offScreenImage.getGraphics(); offScreenGraphics.setColor(getBackground()); offScreenGraphics.fillRect(0,0,AppletWidth,AppletHeight); offScreenGraphics.setColor(g.getColor()); paint(offScreenGraphics); // paint image g.drawImage(offScreenImage,0,0,this); // 0,0 is the image x,y position } public void setWidth(int hx) { xpos=hx; } void CoordUndo(double ixmesh0,double ixmeshN,double y0,double yN) { // changes x-mesh-indexing and y-coordinate definition into // java applet coordinate system of pixels // put graph within a margin from applet window double xxmax = (1.0-margin)*AppletWidth; // right x-pixel-limit double xxmin = margin*AppletWidth; // left x-pixel-limit double yymin = (1.0-margin)*AppletHeight; // upper y-pixel-limit double yymax = margin*AppletHeight; // lower y-pixel-limit // fit data within graph axis // first transform mesh indices into x-window-pixel coordinates Stretchxx = (xxmax-xxmin)/(ixmeshN-ixmesh0); Coefxx = (xxmin*ixmeshN-xxmax*ixmesh0)/(ixmeshN-ixmesh0); // now transform graph y-values to y-window-pixel coordinates Stretchyy = (yymax-yymin)/(yN-y0); Coefyy = (yymin*yN-yymax*y0)/(yN-y0); } private int pixx(int ivalue) { // Given the index of the mesh-xpoint return the pixel equivalent int jvalue = (int)(Stretchxx*ivalue + Coefxx); return jvalue; } private int pixy(double yvalue) { // Given the y-value in desired scale, return the pixel equivalent int jvalue = (int)(Stretchyy*yvalue + Coefyy); return jvalue; } public void rectangulo(Graphics g) { //draws instruction rectangle int Rectx = (int)(xleft+xsize/3.0); int Recty = (int)(yupper+ysize/2.0); int RectW = (int)(xsize/3.0); int RectH = (int)(ysize/2.0)-2; g.drawRect(Rectx,Recty,RectW,RectH); int xstep = (int)(xsize/10.0); int ystep = (int)(ysize/20.0); Xdef = Rectx; Ydef = Recty; g.drawString("Drag mouse",xleft+4*xstep,yupper+13*ystep); g.drawString("in this area",xleft+4*xstep,yupper+14*ystep); g.drawString("to select potential",xleft+4*xstep,yupper+15*ystep); } public void inirec(Graphics g) { //initial rectangle g.drawOval(Xdef+xsize/3-cor,Ydef+cor,10,10); g.drawLine(Xdef+cor,yupper+ysize-2,Xdef+cor,Ydef+cor); // vertical 1 g.drawLine(Xdef+xsize/3-cor,yupper+ysize-2,Xdef+xsize/3-cor,Ydef+cor); g.drawLine(Xdef+cor,Ydef+cor,Xdef+xsize/3-cor,Ydef+cor); // horizontal } public void inipot(Graphics g) { //initial potential shown g.setColor(Color.black); rectangulo(g); g.setColor(Color.blue); if(erase==false){ inirec(g); } else { g.setColor(getBackground()); inirec(g); } g.setColor(Color.blue); } public void potbar(Graphics g) { //selects potential as mouse drags if((XmosXdef) &&(YmosYdef)){ g.drawLine(Xdef+cor,Ymos,Xmos,Ymos); g.drawLine(Xdef+cor,yupper+ysize-2,Xdef+cor,Ymos); g.drawLine(Xmos,yupper+ysize-2,Xmos,Ymos); } } public void selectmom(Graphics g) { //select wave packet momentum with scrollbar and draw frame int i; // put graph within a margin from applet window xleft = (int)(margin*AppletWidth); // x pixel-left point yupper = (int)(margin*AppletHeight); // y pixel-upper point xsize = (int)((AppletWidth-2.0*xleft)); ysize = (int)((AppletHeight-2.0*yupper)); // draw label of scrollbar g.drawString("Use scrollbar to Select Wave Packet Momentum ", xleft,yupper/2); g.setColor(Color.red); // draw frame g.drawRect(xleft,yupper,xsize,ysize); // draw ticks and labels for(i=0; i<6; i++){ int xincr = (int)(xsize/5); int tick = xleft+xincr*i; int dtick = AppletHeight/50; g.drawLine(tick,yupper,tick,yupper+10); g.drawString(Integer.toString(-10+4*i),tick,yupper-5); } for(i=0;i<6;i++){ int yincr = (int)(ysize/5); int tick = yupper+yincr*i; int dtick = AppletHeight/50; g.drawLine(xleft+xsize-10,tick,xleft+xsize,tick); g.drawString(Double.toString((5.-i)/5.),xleft+xsize+5,tick+10); } } public void Equation1(Graphics g) { //to draw initial potential wavefunction //at beginning and after each stop double x,fact2; double k0,vh; double expon,poten; int minix,maxix; int i,n,arrow; xxpos = (double)xpos; x = 0.0; minix=0;// initialize selectmom(g); g.setColor(Color.blue); if(jj == 1){ // initial conditions CoordUndo(ixmesh0,ixmeshN,y0,yN); // transform pixels to coordinates inipot(g); xxpos=(double)xpos; k0=pi*xxpos/10.0; arrow=(int)(1.5*xxpos); g.setColor(Color.red); g.drawLine(xleft+xsize/2-arrow,yupper+ysize/3,xleft+xsize/2,yupper+ysize/3);//arrow g.drawLine(xleft+xsize/2-5,yupper+ysize/3-5,xleft+xsize/2,yupper+ysize/3); //upper tip g.drawLine(xleft+xsize/2-5,yupper+ysize/3+5,xleft+xsize/2,yupper+ysize/3); //lower tip g.setColor(Color.blue); potbar(g); if(Ymos == 0)Ymos = yupper+ysize/2; if(Xmos == 0)Xmos=Xdef+(int)(xsize/3.0); minix = Xdef; poten = AppletHeight/2; maxix = Xmos; if(AppletWidth>0) { minix = (int)(Xdef*(ixmeshN-ixmesh0)/AppletWidth); poten = (double)(AppletHeight-Ymos-yupper); maxix = (int)(Xmos*(ixmeshN-ixmesh0)/AppletWidth); } vh = poten; g.drawLine(xleft,yupper+ysize-3,xleft+xsize,yupper+ysize-2); //base line for(i=0; iminix)&&(i0){ // transform coordinates to pixel coordinates int pixx1=pixx(i-1); int pixx2=pixx(i); int pixy1=pixy(p2[i-1]/1.5); int pixy2=pixy(p2[i]/1.5); // draw probabilities g.drawLine(pixx1,pixy1,pixx2,pixy2); int pixy1v=pixy((v[i-1])*yN/AppletHeight); int pixy2v=pixy((v[i])*yN/AppletHeight); if(v[i] !=v[i-1])pixx1=pixx2; if(n !=1) g.drawLine(pixx1,pixy1v,pixx2,pixy2v); } } } } } public void Equation(Graphics g) { double x,fact2; double k0,vh; double expon,poten; int i,n,arrow; x=0.0; selectmom(g); g.setColor(Color.blue); if(jj == 1){ // initial conditions CoordUndo(ixmesh0,ixmeshN,y0,yN); // transform pixels to coordinates xxpos=(double)xpos; k0=pi*xxpos/10.0; // momentum g.setColor(Color.blue); for(i=0;i0){ // transform coordinates to pixel coordinates int pixx1=pixx(i-1); int pixx2=pixx(i); int pixy1=pixy(p2[i-1]/1.5); int pixy2=pixy(p2[i]/1.5); // draw probabilities g.drawLine(pixx1,pixy1,pixx2,pixy2); int pixy1v=pixy((v[i-1])*yN/AppletHeight); int pixy2v=pixy((v[i])*yN/AppletHeight); if(v[i] !=v[i-1])pixx1=pixx2; if(n !=1)g.drawLine(pixx1,pixy1v,pixx2,pixy2v); } } } // new iterations are now the old ones for(i=1;i= incr+1)first = jj-incr; Equation(g); jj = jj+incr; } } } class MyPanel extends Panel{ //controls Stop, start and scrollbars //transmits to Eqstring the events Potbar runstring; // GridBagLayout is a layout manager that aligns components vertically and // horizontally, without requiring that the components be of the same size. GridBagLayout GBLay; // GridBagConstraints specifies constraints for components that are laid // out using the GridBagLayout class. GridBagConstraints c; MyCanvas canv; public void init(){ GBLay = new GridBagLayout(); c = new GridBagConstraints(); setLayout(GBLay); c.gridx = 1; c.gridy = 1; c.gridheight = 1; // BOTH resizes the component both horizontally and vertically c.fill = GridBagConstraints.BOTH; Button stp = new Button("Stop"); GBLay.setConstraints(stp,c); add(stp); c.gridx = 2; Button rest = new Button("Start"); GBLay.setConstraints(rest,c); add(rest); } public MyPanel(Potbar runstring, MyCanvas canv) { this.canv = canv; this.runstring = runstring; } public boolean action(Event ev, Object arg) { if (ev.target instanceof Button) { String label = (String)ev.arg; if (label.equals("Stop")){ runstring.brk(); } if(label.equals("Start")){ runstring.setFlag(1); runstring.stopped=false; runstring.start(); } return true; } //else if(ev.target instanceof Scrollbar){ runstring.postEvent(ev);//sent to Eqstring handlEvent return true; } if((ev.id==ev.MOUSE_DRAG)){ runstring.postEvent(ev); } return false; } }