同时在Matlab和python中集成代码,Matlab是稳定的,python爆炸了
这里是一个指数时间差分法的算法,使用原始 牛津大学的Matlab代码同时在Matlab和python中集成代码,Matlab是稳定的,python爆炸了,python,matlab,numerical-stability,Python,Matlab,Numerical Stability,这里是一个指数时间差分法的算法,使用原始 牛津大学的Matlab代码 clc clear % viscosity nu = 0.5; % Spatial grid and initial condition: N = 128; x = 2*pi*(0:N-1)'/N; u = cos(x).*(1+sin(x)); v = fft(u); % Precompute various ETDRK4 scalar quantities: h = 0.01; tot = 5; % time st
clc
clear
% viscosity
nu = 0.5;
% Spatial grid and initial condition:
N = 128;
x = 2*pi*(0:N-1)'/N;
u = cos(x).*(1+sin(x));
v = fft(u);
% Precompute various ETDRK4 scalar quantities:
h = 0.01;
tot = 5;
% time step
k = [0:N/2-1 0 -N/2+1:-1]';
% wave numbers
L = 1/16*k.^2 - 1/16^3*nu*k.^4;
% Fourier multipliers
E = exp(h*L);
E2 = exp(h*L/2);
M =16;
% no. of points for complex means
r = exp(1i*pi*((1:M)-.5)/M); % roots of unity
% construct things on the
LR = h*L(:,ones(M,1)) + r(ones(N,1),:);
Q = h*real(mean( (exp(LR/2)-1)./LR ,2) );
f1 = h*real(mean( (-4-LR+exp(LR).*(4-3*LR+LR.^2))./LR.^3 ,2));
f2 = h*real(mean( (2+LR+exp(LR).*(-2+LR))./LR.^3 ,2));
f3 = h*real(mean( (-4-3*LR-LR.^2+exp(LR).*(4-LR))./LR.^3 ,2));
% Main time-stepping loop:
uu=u;tt=0;
vv=v;
NvNV = [];
aa = [];
bb = [];
cc = [];
NvNv = [];
NaNa = [];
NbNb = [];
NcNc = [];
nmax = floor(tot/h);
g = -0.5i*k;
%
for n = 1:nmax
t = n*h;
Nv = g.*fft(real(ifft(v)).^2);
a = E2.*v + Q.*Nv;
Na = g.*fft(real(ifft(a)).^2);
b = E2.*v + Q.*Na;
Nb = g.*fft(real(ifft(b)).^2);
c = E2.*a + Q.*(2*Nb-Nv);
Nc = g.*fft(real(ifft(c)).^2);
v = E.*v + Nv.*f1 + 2*(Na+Nb).*f2 + Nc.*f3;
u = real(ifft(v));
uu = [uu,u];
vv = [vv,v];
tt = [tt,t];
aa = [aa,a];
bb = [bb,b];
cc = [cc,c];
NvNv = [NvNv,Nv];
NaNa = [NaNa,Na];
NbNb = [NbNb,Nb];
NcNc = [NcNc,Nc];
end
Python代码
# spatial domain: 0,2pi
# time domain: 0,2
# init
import numpy as np
from matplotlib import pyplot as plt
np.seterr(all='raise')
plt.style.use('siads')
np.random.seed(0)
pi = np.pi
# viscosity
nu = 0.5
# mesh
mesh = 128
# time restriction
tot = 5
# distributed x point
x = np.linspace(0, 2.0 * pi, mesh, endpoint=False)
# force IC
u0 = np.cos(x)*(1.0 + np.sin(x))
N = mesh
k_array_noshift = np.fft.fftfreq(mesh)*mesh
u = u0
v = np.fft.fft(u)
h = 0.01
## follow them, set -N/2 to zer
k_array_noshift[mesh / 2] = 0
## Linear part in fourier space
L = 1.0/16.0*k_array_noshift**2 - nu*1.0/16.0**3 * k_array_noshift**4
## Fourier mulitplier
E = np.exp(h * L)
E2 = np.exp(h * L / 2.0)
## select number of points on the circle
M = 16
## choose radius 1, since k^2-k^4 ranges a lot... so 1 is enough to make sure only one singular point
r = np.exp(1j * np.pi * (np.arange(1, M + 1) - 0.5) / M)
r = r.reshape(1, -1)
r_on_circle = np.repeat(r, mesh, axis=0)
## define hL on M copies
LR = h * L
LR = LR.reshape(-1, 1)
LR = np.repeat(LR, M, axis=1)
## obtain hL on circle
LR = LR + r_on_circle
## important quantites used in ETDRK4
# g = -0.5*i*k
g = -0.5j * k_array_noshift
# averaged Q, f1,f2,f3
Q = h*np.real(np.mean( (np.exp(LR/2.0)-1)/LR, axis=1 ))
f1 = h*np.real(np.mean( (-4.0-LR + np.exp(LR)*(4.0-3.0*LR+LR**2))/LR**3, axis=1 ))
f2 = h*np.real(np.mean( (2.0+LR + np.exp(LR)*(-2.0 + LR))/LR**3, axis=1 ))
f3 = h*np.real(np.mean( (-4.0-3.0*LR - LR**2 + np.exp(LR)*(4.0 - LR))/LR**3, axis=1 ))
def compute_u2k_zeropad_dealiased(uk_):
u2k = np.fft.fft(np.real(np.fft.ifft(uk_))**2)
# three over two law
# N = uk.size
#
# # map uk to uk_fine
#
# uk_fine = np.hstack((uk[0:N / 2], np.zeros((N / 2)), uk[-N / 2:])) * 3.0 / 2.0
#
# # convert uk_fine to physical space
# u_fine = np.real(np.fft.ifft(uk_fine))
#
# # compute square
# u2_fine = np.square(u_fine)
#
# # compute fft on u2_fine
# u2k_fine = np.fft.fft(u2_fine)
#
# # convert u2k_fine to u2k
# u2k = np.hstack((u2k_fine[0:N / 2], u2k_fine[-N / 2:])) / 3.0 * 2.0
return u2k
print 'dt =', h
# np.linalg.norm(np.fft.ifft(uk_0)-u0) # very good
ntsnap = int(tot/h)
isnap = 0
tsnap = np.linspace(0, tot, ntsnap)
usnap = np.zeros((mesh, ntsnap))
uksnap = np.zeros((mesh, ntsnap),dtype=complex)
aasnap = np.zeros((mesh, ntsnap),dtype=complex)
bbsnap = np.zeros((mesh, ntsnap),dtype=complex)
ccsnap = np.zeros((mesh, ntsnap),dtype=complex)
Nvsnap = np.zeros((mesh, ntsnap),dtype=complex)
Nasnap = np.zeros((mesh, ntsnap),dtype=complex)
Nbsnap = np.zeros((mesh, ntsnap),dtype=complex)
Ncsnap = np.zeros((mesh, ntsnap),dtype=complex)
tcur = 0.0
## main loop time stepping
while tcur <= tot and isnap < ntsnap:
# print tcur
# record snap
# if abs(tcur - tsnap[isnap]) < 1e-2:
print ' current progress =', tcur / tsnap[-1] * 100, ' % '
u = np.real(np.fft.ifft(v))
usnap[:, isnap] = u
uksnap[:, isnap] = v
Nv = g * np.fft.fft(np.real(np.fft.ifft(v))**2)
a = E2 * v + Q * Nv
Na = g * np.fft.fft(np.real(np.fft.ifft(a))**2)
b = E2 * v + Q * Na
Nb = g * np.fft.fft(np.real(np.fft.ifft(b))**2)
c = E2 * a + Q * (2.0*Nb - Nv)
Nc = g * np.fft.fft(np.real(np.fft.ifft(c))**2)
v = E*v + Nv*f1 + 2.0*(Na + Nb)*f2 + Nc*f3
aasnap[:, isnap] = a
bbsnap[:, isnap] = b
ccsnap[:, isnap] = c
Nvsnap[:, isnap] = Nv
Nasnap[:, isnap] = Na
Nbsnap[:, isnap] = Nb
Ncsnap[:, isnap] = Nc
# algo: ETDRK4
# # 1. compute nonlinear part in first fractional step
# u2k = compute_u2k_zeropad_dealiased(uk)
# Nuk = g * u2k
#
# # 2. update fractional step
# uk_a = E2 * uk + Q * Nuk
#
# # 3. compute nonlinear part in second fractional step
# Nuk_a = g * compute_u2k_zeropad_dealiased(uk_a)
#
# # 4. update fractional step
# uk_b = E2 * uk + Q * Nuk_a
#
# # 5. compute nonlinear part in third fractional step
# Nuk_b = g * compute_u2k_zeropad_dealiased(uk_b)
#
# # 6. update fractional step
# uk_c = E2 * uk_a + Q * (2.0 * Nuk_b - Nuk)
#
# # 7 compute nonlinear part in the fourth fractional step
# Nuk_c = g * compute_u2k_zeropad_dealiased(uk_c)
#
# # final, update uk
# uk = E * uk + Nuk * f1 + 2.0 * (Nuk_a + Nuk_b) * f2 + Nuk_c * f3
# record time
tcur = tcur + h
isnap = isnap + 1
# save uksnap
np.savez('output_uk',uksnap=uksnap,f1=f1,f2=f2,f3=f3,Q=Q,LR=LR,L=L,g=g, Nasnap=Nasnap, Nvsnap=Nvsnap, Nbsnap=Nbsnap, Ncsnap=Ncsnap,
aasnap=aasnap, bbsnap=bbsnap, ccsnap=ccsnap, usnap=usnap)
# plot snapshots
plt.figure(figsize=(16,16))
for isnap in xrange(ntsnap):
plt.plot(x, usnap[:,isnap])
plt.xlabel('x')
plt.ylabel('u')
plt.savefig('snapshots.png')
# plot contours
from matplotlib import cm
fig = plt.figure(figsize=(8, 8))
X, Y = np.meshgrid(x, tsnap)
Z = usnap.transpose()
V = np.linspace(-10, 10, 500)
surf = plt.contourf(X, Y, Z, V, cmap=cm.seismic)
plt.savefig('contour.png')
#空间域:0,2pi
#时域:0,2
#初始化
将numpy作为np导入
从matplotlib导入pyplot作为plt
np.seterr(all='raise')
plt.style.use('siads')
np.random.seed(0)
pi=np.pi
#粘度
nu=0.5
#网孔
网格=128
#时间限制
tot=5
#分布x点
x=np.linspace(0,2.0*pi,网格,端点=False)
#强制集成电路
u0=np.cos(x)*(1.0+np.sin(x))
N=网格
k_数组_noshift=np.fft.fftfreq(网格)*mesh
u=u0
v=np.fft.fft(u)
h=0.01
##跟随他们,将-N/2设置为零
k_数组_noshift[mesh/2]=0
##傅里叶空间中的线性部分
L=1.0/16.0*k_阵列无移位**2-nu*1.0/16.0**3*k_阵列无移位**4
##傅里叶倍增管
E=np.exp(h*L)
E2=np.exp(h*L/2.0)
##选择圆上的点数
M=16
##选择半径1,因为k^2-k^4的范围很大。。。所以1足以确保只有一个奇点
r=np.exp(1j*np.pi*(np.arange(1,M+1)-0.5)/M)
r=r。重塑(1,-1)
圆上的r_=np。重复(r,网格,轴=0)
##在M个拷贝上定义hL
LR=h*L
LR=LR.重塑(-1,1)
LR=np.重复(LR,M,轴=1)
##在圆上获得hL
LR=LR+r_在_圆上
##ETDRK4中使用的重要量
#g=-0.5*i*k
g=-0.5j*k_数组_无移位
#平均Q、f1、f2、f3
Q=h*np.real(np.mean((np.exp(LR/2.0)-1)/LR,轴=1))
f1=h*np.实际值(np.平均值((-4.0-LR+np.exp(LR)*(4.0-3.0*LR+LR**2))/LR**3,轴=1))
f2=h*np.real(np.mean((2.0+LR+np.exp(LR)*(-2.0+LR))/LR**3,轴=1))
f3=h*np.real(np.mean(-4.0-3.0*LR-LR**2+np.exp(LR)*(4.0-LR))/LR**3,轴=1))
def compute_u2k_zeropad_dealiased(英国):
u2k=np.fft.fft(np.real(np.fft.ifft(uk_2;))**2)
#三比二定律
#N=英国尺码
#
##将英国映射到英国#
#
#uk_fine=np.hstack((uk[0:N/2],np.zeros((N/2)),uk[-N/2:])*3.0/2.0
#
##将uk#U fine转换为物理空间
#u_fine=np.real(np.fft.ifft(uk_fine))
#
##计算平方
#u2_fine=np.平方(u_fine)
#
##在u2#u上计算fft
#u2k_fine=np.fft.fft(u2_fine)
#
##将u2k#U罚款转换为u2k
#u2k=np.hstack((u2k_fine[0:N/2],u2k_fine[-N/2:]))/3.0*2.0
返回u2k
打印“dt=”,h
#np.linalg.norm(np.fft.ifft(uk_0)-u0)#非常好
ntsnap=int(总吨/小时)
isnap=0
tsnap=np.linspace(0,tot,ntsnap)
usnap=np.零((网格,ntsnap))
uksnap=np.zeros((网格,ntsnap),dtype=complex)
aasnap=np.zeros((网格,ntsnap),dtype=complex)
bbsnap=np.zeros((网格,ntsnap),dtype=complex)
ccsnap=np.zeros((网格,ntsnap),dtype=complex)
Nvsnap=np.zeros((网格,ntsnap),dtype=complex)
Nasnap=np.zeros((网格,ntsnap),dtype=complex)
Nbsnap=np.zeros((网格,ntsnap),dtype=complex)
Ncsnap=np.zeros((网格,ntsnap),dtype=complex)
tcur=0.0
##主回路时间步进
tcur如需更多信息,请查看此linkedIn链接
终于!!!!!!!!一切正常
我发现我可以使python与matlab一样工作(注意python总是在特定的物理时间爆炸到inf),只需
将numpy.fft更改为scipy.fft
请注意,我测试过,代码中计算的numpy.fft和scipy.fft几乎相同,但在1e-16附近不同
但这对于这种混沌系统的模拟很重要
如果我想让我的代码爆炸,只需将scipy.fft更改为numpy.fft
从我作为用户的个人观点来看,numpy.fft里面肯定有一些神秘的问题!因为matlab fft和scipy fft在我的代码中没有任何问题。fft方法是否具有相同的默认行为?@Cleb fft对于numpy和matlab是相同的。您是否检查了此项:?由于您也使用ifft,可能值得研究“完全相同的代码”-显然不是,它们在不同的语言中使用的函数的实现您没有详细说明,它们给出了不同的结果。即使算法相同,您也没有显示图/迭代结果的小摘录等。因此,我们可以判断这是否可能是一个数值精度问题。如果它不是数值精度,那么它必须是fft
/ifft
/exp
/。。。函数。@Vairis感谢您提供的信息。我之前检查过这篇文章,python和matlab的fft似乎是一样的