在 scipy.integrate.odeint 中输出达到 0 时停止积分
Stop Integrating when Output Reaches 0 in scipy.integrate.odeint
我编写了一段代码,用于查看带有拖动的对象的抛射运动。我正在使用 scipy 中的 odeint 来执行正向欧拉方法。集成一直运行到达到时间限制为止。当达到此限制或当 ry = 0 的输出(即射弹已着陆)时,我想停止积分。
def f(y, t):
# takes vector y(t) and time t and returns function y_dot = F(t,y) as a vector
# y(t) = [vx(t), vy(t), rx(t), ry(t)]
# magnitude of velocity calculated
v = np.sqrt(y[0] ** 2 + y[1] **2)
# define new drag constant k
k = cd * rho * v * A / (2 * m)
return [-k * y[0], -k * y[1] - g, y[0], y[1]]
def solve_f(v0, ang, h0, tstep, tmax=1000):
# uses the forward Euler time integration method to solve the ODE using f function
# create vector for time steps based on args
t = np.linspace(0, tmax, tmax / tstep)
# convert angle from degrees to radians
ang = ang * np.pi / 180
return odeint(f, [v0 * np.cos(ang), v0 * np.sin(ang), 0, h0], t)
solution = solve_f(v0, ang, h0, tstep)
我已经尝试了几个循环和类似的尝试在 ry = 0 时停止积分。并在下面发现了这个问题,但无法使用 odeint 实现类似的东西。 solution[:,3] 是 ry 的输出列。有没有一种简单的方法可以用 odeint 做到这一点?
- Does scipy.integrate.ode.set_solout work?
结账 scipy.integrate.ode
here。它比 odeint
更灵活,可以帮助您完成您想做的事情。
使用垂直镜头的简单示例,集成直到它触及地面:
from scipy.integrate import ode, odeint
import scipy.constants as SPC
def f(t, y):
return [y[1], -SPC.g]
v0 = 10
y0 = 0
r = ode(f)
r.set_initial_value([y0, v0], 0)
dt = 0.1
while r.successful() and r.y[0] >= 0:
print('time: {:.3f}, y: {:.3f}, vy: {:.3f}'.format(r.t + dt, *r.integrate(r.t + dt)))
每次调用r.integrate
,r
都会存储当前时间和y值。如果要存储它们,可以将它们传递给列表。
让我们将其作为边值问题来解决。我们有条件 x(0)=0, y(0)=h0, vx(0)=0, vy(0)=0
和 y(T)=0
。要有一个固定的积分间隔,设置 t=T*s
,这意味着 dx/ds=T*dx/dt=T*vx
等
def fall_ode(t,u,p):
vx, vy, rx, ry = u
T = p[0]
# magnitude of velocity calculated
v = np.hypot(vx, vy)
# define new drag constant k
k = cd * rho * v * A / (2 * m)
return np.array([-k * vx, -k * vy - g, vx, vy])*T
def solve_fall(v0, ang, h0):
# convert angle from degrees to radians
ang = ang * np.pi / 180
vx0, vy0 = v0*np.cos(ang), v0*np.sin(ang)
def fall_bc(y0, y1, p): return [ y0[0]-vx0, y0[1]-vy0, y0[2], y0[3]-h0, y1[3] ]
t_init = [0,1]
u_init = [[0,0],[0,0],[0,0], [h0,0]]
p_init = [1]
res = solve_bvp(fall_ode, fall_bc, t_init, u_init, p_init)
print res.message
if res.success:
print "time to ground: ", res.p[0]
# res.sol is a dense output, evaluation interpolates the computed values
return res.sol
sol = solve_fall(300, 30, 20)
s = np.linspace(0,1,501)
u = sol(s)
vx, vy, rx, ry = u
plt.plot(rx, ry)
我编写了一段代码,用于查看带有拖动的对象的抛射运动。我正在使用 scipy 中的 odeint 来执行正向欧拉方法。集成一直运行到达到时间限制为止。当达到此限制或当 ry = 0 的输出(即射弹已着陆)时,我想停止积分。
def f(y, t):
# takes vector y(t) and time t and returns function y_dot = F(t,y) as a vector
# y(t) = [vx(t), vy(t), rx(t), ry(t)]
# magnitude of velocity calculated
v = np.sqrt(y[0] ** 2 + y[1] **2)
# define new drag constant k
k = cd * rho * v * A / (2 * m)
return [-k * y[0], -k * y[1] - g, y[0], y[1]]
def solve_f(v0, ang, h0, tstep, tmax=1000):
# uses the forward Euler time integration method to solve the ODE using f function
# create vector for time steps based on args
t = np.linspace(0, tmax, tmax / tstep)
# convert angle from degrees to radians
ang = ang * np.pi / 180
return odeint(f, [v0 * np.cos(ang), v0 * np.sin(ang), 0, h0], t)
solution = solve_f(v0, ang, h0, tstep)
我已经尝试了几个循环和类似的尝试在 ry = 0 时停止积分。并在下面发现了这个问题,但无法使用 odeint 实现类似的东西。 solution[:,3] 是 ry 的输出列。有没有一种简单的方法可以用 odeint 做到这一点?
- Does scipy.integrate.ode.set_solout work?
结账 scipy.integrate.ode
here。它比 odeint
更灵活,可以帮助您完成您想做的事情。
使用垂直镜头的简单示例,集成直到它触及地面:
from scipy.integrate import ode, odeint
import scipy.constants as SPC
def f(t, y):
return [y[1], -SPC.g]
v0 = 10
y0 = 0
r = ode(f)
r.set_initial_value([y0, v0], 0)
dt = 0.1
while r.successful() and r.y[0] >= 0:
print('time: {:.3f}, y: {:.3f}, vy: {:.3f}'.format(r.t + dt, *r.integrate(r.t + dt)))
每次调用r.integrate
,r
都会存储当前时间和y值。如果要存储它们,可以将它们传递给列表。
让我们将其作为边值问题来解决。我们有条件 x(0)=0, y(0)=h0, vx(0)=0, vy(0)=0
和 y(T)=0
。要有一个固定的积分间隔,设置 t=T*s
,这意味着 dx/ds=T*dx/dt=T*vx
等
def fall_ode(t,u,p):
vx, vy, rx, ry = u
T = p[0]
# magnitude of velocity calculated
v = np.hypot(vx, vy)
# define new drag constant k
k = cd * rho * v * A / (2 * m)
return np.array([-k * vx, -k * vy - g, vx, vy])*T
def solve_fall(v0, ang, h0):
# convert angle from degrees to radians
ang = ang * np.pi / 180
vx0, vy0 = v0*np.cos(ang), v0*np.sin(ang)
def fall_bc(y0, y1, p): return [ y0[0]-vx0, y0[1]-vy0, y0[2], y0[3]-h0, y1[3] ]
t_init = [0,1]
u_init = [[0,0],[0,0],[0,0], [h0,0]]
p_init = [1]
res = solve_bvp(fall_ode, fall_bc, t_init, u_init, p_init)
print res.message
if res.success:
print "time to ground: ", res.p[0]
# res.sol is a dense output, evaluation interpolates the computed values
return res.sol
sol = solve_fall(300, 30, 20)
s = np.linspace(0,1,501)
u = sol(s)
vx, vy, rx, ry = u
plt.plot(rx, ry)