Solve Integro-Differential equation in Python - python

I am trying to solve a physics problem that involves the following equation,
As you can see, sigma could be any function and K1 is a Bessel function. The differential equation has to be solved for Y(x), but x is involved in the integral. In addition, we have another parameter m being a free parameter in the integral and outside the integral. Do you have any idea to solve this?
Sympy does not solve this since it has no analytical solution.
My idea was the following,
I write the integral as a function of x, m.
def get_integral(x,m):
integrand = lambda s: f(s,x,m)
integral = quad(integrand,4*m**2, + np.inf)[0]
return integral
Then write the derivative,
def dYdx(x,Y,m):
x1 = f(x,m))
x2 = get_integral(x,m)
x3 = Y**2-Y_0(x,m)**2
return x1*x2*x3
So I use odeint to solve it like,
solution = odeint(dYdx, y0=0, t = x_array,tfirst=True,args =(m,))
But as you can see I need to solve it for different values of x,s, and m. So that I have an array having the following structure
solution_array = [x,Y,m,integral_value]
for each time I evaluate x and m.

Related

How to solve separable differential equation using Sympy?

I cannot figure out how to solve this separable differential equation using sympy. Help would be greatly appreciated.
y′=(y−4)(y−2),y(0)=5
Here was my attempt, thanks in advance!!!
import sympy as sp
x,y,t = sp.symbols('x,y,t')
y_ = sp.Function('y_')(x)
diff_eq = sp.Eq(sp.Derivative(y_,x), (y-4)*(y-2))
ics = {y_.subs(x,0):5}
sp.dsolve(diff_eq, y_, ics = ics)
the output is y(x) = xy^2 -6xy +8x + 5
The primary error is the introduction of y_. This makes the variable y a constant parameter of the ODE and you get the wrong solution.
If you correct this you get an error of "too many solutions for the integration constant". This is a bug caused by not simplifying the integration constant after it first occurs. So multiplication and addition of constants should just be absorbed, an additive constant in an exponent should become a multiplicative factor for the exponential. As it is, exp(2*C_1)==3 has two solutions if C_1 is considered as an angle (it's a bit of tortured logic from computing roots in the complex plane).
The newer versions can actually solve this fully if you give the third hint in the classification list 'separable', '1st_exact', '1st_rational_riccati', ... that does something different than partial fraction decomposition of the first two
from sympy import *
x = Symbol('x')
y = Function('y')(x)
dsolve(Eq(y.diff(x), (y-2)*(y-4)),y,
ics={y.subs(x,0):5},
hint='1st_rational_riccati')
returning
\displaystyle y{\left(x \right)} = \frac{2 \cdot \left(6 - e^{2 x}\right)}{3 - e^{2 x}}

Find inverse function of solution found through odeint

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)

How to solve this system of IVP differential equations

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.

Is there a way to integrate and get an array or a function instead of all the area under the curve?

I want to integrate the following equation:
d^2[Ψ(z)] / dz^2 = A * ρ(z)
Where Ψ (unknown) and ρ (known) are 1-D arrays and A is a constant.
I have already performed a Taylor expansion, i.e.
d^2[Ψ(z_0)] / dz^2 = [Ψ(z0+Δz) - 2Ψ(z0) + Ψ(z0-Δz)] / [Δz^2]
And successfully solve it by building a matrice.
Now, I would like to know if there is a Python (preferably) or Matlab function that can solve this function without having to do a Taylor expansion.
I have tried numpy.trapz and scipy.integrate.quad, but it seems that these functions only return the area under the curve, i.e. a number, and I am interested to get an array or a function (solving for Ψ).
What you want to do is to solve the differential equation. Because it is a second order differential equation, you should modify your function to make it a system of first order ODEs. So you have to create a function like this:
Assuming ρ=rho
def f(z, y):
return np.array([y[1], A*rho(z)])
where y is a vector containing Ψ in the first position and its derivative in the second position. Then, f returns a vector containing the first and second derivatives of Ψ.
Once done that, you can use scipy.integrate.solve_ivp to solve the problem:
scipy.integrate.solve_ivp(f, [z_start, z_final], y0, method='RK45', z_eval)
where y0 are the initial conditions of Ψ (the value of Ψ and its derivative at z_start). z_eval is the points where you want to store the solution. The solution will be an array containing the values of Ψ and its derivative.
You could integrate rho twice using an indefinite integral . e.g.
import numpy as np
x=np.arange(0,3.1,0.1)
rho = x**3 # replace your rho here....
indef_integral1 = [np.trapz(rho[0:i],x[0:i]) for i in range(2,len(rho))]
indef_integral2 = [np.trapz(indef_integral1[0:i],x[0:i]) for i in range(2,len(indef_integral1))]

Is there a way to setup and solve multiple numerical integration in scipy like in mathematica?

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

Categories