我有一个叫做数值方法的课程,在那里我们学习如何为物理学中的某些问题编写程序。我们必须编写4个可以解决ODE的程序(隐式/显式euler,速度 - verlet,隐式中点规则),现在我们必须使用| y_N - y(T)|来计算误差。我们已经有了一个我们需要填写的模板。 这是我们必须完成的代码。
def ex2_d():
T = 0.2
y0 = np.array([0.3, 0.0])
all_methods = [explicit_euler, implicit_euler, implicit_mid_point, velocity_verlet]
all_rhs = 3*[pendulum_rhs] + [pendulum_verlet_rhs]
resolutions = 2**np.arange(4, 11)
_, y_exact = ode45(pendulum_rhs, (0.0, T), y0, reltol=1e-12)
for method, rhs in zip(all_methods, all_rhs):
error = np.empty(resolutions.size)
for k, N in enumerate(resolutions):
# TODO: Berechen Sie die Lösung und den Fehler
error[k] = np.absolute(methode())
rate = convergence_rate(error, resolutions)
print(method)
print("rate: " + str(rate) + "\n")
我唯一需要填写的是TODO部分。但是我不明白,for循环,它以枚举(分辨率)循环遍历k和N,为什么分辨率数组被声明为无论如何?
提前感谢您的帮助!
答案 0 :(得分:1)
在数值求解ODE时,您希望使用标准方法获得加倍分辨率(将步长减半),以找到收敛速度:
(u_h - u_(h/2))/(u_(h/2) - u_(h/4)) = 2^p + O(h)
u_h
步骤h
的数值解,u_(h/2)
步骤h/2
(例如双倍分辨率)和u_(h/4)
解决方案步骤h/4
(例如,再次双倍分辨率)。错误的顺序为p
,其收敛率为h^p
这就是分辨率被声明为2**np.arange(4,11), which gives
[16,32,64,128,256,512,1024]的原因。 (您可以使用其他网格尺寸,这将相应地更改公式。有关详细信息,请参阅this。
要将错误存储在列表中,您需要相应的分辨率索引,这就是使用enumerate
的原因:
enumerate(resolutions) -> [(0,16), (1,32), (2,64), (3,128), (4,256), (5,512), (6,1024)]
由for循环解压缩:
iteration k N
1 0 16
2 1 32
等
答案 1 :(得分:0)
这个练习的目的是比较解决pendulum_rhs
给出的微分方程的不同方法。
比较发生的数量是收敛率。为了确定这个速率,您需要使用变化的分辨率(底层网格)来解决DE并计算每个分辨率的误差。
使用的决议是:resolutions =[16, 32, 64, ...]
。
因此,对于给定的方法method
,您将迭代分辨率:
for k in range(len(resolutions)):
N = resolutions[k]
# calculate the result using N
result = method(..., N, ...)
#store it in an array called
error[k] = np.abs(y_exact - result)