开发一个 ode 积分器步进器
Develop a ode integrator stepper
我正在创建一个 class 以便对不同的问题执行多个操作(例如求解、绘图、将解决方案保存到文件中)
步进器是更重要的部分,我想将我的代码从简单的 class 方法修改为生成器
这里是我的可用代码快照:
import numpy as np
first_startup , second_startup, third_startup = True, True, True
um1,um2,um3 = 0.,0.,0.
def step(f , t : np.float , u : np.float , dt):
global first_startup , second_startup, third_startup
global um1,um2,um3
if first_startup:
um3 = u.copy()
unext = u + dt*f(t,u) #rungekutta.RK4.step(func,t,um2,dt)
t += dt
first_startup = False
elif second_startup:
um2 = u.copy()
unext = unext = u + dt*f(t,u) #rungekutta.RK4.step(func,t,um2,dt)
t+= dt
second_startup = False
elif third_startup:
um1 = u.copy()
unext = u + dt*f(t,u) #rungekutta.RK4.step(func,t,um1,dt)
t += dt
third_step = False
else: # compute AB 4th order
unext = u + dt/24.* ( 55.*f(t,u) - 59.*f(t-dt,um1) + 37.*f(t-dt-dt,um2) \
- 9.*f(t-dt-dt,um3 ))
um3 = um2.copy()
um2 = um1.copy()
um1 = u.copy()
return unext
def main():
func = lambda t,u : -10*(t-1)*u
t0 = 0.
tf = 2.
dt = 2/50
u = np.exp(-5)
t = t0
with open('output.dat', 'w') as f:
while True:
f.write('%f %f \n' %(t, u) )
u = step(func,t,u,dt)
t += dt
if t > tf:
break
if __name__ == '__main__':
main()
可以创建一个生成器,在步进器上进行 3 次调用,返回 if、elif、else 块内的计算值(这里我写了一个简单的方法,但在步进器中我对调用进行了注释)如果是,是个好主意,我该怎么做?
EDIT jdowner 我已经注释掉了对 运行ge-kutta 的调用,因为我只会提供一个最小的工作代码来调用 运行ge -kutta 用于启动多步(4 步所以我需要计算 3 点才能启动该方法)
EDIT Ilia L 但在多步方法的 运行 期间我也需要这 3 个变量.. 查看 for
编辑
我收到这个错误:
Traceback (most recent call last):
File "drive.py", line 377, in <module>
main()
File "drive.py", line 224, in main
f.write('%f %f \n' %(t, u) ) # u[0]) )
TypeError: must be real number, not generator
如果你想使用生成器执行上述计算,我会这样写,
def step(f, t, u, dt):
um3 = u
yield u + dt * f(t, u)
um2 = u
yield u + dt * f(t, u)
um1 = u
yield u + dt * f(t, u)
while True:
k1 = 55.0 * f(t, u)
k2 = 59.0 * f(t - dt, um1)
k3 = 37.0 * f(t - 2 * dt, um2)
k4 = 9.0 * f(t - 2 * dt, um3)
yield u + dt * (k1 - k2 + k3 - k4) / 24.0
um3 = um2
um2 = um1
um1 = u
我正在创建一个 class 以便对不同的问题执行多个操作(例如求解、绘图、将解决方案保存到文件中) 步进器是更重要的部分,我想将我的代码从简单的 class 方法修改为生成器
这里是我的可用代码快照:
import numpy as np
first_startup , second_startup, third_startup = True, True, True
um1,um2,um3 = 0.,0.,0.
def step(f , t : np.float , u : np.float , dt):
global first_startup , second_startup, third_startup
global um1,um2,um3
if first_startup:
um3 = u.copy()
unext = u + dt*f(t,u) #rungekutta.RK4.step(func,t,um2,dt)
t += dt
first_startup = False
elif second_startup:
um2 = u.copy()
unext = unext = u + dt*f(t,u) #rungekutta.RK4.step(func,t,um2,dt)
t+= dt
second_startup = False
elif third_startup:
um1 = u.copy()
unext = u + dt*f(t,u) #rungekutta.RK4.step(func,t,um1,dt)
t += dt
third_step = False
else: # compute AB 4th order
unext = u + dt/24.* ( 55.*f(t,u) - 59.*f(t-dt,um1) + 37.*f(t-dt-dt,um2) \
- 9.*f(t-dt-dt,um3 ))
um3 = um2.copy()
um2 = um1.copy()
um1 = u.copy()
return unext
def main():
func = lambda t,u : -10*(t-1)*u
t0 = 0.
tf = 2.
dt = 2/50
u = np.exp(-5)
t = t0
with open('output.dat', 'w') as f:
while True:
f.write('%f %f \n' %(t, u) )
u = step(func,t,u,dt)
t += dt
if t > tf:
break
if __name__ == '__main__':
main()
可以创建一个生成器,在步进器上进行 3 次调用,返回 if、elif、else 块内的计算值(这里我写了一个简单的方法,但在步进器中我对调用进行了注释)如果是,是个好主意,我该怎么做?
EDIT jdowner 我已经注释掉了对 运行ge-kutta 的调用,因为我只会提供一个最小的工作代码来调用 运行ge -kutta 用于启动多步(4 步所以我需要计算 3 点才能启动该方法)
EDIT Ilia L 但在多步方法的 运行 期间我也需要这 3 个变量.. 查看 for
编辑 我收到这个错误:
Traceback (most recent call last):
File "drive.py", line 377, in <module>
main()
File "drive.py", line 224, in main
f.write('%f %f \n' %(t, u) ) # u[0]) )
TypeError: must be real number, not generator
如果你想使用生成器执行上述计算,我会这样写,
def step(f, t, u, dt):
um3 = u
yield u + dt * f(t, u)
um2 = u
yield u + dt * f(t, u)
um1 = u
yield u + dt * f(t, u)
while True:
k1 = 55.0 * f(t, u)
k2 = 59.0 * f(t - dt, um1)
k3 = 37.0 * f(t - 2 * dt, um2)
k4 = 9.0 * f(t - 2 * dt, um3)
yield u + dt * (k1 - k2 + k3 - k4) / 24.0
um3 = um2
um2 = um1
um1 = u