我用矢量输入
求解微分方程y'= f(t,y),y(t_0)= y_0
其中 y0 = y(x)
使用显式的Euler方法,即
y_(i + 1)= y_i + h * f(t_i,y_i)
其中 t 是时间向量, h 是步长, f 是微分方程的右侧。
该方法的python代码如下所示:
for i in np.arange(0,n-1):
y[i+1,...] = y[i,...] + dt*myode(t[i],y[i,...])
结果是 k,m 矩阵 y ,其中 k 是 t 维度的大小, m 是 y 的大小。
返回 y 和 t 的向量。
t , x , y 传递给scipy.interpolate.RectBivariateSpline(t, x, y, kx=1, ky=1)
:
g = scipy.interpolate.RectBivariateSpline(t, x, y, kx=1, ky=1)
生成的对象g
使用新的向量ti,xi ( g(p,q) )
来提供y_int
,这是 ti 定义的点处的 y 插值>和 xi 。
这是我的问题:
RectBivariateSpline的文档根据x和y描述了__call__
方法:
__call__(x, y[, mth])
评估坐标数组定义的网格点的样条线
plot_surface的matplotlib文档使用了类似的表示法:
Axes3D.plot_surface(X, Y, Z, *args, **kwargs)
X和Y是由numpy.meshgrid()
生成的2D数组的重要区别。
当我计算简单的例子时,两者的输入顺序是相同的,结果正是我所期望的。然而,在我的显式Euler示例中,初始顺序是ti,xi
,但是如果我颠倒输入的顺序,插值输出的表面图也是有意义的,如下所示:
ax2.plot_surface(xi, ti, u, cmap=cm.coolwarm)
虽然我很高兴它有效,但我并不满意,因为我无法解释为什么,也没有为什么(除了数组几何)有必要交换输入。理想情况下,我想重构代码,以便输入顺序一致。
这是一个工作代码示例来说明我的意思:
# Heat equation example with explicit Euler method
import numpy as np
import matplotlib.pyplot as mplot
import matplotlib.cm as cm
import scipy.sparse as sp
import scipy.interpolate as interp
from mpl_toolkits.mplot3d import Axes3D
import pdb
# explicit Euler method
def eev(myode,tspan,y0,dt):
# Preprocessing
# Time steps
tspan[1] = tspan[1] + dt
t = np.arange(tspan[0],tspan[1],dt,dtype=float)
n = t.size
m = y0.shape[0]
y = np.zeros((n,m),dtype=float)
y[0,:] = y0
# explicit Euler recurrence relation
for i in np.arange(0,n-1):
y[i+1,...] = y[i,...] + dt*myode(t[i],y[i,...])
return y,t
# generate matrix A
# u'(t) = A*u(t) + g*u(t)
def a_matrix(n):
aa = sp.diags([1, -2, 1],[-1,0,1],(n,n))
return aa
# System of ODEs with finite differences
def f(t,u):
dydt = np.divide(1,h**2)*A.dot(u)
return dydt
# homogenous Dirichlet boundary conditions
def rbd(t):
ul = np.zeros((t,1))
return ul
# Initial value problem -----------
def main():
# Metal rod
# spatial discretization
# number of inner nodes
m = 20
x0 = 0
xn = 1
x = np.linspace(x0,xn,m+2)
# Step size
global h
h = x[1]-x[0]
# Initial values
u0 = np.sin(np.pi*x)
# A matrix
global A
A = a_matrix(m)
# Time
t0 = 0
tend = 0.2
# Time step width
dt = 0.0001
tspan = [t0,tend]
# Test r for stability
r = np.divide(dt,h**2)
if r <= 0.5:
u,t = eev(f,tspan,u0[1:-1],dt)
else:
print('r = ',r)
print('r > 0.5. Explicit Euler method will not be stable.')
# Add boundary values back
rb = rbd(t.size)
u = np.hstack((rb,u,rb))
# Interpolate heat values
# Create interpolant. Note the parameter order
fi = interp.RectBivariateSpline(t, x, u, kx=1, ky=1)
# Create vectors for interpolant
xi = np.linspace(x[0],x[-1],100)
ti = np.linspace(t0,tend,100)
# Compute function values from interpolant
u_int = fi(ti,xi)
# Change xi, ti in to 2D arrays
xi,ti = np.meshgrid(xi,ti)
# Create figure and axes objects
fig3 = mplot.figure(1)
ax3 = fig3.gca(projection='3d')
print('xi.shape =',xi.shape,'ti.shape =',ti.shape,'u_int.shape =',u_int.shape)
# Plot surface. Note the parameter order, compare with interpolant!
ax3.plot_surface(xi, ti, u_int, cmap=cm.coolwarm)
ax3.set_xlabel('xi')
ax3.set_ylabel('ti')
main()
mplot.show()
答案 0 :(得分:3)
我可以看到你定义:
# Change xi, ti in to 2D arrays
xi,ti = np.meshgrid(xi,ti)
将其更改为:
ti,xi = np.meshgrid(ti,xi)
和
ax3.plot_surface(xi, ti, u_int, cmap=cm.coolwarm)
到
ax3.plot_surface(ti, xi, u_int, cmap=cm.coolwarm)
它工作正常(如果我理解的话)。