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