I am trying to solve a 4th order bvp using the bvp solver in Python. The differential equation is of the form given below :-
d4w(x)/dx4=t/(t-w(x))
with boundary conditions w(0)=w(10)=w'(0)=w'(10)=0 . If t in the differential equation is a simple constant, the code is simple and is given by
import numpy as np
from scipy.integrate import odeint
import matplotlib.pyplot as plt
from scipy.integrate import solve_bvp
t=1
def fun(x, y):
return np.vstack([y[1], y[2], y[3], t/(t-y[0])])
def bc(ya, yb) :
return np.array([ya[0], ya[1], yb[0], yb[1]])
xmesh = np.linspace(0, 10, 100)
y = np.zeros((4, len(xmesh)))
sol = solve_bvp(fun, bc, xmesh, y)
plt.figure()
plt.plot(xmesh, sol.sol(xmesh)[0])
plt.legend()
But in my case, t is a pre-defined constant 1-D array. I am facing some issues in writing the code for this case. Any help regarding this will be highly appreciated.
Related
As the title suggests, I am looking for an equivalent function or a suggestion on how to achieve the same thing deval does in MATLAB but in Python.
Code:
import numpy as np
from scipy.integrate import odeint
import matplotlib.pyplot as plt
#define model function that returns ds/dt, di/dt/ and dr/dt
def epidemic_model(state, t):
s, i, r = state
d_s = -0.06 * s * i
d_i = 0.06 *s * i - 7*i
d_r = 7 * i
return [d_s, d_i, d_r]
t = np.arange(0, 1, 0.01)
init_state = [990, 10, 0]
state = odeint(epidemic_model, init_state, t)
plt.xlabel('time')
plt.ylabel('population')
plt.plot(t, state)
Now my task is to find at which time the number of the infected population and recovered population is the same.
I would do this in MATLAB using deval, I am looking for a Python version of this.
Check dsolve function in the sympy package below:
http://docs.sympy.org/latest/modules/solvers/ode.html#dsolve
Solves any (supported) kind of ordinary differential equation and system of ordinary differential equations.
Also, solve a system of ordinary differential equations using integrate.solve_ivp from scipy package:
https://docs.scipy.org/doc/scipy/reference/generated/scipy.integrate.solve_ivp.html#scipy-integrate-solve-ivp
This function numerically integrates a system of ordinary differential equations given an initial value
I am trying to fit Gaussian function to my Python plot. I have attached the code here. Any corrections would be appreciated!
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
import math
import random
from numpy import genfromtxt
data= genfromtxt ('PVC_Cs137.txt')
plt.xlim(0,2500)
plt.ylim(0,30000)
plt.xlabel("Channel number")
plt.ylabel("Counts")
x = data[:,0]
y = data[:,1]
n = len(x)
mean = sum(x*y)/n
sigma = sum(y*(x-mean)**2)/n
def gaus(x,a,x0,sigma):
return a*exp(-(x-x0)**2/(2*sigma**2))
popt,pcov = curve_fit(gaus,x,y,p0=[1,mean,sigma])
plt.plot(x,gaus(x,*popt))
plt.show()
And here is the link to my file:
https://www.dropbox.com/s/hrqjr2jgfsjs55x/PVC_Cs137.txt?dl=0
There are two problems with your approach. One is related to programming. The gauss fit function has to work with a numpy array. math functions can't provide this functionality, they work with scalars. Therefore your fit functions should look like this
def gauss(x, a, x0, sigma):
return a * np.exp(-(x - x0) ** 2 / (2 * sigma ** 2))
This produces with the right mean/sigma combination a Gauss curve like this
And now we look at the distribution of the values from your file:
This doesn't even vaguely look like a Gauss curve. No wonder that the fit function doesn't converge.
Actually there is a third problem, your calculation of mean/sigma is wrong, but since you can't fit your data to a Gaussian distribution, we can neglect this problem for now.
Here is my code:
import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import LSQUnivariateSpline
x = np.linspace(-3,3,7)
y = np.sin(x)
t = [-1,1]
LSQ_USpline = LSQUnivariateSpline(x, y, t, k = 3)
print(LSQ_USpline.get_coeffs())
As far I understand I am getting 3 polynomials pieced back together. The output of LSQ_USpline.get_coeffs() is
[-0.14112001 -0.90624802 -1.47578155 1.47578155 0.90624802 0.14112001]
I thought that first two coefficients are related to the first polynomial, in particular a_0 -> -0.14112001 and a_1 -> -0.90624802, where a_0 is the coefficient of x^3. After plotting it I realized that it is not true.
Could somebody help me to understand what how to read output of LSQ_USpline.get_coeffs()?
Update: Overall what do coefficients of spline mean? I thought they are coefficients of polynomials of the spline.
Update: After differentiating and checking values at zero get_coeffs() is definitely not coefficients of polynomials or there is a bug in this function.
I'm trying to solve the equation y'' + (epsilon-x^2)y = 0 numerically using odeint. I know the solutions (the wavefunctions of a QHO), but the output from odeint has no apparent relation to it. I can solve ODEs with constant coefficients just fine, but as soon as I move to variable ones, I can't solve any of the ones I tried. Here's my code:
#!/usr/bin/python2
from __future__ import division
import numpy as np
import matplotlib.pyplot as plt
import scipy.integrate as spi
x = np.linspace(-5,5,1e4)
n = 0
epsilon = 2*n+1
def D(Y,x):
return np.array([Y[1], (epsilon-x**2)*Y[0]])
Y0 = [0,1]
Y = spi.odeint(D,Y0,x)
# Y is an array with the first column being y(x) and the second y'(x) for all x
plt.plot(x,Y[:,0],label='num')
#plt.plot(x,Y[:,1],label='numderiv')
plt.legend()
plt.show()
And the plot:
[not enough rep:] https://drive.google.com/file/d/0B6840LH2NhNpdUVucUxzUGFpZUk/edit?usp=sharing
Look here for plots of solution: http://hyperphysics.phy-astr.gsu.edu/hbase/quantum/hosc5.html
It looks like your equation is not correctly interpreted. You have a differential equation y'' + (epsilon-x^2)y = 0, but you forget a minus sign in your vector form. In particular it should be
y[0]' = y[1]
y[1]' = -(epsilon-x^2)y[0]
So (adding the minus sign in front of the epsilon term
def D(Y,x):
return np.array([Y[1], -(epsilon-x**2)*Y[0]])
In fact the plot you have is consistent with the DE y'' + (epsilon-x^2)y = 0. Check it out: Wolphram Alpha
I was trying to use odeint to solve a problem. My code is as below:
import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import odeint
eta=1.24e-9/2
def fun(x):
f=1.05e-8*eta*x**(1.5)*np.exp(13.6/x)
return (np.sqrt(1.+4*f)-1)/2./f
x=np.arange(0,1,0.001)
y=odeint(fun,x,0)[0]
plt.plot(x,y)
plt.plot(x,x)
plt.show()
It the two curves are the same, which is obviously wrong. If I plot the function, it will looks like a step function, which is very very small before about 0.3 and exponentially goes to 1. Can you help me figure out what's wrong with it? Thank you!
There are several problems with your code, most of which you might be able to solve yourself if you read the docstring for odeint more carefully.
To get you started, the following is a simple example of solving a scalar differential equation with odeint. Instead of trying to understand (and possibly debug) your function, I'll use a very simple equation. I'll solve the equation dy/dt = a * y, with initial condition y(0) = 100. Once you have this example working, you can modify fun to solve your problem.
import numpy as np
from scipy.integrate import odeint
import matplotlib.pyplot as plt
def fun(y, t, a):
"""Define the right-hand side of equation dy/dt = a*y"""
f = a * y
return f
# Initial condition
y0 = 100.0
# Times at which the solution is to be computed.
t = np.linspace(0, 1, 51)
# Parameter value to use in `fun`.
a = -2.5
# Solve the equation.
y = odeint(fun, y0, t, args=(a,))
# Plot the solution. `odeint` is generally used to solve a system
# of equations, so it returns an array with shape (len(t), len(y0)).
# In this case, len(y0) is 1, so y[:,0] gives us the solution.
plt.plot(t, y[:,0])
plt.xlabel('t')
plt.ylabel('y')
plt.show()
Here's the plot:
More complicated examples of the use of odeint can be found in the SciPy Cookbook (scroll down to the bullet labeled "Ordinary differential equations").