1 import java.awt.*; 2 import java.awt.event.*; 3 import JSci.awt.*; 4 import JSci.maths.*; 5 import JSci.maths.matrices.*; 6 import JSci.maths.vectors.*; 7 8 14 public final class Wavefunction extends Frame implements Runnable { 15 private final Runnable animator=this; 16 private final int N=200; 17 private final LineGraph graph; 18 private final GraphModel model=new GraphModel(); 19 private final Label kLabel=new Label("Harmonic coupling"); 20 private final TextField kField=new TextField("0.0",5); 21 private final Label hLabel=new Label("Anharmonic coupling"); 22 private final TextField hField=new TextField("0.0",5); 23 private final Button probButton=new Button("Probability"); 24 private final Button animButton=new Button("Evolve"); 25 private final Label statusLabel=new Label("-",Label.CENTER); 26 private final Button incButton=new Button("+"); 27 private final Button decButton=new Button("-"); 28 private volatile Thread animateThread=null; 29 32 private final AbstractDoubleVector eigenstates[]=new AbstractDoubleVector[N]; 33 36 private double eigenvalues[]; 37 40 private double k=0.0; 41 44 private double h=0.0; 45 48 private final DoubleTridiagonalMatrix T=new DoubleTridiagonalMatrix(N); 49 52 private DoubleDiagonalMatrix V; 53 56 public static void main(String arg[]) { 57 new Wavefunction(); 58 } 59 private static void setDefaultSize(Component c, int defaultWidth, int defaultHeight) { 60 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); 61 final int width = (defaultWidth < screenSize.width) ? defaultWidth : screenSize.width; 62 final int height = (defaultHeight < screenSize.height) ? defaultHeight : screenSize.height; 63 c.setSize(width, height); 64 } 65 68 public Wavefunction() { 69 super("Wavefunction"); 70 constructKineticEnergyOperator(); 71 calculateHamiltonian(); 72 graph=new LineGraph(model); 73 graph.setYExtrema(-0.5f,0.5f); 74 addWindowListener(new WindowAdapter() { 76 public void windowClosing(WindowEvent evt) { 77 dispose(); 78 System.exit(0); 79 } 80 }); 81 incButton.addActionListener(new ActionListener() { 82 public void actionPerformed(ActionEvent evt) { 83 model.incrementLevel(); 84 updateStatusLabel(); 85 } 86 }); 87 decButton.addActionListener(new ActionListener() { 88 public void actionPerformed(ActionEvent evt) { 89 model.decrementLevel(); 90 updateStatusLabel(); 91 } 92 }); 93 kField.addActionListener(new ActionListener() { 94 public void actionPerformed(ActionEvent evt) { 95 k=Double.valueOf(kField.getText()).doubleValue(); 96 calculateHamiltonian(); 97 updateStatusLabel(); 98 } 99 }); 100 hField.addActionListener(new ActionListener() { 101 public void actionPerformed(ActionEvent evt) { 102 h=Double.valueOf(hField.getText()).doubleValue(); 103 calculateHamiltonian(); 104 updateStatusLabel(); 105 } 106 }); 107 probButton.addActionListener(new ActionListener() { 108 public void actionPerformed(ActionEvent evt) { 109 if(model.isShowingProbability()) { 110 model.showAmplitude(); 111 graph.setYExtrema(-0.5f,0.5f); 112 probButton.setLabel("Probability"); 113 } else { 114 model.showProbability(); 115 graph.setYExtrema(0.0f,0.25f); 116 probButton.setLabel("Amplitude"); 117 } 118 } 119 }); 120 animButton.addActionListener(new ActionListener() { 121 public void actionPerformed(ActionEvent evt) { 122 if(animateThread==null) { 123 animateThread=new Thread (animator); 124 animateThread.start(); 125 animButton.setLabel("Freeze"); 126 } else { 127 animateThread=null; 128 animButton.setLabel("Evolve"); 129 } 130 } 131 }); 132 Panel levelPanel=new Panel(); 134 levelPanel.setLayout(new GridLayout(2,1)); 135 levelPanel.add(incButton); 136 levelPanel.add(decButton); 137 Panel optPanel=new Panel(); 138 optPanel.add(kLabel); 139 optPanel.add(kField); 140 optPanel.add(hLabel); 141 optPanel.add(hField); 142 optPanel.add(probButton); 143 optPanel.add(animButton); 144 add(statusLabel,"North"); 145 add(graph,"Center"); 146 add(levelPanel,"East"); 147 add(optPanel,"South"); 148 setDefaultSize(this, 650, 450); 149 updateStatusLabel(); 150 setVisible(true); 151 } 152 public void run() { 153 while(animateThread==Thread.currentThread()) { 154 EventQueue.invokeLater(new Runnable () { 155 public void run() {model.evolve();} 156 }); 157 try { 158 Thread.sleep(100); 159 } catch(InterruptedException e) {} 160 } 161 } 162 165 private void updateStatusLabel() { 166 final int level=model.getLevel(); 167 statusLabel.setText("Energy ["+level+"] = "+(float)eigenvalues[level]); 168 } 169 170 176 private final class GraphModel extends AbstractGraphModel implements Graph2DModel { 177 180 private double t=0.0; 181 184 private int level=0; 185 188 private boolean showProb=false; 189 192 private final static int SERIES_WAVEFUNCTION=0; 193 private final static int SERIES_POTENTIAL=1; 194 private int series=SERIES_WAVEFUNCTION; 195 196 public GraphModel() {} 197 public float getXCoord(int i) { 198 return i*2.0f/(N-1)-1.0f; 199 } 200 public float getYCoord(int i) { 201 if(series==SERIES_WAVEFUNCTION) { 202 final double amp=eigenstates[level].getComponent(i); 203 if(showProb) 204 return (float)(amp*amp); 205 else 206 return (float)(amp*Math.cos(eigenvalues[level]*t)); 207 } else if(series==SERIES_POTENTIAL) 208 return (float)(V.getElement(i,i)-eigenvalues[level]); 209 else 210 return 0.0f; 211 } 212 public void resetTime() { 213 t=0.0; 214 fireGraphSeriesUpdated(SERIES_WAVEFUNCTION); 215 } 216 public void evolve() { 217 t+=2.0; 218 fireGraphSeriesUpdated(SERIES_WAVEFUNCTION); 219 } 220 public void incrementLevel() { 221 if(level<N-1) 222 level++; 223 fireGraphSeriesUpdated(series); 224 } 225 public void decrementLevel() { 226 if(level>0) 227 level--; 228 fireGraphSeriesUpdated(series); 229 } 230 public int getLevel() { 231 return level; 232 } 233 public void showAmplitude() { 234 showProb=false; 235 fireGraphSeriesUpdated(SERIES_WAVEFUNCTION); 236 } 237 public void showProbability() { 238 showProb=true; 239 fireGraphSeriesUpdated(SERIES_WAVEFUNCTION); 240 } 241 public boolean isShowingAmplitude() { 242 return !showProb; 243 } 244 public boolean isShowingProbability() { 245 return showProb; 246 } 247 public int seriesLength() { 248 return N; 249 } 250 public void firstSeries() { 251 series=SERIES_WAVEFUNCTION; 252 } 253 public boolean nextSeries() { 254 series++; 255 if(series>1) 256 return false; 257 else 258 return true; 259 } 260 } 261 262 264 267 private void constructKineticEnergyOperator() { 268 T.setElement(0,0,2.0); 269 T.setElement(0,1,-1.0); 270 int i=1; 271 for(;i<N-1;i++) { 272 T.setElement(i,i-1,-1.0); 273 T.setElement(i,i,2.0); 274 T.setElement(i,i+1,-1.0); 275 } 276 T.setElement(i,i-1,-1.0); 277 T.setElement(i,i,2.0); 278 } 279 283 private void calculateHamiltonian() { 284 final double pot[]=new double[N]; 286 for(int i=0;i<N;i++) 287 pot[i]=potential(i); 288 V=new DoubleDiagonalMatrix(pot); 289 final AbstractDoubleSquareMatrix H=T.add(V); 291 try { 293 eigenvalues=LinearMath.eigenSolveSymmetric(H,eigenstates); 294 } catch(MaximumIterationsExceededException e) { 295 System.err.println(e.getMessage()); 296 System.exit(-1); 297 } 298 sortStates(); 299 model.resetTime(); 300 } 301 304 private double potential(int i) { 305 final double x=model.getXCoord(i); 306 return k*x*x+h*x*x*x*x; 307 } 308 312 private void sortStates() { 313 int i; 314 int limit=eigenstates.length; 315 int st=-1; 316 AbstractDoubleVector vec; 317 double val; 318 while(st<limit) { 319 boolean flipped=false; 320 st++; 321 limit--; 322 for(i=st;i<limit;i++) { 323 if(eigenvalues[i]>eigenvalues[i+1]) { 324 vec=eigenstates[i]; 325 val=eigenvalues[i]; 326 eigenstates[i]=eigenstates[i+1]; 327 eigenvalues[i]=eigenvalues[i+1]; 328 eigenstates[i+1]=vec; 329 eigenvalues[i+1]=val; 330 flipped=true; 331 } 332 } 333 if(!flipped) 334 return; 335 for(i=limit;--i>=st;) { 336 if(eigenvalues[i]>eigenvalues[i+1]) { 337 vec=eigenstates[i]; 338 val=eigenvalues[i]; 339 eigenstates[i]=eigenstates[i+1]; 340 eigenvalues[i]=eigenvalues[i+1]; 341 eigenstates[i+1]=vec; 342 eigenvalues[i+1]=val; 343 flipped=true; 344 } 345 } 346 if(!flipped) 347 return; 348 } 349 } 350 } 351 352 | Popular Tags |