Computational Physics Sheet 6, Computational Physics Course 17105 Professor: H. Ruhl, Exercises: N. Moschüring and N. Elkina Discussion of Solutions: Dec 03, 01, Room A49 Problem 1: Yee solver for Schrödinger s equation in 3D Write a C-program for a FDTD solver of the free Schrödinger equation with periodic boundary conditions in 3D. Assume that ψ( x, 0) = e x w x e y w y e z w z e ikx0x (1) holds, where w x, w y, and w z determine the widths of the Gaussian wave packet and k x0 is the initial momentum of the wave. Solution 1: Yee solver for Schrödinger s equation in 3D Header file for implementation: code/schroedinger.h // // s c h r o e d i n g e r. h // Uebungen Computational Physics 01/13 // // Created by N i l s Moschuering on 6. 1 1. 1. // n i l s. moschuering@physik. uni muenchen. de // // f i e l d component i d e n t i f i e r s enum PSIRE, PSIIM, NR COMPS, ; #define sqr ( x ) ( ( x ) ( x ) ) // i d e n t i f i e r s f o r t he d i f f e r e n t boundaries // unused f o r s c h r o e d i n g e r f i e l d s enum BND REFLECT, BND PERIODIC, BND PML, BND UPML, ; //macro to l i n e a r i z e 3d space #define F3 OFF( pf, f l d n r, jx, jy, j z ) \ ( ( ( ( ( ( f l d n r ) \
( pf ) >im [ ] + ( ( j z ) (pf ) >ib [ ] ) ) \ ( pf ) >im [ 1 ] + ( ( jy ) (pf ) >ib [ 1 ] ) ) \ ( pf ) >im [ 0 ] + ( ( jx ) (pf ) >ib [ 0 ] ) ) ) ) #define F3( pf, f l d n r, jx, jy, j z ) \ ( ( ( pf ) >data ) [ F3 OFF( pf, f l d n r, jx, jy, j z ) ] ) //macro to perform l o o p i n g over whole 3d space with c o r r e c t argument order // g h o s t c e l l s may be omitted v i a l = r = 0 // x i s the f a s t e s t changing dimension ( compare to F3 macro ) #define f o r e a c h 3 d ( ix, iy, iz, l, r ) \ int i l o [ 3 ] = l, l, l ; \ int i h i [ 3 ] = domain >im [ 0 ] + r, \ domain >im [ 1 ] + r, \ domain >im [ ] + r ; \ for ( int i z = i l o [ ] ; i z < i h i [ ] ; i z++) \ for ( int i y = i l o [ 1 ] ; i y < i h i [ 1 ] ; i y++) \ for ( int i x = i l o [ 0 ] ; i x < i h i [ 0 ] ; i x++) //macro to reduce confusion o f IDEs #define f o r e a c h 3 d e n d \ //macro to perform l o o p i n g over whole 3d space with c o r r e c t argument order // g h o s t c e l l s are i n c l u d e d // x i s the f a s t e s t changing dimension ( compare to F3 macro ) #define f o r e a c h 3 d g ( ix, iy, i z ) \ int i l o [ 3 ] = domain >ib [ 0 ], domain >ib [ 1 ], domain >ib [ ] ; \ int i h i [ 3 ] = domain >im [ 0 ] + domain >ib [ 0 ], \ domain >im [ 1 ] + domain >ib [ 1 ], \ domain >im [ ] + domain >ib [ ] ; \ for ( int i z = i l o [ ] ; i z < i h i [ ] ; i z++) \ for ( int i y = i l o [ 1 ] ; i y < i h i [ 1 ] ; i y++) \ for ( int i x = i l o [ 0 ] ; i x < i h i [ 0 ] ; i x++) / macro to c r e a t e f u n c t i o n s f o r s t r u c t u r e s c r e a t e : a l l o c a t e s memory f o r the s t r u c t u r e and i n i t i a l i z e s i t to zero d e s t r o y : o p t i o n a l l y c a l l s s u p p l i e d d e s t r o y f u n c t i o n f r e e s memory o f s t r u c t u r e / #define MAKE FUNCS(name, destroy ) \ struct name c r e a t e ##name ( ) \ \ return ( struct name ) c a l l o c ( 1, sizeof ( struct name) ) ; \ \ void d e s t r o y ##name( struct name obj ) \ \ void ( ##name## d e s t r o y ) ( struct name name) = destroy ; \ i f ( ##name## d e s t r o y ) ##name## d e s t r o y ( obj ) ; \
f r e e ( obj ) ; \ // return t r u e i f p o s i t i o n [ x, y, z ] can be found i n s i d e the pml r egion o f the domain #define i n s i d e p m l ( x, y, z ) \ ( ( ( x ) < domain >pml [ 0 ] ) ( ( x ) >= domain >im [ 0 ] domain >pml [ 0 ] ) \ ( ( y ) < domain >pml [ 1 ] ) ( ( y ) >= domain >im [ 1 ] domain >pml [ 1 ] ) \ ( ( z ) < domain >pml [ ] ) ( ( z ) >= domain >im [ ] domain >pml [ ] ) ) // s t r u c t u r e to contain f i e l d information struct f i e l d double data ; int im [ 3 ] ; int ib [ 3 ] ; ; // s t r u c t u r e to hold output information struct output FILE f i l e ; int output every ; // i n t e r v a l l between f i e l d o u t p u t s ; // s t r u c t u r e to hold information about the domain s t r u c t u r e struct domain double length [ 3 ] ; //some normalized box s i z e int im [ 3 ] ; //number o f grid p o i n t s int ib [ 3 ] ; //number o f g h o s t c e l l s ( must be 1) int tmax ; //number o f d e s i r e d t i m e s t e p s int bnds [ 3 ] ; // boundary type in each d i r e c t i o n int pml [ 3 ] ; //pml r e g i o n s i z e in each d i r e c t i o n // i f PMLs a c t i v e : constant c o n d u c t i v i t y in pml r e g i o n s // e l s e : constant c o n d u c t i v i t y everywhere // unused f o r s c h r o e d i n g e r f i e l d s double sigma [ 3 ] ; double s i g m a i [ 3 ] ; ; struct c o e f f double dx [ 3 ] ; double dt ; double eps0 ; ; Source file: code/schroedinger.c // // s c h r o e d i n g e r. c // Uebungen Computational Physics 01/13 // // Created by N i l s Moschuering on 6. 1 1. 1. // n i l s. moschuering@physik. uni muenchen. de
// #include <s t d i o. h> #include <math. h> #include <s t d l i b. h> #include <a s s e r t. h> #include s c h r o e d i n g e r. h // f u n c t i o n to d e s t r o y memory s t r u c t u r e f o r f i e l d information void f r e e f i e l d ( struct f i e l d fp ) f r e e ( fp >data ) ; MAKE FUNCS( f i e l d, f r e e f i e l d ) ; // f u n c t i o n to d e s t r o y memory s t r u c t u r e f o r output information void f r e e o u t p u t ( struct output output ) f c l o s e ( output > f i l e ) ; MAKE FUNCS( output, f r e e o u t p u t ) ; MAKE FUNCS( domain, NULL) ; MAKE FUNCS( c o e f f, NULL) ; // f u n c t i o n to c r e a t e memory s t r u c t u r e f o r f i e l d information void c r e a t e f i e l d d a t a ( struct f i e l d fp, struct domain domain, int nr comps ) int s i z e = nr comps ; for ( int i = 0 ; i < 3 ; i++) fp >im [ i ] = domain >im [ i ] + domain >ib [ i ] ; fp >ib [ i ] = domain >ib [ i ] ; s i z e = fp >im [ i ] ; fp >data = ( double ) c a l l o c ( s i z e, sizeof ( fp >data ) ) ; // v a l u e o f a 3d gaussian ( with maximum at xm, width dxm and frequency f, // f l y i n g in x d i r e c t i o n ) r e a l p a rt // at p o s i t i o n [ xx, yy, z z ] // needed f o r i n i t i a l i z a t i o n i n l i n e double wave 3d re ( double xx, double yy, double zz, double xm, double dxm, double f ) double xr = xx xm [ 0 ] ; double yr = yy xm [ 1 ] ; double zr = zz xm [ ] ; return ( exp( sqr ( xr /dxm [ 0 ] ) ) exp( sqr ( yr /dxm [ 1 ] ) ) exp( sqr ( zr /dxm [ ] ) ) ) cos ( f. M PI ( xr ) ) ;
// v a l u e o f a 3d gaussian ( with maximum at xm, width dxm and frequency f, // f l y i n g in x d i r e c t i o n ) imaginary part // at p o s i t i o n [ xx, yy, z z ] // needed f o r i n i t i a l i z a t i o n i n l i n e double wave 3d im ( double xx, double yy, double zz, double xm, double dxm, double f ) double xr = xx xm [ 0 ] ; double yr = yy xm [ 1 ] ; double zr = zz xm [ ] ; return ( exp( sqr ( xr /dxm [ 0 ] ) ) exp( sqr ( yr /dxm [ 1 ] ) ) exp( sqr ( zr /dxm [ ] ) ) ) s i n ( f. M PI ( xr ) ) ; // p e r i o d i c boundaries f o r f i e l d s ( one g h o s t c e l l ) void exchange PSI ( struct f i e l d fp, int im ) for ( int i z = 0 ; i z < im [ ] ; i z++) for ( int i y = 0 ; i y < im [ 1 ] ; i y++) F3( fp, PSIRE, 1, iy, i z ) = F3( fp, PSIRE, im [ 0 ] 1, iy, i z ) ; F3( fp, PSIIM, 1, iy, i z ) = F3( fp, PSIIM, im [ 0 ] 1, iy, i z ) ; F3( fp, PSIRE, im [ 0 ], iy, i z ) = F3( fp, PSIRE, 0, iy, i z ) ; F3( fp, PSIIM, im [ 0 ], iy, i z ) = F3( fp, PSIIM, 0, iy, i z ) ; for ( int i z = 0 ; i z < im [ ] ; i z++) for ( int i x = 0 ; i x < im [ 0 ] ; i x++) F3( fp, PSIRE, ix, 1, i z ) = F3( fp, PSIRE, ix, im [ 1 ] 1, i z ) ; F3( fp, PSIIM, ix, 1, i z ) = F3( fp, PSIIM, ix, im [ 1 ] 1, i z ) ; F3( fp, PSIRE, ix, im [ 1 ], i z ) = F3( fp, PSIRE, ix, 0, i z ) ; F3( fp, PSIIM, ix, im [ 1 ], i z ) = F3( fp, PSIIM, ix, 0, i z ) ; for ( int i y = 0 ; i y < im [ 1 ] ; i y++) for ( int i x = 0 ; i x < im [ 0 ] ; i x++) F3( fp, PSIRE, ix, iy, 1) = F3( fp, PSIRE, ix, iy, im [ ] 1) ; F3( fp, PSIIM, ix, iy, 1) = F3( fp, PSIIM, ix, iy, im [ ] 1) ; F3( fp, PSIRE, ix, iy, im [ ] ) = F3( fp, PSIRE, ix, iy, 0) ; F3( fp, PSIIM, ix, iy, im [ ] ) = F3( fp, PSIIM, ix, iy, 0) ; void i n i t o u t p u t ( struct output out, struct domain domain, int output every ) out > f i l e = fopen (. / out, wb ) ; f w r i t e (&domain >tmax, sizeof ( domain >tmax ), 1, out > f i l e ) ; f w r i t e ( domain >im, sizeof ( int ), 3, out > f i l e ) ;
f w r i t e (&output every, sizeof ( int ), 1, out > f i l e ) ; out >output every = output every ; // i n i t i a l i z a t i o n o f f i e l d data void i n i t f i e l d ( struct f i e l d fp, struct c o e f f c o e f f, struct domain domain ) double x0 [ 3 ] =. 5,. 5,. 5 ; double sigma [ 3 ] =. 1 5,. 1 5,. 1 5 ; double f r e q = 5. ; f o r e a c h 3 d g ( ix, iy, i z ) F3( fp, PSIRE, ix, iy, i z ) = wave 3d re ( i x c o e f f >dx [ 0 ], i y c o e f f >dx [ 1 ], i z c o e f f >dx [ ], x0, sigma, f r e q ) ; F3( fp, PSIIM, ix, iy, i z ) = wave 3d im ( i x c o e f f >dx [ 0 ], i y c o e f f >dx [ 1 ], i z c o e f f >dx [ ], x0, sigma, f r e q ) ; f o r e a c h 3 d e n d ; // output a b s o l u t e v a l u e o f wave f u n c t i o n to f i l e void output data ( struct output output, int t, struct f i e l d fp, struct domain domain ) i f ( ( t % output >output every ) == 0) f o r e a c h 3 d ( ix, iy, iz, 0, 0) double a b s v a l u e = sqr (F3( fp, PSIRE, ix, iy, i z ) ) + sqr (F3( fp, PSIIM, ix, iy, i z ) ) ; f w r i t e (& abs value, sizeof ( double ), 1, output > f i l e ) ; // f w r i t e (&F3( fp, PSIRE, ix, iy, i z ), s i z e o f ( double ), 1, output > f i l e ) ; f o r e a c h 3 d e n d ; // s p a t i a l and temporal s t e p s i z e c a l c u l a t i o n in 3d void i n i t c o e f f ( struct c o e f f c o e f f, struct domain domain ) for ( int i = 0 ; i < 3 ; i ++) c o e f f >dx [ i ] = domain >l e n g t h [ i ] / domain >im [ i ] ; double inv sum = 0. ; for ( int d=0;d<3;d++) i f ( domain >im [ d ] > 1) inv sum += sqr ( 1. / ( c o e f f >dx [ d ] c o e f f >dx [ d ] ) ) ; a s s e r t ( inv sum ) ; // Simulation has 0 dimensions c o e f f >dt = 0. 5 s q r t ( 1. / inv sum ) ; // courant f a c t o r a p p a r e n t l y needs to very low c o e f f >eps0 = 1. ; // i n i t i a l i z e your s i m u l a t i o n domain
void i n i t d o m a i n ( struct domain domain ) domain >length [ 0 ] = 1. ; domain >length [ 1 ] = 1. ; domain >length [ ] = 1. ; domain >im [ 0 ] = 5 0 ; domain >im [ 1 ] = 5 0 ; domain >im [ ] = 5 0 ; domain >ib [ 0 ] = 1 ; domain >ib [ 1 ] = 1 ; domain >ib [ ] = 1 ; domain >tmax = 00; domain >bnds [ 0 ] = BND PERIODIC ; domain >bnds [ 1 ] = BND PERIODIC ; domain >bnds [ ] = BND PERIODIC ; // unused double sigma = 3 0. ; domain >sigma [ 0 ] = sigma ; domain >sigma [ 1 ] = sigma ; domain >sigma [ ] = sigma ; domain >s i g m a i [ 0 ] = sigma ; domain >s i g m a i [ 1 ] = sigma ; domain >s i g m a i [ ] = sigma ; domain >pml [ 0 ] = 7 ; domain >pml [ 1 ] = 7 ; domain >pml [ ] = 7 ; ; int main ( int argc, char argv ) // c r e a t e and i n i t i a l i z e s t r u c t u r e s struct domain domain = create domain ( ) ; i n i t d o m a i n ( domain ) ; struct c o e f f c o e f f i c i e n t s = c r e a t e c o e f f ( ) ; i n i t c o e f f ( c o e f f i c i e n t s, domain ) ; struct output output = c r e a t e o u t p u t ( ) ; int output every = 1 0 ; i n i t o u t p u t ( output, domain, output every ) ; struct f i e l d fp = c r e a t e f i e l d ( ) ; c r e a t e f i e l d d a t a ( fp, domain, NR COMPS) ; i n i t f i e l d ( fp, c o e f f i c i e n t s, domain ) ; double cnx = c o e f f i c i e n t s >dt / (. 0 c o e f f i c i e n t s >dx [ 0 ] c o e f f i c i e n t s >dx [ 0 ] ) ; double cny = c o e f f i c i e n t s >dt / (. 0 c o e f f i c i e n t s >dx [ 1 ] c o e f f i c i e n t s >dx [ 1 ] ) ; double cnz = c o e f f i c i e n t s >dt / (. 0 c o e f f i c i e n t s >dx [ ] c o e f f i c i e n t s >dx [ ] ) ; //FDTD i n t e g r a t i o n loop for ( double t = 0 ; t < domain >tmax ; t++)
output data ( output, t, fp, domain ) ; // data output exchange PSI ( fp, domain >im ) ; // p e r i o d i c boundary c o n d i t i o n s // imaginary p a r t update f o r e a c h 3 d ( ix, iy, iz, 0, 0) F3( fp, PSIIM, ix, iy, i z ) += ( cnx (F3( fp, PSIRE, i x +1, iy, i z ). F3( fp, PSIRE, ix, iy, i z ) + F3( fp, PSIRE, ix 1, iy, i z ) ) + cny (F3( fp, PSIRE, ix, i y +1, i z ). F3( fp, PSIRE, ix, iy, i z ) + F3( fp, PSIRE, ix, iy 1, i z ) ) + cnz (F3( fp, PSIRE, ix, iy, i z +1). F3( fp, PSIRE, ix, iy, i z ) + F3( fp, PSIRE, ix, iy, iz 1) ) ) ; f o r e a c h 3 d e n d ; exchange PSI ( fp, domain >im ) ; // p e r i o d i c boundary c o n d i t i o n s // r e a l p a rt update f o r e a c h 3 d ( ix, iy, iz, 0, 0) F3( fp, PSIRE, ix, iy, i z ) = ( cnx (F3( fp, PSIIM, i x +1, iy, i z ). F3( fp, PSIIM, ix, iy, i z ) + F3( fp, PSIIM, ix 1, iy, i z ) ) + cny (F3( fp, PSIIM, ix, i y +1, i z ). F3( fp, PSIIM, ix, iy, i z ) + F3( fp, PSIIM, ix, iy 1, i z ) ) + cnz (F3( fp, PSIIM, ix, iy, i z +1). F3( fp, PSIIM, ix, iy, i z ) + F3( fp, PSIIM, ix, iy, iz 1) ) ) ; f o r e a c h 3 d e n d ; // cleanup d e s t r o y c o e f f ( c o e f f i c i e n t s ) ; d e s t r o y f i e l d ( fp ) ; d e s t r o y o u t p u t ( output ) ; destroy domain ( domain ) ; The following python script can be used to analyze the resulting data: from pylab import import array as ar code/anim.py ion ( ) f = open ( out, rb ) x = ar. array ( i ) x. f r o m f i l e ( f, 5) x = x. t o l i s t ( ) t i m e s t e p s = x [ 0 ] g r i d s i z e = x [ 1 : 4 ] output every = x [ 4 ] t i m e s t e p s = ( ( t i m e s t e p s 1) / output every + 1)
(a) (b) Figure 1: Plot of the real part of a Gaussian wave packet propagating to the right with h = m e = 1, box dimensions L x = L y = L z = 1.0, resolution x = y = z = 0.01, t =.3 10 5, Gaussian packet widths w x = w y = w z = 0.1. Plot (a) gives the real part of the wave packet at t = 0 and plot (b) at t = 300 t. s i z e = t i m e s t e p s g r i d s i z e [ 0 ] g r i d s i z e [ 1 ] g r i d s i z e [ ] x = ar. array ( d ) x. f r o m f i l e ( f, s i z e ) x = array ( x. t o l i s t ( ) ) f. c l o s e ( ) g r i d s i z e. r e v e r s e ( ) x = x. reshape ( timesteps, g r i d s i z e ) #s l i c e in x y d i r e c t i o n image = imshow ( x [ 0 ] [ g r i d s i z e [ 0 ] / ], animated=true ) for i in arange ( 1, t i m e s t e p s ) : raw input ( Wait ) image. s e t d a t a ( x [ i ] [ g r i d s i z e [ 0 ] / ] ) #image. a u t o s c a l e ( ) draw ( ) A plot of the real part can be found in fig. 1. A plot of the absolute value of the wave function can be found in fig.. Problem : Dispersion relation for the Yee solver of Schrödinger s equation Obtain the dispersion relation of the free non-relativistic Schrödinger equation in 3D. Solution : Dispersion relation for the Yee solver of Schrödinger s equation
(a) (b) Figure : Plot of the absolute value of a Gaussian wave packet propagating to the right with h = m e = 1, box dimensions L x = L y = L z = 1.0, resolution x = y = z = 0.01, t =.3 10 5, Gaussian packet widths w x = w y = w z = 0.1. Plot (a) gives the absolute value of the wave packet at t = 0 and plot (b) at t = 300 t. The FDTD discretization for the free Schrödinger equation becomes ψ n+ 1 j,im 1 ψn j,im = + ( ψ n m x j+1,re ψj,re n + ψj 1,Re n ), () ψ n+1 j,re ψn j,re = ( ) m x ψ n+ 1 j+1,im 1 ψn+ j,im + 1 ψn+ j 1,Im. (3) To solve the discrete free Schrödinger equation we make the ansatz We obtain ψ n j,re = ψ 0,Re e i(ωn t kj x), (4) ψ n j,im = ψ 0,Im e i(ωn t kj x). (5) Or alternatively we find ωn t ωn t i e +i e ψ 0,Re t ωn t ωn t i e +i e ψ 0,Im t = hψ 0,Im m = hψ 0,Re m e +ik x + e ik x x, (6) e +ik x + e ik x x. (7) ( ) ( ) ω t k x i ψ 0,Re sin = ψ 0,Im m x sin, (8) ( ) ( ) ω t k x i ψ 0,Im sin = +ψ 0,Re m x sin (9) or alternatively Finally, we obtain ( i sin ( ) ω t sin ( k x m x ) m x sin ( ) ) ( ) k x ) ψre = 0. (10) ψ Im i sin ( ω t ( ) ( ) ( ) ω t k x sin = m x sin 4. (11)
Performing this calculation in 3D leads to the following or ( ) ω t sin ω t ( ) ( ) = m x sin 4 kx x ( ) ( ) + m y sin 4 ky y ( ) ( ) + m z sin 4 kz z ([ ( ) ( ) = arcsin m x sin 4 kx x ( ) ( ) + m y sin 4 ky y ( ) ( ) ] 1 + m z sin 4 kz z. (1) (13) Problems are published in the lecture material. Hence, there is always the chance to work on the problems ahead of time.