|
From: <fer...@us...> - 2007-07-28 21:31:24
|
Revision: 3625
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3625&view=rev
Author: fer_perez
Date: 2007-07-28 14:31:18 -0700 (Sat, 28 Jul 2007)
Log Message:
-----------
Add Schrodinger equation example, contributed by James Nagel <na...@me...>
Added Paths:
-----------
trunk/py4science/examples/schrodinger/
trunk/py4science/examples/schrodinger/Schrodinger_FDTD.pdf
trunk/py4science/examples/schrodinger/schrod_fdtd.py
Added: trunk/py4science/examples/schrodinger/Schrodinger_FDTD.pdf
===================================================================
(Binary files differ)
Property changes on: trunk/py4science/examples/schrodinger/Schrodinger_FDTD.pdf
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/py4science/examples/schrodinger/schrod_fdtd.py
===================================================================
--- trunk/py4science/examples/schrodinger/schrod_fdtd.py (rev 0)
+++ trunk/py4science/examples/schrodinger/schrod_fdtd.py 2007-07-28 21:31:18 UTC (rev 3625)
@@ -0,0 +1,258 @@
+#!/usr/bin/env python
+#=============================================================================
+#
+# Quantum Mechanical Simulation using Finite-Difference
+# Time-Domain (FDTD) Method
+#
+# This script simulates a probability wave in the presence of multiple
+# potentials. The simulation is c arried out by using the FDTD algorithm
+# applied to the Schrodinger equation. The program is intended to act as
+# a demonstration of the FDTD algorithm and can be used as an educational
+# aid for quantum mechanics and numerical methods. The simulation
+# parameters are defined in the code constants and can be freely
+# manipulated to see different behaviors.
+#
+# NOTES
+#
+# The probability density plots are amplified by a factor for visual
+# purposes. The psi_p quanity contains the actual probability density
+# without any rescaling.
+#
+# BEWARE: The time step, dt, has strict requirements or else the
+# simulation becomes unstable.
+#
+# The code has three built-in potential functions for demonstration.
+#
+# 1) Constant potential: Demonstrates a free particle with dispersion.
+#
+# 2) Step potential: Demonstrates transmission and reflection.
+#
+# 3) Potential barrier: Demonstrates tunneling.
+#
+# By tweaking the height of the potential (V0 below) as well as the
+# barrier thickness (THCK below), you can see different behaviors: full
+# reflection with no noticeable transmission, transmission and
+# reflection, or mostly transmission with tunneling.
+#
+# This script requires pylab and numpy to be installed with
+# Python or else it will not run.
+#
+#============================================================================
+# Author: James Nagel <na...@me...>
+# 5/25/07
+#
+# Updates by Fernando Perez <Fer...@co...>, 7/28/07
+#============================================================================
+
+# Numerical and plotting libraries
+import numpy as np
+import pylab
+
+# Set pylab to interactive mode so plots update when run outside ipython
+pylab.ion()
+
+#=============================================================================
+
+# Utility functions
+
+# Defines a quick Gaussian pulse function to act as an envelope to the wave
+# function.
+def Gaussian(x,t,sigma):
+ """ A Gaussian curve.
+ x = Variable
+ t = time shift
+ sigma = standard deviation """
+ return np.exp(-(x-t)**2/(2*sigma**2))
+
+def free(npts):
+ "Free particle."
+ return np.zeros(npts)
+
+def step(npts,v0):
+ "Potential step"
+ v = free(npts)
+ v[npts/2:] = v0
+ return v
+
+def barrier(npts,v0,thickness):
+ "Barrier potential"
+ v = free(npts)
+ v[npts/2:npts/2+thickness] = v0
+ return v
+
+#=============================================================================
+#
+# Simulation Constants. Be sure to include decimal points on appropriate
+# variables so they become floats instead of integers.
+#
+N = 1200 # Number of spatial points.
+T = 5*N # Number of time steps. 5*N is a nice value for terminating
+ # before anything reaches the boundaries.
+Tp = 40 # Number of time steps to increment before updating the plot.
+dx = 1.0e0 # Spatial resolution
+m = 1.0e0 # Particle mass
+hbar = 1.0e0 # Plank's constant
+X = dx*np.linspace(0,N,N) # Spatial axis.
+
+# Potential parameters. By playing with the type of potential and the height
+# and thickness (for barriers), you'll see the various transmission/reflection
+# regimes of quantum mechanical tunneling.
+V0 = 1.0e-2 # Potential amplitude (used for steps and barriers)
+THCK = 10 # "Thickness" of the potential barrier (if appropriate
+ # V-function is chosen)
+
+# Uncomment the potential type you want to use here:
+
+# Zero potential, packet propagates freely.
+#POTENTIAL = 'free'
+
+# Potential step. The height (V0) of the potential chosen above will determine
+# the amount of reflection/transmission you'll observe
+#POTENTIAL = 'step'
+
+# Potential barrier. Note that BOTH the potential height (V0) and thickness
+# of the barrier (THCK) affect the amount of tunneling vs reflection you'll
+# observe.
+POTENTIAL = 'barrier'
+
+# Initial wave function constants
+sigma = 40.0 # Standard deviation on the Gaussian envelope (remember Heisenberg
+ # uncertainty).
+x0 = round(N/2) - 5*sigma # Time shift
+k0 = np.pi/20 # Wavenumber (note that energy is a function of k)
+
+#=============================================================================
+# Code begins
+#
+# You shouldn't need to change anything below unless you want to actually play
+# with the numerical algorithm or modify the plotting.
+#
+# Fill in the appropriate potential function (is there a Python equivalent to
+# the SWITCH statement?).
+if POTENTIAL=='free':
+ V = free(N)
+elif POTENTIAL=='step':
+ V = step(N,V0)
+elif POTENTIAL=='barrier':
+ V = barrier(N,V0,THCK)
+else:
+ raise ValueError("Unrecognized potential type: %s" % POTENTIAL)
+
+# More simulation parameters. The maximum stable time step is a function of
+# the potential, V.
+Vmax = max(V) # Maximum potential of the domain.
+dt = hbar/(2*hbar**2/(m*dx**2)+Vmax) # Critical time step.
+c1 = hbar*dt/(m*dx**2) # Constant coefficient 1.
+c2 = 2*dt/hbar # Constant coefficient 2.
+c2V = c2*V # pre-compute outside of update loop
+
+# Print summary info
+print 'One-dimensional Schrodinger equation - time evolution'
+print 'Potential type: ',POTENTIAL
+print 'Potential height V0: ',V0
+print 'Barrier thickness: ',THCK
+
+# Wave functions. Three states represent past, present, and future.
+psi_r = np.zeros((3,N)) # Real
+psi_i = np.zeros((3,N)) # Imaginary
+psi_p = np.zeros(N,) # Observable probability (magnitude-squared
+ # of the complex wave function).
+
+# Temporal indexing constants, used for accessing rows of the wavefunctions.
+PA = 0 # Past
+PR = 1 # Present
+FU = 2 # Future
+
+# Initialize wave function. A present-only state will "split" with half the
+# wave function propagating to the left and the other half to the right.
+# Including a "past" state will cause it to propagate one way.
+xn = range(1,N/2)
+x = X[xn]/dx # Normalized position coordinate
+gg = Gaussian(x,x0,sigma)
+cx = np.cos(k0*x)
+sx = np.sin(k0*x)
+psi_r[PR,xn] = cx*gg
+psi_i[PR,xn] = sx*gg
+psi_r[PA,xn] = cx*gg
+psi_i[PA,xn] = sx*gg
+
+# Initial normalization of wavefunctions
+# Compute the observable probability.
+psi_p = psi_r[PR]**2 + psi_i[PR]**2
+
+# Normalize the wave functions so that the total probability in the simulation
+# is equal to 1.
+P = dx * psi_p.sum() # Total probability.
+nrm = np.sqrt(P)
+psi_r /= nrm
+psi_i /= nrm
+psi_p /= P
+
+# Initialize the figure and axes.
+pylab.figure()
+ymax = 1.5*(psi_r[PR]).max()
+pylab.axis([X.min(),X.max(),-ymax,ymax])
+
+# Initialize the plots with their own line objects. The figures plot MUCH
+# faster if you simply update the lines as opposed to redrawing the entire
+# figure. For reference, include the potential function as well.
+lineR, = pylab.plot(X,psi_r[PR],'b',alpha=0.7) # "Real" line
+lineI, = pylab.plot(X,psi_i[PR],'r',alpha=0.7) # "Imag" line.
+lineP, = pylab.plot(X,psi_p,'k') # "Probability" line
+pylab.title('Potential height: %.2e' % V0)
+pylab.legend(('Real','Imag','Prob'))
+
+# For non-zero potentials, plot them and shade the classically forbidden region
+# in light red
+if V.max() !=0 :
+ V_plot = V/V.max()*ymax/2
+ pylab.plot(X,V_plot,':k',zorder=0) # Potential line.
+ # reverse x and y2 so the polygon fills in order
+ y1 = free(N) # lower boundary for polygon drawing
+ x = np.concatenate( (X,X[::-1]) )
+ y = np.concatenate( (y1,V_plot[::-1]) )
+ pylab.fill(x, y, facecolor='y', alpha=0.2,zorder=0)
+pylab.draw()
+
+# Direct index assignment is MUCH faster than using a spatial FOR loop, so
+# these constants are used in the update equations. Remember that Python uses
+# zero-based indexing.
+IDX1 = range(1,N-1) # psi [ k ]
+IDX2 = range(2,N) # psi [ k + 1 ]
+IDX3 = range(0,N-2) # psi [ k - 1 ]
+
+for t in range(0,T+1):
+ # Apply the update equations.
+ psi_i[FU,IDX1] = psi_i[PA,IDX1] + \
+ c1*(psi_r[PR,IDX2] - 2*psi_r[PR,IDX1] +
+ psi_r[PR,IDX3])
+ psi_i[FU] = psi_i[FU] - c2V*psi_r[PR]
+
+ psi_r[FU,IDX1] = psi_r[PA,IDX1] - \
+ c1*(psi_i[PR,IDX2] - 2*psi_i[PR,IDX1] +
+ psi_i[PR,IDX3])
+ psi_r[FU] = psi_r[FU] + c2V*psi_i[PR]
+
+ # Increment the time steps. PR -> PA and FU -> PR
+ psi_r[PA] = psi_r[PR]
+ psi_r[PR] = psi_r[FU]
+ psi_i[PA] = psi_i[PR]
+ psi_i[PR] = psi_i[FU]
+
+ # Only plot after a few iterations to make the simulation run faster.
+ if t % Tp == 0:
+ # Compute observable probability for the plot.
+ psi_p = psi_r[PR]**2 + psi_i[PR]**2
+
+ # Update the plots.
+ lineR.set_ydata(psi_r[PR])
+ lineI.set_ydata(psi_i[PR])
+ # Note: we plot the probability density amplified by a factor so it's a
+ # bit easier to see.
+ lineP.set_ydata(6*psi_p)
+
+ pylab.draw()
+
+# So the windows don't auto-close at the end if run outside ipython
+pylab.ioff()
+pylab.show()
Property changes on: trunk/py4science/examples/schrodinger/schrod_fdtd.py
___________________________________________________________________
Name: svn:executable
+ *
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|