Solving second order differential equation in python - python

I want to solve second ODE's with the help of python.
The objective is:
d^2V/dx^2 = hsin(ex)
dV/dx = 0
Some info: L is the thickness of a plate, and it is equal to 5 mm. x is the position in the plate and goes from 0 to L. V is the electrical potential.
I dont understand how to put this in the code.
So far i have done this in python:
import numpy as np
from scipy.integrate import odeint
import math
rho_0 =3.3*10**16 #C/m^3
epsilon = 2.1*10**10 #Nm^2/C^2
L = 5*10**-3
h = rho_0/epsilon
e = (4*math.pi)/L
def dV_dx(x,V):
return [h*np.sin(e*x)]
t = np.linspace(0,1,100)
sol = odeint(model,y,t) #need to put in the 'model',and 'y' value above in the code
thanks in advance!

Related

What is the logic for parameter entry order in the initial state field of solve_ivp?

The van der Pol equation is:
d'' x/dt'' - mu*(1 - x**2)*dx/dt + x = 0
Since it is second order, it has to be reduced for Scipy's solve_ivp to be able to process it. So it gets converted to
dx/dt = v
plus
dv/dt = mu*(1 - x^2)*v - x
A video I have then continues with
import sympy as sp
import matplotlib.pyplot as plt
import numpy as np
def vdp_derivatives(t, y):
x = y[0]
v = y[1]
return [v, mu*(1 - x*x)*v - x]
t = np.linspace(0, 10, 500)
mu = 1
sol = solve_ivp(fun=vdp_derivatives, t_span=[t[0], t[-1]], y0=[1,0], t_eval=t)
and further. My question is about the initial state variable, the 'array-like' one. I do not understand why it was chosen as it was. Flipped order works too, though it offsets the plotted curve by about 1.5 along x. What decides, and what are the constraints? If someone has an answer, preferably extendable to other higher order situations, I would appreciate the info.

2nd order differential equation coupled to integro-differential equation in python

I'm trying to solve the following equations numerically in python
where f(r)=S*exp(-r^2/b^2) and µ and m_π are constants.
I have tried rewriting the 2nd order differential equation into two first order equations and solving the system of equations with root finding.
import numpy as np
from scipy.integrate import odeint
import matplotlib.pyplot as plt
from scipy.integrate import trapz
from scipy.optimize import root
b=1
S=20
m=135
mn = 939.5
mu = m*mn/(mn+m)
g = (2*mu)
def f(r):
return S*np.exp(-r**2/b**2)
def diff(phi,r,E):
return (phi[1],g*(-E+m)*phi[0]-2/r*phi[1]+g*f(r))
phi0 = [b/m,b/m] #Initial
def phi_fun(E):
rs = np.linspace(1e-5,50,1000)
ys = odeint(lambda phi,r: diff(phi,r,E), phi0, rs)
integral = 12*np.pi*trapz(ys[:,0]*f(rs)*rs**4,rs)
return integral - E
E_true = root(phi_fun, -2).x
rs = np.linspace(1e-5,50,1000)
ys = odeint(lambda phi,r: diff(phi,r,E_true), phi0, rs)
phi_true = ys[:,0]
plt.plot(rs, phi_true,linewidth=2,label=r'$\phi(r)$')
print("Minimum found at E =",E_true)
This does not produce a result I would expect and maybe I have done something wrong. I was thinking about using IDEsolver but I'm not sure how to implement this. Any suggestions?
Thanks in advance!

ODE boundary value problem with singularities

