为什么指数积分器方法会产生不良结果?

时间:2017-03-31 18:38:05

标签: matlab octave julia differential-equations runge-kutta

//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

为什么他们的结果不佳?

该方法爆炸性非常糟糕,它应该收敛到[1.99] * 11,或类似的东西?

实施Exp Integrator时是否有错误?

2 个答案:

答案 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) -> 1z->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)

exponential Euler-Rosenbrock step should be
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)) )

这同样应该导致一阶方法。