使用Vertel算法求解微分方程触发'int' object is not subscriptable报错求助
Vertel算法代码报错排查与修复
核心报错原因
代码在计算加速度的行触发如下报错:
'int' object is not subscriptable
直接触发原因是:代码对int类型的变量执行了下标取值操作。你传入的x0、v0、初始时间t都是整数,代码直接把整数赋值给x、v、t变量后,后续用x[i]、v[i]、t[i]做索引取值,整数不支持下标操作,就会直接抛错。
逐点问题与修复方案
- 变量类型不匹配
你当前代码中初始化逻辑为x = x0、v = v0、t = t,传入的三个值都是单整数,但后续逻辑需要对这三个变量执行append()追加元素、按下标取历史值的操作,必须把单个初始值转成带初始元素的列表才能支持这类操作。
替换为以下初始化逻辑即可匹配类型要求:x = [x0] v = [v0] t = [t] - 循环逻辑与缩进错误
原代码的while循环块没有做缩进,Python语法中循环体必须缩进才能被正常执行;同时原循环判断条件while t <= tstop,在t改成列表后不能直接和整数比较大小,需要取列表最后一个元素做判断,修正后的循环头为:
所有循环内的计算、逻辑判断、列表追加操作都要缩进放到这个循环块内部。while t[-1] <= tstop: - 变量逻辑混乱
原代码同时存在两种时间操作逻辑:既写了t.append(t[i] + dt)要把时间存成列表,又写了t = t + dt要把时间当整数累加,两种逻辑完全冲突。直接删掉多余的t = t + dt行,统一用列表存储所有时间步的取值即可。 - Verlet公式笔误
原递推公式中写的a* dt** dt是输入错误,标准Verlet算法的递推项是加速度乘时间步长的平方,正确写法为:x_next = 2* x[i] - x[i-1] + a * dt**2 - 函数参数未实际生效
原函数定义的质量参数M=1没有被实际使用,计算加速度时硬编码了m=1、弹簧力系数的逻辑;同时传入的右端项参数pravastrana完全没有参与计算。需要把加速度计算逻辑替换为调用传入的右端项,真正用上自定义参数:# 移除硬编码的k、m,用传入的参数计算加速度 a = pravastrana(x[i], v[i], t[i]) / M - 列表追加逻辑漏写
原代码只追加了x和t的列表,没有把计算出的v_next追加到速度列表里,后续循环取下标时会出现索引越界。统一把每一步计算得到的x_next、v_next、新时间点追加到对应列表:x.append(x_next) v.append(v_next) t.append(t[-1] + dt) i += 1
修正后的可运行参考代码
def Vertel(dt, x0, v0, t0, tstop, pravastrana, M=1): # 初始化带初始元素的列表,支持下标取值和追加 x = [x0] v = [v0] t = [t0] i = 0 while t[-1] <= tstop: # 调用传入的右端项计算加速度 a = pravastrana(x[i], v[i], t[i]) / M if i == 0: v_next = v[i] + a * dt x_next = x[i] + v_next * dt else: x_next = 2 * x[i] - x[i-1] + a * dt**2 # 由位置递推反推当前步速度 v_next = (x_next - x[i-1]) / (2 * dt) # 统一追加所有计算结果到列表 x.append(x_next) v.append(v_next) t.append(t[-1] + dt) i += 1 return x, t # 示例:定义弹簧力右端项,调用函数 def spring_force(x, v, t): k = 1 return -k * x x_res, t_res = Vertel(0.1, 1, 0, 0, 10, spring_force) print(x_res, t_res)
内容的提问来源于stack exchange,提问作者Nitaa a
相关产品推荐
相关产品推荐

