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").
Related
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.
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 have a physics problem and have never used odeint or any numerical solving for ODE on python and am a little confused. I tried looking at other examples but could not understand and am hoping for a little help. My ODE is:
Where α is a given angle and g is a constant.
r=sqrt(x^2+y^2)
The program will ask for x_0, dx/dt_0 and dy/dt_0.
I'm mostly unsure how to solve ODE's in python. I have seen that I should split my ODE into dr'/dt because odeint will only do a first order ODE's. Could someone help explain how to do this?
I tried using another example to do as much as possible but am stuck:
import numpy as np
import matplotlib.pylab as plt
from scipy.integrate import odeint
pi=np.pi
sin=np.sin
cos=np.cos
sqrt=np.sqrt
alpha=pi/4
g=9.80665
y0=0.0
theta0=0.0
x=[]
y=[]
sina = sin(alpha)**2
second_term = g*sin(alpha)*cos(alpha)
x0 = float(raw_input('What is the initial x in meters?'))
x_vel0 = float(raw_input('What is the initial velocity in the x direction in m/s?'))
y_vel0 = float(raw_input('what is the initial velocity in the y direction in m/s?'))
t_f = float(raw_input('What is the maximum time in seconds?'))
r0 = x0
r = sqrt(float(x)**2 + float(y)**2)
def deriv_z(z,r):
r, rdot=z
return [rdot,r*sina-second_term]
zdot0=x_vel0**2+y_vel0**2
z0 = [r0,zdot0]
times = np.linespace(0, t_f, 1000)
z = odeint(deriv_z,z0,times)
There's a great example I found to help me with my planetary orbit ODE solving.
It uses an adaptive step size solver and plots the orbit nicely. If your solution can handle it, you may also try to use the faster 'lsoda' or 'vode' options instead of 'dopri5' (which is a very solid standard).
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