我真的不知道从哪里开始这个问题,因为我没有太多经验,但需要使用计算机解决项目的这一部分。
我有二阶ODE,即:
m = 1220
k = 35600
g = 17.5
a = 450000
和b介于1000和10000之间,增量为500。
x(0)= 0
x'(0)= 5
m*x''(t) + b*x'(t) + k*x(t)+a*(x(t))^3 = -m*g
我需要找到最小的b,这样解决方案永远不会是积极的。我知道图形应该是什么样的,但我只是不知道如何使用odeint来获得微分方程的解。 这是我到目前为止的代码:
from numpy import *
from matplotlib.pylab import *
from scipy.integrate import odeint
m = 1220.0
k = 35600.0
g = 17.5
a = 450000.0
x0= [0.0,5.0]
b = 1000
tmax = 10
dt = 0.01
def fun(x, t):
return (b*x[1]-k*x[0]-a*(x[0]**3)-m*g)*(1.0/m)
t_rk = arange(0,tmax,dt)
sol = odeint(fun, x0, t_rk)
plot(t_rk,sol)
show()
这并没有真正产生太多任何东西。
有什么想法?感谢
答案 0 :(得分:10)
要使用scipy.integrate.odeint
解决二阶ODE,您应该将其编写为一阶ODE系统:
我将定义z = [x', x]
,然后定义z' = [x'', x']
,那就是你的系统!当然,你必须插入你真实的关系:
x'' = -(b*x'(t) + k*x(t) + a*(x(t))^3 + m*g) / m
变为:
z[0]' = -1/m * (b*z[0] + k*z[1] + a*z[1]**3 + m*g)
z[1]' = z[0]
或者,只需将其称为d(z)
:
def d(z, t):
return np.array((
-1/m * (b*z[0] + k*z[1] + a*z[1]**3 + m*g), # this is z[0]'
z[0] # this is z[1]'
))
现在您可以将其提供给odeint
:
_, x = odeint(d, x0, t).T
(_
是我们制作的x'
变量的空白占位符。
为了最大限度地减少b
受限制,x
的最大值始终为负,您可以使用scipy.optimize.minimize
。我将通过实际最大化x
的最大值来实现它,但受限于它仍为负值,因为我无法想到如何在不能反转函数的情况下最小化参数。
from scipy.optimize import minimize
from scipy.integrate import odeint
m = 1220
k = 35600
g = 17.5
a = 450000
z0 = np.array([-.5, 0])
def d(z, t, m, k, g, a, b):
return np.array([-1/m * (b*z[0] + k*z[1] + a*z[1]**3 + m*g), z[0]])
def func(b, z0, *args):
_, x = odeint(d, z0, t, args=args+(b,)).T
return -x.max() # minimize negative max
cons = [{'type': 'ineq', 'fun': lambda b: b - 1000, 'jac': lambda b: 1}, # b > 1000
{'type': 'ineq', 'fun': lambda b: 10000 - b, 'jac': lambda b: -1}, # b < 10000
{'type': 'ineq', 'fun': lambda b: func(b, z0, m, k, g, a)}] # func(b) > 0 means x < 0
b0 = 10000
b_min = minimize(func, b0, args=(z0, m, k, g, a), constraints=cons)
答案 1 :(得分:6)
我认为你不能解决你所说的问题:你的初始条件x = 0
和x' > 0
意味着解决方案对于非常接近起点的某些值是正的。所以没有b
解决方案永远不会是正面的......
除此之外,要解决二阶微分方程,首先需要将其重写为两个一阶微分方程组。定义y = x'
我们可以将您的单个等式重写为:
x' = y
y' = -b/m*y - k/m*x - a/m*x**3 - g
x[0] = 0, y[0] = 5
所以你的函数应该是这样的:
def fun(z, t, m, k, g, a, b):
x, y = z
return np.array([y, -(b*y + (k + a*x*x)*x) / m - g])
你可以解决并绘制你的方程式:
m, k, g, a = 1220, 35600, 17.5, 450000
tmax, dt = 10, 0.01
t = np.linspace(0, tmax, num=np.round(tmax/dt)+1)
for b in xrange(1000, 10500, 500):
print 'Solving for b = {}'.format(b)
sol = odeint(fun, [0, 5], t, args=(m, k, g, a, b))[..., 0]
plt.plot(t, sol, label='b = {}'.format(b))
plt.legend()