I am trying to integrate a definite integral with respect to dE for a function that depends on E and x, x being another parameter that I will use later. I defined a function of x that could help me with this, but it does not seem to work. When I give the new function a certain value--such as 1 or 10--it always returns 0. Here is my code:
%matplotlib inline
import matplotlib.pyplot as plt
from scipy.integrate import quad
import numpy as np
from numpy import pi
from numpy import arange
gg=100.0
ms=100.0
def integrand(E, xx):
return (gg/2*pi)*E*(E**2-ms**2)**(1/2)/(np.exp(E*xx*ms)-1)
def nn(x):
return quad(integrand, ms, np.inf, args=(x)) ## quad(funcion, lim inf, lim sup, args)
What I need is to be able to later call the function nn with the parameter x being the variable.
You could simply define all the values outside of the function:
from scipy.integrate import quad
import numpy as np
from numpy import pi
gg = 100.0
ms = 100.0
xx = 5.0
ms = 1.0
def integrand(E):
return (gg / 2 * pi) * E * (E ** 2 - ms ** 2) ** (1 / 2) / (np.exp(E * xx * ms) - 1)
val, err = quad(integrand, ms, np.inf)
print(val)
0.16712443596152543
Related
I'm creating a function to compute Newton's method. However, the functions f and df keep returning a complex number. I am getting a type error: "can't convert complex to float" at the line where I am defining f.
How do I stop python from returning a complex number and not a float?
from cmath import cos, sin
import numpy as np
import matplotlib.pyplot as plt
import numpy as np
def Newtons_method(f, df, x0, i_max, eps_x, eps_f):
errors = []
conv = 0
xk = x0
for k in range(i_max):
res = f(xk)
approx_err = -1.0 * res / df(xk)
errors.append([k, abs(approx_err), res])
if (abs(approx_err) < eps_x) and (res < eps_f):
array_errors = np.array(errors)
conv = 1
return xk, array_errors, conv
der = df(xk)
if der == 0:
print("Derivative is zero")
return None
xk = xk + approx_err
print("Exceeded maximum iterations")
return None
def f(x):
return float(x * x - 2 * x * cos(x) + cos(x) * cos(x))
def df(x):
return float(2 * x - 2 * (cos(x) - x * sin(x)) - sin(2 * x))
x0 = 1.0
i_max = 50
eps_x = 1.0e-12
eps_f = 1.0
solution_Newton, record_Newton, flag_Newton = Newtons_method(f, df, x0, i_max, eps_x, eps_f)
x = record_Newton[:,0]
y = record_Newton[:,1]
plt.plot(x, y)
plt.yscale("log")
plt.title("Newton's method")
plt.xlabel("Number of iterations")
plt.ylabel("Approximate errors")
plt.show()
I think it is because you are using cmath instead of math:
>>> import cmath
>>> import math
>>> cmath.cos(0)
(1-0j)
>>> math.cos(0)
1.0
The help for cmath starts by explaining that it is for complex numbers:
Help on built-in module cmath:
NAME
cmath
DESCRIPTION
This module provides access to mathematical functions for complex
numbers.
If you don't want to be working with complex numbers, simply replace cmath with math and your error should go away. When I do that your code runs and produces this figure instead of spitting out a TypeError:
I need to obtain a derivative to use it later in numerical calculations. And my code doesn't work at all. I tried to use lambdify but the error is "can't convert symbols int". I read other answers for similar questions but it still doesn't work.
import numpy as np
from scipy.integrate import odeint
from scipy.integrate import quad
from scipy.integrate import solve_bvp as bvp
import matplotlib.pyplot as plt
from scipy.special import genlaguerre as L
from scipy.special import gamma as G
from math import factorial
from math import sqrt
import sympy as sym
from sympy.utilities.lambdify import lambdify
mp = 938.2720813
mn = 939.5654133
mu = (mn + mp)/4
hbar = 197.3270533
h2m = hbar**2/(2*mu)
V0 = 20
Rv = 1.5
Q0 = 1.5
Rq = 4.5
EIm = 0.3
ERe = 1
V = lambda r : -V0*np.exp(-r/Rv)
Q = lambda r : -Q0*np.exp(-r/Rq)
chi = lambda r, l : sqrt(factorial(l)*beta**3/(G(3 + l))) * r * L(l,2)(beta * r) * np.exp(- beta * r / 2)
r, l, beta = sym.symbols('r, l, beta')
def chifD(r, l, beta):
return sqrt(factorial(l)*beta**3/(G(3 + l))) * r * L(l,2)(beta * r) * np.exp(- beta * r / 2)
def chiD(r, l, beta):
return sym.diff(chifD(r ,l, beta), r)
print(chiD(r, l, beta))
chiLambdified = lambdify(((r,l, beta),),chiD(r,l, beta),"numpy")
print(chiD(1, 1, 1))
I'm pretty sure you're mixing modules you shouldn't. I kept modifying your chi function until I got something that works. Nothing short of removing all math and scipy functions returned something that wasn't a TypeError.
# works with sympy sqrt.
chi = lambda r, l : sym.sqrt(l*r)
print(chi(r,l))
# doesn't work with math or numpy sqrt.
chi = lambda r, l : math.sqrt(l*r)
print(chi(r,l))
If you want to use functions, you'll have to use the ones that come with sympy, define your own using basic operators (so that sympy objects will be accepted) or find simpler ways to define your operations: sqrt() can simply be substituted by **(1/2).
Maybe you should look for a way that can make sympy accept functions from other modules because writing all of the special functions from scipy yourself looks like it will be a pain.
I am trying to use Python with Numpy to solve a basic equation using the finite difference method. The code gives me the correct first value for a i.e it gives me a[1]; however, every other value after that is just zero?
I don't know what I'm doing wrong because it obviously works for the first value so how do I fix this?
Any ideas would be very helpful.
from numpy import *
import numpy as np
import matplotlib.pyplot as plt
import scipy as sp
from scipy.integrate import odeint
def solver(omega_m, dt):
#t_0, H_0, a_0, dt, n, T; always the same; omega's change
t_0 = 0.0004
a_0 = 0.001
H_0 = 1./13.7
T = 13.7
dt = float(dt)
n = int(round((T - t_0)/dt))
x = zeros(n+1)
t = linspace(t_0, T, n+1)
x[0] = a_0
for i in range (0, n):
x[i+1] = x[i] + (H_0 * ((omega_m)**(1./2.)) * ((x[i])**(-1./2.)) * dt)
return x, t
a, t = solver(omega_m =1, dt=0.001)
print a, t
Your function returns after the first iteration because your return statement is inside the for loop. You should dedent the return statement so your loop does not terminate prematurely:
for i in range (0, n):
x[i+1] = x[i] + (H_0 * ((omega_m)**(1./2.)) * ((x[i])**(-1./2.)) * dt)
return x, t
I would like to be able to do something else in each time step during solving an ODE (using scipy's integrate). Is there a way to do so? Can I somehow write my own time loop and just call a single e.g. Runge-Kutta step by myself? Is there a routine in python or would I have to come up with my own? I think there must be one since odeint etc have to use such a function. So the question is, how do I access them?
So it should looking something along these lines:
from scipy.integrate import *
from pylab import *
def deriv(y, t):
a = -2.0
b = -0.1
return array([y[1], a*y[0]+b*y[1]])
time = linspace(0.0, 10.0, 1000)
dt = 10.0/(1000-1)
yinit = array([0.0005, 0.2])
for t in time:
# doSomething, write into a file or whatever
y[t] = yinit
yinit = RungeKutta(deriv, yinit, t, dt, varargs)
I now came along with this:
from pylab import *
from scipy.integrate import *
def RHS(t, x):
return -x
min_t = 0.0
max_t = 10.0
num_t = 1e2
grid_t = linspace(min_t, max_t, num_t)
grid_dt = (max_t - min_t)/(num_t - 1)
y = zeros(num_t, dtype=complex)
y[0] = complex(1.0, 0.0)
solver = complex_ode(RHS)
solver.set_initial_value(y[0], grid_t[0]).set_integrator('dopri5')
for idx in range(1, int(num_t)):
solver.integrate(solver.t + grid_dt)
y[idx] = solver.y[0]
In here I can do whatever I want during the integration.
How do I numerically solve an ODE in Python?
Consider
\ddot{u}(\phi) = -u + \sqrt{u}
with the following conditions
u(0) = 1.49907
and
\dot{u}(0) = 0
with the constraint
0 <= \phi <= 7\pi.
Then finally, I want to produce a parametric plot where the x and y coordinates are generated as a function of u.
The problem is, I need to run odeint twice since this is a second order differential equation.
I tried having it run again after the first time but it comes back with a Jacobian error. There must be a way to run it twice all at once.
Here is the error:
odepack.error: The function and its Jacobian must be callable functions
which the code below generates. The line in question is the sol = odeint.
import numpy as np
from scipy.integrate import odeint
import matplotlib.pyplot as plt
from numpy import linspace
def f(u, t):
return -u + np.sqrt(u)
times = linspace(0.0001, 7 * np.pi, 1000)
y0 = 1.49907
yprime0 = 0
yvals = odeint(f, yprime0, times)
sol = odeint(yvals, y0, times)
x = 1 / sol * np.cos(times)
y = 1 / sol * np.sin(times)
plot(x,y)
plt.show()
Edit
I am trying to construct the plot on page 9
Classical Mechanics Taylor
Here is the plot with Mathematica
In[27]:= sol =
NDSolve[{y''[t] == -y[t] + Sqrt[y[t]], y[0] == 1/.66707928,
y'[0] == 0}, y, {t, 0, 10*\[Pi]}];
In[28]:= ysol = y[t] /. sol[[1]];
In[30]:= ParametricPlot[{1/ysol*Cos[t], 1/ysol*Sin[t]}, {t, 0,
7 \[Pi]}, PlotRange -> {{-2, 2}, {-2.5, 2.5}}]
import scipy.integrate as integrate
import matplotlib.pyplot as plt
import numpy as np
pi = np.pi
sqrt = np.sqrt
cos = np.cos
sin = np.sin
def deriv_z(z, phi):
u, udot = z
return [udot, -u + sqrt(u)]
phi = np.linspace(0, 7.0*pi, 2000)
zinit = [1.49907, 0]
z = integrate.odeint(deriv_z, zinit, phi)
u, udot = z.T
# plt.plot(phi, u)
fig, ax = plt.subplots()
ax.plot(1/u*cos(phi), 1/u*sin(phi))
ax.set_aspect('equal')
plt.grid(True)
plt.show()
The code from your other question is really close to what you want. Two changes are needed:
You were solving a different ODE (because you changed two signs inside function deriv)
The y component of your desired plot comes from the solution values, not from the values of the first derivative of the solution, so you need to replace u[:,0] (function values) for u[:, 1] (derivatives).
This is the end result:
import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import odeint
def deriv(u, t):
return np.array([u[1], -u[0] + np.sqrt(u[0])])
time = np.arange(0.01, 7 * np.pi, 0.0001)
uinit = np.array([1.49907, 0])
u = odeint(deriv, uinit, time)
x = 1 / u[:, 0] * np.cos(time)
y = 1 / u[:, 0] * np.sin(time)
plt.plot(x, y)
plt.show()
However, I suggest that you use the code from unutbu's answer because it's self documenting (u, udot = z) and uses np.linspace instead of np.arange. Then, run this to get your desired figure:
x = 1 / u * np.cos(phi)
y = 1 / u * np.sin(phi)
plt.plot(x, y)
plt.show()
You can use scipy.integrate.ode. To solve dy/dt = f(t,y), with initial condition y(t0)=y0, at time=t1 with 4th order Runge-Kutta you could do something like this:
from scipy.integrate import ode
solver = ode(f).set_integrator('dopri5')
solver.set_initial_value(y0, t0)
dt = 0.1
while t < t1:
y = solver.integrate(t+dt)
t += dt
Edit: You have to get your derivative to first order to use numerical integration. This you can achieve by setting e.g. z1=u and z2=du/dt, after which you have dz1/dt = z2 and dz2/dt = d^2u/dt^2. Substitute these into your original equation, and simply iterate over the vector dZ/dt, which is first order.
Edit 2: Here's an example code for the whole thing:
import numpy as np
import matplotlib.pyplot as plt
from numpy import sqrt, pi, sin, cos
from scipy.integrate import ode
# use z = [z1, z2] = [u, u']
# and then f = z' = [u', u''] = [z2, -z1+sqrt(z1)]
def f(phi, z):
return [z[1], -z[0]+sqrt(z[0])]
# initialize the 4th order Runge-Kutta solver
solver = ode(f).set_integrator('dopri5')
# initial value
z0 = [1.49907, 0.]
solver.set_initial_value(z0)
values = 1000
phi = np.linspace(0.0001, 7.*pi, values)
u = np.zeros(values)
for ii in range(values):
u[ii] = solver.integrate(phi[ii])[0] #z[0]=u
x = 1. / u * cos(phi)
y = 1. / u * sin(phi)
plt.figure()
plt.plot(x,y)
plt.grid()
plt.show()
scipy.integrate() does ODE integration. Is that what you are looking for?