KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > Wavefunction


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 /**
9 * Wavefunction numerically solves the time-independent
10 * Schrödinger equation.
11 * @author Mark Hale
12 * @version 1.2
13 */

14 public final class Wavefunction extends Frame implements Runnable JavaDoc {
15         private final Runnable JavaDoc 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 JavaDoc animateThread=null;
29         /**
30         * Eigenstates.
31         */

32         private final AbstractDoubleVector eigenstates[]=new AbstractDoubleVector[N];
33         /**
34         * Eigenvalues.
35         */

36         private double eigenvalues[];
37         /**
38         * Harmonic coupling.
39         */

40         private double k=0.0;
41         /**
42         * Anharmonic coupling.
43         */

44         private double h=0.0;
45         /**
46         * Kinetic energy operator.
47         */

48         private final DoubleTridiagonalMatrix T=new DoubleTridiagonalMatrix(N);
49         /**
50         * Potential energy operator.
51         */

52         private DoubleDiagonalMatrix V;
53         /**
54         * Runs an instance of Wavefunction.
55         */

56         public static void main(String JavaDoc 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         /**
66         * Constructs Wavefunction.
67         */

68         public Wavefunction() {
69                 super("Wavefunction");
70                 constructKineticEnergyOperator();
71                 calculateHamiltonian();
72                 graph=new LineGraph(model);
73                 graph.setYExtrema(-0.5f,0.5f);
74 // register listeners
75
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 JavaDoc(animator);
124                                         animateThread.start();
125                                         animButton.setLabel("Freeze");
126                                 } else {
127                                         animateThread=null;
128                                         animButton.setLabel("Evolve");
129                                 }
130                         }
131                 });
132 // construct gui
133
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 JavaDoc() {
155                                 public void run() {model.evolve();}
156                         });
157                         try {
158                                 Thread.sleep(100);
159                         } catch(InterruptedException JavaDoc e) {}
160                 }
161         }
162         /**
163         * Updates the status label.
164         */

165         private void updateStatusLabel() {
166                 final int level=model.getLevel();
167                 statusLabel.setText("Energy ["+level+"] = "+(float)eigenvalues[level]);
168         }
169
170         /**
171         * A custom graph model class.
172         * This provides a graph interface onto the eigenstates
173         * and eigenvalues.
174         * There are various methods to alter the data view.
175         */

176         private final class GraphModel extends AbstractGraphModel implements Graph2DModel {
177                 /**
178                 * Time.
179                 */

180                 private double t=0.0;
181                 /**
182                 * Energy level.
183                 */

184                 private int level=0;
185                 /**
186                 * Show probability or amplitude.
187                 */

188                 private boolean showProb=false;
189                 /**
190                 * Series.
191                 */

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 // Solve the Schrodinger equation
263

264         /**
265         * Constructs the kinetic energy operator.
266         */

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         /**
280         * Constructs the Hamiltonian
281         * and solves the Schr&ouml;dinger equation.
282         */

283         private void calculateHamiltonian() {
284                 // potential energy operator
285
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                 // Hamiltonian
290
final AbstractDoubleSquareMatrix H=T.add(V);
291                 // solve
292
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         /**
302         * Potential energy function.
303         */

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         /**
309         * Sorts the eigenstates and eigenvalues.
310         * (Bidirectional bubble sort.)
311         */

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