In the first analysis, two different errors were apparent.
(, python numpy) , fft , . , u n,
fft(ifft(uhat)) == n*uhat and ifft(fft(u))==n*u
uhat = fft(u), u=ifft(uhat)/n.
RK4 h. (, )
k2 = f(t+0.5*h, y+0.5*h*k1)
k2 = h*f(t+0.5*h, y+0.5*k1)
. , , , . "" , .
"" , , . u^2, . , 1000 [0,1], .. h=0.001, . 10 000 [0,10].
. , , ( ) . , . , "" , . , , , . - " ": - .
Update2: , , ,
vhat = exp( 0.5j * kx**2 * t) * uhat
. KdV, i*u_t+0.5*u_xx=0 DFT
i*uhat_t-0.5*kx**2*uhat=0
, ,
exp( -0.5j * kx**2 * t).
,
uhat = exp (-0.5j * kx ** 2 * t) * vhat.
kx, , , . , , .
import numpy as np
import math
from matplotlib import pyplot as plt
from matplotlib import animation
def RK4Stream(odefunc,TimeSpan,uhat0,nt):
h = float(TimeSpan[1]-TimeSpan[0])/nt
print h
w = uhat0
t = TimeSpan[0]
while True:
w = RK4Step(odefunc, t, w, h)
t = t+h
yield t,w
def RK4Step(odefunc, t,w,h):
k1 = odefunc(t,w)
k2 = odefunc(t+0.5*h, w+0.5*k1*h)
k3 = odefunc(t+0.5*h, w+0.5*k2*h)
k4 = odefunc(t+h, w+k3*h)
return w + (k1+2*k2+2*k3+k4)*(h/6.)
L = 40
nx = 512
x = np.linspace(-L/2,L/2, nx+1)
x = x[:nx]
kx1 = np.linspace(0,nx/2-1,nx/2)
kx2 = np.linspace(1,nx/2, nx/2)
kx2 = -1*kx2[::-1]
kx = (2.* np.pi/L)*np.concatenate((kx1,kx2))
def uhat2vhat(t,uhat):
return np.exp( 0.5j * (kx**2) *t) * uhat
def vhat2uhat(t,vhat):
return np.exp(- 0.5j * (kx**2) *t) * vhat
def uhatprime(t, uhat):
u = np.fft.ifft(uhat)
return - 0.5j * (kx**2) * uhat + 1j * np.fft.fft((abs(u)**2) * u)
def vhatprime(t, vhat):
u = np.fft.ifft(vhat2uhat(t,vhat))
return 1j * uhat2vhat(t, np.fft.fft((abs(u)**2) * u) )
u0 = 1./np.cosh(x) #+ 1./np.cosh(x+0.4*L)+1./np.cosh(x-0.4*L) #symmetric or remove jump at wrap-around
uhat0 = np.fft.fft(u0)
t0 = 0; tf = 10.0;
TimeSpan = [t0, tf]
nt = 1000 # boring but stable. smaller step sizes give same picture
vhat0 = uhat2vhat(t0,uhat0)
fig = plt.figure()
ax1 = plt.subplot(211,ylim=(-0.1,2))
ax2 = plt.subplot(212,ylim=(-3.2,3.2))
line1, = ax1.plot(x,u0)
line2, = ax2.plot(x,u0*0)
vhatstream = RK4Stream(vhatprime,[t0,tf],vhat0,nt)
def animate(i):
t,vhat = vhatstream.next()
print t
u = np.fft.ifft(vhat2uhat(t,vhat))
line1.set_ydata(np.real(np.abs(u)))
line2.set_ydata(np.real(np.angle(u)))
return line1,line2
anim = animation.FuncAnimation(fig, animate, interval=15000/nt+10, blit=False)
plt.show()