I have numerically integrated a system of differential equations and now want to invert the solution in order to use it later in my code. Any help will be greatly appreciated.
System of differential equations:
def evolution(a,z):
w=0
q,y,h,v,x=a
dq = -(2*q**2+q-1)/(z+1)
dx = -(-x*(x-q)+2*(x+q)-3*(-v+x+q)+2)/(z+1)
dy = (2*q**2+q-1)/(z+1)
dv = (-x*(x-q)+2*(x+q)-3*(-v+x+q)+2+(-v+x+q)*(x-2*q+1)+2*q**2+q-1)/(z+1)
dh=h*(1+q)/(z+1)
dadt = [dq,dy,dh,dv,dx]
return dadt
Initial conditions: (Note that I take the initial conditions at z=20 and integrate backwards)
x0=0
h0=54.0176
q0=0.499
y0=1-q0
v0=0.5
N=3000
t=np.linspace(20.0,0.0,N)
a0=[q0,y0,h0,v0,x0]
sol=odeint(evolution,a0,t)
plt.plot(t,sol[:,1])
plt.show()
I am essentially plotting y=R(z) and want to get z(R) so that I can solve the differential equation v(z(R))=f/f'(R) i.e. get f(R)
Related
How do we solve a system of linear equations in Python and NumPy:
We have a system of equations and there is the right side of the
values after the equal sign. We write all the coefficients into the
matrix matrix = np.array(...),, and write the
right side into the vector vector = np.array(...) and then
use the command np.linalg.solve(matrix, vector) to find the
variables.
But if I have derivatives after the equal sign and I want to do the same with the system of differential equations, how can I implement this?
(Where are the lambda known values, and I need to find A
P.S. I saw the use of this command y = odeint(f, y0, t) from the library scipy but I did not understand how to set my own function f if I have a matrix there, what are the initial values y0 and what t?
You can solve your system with the compact form
t = arange(t0,tf,h)
solX = odeint(lambda X,t: M.dot(X), X0, t)
after setting the parameters and initial condition.
For advanced use set also the absolute and relative error thresholds according to the scale of the state vector and the desired accuracy.
I have a system of differential equations like this
dy/dt = f(t,y,y1,y2,....,yn,x),
dy1/dt = f(t,y,y1,y2,..yn,x),
.
.
.
dyn/dt = f(t,y,y1,y2,..yn,x),
x(t) = f(t,y1,y2,...yn,x)
And I have the values y_i(0),x(0)
If I had dx/dt then simply using scipy.integrate IVP I could solve this. I can't calculate the derivative of x(t) it's too complex . Can I simulate this system in python without finding dx/dt ?
No problem, define
def derivatives(t,y):
xt = func_x(t,y);
dy = func_y(t,y,xt)
return dy
where func_y takes scalar (t,xt) and vector (y) arguments and returns a vector of the same size as y. This then works well with solve_ivp.
I have solved a single second order differential equation with two boundary conditions using the module solve_bvp. However, now I am trying to solve the system of two second order differential equations;
U'' + a*B' = 0
B'' + b*U' = 0
with the boundary conditions U(+/-0.5) = +/-0.01 and B(+/-0.5) = 0. I have split this into a system of first ordinary differential equations and I am trying to use solve_bvp to solve them numerically. However, I am just getting arrays full of zeros for my solution. I believe I am implementing the boundary conditions wrong. It is not clear to me how to handle more than two equations from the documentation. My attempt is below
import numpy as np
from scipy.integrate import solve_bvp
import matplotlib.pyplot as plt
%matplotlib inline
from scipy.integrate import solve_bvp
alpha = 1E-8
zeta = 8E-3
C_k = 0.05
sigma = 0.01
def fun(x, y):
return np.vstack((y[1],-((alpha)/(C_k*sigma))*y[2],y[2], -(1/(C_k*zeta))*y[1]))
def bc(ya, yb):
return np.array([ya[0]+0.001, yb[0]-0.001,ya[0]-0, yb[0]-0])
x = np.linspace(-0.5, 0.5, 5000)
y = np.zeros((4, x.size))
print(y)
sol = solve_bvp(fun, bc, x, y)
print(sol)
In my question I have just relabeled a and b, but they're just parameters that I input. I have the analytic solution for this set of equations so I know one exists that is non-trivial. Any help would be greatly appreciated.
It is most times really helpful if you state at least once in a comment or by assignment to specifically named variables how you want to compose the state vector.
By the form of the derivative return vector, I would think you intend
U, U', B, B'
which means that U=y[0], U'=y[1] and B=y[2],B'=y[3], so that your derivatives vector should correctly be
return y[1], -((alpha)/(C_k*sigma))*y[3], y[3], -(1/(C_k*zeta))*y[1]
and the boundary conditions
return ya[0]+0.001, yb[0]-0.001, ya[2]-0, yb[2]-0
Especially your boundary condition should throw the algorithm in the first step because of a singular Jacobian, always check the .success field and the .message field of the solution structure.
Note that by default the absolute and relative tolerance of the experimental solve_bvp is 1e-3, and the number of nodes is limited to 500.
Setting the initial node number to 50 (5000 is much too much, the solver refines where necessary), and the tolerance to 1-6, I get the following solution plots that visibly satisfy the boundary conditions.
I would like to solve the following formulas numerically in Python;
In Mathematica, you can input multiple differential equations and solve it at the same time. Is there a way to do the similar thing with Scipy?
edit: yes, I have looked at scipy.integrate.odeint already, but I'm still not sure how I can solve multiple equations that correlates each other at the same time. Does anyone have suggestion for that?
Eventually I figured out myself and I'm writing down for other people who might be clueless like me;
in odeint, you give three parameters model, y, and t where model is a function that takes in y and t then return dydt, y is the initial value of y, and t is the variable you're trying to take integral over. If you have multiple differential equations that are dependent on each other, you can just pass in all of them to odeint. In my case,
t = np.linspace(0, 20) # range of t
y0 = [No_0, Na_0, Ni_0, Nn_0] # initial condition for each Ns
def model(y, t):
No, Na, Ni, Nn = y
dNodt = -k_oa * No
dNadt = k_oa * No - k_ai * Na
dNidt = k_ai * Na - k_in * Ni
dNndt = k_in * Ni
return [dNodt, dNadt, dNidt, dNndt]
y = odeint(model, y0, t)
You can define multiple differential equations you want to solve within the model you define, and pass in to odeint along with the initial values for all species.
Have a loot at SciPy's Integration package:
https://docs.scipy.org/doc/scipy/reference/integrate.html
specifically at odeint to solve systems of ODE's:
https://docs.scipy.org/doc/scipy/reference/generated/scipy.integrate.odeint.html#scipy.integrate.odeint
I have a university project in which we are asked to simulate a satellite approach to Mars using ODE's and SciPy's odeint function.
I manage to simulate it in 2D by making a second-order ODE into two first-order ODE's. However I am stuck in the time limitation because my code is using SI units therefore running in seconds and Python's linspace limits does not even simulate one complete orbit.
I tried converting the variables and constants to hours and kilometers but now the code keeps giving errors.
I followed this method:
http://bulldog2.redlands.edu/facultyfolder/deweerd/tutorials/Tutorial-ODEs.pdf
And the code is:
import numpy
import scipy
from scipy.integrate import odeint
def deriv_x(x,t):
return array([ x[1], -55.3E10/(x[0])**2 ]) #55.3E10 is the value for G*M in km and hours
xinit = array([0,5251]) # this is the velocity for an orbit of period 24 hours
t=linspace(0,24.0,100)
x=odeint(deriv_x, xinit, t)
def deriv_y(y,t):
return array([ y[1], -55.3E10/(y[0])**2 ])
yinit = array([20056,0]) # this is the radius for an orbit of period 24 hours
t=linspace(0,24.0,100)
y=odeint(deriv_y, yinit, t)
I don't know how to copy/paste the error code from PyLab so I took a PrintScreen of the error:
Second error with t=linspace(0.01,24.0,100) and xinit=array([0.001,5251]):
If anyone has any suggestions on how to improve the code I will be very grateful.
Thank you very much!
odeint(deriv_x, xinit, t)
uses xinit as its initial guess for x. This value for x is used when evaluating deriv_x.
deriv_x(xinit, t)
raises a divide-by-zero error since x[0] = xinit[0] equals 0, and deriv_x divides by x[0].
It looks like you are trying to solve the second-order ODE
r'' = - C rhat
---------
|r|**2
where rhat is the unit vector in the radial direction.
You appear to be separating the x and y coordinates into separate second-order ODES:
x'' = - C y'' = - C
----- and -----
x**2 y**2
with initial conditions x0 = 0 and y0 = 20056.
This is very problematic. Among the problems is that when x0 = 0, x'' blows up. The original second-order ODE for r'' does not have this problem -- the denominator does not blow up when x0 = 0 because y0 = 20056, and so r0 = (x**2+y**2)**(1/2) is far from zero.
Conclusion: Your method of separating the r'' ODE into two ODEs for x'' and y'' is incorrect.
Try searching for a different way to solve the r'' ODE.
Hint:
What if your "state" vector is z = [x, y, x', y']?
Can you write down a first-order ODE for z' in terms of x, y,
x' and y'?
Can you solve it with one call to integrate.odeint?