Need help solving second order nonlinear ODE in python

I do not know where to start with this problem, because I did not have much experience in this, but I need to solve this part of the project using a computer.

I have a 2nd order ODE:

m = 1220 k = 35600 g = 17.5 a = 450000 

and b is between 1000 and 10000 in increments of 500.

 x(0)= 0 x'(0)= 5 m*x''(t) + b*x'(t) + k*x(t)+a*(x(t))^3 = -m*g 

I need to find the smallest value of b so that the solution is never positive. I know what a graph should look like, but I just don't know how to use odeint to solve a differential equation. This is the code that I still have:

 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() 

Which really doesn’t produce anything.

Any thoughts? Thanks

+6
source share
2 answers

To solve a second-order ODE using scipy.integrate.odeint , you must write it as a first-order ODE system:

I define z = [x', x] , then z' = [x'', x'] , and your system! Of course, you should connect your real relationship:

 x'' = -(b*x'(t) + k*x(t) + a*(x(t))^3 + m*g) / m 

becomes:

z[0]' = -1/m * (b*z[0] + k*z[1] + a*z[1]**3 + m*g)
z[1]' = z[0]

Or just call it 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]' )) 

Now you can send it to odeint as follows:

 _, x = odeint(d, x0, t).T 

( _ is the empty placeholder for the x' variable we made)

To minimize b , provided that the maximum of x always negative, you can use scipy.optimize.minimize . I implement it by actually maximizing the maximum of x , provided that the constraint remains negative, because I cannot figure out how to minimize the parameter without the ability to invert the function.

 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) 
+7
source

I don’t think you can solve your problem as indicated: your initial conditions, with x = 0 and x' > 0 imply that the solution will be positive for some values ​​very close to the starting point. So there is no b for which the solution is never positive ...

Leaving this aside, in order to solve the second-order differential equation, we first need to rewrite it as a system of two first-order differential equations. By defining y = x' , we can rewrite your only equation as follows:

 x' = y y' = -b/m*y - k/m*x - a/m*x**3 - g x[0] = 0, y[0] = 5 

So your function should look something like this:

 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]) 

And you can solve and build your equations:

 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() 

enter image description here

+4
source

Source: https://habr.com/ru/post/957389/


All Articles