//u' + Au = g(t,u) can be solved by exponential integrators also
//Following snippet is for exp INtegrators
A = -full(Strang(11))
A[end,1]=1;A[1,end]=1;
g(t,u) = 2-u
u0 = zeros(11);u0[6]=1
nsteps = 1000
tmax = 10.0
h = tmax/nsteps
u = u0
t = 0
for k in 1:nsteps
u = expm(-h*A)*u + h*((expm(-h*A)-1)\(-h*A))*g(t,u)
t = k*h
end
//this is for euler's method
for k in 1:nsteps
u += h*(A*u + h*g(t,u))
t = k*h
end
实施Exp Integrator时是否有错误?
答案 0 :(得分:3)
测试问题是一个奇异矩阵。更好的测试是设置:
using SpecialMatrices
A = -full(Strang(11))
g(t,u) = 2-u
u = zeros(11);u[6]=1
nsteps = 10000
tmax = 1.0
h = tmax/nsteps
t = 0
使用此功能,修复Euler中的h
以获取(注意有一个额外的h
,我的错误:
u = zeros(11);u[6]=1
for k in 1:nsteps
u += h*(A*u + g(t,u))
t = k*h
end
@show u
u = [0.93573,1.19361,1.26091,1.29627,1.34313,1.37767,1.34313,1.29627,1.26091,1.19361,0.93573]
但要找出问题所在,请先查看数字。 A = 0会发生什么?好吧,我们知道phi(z) = (e^z - 1)/z
。根据L'Hopital的规则,phi(z) -> 1
为z->0
。因此,为了使我们的实现具有相同的行为,我们必须具有相同的结果。但是,让我们检查一下会发生什么:
expm(zeros(5,5))
5×5 Array{Float64,2}:
1.0 0.0 0.0 0.0 0.0
0.0 1.0 0.0 0.0 0.0
0.0 0.0 1.0 0.0 0.0
0.0 0.0 0.0 1.0 0.0
0.0 0.0 0.0 0.0 1.0
请注意,这给出了单位矩阵。所以考虑一下这个极限:如果底部为零......这怎么可以保持不变?我们必须让顶部变为零...所以顶部将转到I
。
这就是明确的时刻:作者在你所在的领域意味着1
。所以对于矩阵输入,1=I
。当你意识到这一点,你修复了代码:
# Norsett-Euler
u = zeros(11);u[6]=1
for k in 1:nsteps
u = expm(h*A)*u + ((expm(h*A)-I)/A)*g(t,u)
t = k*h
end
@show u
u = [0.935722,1.1936,1.26091,1.29627,1.34313,1.37768,1.34313,1.29627,1.26091,1.1936,0.935722]
故事的道德:对于数学编程,你还必须调试你的数学。
一次一步获得更高效的表格。首先,尝试强制使用另一个varphi术语:
# Norsett-Euler
u = zeros(11);u[6]=1
for k in 1:nsteps
u = (I + A*(expm(h*A)-I)/A)*u + ((expm(h*A)-I)/A)*g(t,u)
t = k*h
end
@show u
现在聚集:
# Norsett-Euler
u = zeros(11);u[6]=1
for k in 1:nsteps
u = u + ((expm(h*A)-I)/A)*(A*u + g(t,u))
t = k*h
end
@show u
这是您尝试编写的方法的有效形式。然后你可以缓存运算符,因为A是常数:
# Norsett-Euler
u = zeros(11);u[6]=1
phi1 = ((expm(h*A)-I)/A)
for k in 1:nsteps
u = u + phi1*(A*u + g(t,u))
t = k*h
end
@show u
答案 1 :(得分:0)
u'=Lu+g(t,u)
u = expm(h*L)*u + ((expm(h*L)-1)/L)*g(t,u)
请注意,反转矩阵为L
(在Matlab A/B == A*inv(B)
和A\B == inv(A)*B
中),并且公式中没有裸h
。在您的情况下,L = -A
。
分离指数部分的另一种方法如下。设置u(t) = exp(-t*A)*v(t)
,转换为微分方程
exp(-t*A)*v'(t) = g(t,exp(-t*A)*v((t))
现在为v
v(t+h) = v(t) + h * exp(t*A)*g(t,exp(-t*A)*v((t))
转换回u
中的术语
u(t+h) = exp(-(t+h)*A)*v(t+h)
= exp(-h*A) * ( u(t) + h * g(t,u(t)) )
这同样应该导致一阶方法。