// Shrodinger's Wave Equation in One Dimension // To add a new potential you must add one to npot (number of potentials) // Fill in the sname and lname for your new potential // Add the potential function to the setPotentials() routine import java.awt.*; import java.awt.event.*; import java.lang.*; import java.applet.Applet; public class quantum extends Applet implements Runnable, ActionListener, AdjustmentListener, TextListener, ItemListener { static Frame frm; String version="0.99"; // Version number int MAXX=320; //graph viewing size int MAXY=320; //graph viewing size Thread kicker = null; // Used for Java Applets boolean auto=false; // automatic integration flag boolean poto=true; // potential graph flag boolean norm=false; // normalization flag boolean print=false; // print flag boolean drawSave=false; // draw saved values flag boolean overLap=false; // draw overlap flag boolean smooth=false; // smooth flag int savep=1; // saved plotting method to use double offsetx=10.5; double offsety=30.5; // graph offsets double eigen=1.0; // initial eigen value double beta=2; // initial beta constant double rmass=1; // reduced mass constant int ipot=1; // potential number (1=infinite square) double zatomic=1.0; // atomic number int quantuml=0; // l quantum number int ql2=quantuml*(quantuml+1); double xmin=-2.0; double xmax=2.0; double ymax=1.0; double ymin=-1.0; // Initial min/max values double ymaxa=1.0; double ymina=-1.0; // Initial displayed min/max y values int id=1; //Save location double fac=0.125; // fraction of additional space to include in saved plots double big=Math.pow(10, 30); // largest real number accepted double yymax=big/Math.pow(10, 6); // The max y value plotted double yymin=-big/Math.pow(10, 6); // The min y value plotted double damp=Math.pow(10, -2); // damping eigen value double erchk=Math.pow(10, -12); // maximum accpected eigen value error double maxiter=Math.pow(10, 2); // maximum number of iterations in autoint double force=0.3299; // inital force constant double de=0.1744; // hydrogen disscociation energy double re=1.4011; // Hydrogen Bond Length double aexp=Math.sqrt(force/(2.0*de)); double v0=10.0; //size of potential step double errNum=42.42; //number to return for Number Format Exceptions String s=""; String arg=""; Font f; FontMetrics fm; // initialize commonly used variables int saves=6; // max number of saved data points int npot=7; // number of different potentials int nplots=7; // number of saved plot functions int nbuts=7; // number of buttons int nvars=14; // number of saved text-field variables int nmax=181; // number of x data points double dx=(xmax-xmin)/(nmax-1); // x increment int knumber=100; // number of integration steps between plot data points double dxx=dx/knumber; // used for precise integrating double yzero=0.0; // y[0] boundary condition double vzero=1/(xmax-xmin); // slope at xmin double astep=.5; // potential step position Scrollbar eigens; // Slider used for eigen value adjustment // Canvas c; double scalex = (MAXX-2*offsetx)/(xmax-xmin); double scaley = (MAXY-2*offsety)/(ymax-ymin); // graph scaling double escale=0.0001; // decimal places of precision (for slider) double eoffset=50; // eigen value offset (for slider) double erange=50; // eigen value range (for slider) String[] sname=new String[npot+1]; // potential names (short) String[] lname=new String[npot+1]; // potential names (long) String[] pname=new String[nplots+1]; // plot names String[] bname=new String[nbuts+1]; // button names double[] x=new double[nmax+1]; // x values array double[] y=new double[nmax+1]; // wavefunction graph array double[] v=new double[nmax+1]; // potential graph array double[] vh=new double[nmax+1]; // potential halfstep array double[] p=new double[nmax+1]; // p-norm graph array double[] t=new double[nmax+1]; // overlap storage array double yp; // endpoint used for hydrogen integration double[][] xsave=new double[nmax+1][saves+1]; double[][] ysave=new double[nmax+1][saves+1]; double[][] vsave=new double[nmax+1][saves+1]; int[] ipotsave=new int[saves+1]; double[] esave=new double[saves+1]; // saved graph arrays double[] span=new double[saves+1]; // save span String[] var=new String[nvars+1]; // variable storage array String[][] defVar=new String[nvars+1][npot+1]; // default variable array TextField eigent, xmint, xmaxt, yzerot, vzerot, rmasst, quantumlt, zatomict, astept, v0t, forcet, ret; // Variable text-fields Checkbox[] savec= new Checkbox[saves+1]; // Saved plot checkboxes Checkbox smoothc; // Smooth checkbox // Button[] idb= new Button[saves+1]; Label[] potName = new Label[saves+1]; // Saved plot names Choice idt= new Choice(); // save slot pull-down menu Choice viewt= new Choice(); // plotting pull-down menu Choice maint= new Choice(); // potential pull-down menu Label zatomicl, v0l; // Labels which are different for Rigid Rotor Panel pp = new Panel(); // main panel GridBagConstraints gbc = new GridBagConstraints(); public void init(){ // initializes the program and sets the layout setNames(); // assign names to potentials/plotting styles setDefaults(); // set default values for each potential setFont(new Font("SansSerif", 0, 12)); GridBagLayout gbl = new GridBagLayout(); pp.setLayout(gbl); for (int i=0; i<=npot; i++) { maint.add(lname[i]); } maint.addItemListener(this); Button restb=new Button(bname[1]); Button autob=new Button(bname[2]); Button potob=new Button(bname[3]); Button normb=new Button(bname[4]); Button saveb=new Button(bname[5]); Button chngb=new Button(bname[7]); restb.addActionListener(this); autob.addActionListener(this); potob.addActionListener(this); normb.addActionListener(this); saveb.addActionListener(this); chngb.addActionListener(this); for (int i=1; i<=saves; i++) { savec[i]=new Checkbox(); savec[i].addItemListener(this); potName[i]=new Label("[ Save "+i+" ]"); for (int j=1; j<=nmax; j++) { xsave[j][i]=0; ysave[j][i]=0; vsave[j][i]=0; } ipotsave[i]=0; esave[i]=0; span[i]=0; } smoothc=new Checkbox(bname[6]); smoothc.addItemListener(this); Label verl= new Label(" v "+version); Label mainl= new Label("Potential Function"); Label xminl= new Label("xmin:"); Label xmaxl= new Label("xmax:"); Label yzerol= new Label("initial Y:"); Label vzerol= new Label("initial dy:"); Label eigenl= new Label("eigen value:"); Label rmassl= new Label("reduced mass:"); Label quantumll= new Label("l quantum #:"); zatomicl= new Label("atomic number:"); v0l= new Label("potential step:"); Label astepl= new Label("potential width:"); Label forcel= new Label("force constant:"); Label rel= new Label("bond length:"); int rsize=6; xmint= new TextField("-2.0", rsize); xmaxt= new TextField("2.0", rsize); yzerot= new TextField("0.0", rsize); vzerot= new TextField("1.0", rsize); eigent= new TextField("1.0", rsize); rmasst= new TextField("1.0", rsize); quantumlt= new TextField("N/A", rsize); zatomict= new TextField("N/A", rsize); v0t= new TextField("N/A", rsize); astept= new TextField("N/A", rsize); forcet= new TextField("N/A", rsize); ret= new TextField("N/A", rsize); xmint.addTextListener(this); xmaxt.addTextListener(this); yzerot.addTextListener(this); vzerot.addTextListener(this); eigent.addTextListener(this); rmasst.addTextListener(this); quantumlt.addTextListener(this); zatomict.addTextListener(this); v0t.addTextListener(this); astept.addTextListener(this); forcet.addTextListener(this); ret.addTextListener(this); viewt.addItemListener(this); for (int i=0; i<=nplots; i++) { viewt.add(pname[i]); } idt.addItemListener(this); for (int i=1; i<=saves; i++) { s="["+i+"]"; idt.add(s); } eigens= new Scrollbar(Scrollbar.VERTICAL, (int)(eigen/escale), 0, (int)(-erange/escale+eoffset/escale), (int)(erange/escale+eoffset/escale)); eigens.addAdjustmentListener(this); eigens.setBlockIncrement(20); // Amount moved when scrollbar is clicked eigens.setUnitIncrement(1); // Amount moved when arrow is clicked gbc.fill=GridBagConstraints.HORIZONTAL; addp(mainl, gbc, pp, 0, 0, 4, 1); addp(maint, gbc, pp, 0, 1, 4, 1); addp(restb, gbc, pp, 0, 2, 4, 1); addp(autob, gbc, pp, 0, 3, 4, 1); addp(potob, gbc, pp, 0, 4, 4, 1); addp(normb, gbc, pp, 0, 5, 4, 1); addp(savec[1], gbc, pp, 0, 6, 1, 1); addp(savec[2], gbc, pp, 2, 6, 1, 1); addp(savec[3], gbc, pp, 0, 7, 1, 1); addp(savec[4], gbc, pp, 2, 7, 1, 1); addp(savec[5], gbc, pp, 0, 8, 1, 1); addp(savec[6], gbc, pp, 2, 8, 1, 1); addp(potName[1], gbc, pp, 1, 6, 1, 1); addp(potName[2], gbc, pp, 3, 6, 1, 1); addp(potName[3], gbc, pp, 1, 7, 1, 1); addp(potName[4], gbc, pp, 3, 7, 1, 1); addp(potName[5], gbc, pp, 1, 8, 1, 1); addp(potName[6], gbc, pp, 3, 8, 1, 1); addp(saveb, gbc, pp, 0, 9, 3, 1); addp(idt, gbc, pp, 3, 9, 1, 1); addp(viewt, gbc, pp, 0, 10, 4, 1); addp(smoothc, gbc, pp, 0, 11, 4, 1); addp(verl, gbc, pp, 0, 12, 4, 1); gbc.fill=GridBagConstraints.NONE; gbc.anchor=GridBagConstraints.EAST; addp(xminl, gbc, pp, 4, 0, 1, 1); addp(xmaxl, gbc, pp, 4, 1, 1, 1); addp(yzerol, gbc, pp, 4, 2, 1, 1); addp(vzerol, gbc, pp, 4, 3, 1, 1); addp(eigenl, gbc, pp, 4, 4, 1, 1); addp(rmassl, gbc, pp, 4, 5, 1, 1); addp(quantumll, gbc, pp, 4, 6, 1, 1); addp(zatomicl, gbc, pp, 4, 7, 1, 1); addp(v0l, gbc, pp, 4, 8, 1, 1); addp(astepl, gbc, pp, 4, 9, 1, 1); addp(forcel, gbc, pp, 4, 10, 1, 1); addp(rel, gbc, pp, 4, 11, 1, 1); gbc.anchor=GridBagConstraints.CENTER; addp(xmint, gbc, pp, 5, 0, 1, 1); addp(xmaxt, gbc, pp, 5, 1, 1, 1); addp(yzerot, gbc, pp, 5, 2, 1, 1); addp(vzerot, gbc, pp, 5, 3, 1, 1); addp(eigent, gbc, pp, 5, 4, 1, 1); addp(rmasst, gbc, pp, 5, 5, 1, 1); addp(quantumlt, gbc, pp, 5, 6, 1, 1); addp(zatomict, gbc, pp, 5, 7, 1, 1); addp(v0t, gbc, pp, 5, 8, 1, 1); addp(astept, gbc, pp, 5, 9, 1, 1); addp(forcet, gbc, pp, 5, 10, 1, 1); addp(ret, gbc, pp, 5, 11, 1, 1); addp(chngb, gbc, pp, 4, 12, 2, 1); gbc.fill=GridBagConstraints.VERTICAL; addp(eigens, gbc, pp, 6, 0, 1, 13); gbc.fill=GridBagConstraints.NONE; setLayout(new BorderLayout()); add (pp, "East"); } public void start(){ if (kicker == null) { kicker = new Thread(this); kicker.setPriority(kicker.MIN_PRIORITY); kicker.start(); } } public void stop(){ kicker = null; } public void run() { while(kicker != null){ repaint(); try {kicker.sleep(25);} catch (InterruptedException e) {} } } // start, run, stop are all necessary for Java Applets to function public void paint(Graphics gg){ // Main Loop Image bufferedImage = createImage(MAXX, MAXY+70); Graphics g = bufferedImage.getGraphics(); // double buffering if (overLap) drawOverlap(g); else if (drawSave) drawSaved(g); else if (auto) autoint(g); else if (poto) graphPotential(g); else if (ipot==6) hydrogen(g); else if (ipot==7) rigid(g); else integrate(g); gg.drawImage(bufferedImage, 0, 0, null); // draw the buffered image if (print) { print=false; PrintJob pj = Toolkit.getDefaultToolkit().getPrintJob(frm, "Print-Test", null); Graphics pg = pj.getGraphics(); pg.drawImage(bufferedImage, 0, 0, null); pj.end(); } //g.dispose(); } public void update(Graphics gg) { paint(gg); } public void itemStateChanged (ItemEvent Evt) { // handles checkboxes and pulldown menus for (int i=1; i<=saves; i++) { if (savec[i].getState()) { ipot=ipotsave[i]; if (ipot==0) ipot=1; } } // checks to see if at least one drawSave checkbox is checked // and sets the current potential to the last one checked smooth=smoothc.getState(); arg=(String)Evt.getItem(); for (int i=1; i<=npot; i++) { if (arg.equals(lname[i])) { saveVars(); // saves the current variable ipot=i; // sets the current potential to whatever the user // just selected getVars(); // sets any common variables to the last ones } } // allows the user to select a new potential from the pull-down menu for (int i=1; i<=nplots; i++) { if (arg.equals(pname[i])) { savep=i; drawSave=true; } } // allows the user to select a new method of saved plotting from the menu if (arg.equals(pname[0])) savedOff(); if (arg.equals(pname[1]) || arg.equals(pname[2])) overLap=false; if (arg.equals(pname[3]) || arg.equals(pname[4]) || arg.equals(pname[5]) || arg.equals(pname[6]) || arg.equals(pname[7])) overLap=true; if (arg.length()>1) arg=arg.substring(1, 2); try { id=Integer.parseInt(arg); } catch (NumberFormatException e) { // } // allows the user to select a new plot style from the menu } public void textValueChanged(TextEvent evt) { // handles text-fields // changeValues(); // allows user to change textfield values } public void adjustmentValueChanged(AdjustmentEvent evt) { // handles scrollbars eigen=eigens.getValue()*escale; arg=Double.toString(eigen); eigent.setText(arg); // allows user to adjust the eigen-value slider } public void actionPerformed(ActionEvent evt) { // handles buttons arg = evt.getActionCommand(); if (arg.equals(bname[1])) resetVars(); else if (arg.equals(bname[2])) { auto=true; poto=false; } else if (arg.equals(bname[3])) poto=swbool(poto); else if (arg.equals(bname[4])) { norm=swbool(norm); poto=false; } else if (arg.equals(bname[5])) saveGraph(); else if (arg.equals(bname[6])) smooth=swbool(smooth); else if (arg.equals(bname[7])) changeValues(); // checks for button presses } public void saveVars() { // saves the current variable settings to an array var[1]=eigent.getText(); var[2]=xmint.getText(); var[3]=xmaxt.getText(); var[4]=yzerot.getText(); var[5]=vzerot.getText(); var[6]=rmasst.getText(); var[7]=v0t.getText(); var[8]=astept.getText(); var[9]=forcet.getText(); var[10]=ret.getText(); var[11]=quantumlt.getText(); var[12]=zatomict.getText(); var[13]=""+eoffset; var[14]=""+erange; } public void getVars() { // gets the current variable values blankVars(); // Make sure unused variables have an "N/A" eigent.setText(var[1]); xmint.setText(var[2]); xmaxt.setText(var[3]); yzerot.setText(var[4]); vzerot.setText(var[5]); rmasst.setText(var[6]); v0t.setText(var[7]); astept.setText(var[8]); forcet.setText(var[9]); ret.setText(var[10]); quantumlt.setText(var[11]); zatomict.setText(var[12]); if (var[7].equals("N/A")) v0t.setText(defVar[7][ipot]); if (var[8].equals("N/A")) astept.setText(defVar[8][ipot]); if (var[9].equals("N/A")) forcet.setText(defVar[9][ipot]); if (var[10].equals("N/A")) ret.setText(defVar[10][ipot]); if (var[11].equals("N/A")) quantumlt.setText(defVar[11][ipot]); if (var[12].equals("N/A")) zatomict.setText(defVar[12][ipot]); // If the variable did not exist for the last potential, set the // variable to the default for the current potential setLabels(); // Rigid Rotor uses different variabel names changeValues(); // set variables to current values savedOff(); // Turn off saved plotting } public void setLabels() { // The rigid rotor uses different variable labels than the // first six potentials, so the labels must be changed if (ipot==7) { v0l.setText("m quantum #:"); zatomicl.setText("moment of I:"); } else if (ipot==3) { v0l.setText("potential step:"); zatomicl.setText("potential step:"); } else { v0l.setText("potential step:"); zatomicl.setText("atomic number:"); } } public void autoint(Graphics g) { // uses guess and check to find an eigen value which works norm=false; double e0=eigen; double u0; double epos=big; double eneg=-big; int l=0; if (ipot==6) u0=yp; else u0=y[nmax]; double er=erchk+1; double e00, u00, diffe, diffu; eigen+=eigen*damp; int m=(int)v0; if ((m==0) && (ipot==7)) v0=1; // rigid rotor is solved for m>=1, but the valuse still work for m=0 while ((er>erchk)&&(l0)&&(e0eneg)) eneg=e0; diffu=u0-u00; diffe=e0-e00; if (diffu==0) eigen=0.5*(e0+e00); else eigen-=u0*diffe/diffu; //if (((eigen>epos)||(eigen-astep && xx-astep && xhastep) v[i]=v0; if (xh>astep) vh[i]=v0; if (xx==astep) v[i]=v0/2.0; if (xh==astep) vh[i]=v0/2.0; if (xx==-astep) v[i]=v1/2.0; if (xh==-astep) vh[i]=v1/2.0; break; case 4: // Harmonic Potential v[i]=xx*xx*force/2.0; vh[i]=xh*xh*force/2.0; break; case 5: // Morse Potential temp = (1.0 - Math.exp(-aexp*xx)); temph = (1.0 - Math.exp(-aexp*xh)); v[i]=de*temp*temp; vh[i]=de*temph*temph; if (vh[i]>big) vh[i]=big; if (v[i]>big) v[i]=big; break; case 6: // Hydrogen Atom v[i]=-zatomic/Math.abs(xx); vh[i]=-zatomic/Math.abs(xh); if (v[i]<-big) v[i]=-big; if (vh[i]<-big) vh[i]=-big; break; case 7: // Rigid Rotor Potential v[i]=0; vh[i]=0; break; } xx+=dx; xh+=dx; } getMinMax(y); setScale(); } public void saveGraph() { // saves potential graph to an array for (int i=1; i<=nmax; i++) { ysave[i][id]=y[i]; vsave[i][id]=v[i]; xsave[i][id]=x[i]; } esave[id]=eigen; ipotsave[id]=ipot; span[id]=ymax-ymin; potName[id].setText(sname[ipot]); id++; if (id>saves) {id=1;} idt.select(id-1); } public void changeValues(){ // all variables are set the the values currently in the textfields eigen=changeVar (eigent); xmin=changeVar (xmint); xmax=changeVar (xmaxt); yzero=changeVar (yzerot); vzero=changeVar (vzerot); rmass=changeVar (rmasst); v0=changeVar (v0t); astep=changeVar (astept); force=changeVar (forcet); re=changeVar (ret); quantuml=changeInt (quantumlt); zatomic=changeVar (zatomict); ql2=quantuml*(quantuml+1); beta=2*rmass; aexp=Math.sqrt(force/(2.0*de)); dx=(xmax-xmin)/(nmax-1); double xx=xmin; for (int i=1; i<=nmax; i++) { x[i]=xx; xx+=dx; } setSlider(); //eigens.setValue((int)(eigen/escale)); setPotentials(); // The potential may need to be recalculated } public void drawOverlap(Graphics g) { // used for plotting options 3-7 int iov1=0; int iov2=0; int k=1; for (int i=1; i<=saves; i++) { if (savec[i].getState()) { if (k==1) iov1=i; if (k==2) iov2=i; k++; } } // finds two functions to overlap if (k==2) iov2=iov1; // if only one is checked, use that with itself if (k==1) { iov1=1; iov2=1; } // if none are checkd, default to 1 to avoid errors double deltax=x[2]-x[1]; for (int j=1; j<=nmax; j++) { y[j]=ysave[j][iov1]; t[j]=ysave[j][iov2]; x[j]=xsave[j][iov1]; double xx=1.0; if (ipotsave[iov1]==6) xx=x[j]*x[j]; if (ipotsave[iov1]==7) xx=Math.sin(x[j]); if (savep==3) p[j]=y[j]*t[j]*xx; // Overlap functions else if (savep==4) p[j]=y[j]*t[j]*x[j]*xx; // Average x else if (savep==5) p[j]=y[j]*t[j]*x[j]*x[j]*xx; // Average x^2 else if (savep==6) { // Average d/dx if (j==1) dx=(4*y[2]-3*y[1]-y[3])/(2*deltax); else if (j==nmax) dx=(y[nmax-2]+3*y[nmax]-4*y[nmax-1])/(2*deltax); else dx=(y[j+1]-y[j-1])/(2*deltax); p[j]=y[j]*t[j]*dx*xx; } else if (savep==7) { // Average potential difference t[j]=vsave[j][iov2]-vsave[j][iov1]; p[j]=y[j]*y[j]*t[j]*xx; } } overLapMinMax(iov1, iov2); // Find the absolute min/max from all the different graphs setScale(); setPlot(g); plot(x, y, Color.darkGray, false, g); plot(x, t, Color.gray, false, g); plot(x, p, Color.blue, true, g); double onorm=simpson(nmax, deltax, p); if (savep==3) s="Overlap of "+iov1+" with "+iov2+" is "; else if (savep==4) { if (iov1==iov2) { if (ipotsave[iov1]==6) s="Average radius of "+iov1+" is "; else s="Average x of "+iov1+" is "; } else s="Transition Dipole of "+iov1+ " to "+iov2+" is "; } else if (savep==5) { if (ipotsave[iov1]==6) s="Average radius^2 of "+iov1+" to "+iov2+" is "; else s="Average x^2 of "+iov1+" to "+iov2+" is "; } else if (savep==6) { if (ipotsave[iov1]==6) s="Average radius(dx) of "+iov1+" to "+iov2+" is "; else s="Average d/dx of "+iov1+" to "+iov2+" is "; } else if (savep==7) s="Av Potential "+iov1+" minus "+iov2+" is "; s=cropString(s, onorm, 8); g.setColor(Color.black); g.drawString(s, 10, MAXY+22); if (!((xsave[1][iov1]==xsave[1][iov2]) && (xsave[nmax][iov1]==xsave[nmax][iov2]))) { s="Error: x values are not the same"; g.setColor(Color.red); g.drawString(s, 10, MAXY+37); } } public void drawSaved(Graphics g) { // displays saved wave-functions along with their eigen values savedMinMax(); // find the min/max saved values double sp=ymax-ymin; ymin-=sp*fac; ymax+=sp*1.5*fac; // add a little more room at the top and bottom setScale(); setPlot(g); for (int j=1; j<=saves; j++) { if (savec[j].getState()) { // check to see if the checkbox is checked int yl=(int)(offsety + scaley*(ymax-esave[j])); int xl=(int)(offsetx + scalex*(x[nmax]-xmin)); g.setColor(Color.gray); g.drawLine((int)offsetx, yl, xl, yl); // graph the eigen value at the appropriate height for (int i=1; i<=nmax; i++) { x[i]=xsave[i][j]; if (savep==1) y[i]=ysave[i][j]*sp*fac/span[j]+esave[j]; // graph the function on its eigen value within the // span allowed by the graph else if (savep==2) { if (ipot==6) y[i]= xsave[i][j]*xsave[i][j]*ysave[i][j]*ysave[i][j]*sp*fac/span[j]+esave[j]; else if (ipot==7) y[i]= ysave[i][j]*ysave[i][j]*Math.sin(xsave[i][j])*sp*fac/span[j]+esave[j]; else y[i]=ysave[i][j]*ysave[i][j]*sp*fac/span[j]+esave[j]; } v[i]=vsave[i][j]; } if (savep==1) plot (x, y, Color.black, false, g); else if (savep==2) plot (x, y, Color.red, false, g); plot (x, v, Color.blue, true, g); // plot the potential for the first save graph checked f = new Font("SansSerif", Font.PLAIN, 12); fm=g.getFontMetrics(f); s=cropString("eigen=", esave[j], 8); xl=MAXX-fm.stringWidth(s)-2; yl=(int)(offsety + scaley*(ymax-esave[j])); g.setColor(new Color(32, 128, 0)); g.drawString(s,xl,yl-2); // display the eigen value for the first saved graph checked } } } public void hydrogen(Graphics g) { // special integration routine used for hyrogren double rn=quantuml+1; double zeta=zatomic/rn; double r=x[nmax]; double yy=yzero*Math.pow(r, rn)*Math.exp(-zeta*r); double dy=vzero*(rn-zeta*r)*Math.pow(r, rn-1)*Math.exp(-zeta*r); double dy2=-beta*(eigen-(-zatomic/r)-ql2/(beta*r*r))*yy/2.0; double p0=yy; double p1=yy; double p2=yy; dxx=-1.0*dx/knumber; y[nmax]=yy/r; for (int i=2; i<=nmax; i++) { r=x[nmax-i+2]; for (int k=1; k<=knumber; k++) { dy+=dy2*dxx; yy+=dy*dxx; r+=dxx; if (!(r==0)) dy2=-beta*(eigen-(-zatomic/r)-ql2/(beta*r*r))*yy; p2=p1; p1=p0; p0=yy; } if (i==nmax) { y[1]=2.0*p1/(xmin-dxx) - p2/(xmin-2.0*dxx); yp=yy; } else y[nmax-i+1]=yy/r; } if (!norm) basicPlot(g); else normalize(g); } public void rigid(Graphics g) { // special integration routine used for the rigid rotor potential int m; double xx=xmin; m=(int)v0; double ii=zatomic; // the variables originally labeled v0 and zatomic are used for the // variables m and I in the Rigid Rotor potential dxx=dx/knumber; double yy=0.0; yy=Math.sin(dxx/2.0)/2.0; // A good guess for the intial y value if (m==0) yy=1.0; if (m==1) yy=0.0; if (m==2) yy=0.0; // we know the exact values for 0<=m<=2 double dy=0.0; dy=m*Math.pow(Math.sin(dxx/2.0), m-1)* Math.cos(dxx/2.0)/2.0; // a good guess for the initial dy value if (m==0) dy=0.0; if (m==1) dy=1.0; if (m==2) dy=0.0; // we know the exact values for 0<=m<=2 double dy2=0.0; dy2=m*((m-1)*Math.pow(Math.sin(dxx/2.0), m-2)* Math.pow(Math.cos(dxx/2.0), 2)-m*Math.sin(dxx/2.0)); // using the sin^m solution, we can guess at initial dy^2 if (m==0) dy2=-1.0; if (m==1) dy2=0.0; if (m==2) dy2=1.0; // we know the exact values for 0<=m<=2 double sx; double cx; dy2*=0.5; // dy^2 is halved for the first point y[1]=yy; for (int i=1; i<=nmax; i++) { for (int k=1;k<=knumber; k++) { xx+=dxx; dy+=dy2*dxx; yy+=dy*dxx; sx=Math.sin(xx); cx=Math.cos(xx); dy2=yy*((m*m)/(sx*sx)-2.0*ii*eigen)-dy*(cx/sx); } y[i]=yy; } y[nmax]=4*y[nmax-1]-6*y[nmax-2]+4*y[nmax-3]-1*y[nmax-4]; // use interpolation to find a better value for the last point if (!norm) { basicPlot(g); double i=Math.sqrt(1+8.0*zatomic*eigen); s=cropString("l value = ", (i-1)/2.0, 8); s=s+" ~= "+(int)(i/2.0); // displays the integer l value g.drawString(s, 10, MAXY+22); } else normalize(g); } public double average(int n, double dx, double[] xx, double[] pp) { // finds the integration average double[] tt=new double[nmax+1]; for (int i=1; i<=n; i++) { tt[i]=xx[i]*pp[i]; } return simpson(n, dx, tt); } public double simpson (int n, double dx, double[] f) { // simpsons rule for integration double sumeven=0; double sumodd=0; for (int i=2; i<=n-1; i+=2) { sumeven+=f[i]; } for (int i=3; i<=n-2; i+=2) { sumodd+=f[i]; } return dx*(f[1]+f[n]+4.0*sumeven+2.0*sumodd)/3.0; } public void correctFunction() { getMinMax(y); for (int i=1; i<=nmax; i++) { if (y[i]>ymaxa) y[i]=ymaxa; if (y[i]=ymin) && (y[i-1]<=ymax) && (y[i-1]>=ymin)) { // only plot if the line is on the screen g.drawLine(xx, yy, xl, yl); if (big) g.drawLine (xx, yy-1, xl, yl-1); } xl=xx; yl=yy; } } public void setPlot (Graphics g) { // blanks the screen, draws axis, hatch marks, and labels the graph g.setColor(Color.white); g.fillRect(0, 0, MAXX, MAXY+70); // erase the screen g.setColor(Color.black); g.drawLine(0, MAXY+5, MAXX, MAXY+5); g.drawLine(0, MAXY+3, MAXX, MAXY+3); // draw the divider separating the drawing and info windows int x0=(int)(offsetx - scalex*xmin); int y0=(int)(offsety + scaley*ymax); int xend=(int)(MAXX-offsetx); g.drawLine (xend,y0,(int)offsetx,y0); // plot the x axis for (int s=x0; s<=xend; s+=20) { g.drawLine (s, y0, s, y0+4); } for (int s=x0; s>=offsetx; s-=20) { g.drawLine (s, y0, s, y0+4); } // draw hatch marks int yend=(int)(MAXY-offsety); g.drawLine (x0,yend,x0,(int)offsety); // plot the y axis for (int s=y0; s<=yend; s+=20) { g.drawLine (x0, s, x0+4, s); } for (int s=y0; s>=offsety; s-=20) { g.drawLine (x0, s, x0+4, s); } // draw hatch marks int l; f = new Font("SansSerif", Font.PLAIN, 12); fm=g.getFontMetrics(f); s=cropString("eigen=", eigen, 8); g.drawString(s,2,14); s=cropString("ymax=", ymaxa, 8); g.drawString(s, x0,(int)offsety-3); s=cropString("ymin=", ymina, 8); g.drawString(s, x0,(int)(MAXY-(offsety/2)-3)); s=cropString("xmax=", xmax, 6); int i=MAXX-fm.stringWidth(s)-2; int h=MAXY-3; g.drawString(s, i, h); s=cropString("xmin=", xmin, 6); g.drawString(s, 3, h); s=sname[ipot]; i=(int)((MAXX-fm.stringWidth(s))/2.0); g.drawString(s, i, h); // label the graph appropriately } public void basicPlot(Graphics g) { // basic routine for plotting wave-functions basicMinMax(); setScale(); setPlot (g); plot(x, y, Color.black, false, g); } public void graphPotential(Graphics g) { // graphs the potential getMinMax(v); setScale(); setPlot(g); plot(x, v, Color.blue, true, g); } public void setSlider() { // adjusts the eigen value range //eoffset=Double.valueOf(defVar[13][ipot]).doubleValue(); //erange=Double.valueOf(defVar[14][ipot]).doubleValue(); eoffset=eigen; if (eigen>0) erange=eoffset; if (eigen<0) erange=-eoffset; eigens.setValues((int)(eigen/escale), 0, (int)(-2*erange/escale+eoffset/escale), (int)(2*erange/escale+eoffset/escale)); } public void overLapMinMax(int iov1, int iov2) { // Finds the min and max for the wide range of graphs // used in the graph overlap xmin=xsave[1][iov1]; xmax=xsave[nmax][iov1]; ymin=0; ymax=0; for (int j=1; j<=nmax; j++) { if (y[j]>ymax) ymax=y[j]; if (y[j]ymax) ymax=t[j]; if (t[j]ymax) ymax=p[j]; if (p[j]ymax) ymax=esave[j]; if (esave[j]xmax) xmax=xsave[nmax][j]; if (xsave[1][j]ymax) ymax=my; if (ipot==7) symRange(); // Rigid rotor has symettrical ymin/ymax } public void getMinMax(double[] m) { // Finds the min/max values of an array set ymin=0.0; ymax=0.0; for (int i=2; i<=nmax; i++) { if ((m[i]<=ymin) && (m[i]>=m[i-1])) ymin=m[i]; if ((m[i]>=ymax) && (m[i]<=m[i-1])) ymax=m[i]; } ymina=ymin; ymaxa=ymax; fixMinMax(); // makes the min/max a little bit bigger } public void fixMinMax() { // increases the viewing area by adding 10% to the min and max double range=(ymax-ymin); double midp=(ymax+ymin)/2.0; ymin=midp-range*0.55; ymax=midp+range*0.55; if (ymin==ymax) { ymin=-2.0; ymax=2.0; } // if both the min and max are the same, default to -2,2 } public double changeVar (TextField t) { // sets the variable to its textfield value (if possible) double temp; s=t.getText(); try { temp=Double.valueOf(s).doubleValue(); } catch (NumberFormatException e) { temp=errNum; } return temp; } public String cropString(String s, double v, int l) { // crops the number and returns it with the string String ss=""+v; if (ss.length()yymax) ymax=yymax; //if (ymin-ymin) ymin=-ymax; if (-ymin>ymax) ymax=-ymin; } public void blankVars() { // makes sure unused variables have an "N/A" for (int i=1; i<=nvars; i++) { if (defVar[i][ipot].equals("N/A")) var[i]="N/A"; } } public void setNames() { // sets the long and short names for potentials // as well as the different plotting names sname[0]="Error"; sname[1]="Inf.Square"; sname[2]="Inf.Tunnel"; sname[3]="Fin.Sqaure"; sname[4]="Harmonic"; sname[5]="Morse"; sname[6]="Hydrogen"; sname[7]="RigidRotor"; lname[0]="- Select Potential -"; lname[1]="Infinite Square"; lname[2]="Infinite Tunnel"; lname[3]="Finite Sqaure"; lname[4]="Harmonic Potential"; lname[5]="Morse Potential"; lname[6]="Hydrogen Atom"; lname[7]="Rigid Rotor Potential"; pname[0]="Graph Current Solution"; pname[1]="Graph Eigen Values"; pname[2]="Plot Densities"; pname[3]="Overlap Functions"; pname[4]="Average x/Transition Dipole"; pname[5]="Average x^2"; pname[6]="Average d/dx"; pname[7]="Av Potential Difference"; bname[1]="Reset Variables"; bname[2]="Satisfy Boundary C"; bname[3]="Potential Graph"; bname[4]="Normalize"; bname[5]="Save Function"; bname[6]="Smooth Function"; bname[7]="Accept Changes"; } public void setDefaults() { // sets the default values for each variable in each potential for (int j=1; j<=npot; j++) { for (int i=7; i<=nvars; i++) { defVar[i][j]="N/A"; // Blank out the unique variables } defVar[4][j]="0.0"; } for (int j=1; j<=3; j++) { defVar[1][j]="1.0"; defVar[2][j]="-2.0"; defVar[3][j]="2.0"; defVar[5][j]="1.0"; defVar[6][j]="1.0"; defVar[13][j]="10.0"; defVar[14][j]="10.0"; } for (int j=2; j<=3; j++) { defVar[5][j]="0.25"; defVar[7][j]="10.0"; defVar[8][j]="0.5"; } defVar[1][3]="2.0"; defVar[12][3]="10.0"; defVar[1][4]="0.01"; defVar[2][4]="-1.5"; defVar[3][4]="1.5"; defVar[5][4]="0.333"; defVar[6][4]="925.26"; defVar[9][4]="0.3299"; defVar[13][4]="0.1"; defVar[14][4]="0.1"; defVar[1][5]="0.01"; defVar[2][5]="-1.4011"; defVar[3][5]="2.0"; defVar[5][5]="0.25"; defVar[6][5]="925.26"; defVar[9][5]="0.3299"; defVar[10][5]="1.4011"; defVar[13][5]="0.1"; defVar[14][5]="0.1"; defVar[1][6]="-0.5"; defVar[2][6]="0.0"; defVar[3][6]="30.0"; defVar[4][6]="1.0"; defVar[5][6]="1.0"; defVar[6][6]="1.0"; defVar[11][6]="0"; defVar[12][6]="1.0"; defVar[13][6]="-0.25"; defVar[14][6]="0.25"; double xm=Math.PI; s=xm+""; defVar[1][7]="2.0"; defVar[2][7]="0.0"; defVar[3][7]=s; defVar[5][7]="0.0"; defVar[6][7]="1.0"; defVar[7][7]="0"; defVar[12][7]="0.5"; defVar[13][7]="50.0"; defVar[14][7]="50.0"; } }