Ian Jauslin
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'figs/animation')
-rw-r--r--figs/animation/FN_base.jl170
-rw-r--r--figs/animation/Makefile12
-rw-r--r--figs/animation/animate.py127
-rw-r--r--figs/animation/animate_compute.jl66
4 files changed, 375 insertions, 0 deletions
diff --git a/figs/animation/FN_base.jl b/figs/animation/FN_base.jl
new file mode 100644
index 0000000..af2a1ee
--- /dev/null
+++ b/figs/animation/FN_base.jl
@@ -0,0 +1,170 @@
+# fractional power with an arbitrary branch cut
+function pow(x,a,cut)
+ if(angle(x)/cut<=1)
+ return(abs(x)^a*exp(1im*angle(x)*a))
+ else
+ return(abs(x)^a*exp(1im*(angle(x)-sign(cut)*2*pi)*a))
+ end
+end
+
+# asymptotic airy functions
+# specify a branch cut for the fractional power
+function airyai_asym(x,cut)
+ if(abs(real(pow(x,3/2,cut)))<airy_threshold)
+ return(exp(2/3*pow(x,3/2,cut))*airyai(x))
+ else
+ ret=0
+ for n in 0:airy_order
+ ret+=gamma(n+5/6)*gamma(n+1/6)*(-3/4)^n/(4*pi^(3/2)*factorial(n)*pow(x,3*n/2+1/4,cut))
+ end
+ return ret
+ end
+end
+function airyaiprime_asym(x,cut)
+ if(abs(real(pow(x,3/2,cut)))<airy_threshold)
+ return(exp(2/3*pow(x,3/2,cut))*airyaiprime(x))
+ else
+ ret=0
+ for n in 0:airy_order
+ ret+=gamma(n+5/6)*gamma(n+1/6)*(-3/4)^n/(4*pi^(3/2)*factorial(n))*(-1/pow(x,3*n/2-1/4,cut)-(3/2*n+1/4)/pow(x,3*n/2+5/4,cut))
+ end
+ return ret
+ end
+end
+
+# solutions of (-\Delta+V-ip)phi=0
+# assume that p has an infinitesimal real part (and adjust the branch cuts appropriately)
+function phi(p,x,E,V)
+ return(airyai_asym(exp(-1im*pi/3)*(E^(1/3)*x-E^(-2/3)*(V-1im*p)),pi))
+end
+function dphi(p,x,E,V)
+ return(exp(-1im*pi/3)*E^(1/3)*airyaiprime_asym(exp(-1im*pi/3)*(E^(1/3)*x-E^(-2/3)*(V-1im*p)),pi))
+end
+function eta(p,x,E,V)
+ return(exp(-1im*pi/3)*airyai_asym(-(E^(1/3)*x-E^(-2/3)*(V-1im*p)),pi/2))
+end
+function deta(p,x,E,V)
+ return(-exp(-1im*pi/3)*E^(1/3)*airyaiprime_asym(-(E^(1/3)*x-E^(-2/3)*(V-1im*p)),pi/2))
+end
+
+# Laplace transform of psi
+# assume that p has an infinitesimal real part (and adjust the branch cuts appropriately)
+# for example, (1im*p-V)^(3/2) becomes pow(1im*p-V,3/2,-pi/2) because when 1im*p is real negative, its square root should be imaginary positive
+function f(p,x,k0,E,V)
+ T=2im*k0/(1im*k0-sqrt(V-k0*k0))
+ R=T-1
+
+ if x>=0
+ C2=-1im*T/(pow(-1im*p,1/2,pi/2)*phi(p,0,E,V)-dphi(p,0,E,V))*((sqrt(V-k0*k0)+pow(-1im*p,1/2,pi/2))/(-1im*p+k0*k0)-2im*E^(-1/3)*pi*quadgk(y -> (pow(-1im*p,1/2,pi/2)*eta(p,0,E,V)-deta(p,0,E,V))*phi(p,y,E,V)*exp(-sqrt(V-k0*k0)*y)*exp(2im/3*(pow(E^(1/3)*y+E^(-2/3)*(1im*p-V),3/2,-pi/2)-E^(-1)*pow(1im*p-V,3/2,-pi/2))),0,Inf)[1])
+ FT=2*E^(-1/3)*pi*(quadgk(y -> phi(p,x,E,V)*eta(p,y,E,V)*exp(-sqrt(V-k0*k0)*y)*exp(2im/3*(pow(E^(1/3)*x+E^(-2/3)*(1im*p-V),3/2,-pi/2)-pow(E^(1/3)*y+E^(-2/3)*(1im*p-V),3/2,-pi/2))),0,x)[1]+quadgk(y -> eta(p,x,E,V)*phi(p,y,E,V)*exp(-sqrt(V-k0*k0)*y)*exp(2im/3*(pow(E^(1/3)*y+E^(-2/3)*(1im*p-V),3/2,-pi/2)-pow(E^(1/3)*x+E^(-2/3)*(1im*p-V),3/2,-pi/2))),x,Inf)[1])
+ main=C2*phi(p,x,E,V)*exp(2im/3*(pow(E^(1/3)*x+E^(-2/3)*(1im*p-V),3/2,-pi/2)-E^(-1)*pow(1im*p-V,3/2,-pi/2)))+T*FT
+
+ # subtract the contribution of the pole, which will be added back in after the integration
+ pole=psi_pole(x,k0,E,V)/(p+1im*k0*k0)
+ return(main-pole)
+ else
+ C1=-1im*T*((sqrt(V-k0*k0)*phi(p,0,E,V)+dphi(p,0,E,V))/(-1im*p+k0*k0)/(pow(-1im*p,1/2,pi/2)*phi(p,0,E,V)-dphi(p,0,E,V))+E^(-1/3)*quadgk(y -> phi(p,y,E,V)/(pow(-1im*p,1/2,pi/2)*phi(p,0,E,V)-dphi(p,0,E,V))*exp(-sqrt(V-k0*k0)*y)*exp(2im/3*(pow(E^(1/3)*y+E^(-2/3)*(1im*p-V),3/2,-pi/2)-E^(-1)*pow(1im*p-V,3/2,-pi/2))),0,Inf)[1])
+ FI=-1im*exp(1im*k0*x)/(-1im*p+k0*k0)
+ FR=-1im*exp(-1im*k0*x)/(-1im*p+k0*k0)
+ main=C1*exp(pow(-1im*p,1/2,pi/2)*x)+FI+R*FR
+
+ # subtract the contribution of the pole, which will be added back in after the integration
+ pole=psi_pole(x,k0,E,V)/(p+1im*k0*k0)
+ return(main-pole)
+ end
+end
+# its derivative
+function df(p,x,k0,E,V)
+ T=2im*k0/(1im*k0-sqrt(V-k0*k0))
+ R=T-1
+
+ if x>=0
+ C2=-1im*T/(pow(-1im*p,1/2,pi/2)*phi(p,0,E,V)-dphi(p,0,E,V))*((sqrt(V-k0*k0)+pow(-1im*p,1/2,pi/2))/(-1im*p+k0*k0)-2im*E^(-1/3)*pi*quadgk(y -> (pow(-1im*p,1/2,pi/2)*eta(p,0,E,V)-deta(p,0,E,V))*phi(p,y,E,V)*exp(-sqrt(V-k0*k0)*y)*exp(2im/3*(pow(E^(1/3)*y+E^(-2/3)*(1im*p-V),3/2,-pi/2)-E^(-1)*pow(1im*p-V,3/2,-pi/2))),0,Inf)[1])
+ dFT=2*E^(-1/3)*pi*(quadgk(y -> dphi(p,x,E,V)*eta(p,y,E,V)*exp(-sqrt(V-k0*k0)*y)*exp(2im/3*(pow(E^(1/3)*x+E^(-2/3)*(1im*p-V),3/2,-pi/2)-pow(E^(1/3)*y+E^(-2/3)*(1im*p-V),3/2,-pi/2))),0,x)[1]+quadgk(y -> deta(p,x,E,V)*phi(p,y,E,V)*exp(-sqrt(V-k0*k0)*y)*exp(2im/3*(pow(E^(1/3)*y+E^(-2/3)*(1im*p-V),3/2,-pi/2)-pow(E^(1/3)*x+E^(-2/3)*(1im*p-V),3/2,-pi/2))),x,Inf)[1])
+ main=C2*dphi(p,x,E,V)*exp(2im/3*(pow(E^(1/3)*x+E^(-2/3)*(1im*p-V),3/2,-pi/2)-E^(-1)*pow(1im*p-V,3/2,-pi/2)))+T*dFT
+
+ # subtract the contribution of the pole, which will be added back in after the integration
+ pole=dpsi_pole(x,k0,E,V)/(p+1im*k0*k0)
+ return(main-pole)
+ else
+ C1=-1im*T*((sqrt(V-k0*k0)*phi(p,0,E,V)+dphi(p,0,E,V))/(-1im*p+k0*k0)/(pow(-1im*p,1/2,pi/2)*phi(p,0,E,V)-dphi(p,0,E,V))+E^(-1/3)*quadgk(y -> phi(p,y,E,V)/(pow(-1im*p,1/2,pi/2)*phi(p,0,E,V)-dphi(p,0,E,V))*exp(-sqrt(V-k0*k0)*y)*exp(2im/3*(pow(E^(1/3)*y+E^(-2/3)*(1im*p-V),3/2,-pi/2)-E^(-1)*pow(1im*p-V,3/2,-pi/2))),0,Inf)[1])
+ dFI=k0*exp(1im*k0*x)/(-1im*p+k0*k0)
+ dFR=-k0*exp(-1im*k0*x)/(-1im*p+k0*k0)
+ main=C1*pow(-1im*p,1/2,pi/2)*exp(pow(-1im*p,1/2,pi/2)*x)+dFI+R*dFR
+
+ # subtract the contribution of the pole, which will be added back in after the integration
+ pole=dpsi_pole(x,k0,E,V)/(p+1im*k0*k0)
+ return(main-pole)
+ end
+end
+
+# psi (returns t,psi(x,t))
+function psi(x,k0,E,V,p_npoints,p_cutoff)
+ fft=fourier_fft(f,x,k0,E,V,p_npoints,p_cutoff)
+ # add the contribution of the pole
+ for i in 1:p_npoints
+ fft[2][i]=fft[2][i]+psi_pole(x,k0,E,V)*exp(-1im*k0*k0*fft[1][i])
+ end
+ return(fft)
+end
+# its derivative
+function dpsi(x,k0,E,V,p_npoints,p_cutoff)
+ fft=fourier_fft(df,x,k0,E,V,p_npoints,p_cutoff)
+ # add the contribution of the pole
+ for i in 1:p_npoints
+ fft[2][i]=fft[2][i]+dpsi_pole(x,k0,E,V)*exp(-1im*k0*k0*fft[1][i])
+ end
+ return(fft)
+end
+
+# compute Fourier transform by sampling and fft
+function fourier_fft(A,x,k0,E,V,p_npoints,p_cutoff)
+ fun=zeros(Complex{Float64},p_npoints)
+ times=zeros(p_npoints)
+
+ # prepare fft
+ for i in 1:p_npoints
+ fun[i]=p_cutoff/pi*A(1im*(-p_cutoff+2*p_cutoff*(i-1)/p_npoints),x,k0,E,V)
+ times[i]=(i-1)*pi/p_cutoff
+ end
+
+ ifft!(fun)
+
+ # correct the phase
+ for i in 2:2:p_npoints
+ fun[i]=-fun[i]
+ end
+ return([times,fun])
+end
+
+# asymptotic value of psi
+function psi_pole(x,k0,E,V)
+ if x>=0
+ return(1im*phi(-1im*k0*k0,x,E,V)*2*k0/(1im*k0*phi(-1im*k0*k0,0,E,V)+dphi(-1im*k0*k0,0,E,V))*exp(2im/3*(pow(E^(1/3)*x+E^(-2/3)*(k0*k0-V),3/2,-pi/2)-E^(-1)*pow(k0*k0-V,3/2,-pi/2))))
+ else
+ return((1im*k0*phi(-1im*k0*k0,0,E,V)-dphi(-1im*k0*k0,0,E,V))/(1im*k0*phi(-1im*k0*k0,0,E,V)+dphi(-1im*k0*k0,0,E,V))*exp(-1im*k0*x)+exp(1im*k0*x))
+ end
+end
+function dpsi_pole(x,k0,E,V)
+ if x>=0
+ return(1im*dphi(-1im*k0*k0,x,E,V)*2*k0/(1im*k0*phi(-1im*k0*k0,0,E,V)+dphi(-1im*k0*k0,0,E,V))*exp(2im/3*(pow(E^(1/3)*x+E^(-2/3)*(k0*k0-V),3/2,-pi/2)-E^(-1)*pow(k0*k0-V,3/2,-pi/2))))
+ else
+ return(-1im*k0*(1im*k0*phi(-1im*k0*k0,0,E,V)-dphi(-1im*k0*k0,0,E,V))/(1im*k0*phi(-1im*k0*k0,0,E,V)+dphi(-1im*k0*k0,0,E,V))*exp(-1im*k0*x)+1im*k0*exp(1im*k0*x))
+ end
+end
+
+# current
+function J(ps,dps)
+ return(2*imag(conj(ps)*dps))
+end
+
+# complete computation of the current
+function current(x,k0,E,V,p_npoints,p_cutoff)
+ ps=psi(x,k0,E,V,p_npoints,p_cutoff)
+ dps=dpsi(x,k0,E,V,p_npoints,p_cutoff)
+ Js=zeros(Complex{Float64},p_npoints)
+ for i in 1:p_npoints
+ Js[i]=J(ps[2][i],dps[2][i])
+ end
+ return(Js)
+end
diff --git a/figs/animation/Makefile b/figs/animation/Makefile
new file mode 100644
index 0000000..d582a40
--- /dev/null
+++ b/figs/animation/Makefile
@@ -0,0 +1,12 @@
+PROJECTNAME=animate
+
+all: animate.dat
+
+run: animate.dat
+ python3 animate.py animate.dat &
+
+animate.dat:
+ julia animate_compute.jl > animate.dat
+
+clean:
+ rm -f animate.dat
diff --git a/figs/animation/animate.py b/figs/animation/animate.py
new file mode 100644
index 0000000..aaa3a80
--- /dev/null
+++ b/figs/animation/animate.py
@@ -0,0 +1,127 @@
+from matplotlib import pyplot as pl
+from matplotlib import animation
+import sys
+
+# read data
+# time dependent data
+frames=[]
+# asymptotic data (located in the first block)
+asym=[]
+infile=open(sys.argv[1],'r')
+row=[]
+for line in infile:
+ # read first block
+ if len(asym)==0:
+ if line=='\n':
+ asym=row
+ row=[]
+ else:
+ dat=[]
+ for n in line.split():
+ dat.append(float(n))
+ row.append(dat)
+ # read other blocks
+ else:
+ if line=='\n':
+ frames.append(row)
+ row=[]
+ else:
+ dat=[]
+ for n in line.split():
+ dat.append(float(n))
+ row.append(dat)
+infile.close()
+
+
+# set up plot
+fig = pl.figure()
+#pl.subplot(211)
+axr=fig.gca()
+asym_rho, = axr.plot([],[],linewidth=3.5,color='#00FF00')
+rho, = axr.plot([],[],color='red')
+
+#pl.subplot(212)
+#axJ=fig.gca()
+#asym_J, = axJ.plot([],[],linewidth=3.5,color='#00FF00')
+#J, = axJ.plot([],[],color='red')
+
+# plot ranges
+xmax=0
+maxyr=0
+maxyJ=0
+for frame in frames:
+ for i in range(len(frame)):
+ if frame[i][1]>xmax:
+ xmax=frame[i][1]
+ if frame[i][2]>maxyr:
+ maxyr=frame[i][2]
+ if frame[i][3]>maxyJ:
+ maxyJ=frame[i][3]
+for i in range(len(asym)):
+ if asym[i][0]>xmax:
+ xmax=asym[i][0]
+ if asym[i][1]>maxyr:
+ maxyr=asym[i][1]
+ if asym[i][2]>maxyJ:
+ maxyJ=asym[i][2]
+xmin=0
+minyr=0
+minyJ=0
+for frame in frames:
+ for i in range(len(frame)):
+ if frame[i][1]<xmin:
+ xmin=frame[i][1]
+ if frame[i][2]<minyr:
+ minyr=frame[i][2]
+ if frame[i][3]<minyJ:
+ minyJ=frame[i][3]
+for i in range(len(asym)):
+ if asym[i][0]<xmin:
+ xmin=asym[i][0]
+ if asym[i][1]<minyr:
+ minyr=asym[i][1]
+ if asym[i][2]<minyJ:
+ minyJ=asym[i][2]
+
+
+# plot asymptotes
+asym_rho_datax=[]
+asym_rho_datay=[]
+for i in range(len(asym)):
+ asym_rho_datax.append(asym[i][0])
+ asym_rho_datay.append(asym[i][1])
+asym_rho.set_data(asym_rho_datax,asym_rho_datay)
+#asym_J_datax=[]
+#asym_J_datay=[]
+#for i in range(len(asym)):
+# asym_J_datax.append(asym[i][0])
+# asym_J_datay.append(asym[i][2])
+#asym_J.set_data(asym_J_datax,asym_J_datay)
+
+# animate
+def init_plot():
+ axr.set_ylim(minyr,maxyr)
+ axr.set_xlim(xmin,xmax)
+ #axJ.set_ylim(minyJ,maxyJ)
+ #axJ.set_xlim(xmin,xmax)
+
+ axr.vlines(0,minyr,maxyr,linestyles="dotted")
+ #axJ.vlines(0,minyJ,maxyJ,linestyles="dotted")
+def update(frame):
+ axr.set_title("t=% .3f fs" % (frame[0][0]))
+ xdata=[]
+ ydata=[]
+ for i in range(len(frame)):
+ xdata.append(frame[i][1])
+ ydata.append(frame[i][2])
+ rho.set_data(xdata,ydata)
+
+ #xdata=[]
+ #ydata=[]
+ #for i in range(len(frame)):
+ # xdata.append(frame[i][1])
+ # ydata.append(frame[i][3])
+ #J.set_data(xdata,ydata)
+anim = animation.FuncAnimation(fig, update, frames=frames, blit=False, interval=100, repeat=True, init_func=init_plot)
+#anim.save('schrodinger_barrier.mp4', fps=15, extra_args=['-vcodec', 'libx264'])
+pl.show()
diff --git a/figs/animation/animate_compute.jl b/figs/animation/animate_compute.jl
new file mode 100644
index 0000000..452320e
--- /dev/null
+++ b/figs/animation/animate_compute.jl
@@ -0,0 +1,66 @@
+using QuadGK
+using SpecialFunctions
+using FFTW
+
+# numerical values
+hbar=6.58e-16 # eV.s
+m=9.11e-31 # kg
+Vn=9 # eV
+#En=14e9 # V/m
+En=10e9 # V/m
+Kn=4.5 # eV
+
+V=1
+E=En*hbar/(2*Vn^1.5*m^0.5)*sqrt(1.60e-19)
+k0=sqrt(Kn/Vn)
+
+# rescale x to nm
+nm_scale=hbar*sqrt(1.6e-19)/sqrt(2*m*Vn)*1e9
+
+# cutoffs
+p_cutoff=20*k0
+p_npoints=256
+
+# airy approximations
+airy_threshold=30
+airy_order=5
+
+# xbounds
+xmax=10
+xmin=-10
+x_npoints=200
+
+include("FN_base.jl")
+
+# compute wave function
+ps=Array{Array{Array{Complex{Float64},1},1}}(undef,x_npoints)
+dps=Array{Array{Array{Complex{Float64},1},1}}(undef,x_npoints)
+for i in 1:x_npoints
+ print(stderr,i,'/',x_npoints,'\n')
+ x=xmin+(xmax-xmin)*i/x_npoints
+ ps[i]=psi(x,k0,E,V,p_npoints,p_cutoff)
+ dps[i]=dpsi(x,k0,E,V,p_npoints,p_cutoff)
+end
+
+# compute asymptotic values
+ps_asym=Array{Complex{Float64}}(undef,x_npoints)
+dps_asym=Array{Complex{Float64}}(undef,x_npoints)
+for i in 1:x_npoints
+ x=xmin+(xmax-xmin)*i/x_npoints
+ ps_asym[i]=psi_pole(x,k0,E,V)
+ dps_asym[i]=dpsi_pole(x,k0,E,V)
+end
+
+# print asymptotic values
+for i in 1:x_npoints
+ print((xmin+(xmax-xmin)*i/x_npoints)*nm_scale,' ',abs(ps_asym[i])^2,' ',J(ps_asym[i],dps_asym[i])/(2*k0),'\n')
+end
+print('\n')
+
+# print values at each time
+for j in 1:p_npoints
+ for i in 1:x_npoints
+ print(real(ps[i][1][j])*hbar/Vn*1e15,' ',(xmin+(xmax-xmin)*i/x_npoints)*nm_scale,' ',abs(ps[i][2][j])^2,' ',J(ps[i][2][j],dps[i][2][j])/(2*k0),'\n')
+ end
+ print('\n')
+end