Here is a relatively simple boundary value problem solved with shooting method and Python
import numpy as np
from scipy.optimize import fsolve
from scipy.integrate import odeint
import matplotlib.pyplot as plt
%matplotlib inline
R = 0.5
ka = 6.4
De = 0.1
Cas = 0.2
def odefun(U, r):
Ca, Na = U
dCa = -Na/De
if np.abs(r) <= 1e-10:
dNa = ka/3*Ca
else:
dNa = -2/r*Na-ka*Ca
return [dCa, dNa]
r = np.linspace(0, R)
Na_0 = 0
Ca_R = 0.2
def objective(x):
U = odeint(odefun, [x, Na_0], r)
u = U[-1,0]-Ca_R
return u
x0 = 0.1 #initial guess
x, = fsolve(objective, x0)
print ("Ca_0=",x)
U = odeint(odefun, [x, Na_0], r)
print ("r=0 =>",U[0])
print ("r=R =>",U[-1])
plt.plot(t.value,Ca.value)
plt.plot(t.value,Na.value)
The system is singular at r=0 (divison by zero) and we took care about this by defining limiting dNa at the boundary r=0
dNa = ka/3*Ca
Other methods are possible to solve this numerically (using r as a small number at the boundary, dividing by r+small number)
Solving the same problem in Gekko ignoring the singular boundary problem might be this way
#Boundary value problem
import numpy as np
from gekko import GEKKO
import matplotlib.pyplot as plt
R = 0.5
ka = 6.4
De = 0.1
Cas = 0.2
Na_0 = 0
Ca_R = 0.2
m = GEKKO()
nt = 101
m.time = np.linspace(0,R,nt) # time points
Na = m.Var(Na_0) # known at r=0
Ca = m.Var(fixed_initial=False) # unknown at r=0
pi = np.zeros(nt)
pi[-1]=1
p = m.Param(value=pi)
# create GEEKO equations
t = m.Var(m.time)
m.Equation(t.dt() == 1)
m.Equation(Na.dt() == -2/t*Na-ka*Ca)
m.Equation(Ca.dt() == -Na/De)
m.Minimize(p*(Ca - Ca_R)**2) # minimizing at r=R
# solve ODE
m.options.IMODE = 6
m.options.NODES = 7
m.solve(disp=False)
# plot results
print ("r=0 =>",Ca[0],Na[0])
print ("r=R =>",Ca[-1],Na[-1])
plt.plot(r,U[:,1])
plt.plot(r,U[:,0])
Gekko will not complain about singularity at the boundary and will solve this.
Both Pythone and Gekko will solve this satisfying boundary conditions
Python
r=0 => [0.02931475 0. ]
r=R => [ 0.2 -0.12010739]
Gekko
r=0 => 0.029314856906 0.0
r=R => 0.2 -0.12010738377
I do not know how to include the singularity at he boundary in Gekko. On the other hand, Gekko gave the result, did not complain about the singularity and boundary conditions are satisfied Na(0)=0, Ca(R)=0.2.
I suppose that collocation method can successfully avoid the problem with singularities at the boundaries, but I would like the confirmation whether this is correct or not in Gekko - just to ignore it.
What could be done about this?
Best Regards,
Radovan
One way to overcome most divide-by-zero issues is to reform the equation by multiplying both sides by the denominator such as:
#m.Equation(Na.dt() == -2/t*Na-ka*Ca)
m.Equation(t*Na.dt() == -2*Na-t*ka*Ca)
When t=0, the equation is 0==-2*Na. With the initial condition Na.value=0 with Na = m.Var(Na_0), this equation is satisfied even though Gekko doesn't include the equations at the initial time point.
This isn't a problem but the valid range of nodes is 2 to 6 so when m.options.NODES = 7 the actual nodes used is 6.
Your problem looks correct. Try the m.fix_final(Ca,Ca_R) to ensure that the final condition is satisfied.

Make a chi-2 test and 3d spectral test with python LCG

I'm developping for my math stuff but I'm blocked. Here is the statement :
We denote by U and V two sequences of random floats, obtained using a random type generator in the interval [0,1].
If we combine the U and V sequences according to the transformation: Z = m + σ √(−2lnU) sin (2πV). We obtain a variable Z according to the law N (m, σ).
I want to obtain a normal distribution with mean m = 3 and standard deviation 1.
So, I've generated my array of 30 000 Z floats with :
def generateFloat(tr):
list = []
for i in range(tr):
list.append(random.uniform(0,1))
return list
def generateZ(nb,m,o):
U = generateFloat(nb)
V = generateFloat(nb)
tab = []
for i in range(nb):
Z = m+(o*sqrt(-2*log(U[i])) * sin (2*pi*V[i]) )
tab.append(Z)
return tab
I would like to make the chi-square test and do the 3D spectral test. Actually my chi-square test give me weird values...
def khi2(x):
S = 0
E = len(x)/(max(x))
print(max(x)-1)
for i in range(max(x)):
O = x[i]
S += ((O-E)**2)/E
return S
and for my 3d spectral test i have this code :
from mpl_toolkits import mplot3d
from matplotlib import pyplot
import numpy as np
fig = pyplot.figure()
ax = pyplot.axes()
num_bars = 30000
x_pos = genererFlottant(num_bars)
y_pos = genererFlottant(num_bars)
ax.scatter(x_pos, y_pos)
pyplot.show()
I think but i'm not sure about values that i obtened are good on my graph... And this isn't in 3d. So, i don't think it's a good graph
I don't know if i'm doing right. If someone can help me with something, i take any help that i can have :/
thank you.

Python solving 2nd order ODE with quad function

I am studying the dynamics of a damped, driven pendulum with second order ODE defined like so, and specifically I am progamming:
d^2y/dt^2 + c * dy/dt + sin(y) = a * cos(wt)
import numpy as np
import matplotlib.pyplot as plt
from scipy import integrate
def pendeq(t,y,a,c,w):
y0 = -c*y[1] - np.sin(y[0]) + a*np.cos(w*t)
y1 = y[1]
z = np.array([y0, y1])
return z
a = 2.1
c = 1e-4
w = 0.666667 # driving angular frequency
t = np.array([0, 5000]) # interval of integration
y = np.array([0, 0]) # initial conditions
yp = integrate.quad(pendeq, t[0], t[1], args=(y,a,c,w))
This problem does look quite similar to Need help solving a second order non-linear ODE in python, but I am getting the error
Supplied function does not return a valid float.
What am I doing wrong??
integrate.quad requires that the function supplied (pendeq, in your case) returns only a float. Your function is returning an array.

Categories

Resources