I want to do a plot of this equation below:
Problem 1: You see... since my function is a function of ν I have to calculate my integral to each ν in my domain. My question is: what is the best way to do that?
I thought about using scipy to do the integral and a for loop to calculate it several times to each ν, but it seems a very inelegant way to solve my problem. Does someone know a better alternative? Does someone have a different idea?
Problem 2: When I write my code I get some errors, mainly because I think that the exponential has a very small expoent. Do you have any ideas of how should I change it so I can do this plot using Python?
Oh, if you try with a different method, it is supposed to look like this
Here is the code I was working on. I'm coming back to Python now, so maybe there is some errors. The plot I'm getting is very different from the one that this is supposed to look.
from scipy.integrate import quad
from scipy.constants import c, Planck, k, pi
import numpy as np
import matplotlib.pyplot as plt
def luminosity_integral(r, x):
T_est = 4000
R_est = 2.5 * (696.34*1e6)
Temp = ((2/(3*pi))**(1/4)) * T_est * ((R_est/r)**(3/4))
termo1 = ((4 * (pi**2) * Planck * (x**4) ) / (c**2))
termo2 = ((Planck * x) / (k*Temp))
return ((termo1 * r ) / (np.exp(termo2) - 1))
freqs = np.linspace(1e10, 1e16)
y = np.array([])
for i in freqs:
I = quad(luminosity_integral, (6 * 2.5 * (696.34*1e6)), (7e4 * 2.5 * (696.34*1e6)), args = (i))
temp = np.array([I[0]])
y = np.concatenate((y, temp))
plt.loglog(freqs, y)
plt.show()
Reuse the term R_est instead instead of writing its expression 3 times (better if you want to change that parameter).
you used a pi**2 in the constant multiplying the integral (don't affect the shape)
The shape resembles what you put as reference, but not in the suggested range.
You are using the value of T as T_*, are you sure about that?
Try this version of the code
from scipy.integrate import quad
from scipy.constants import c, Planck, k, pi
import numpy as np
import matplotlib.pyplot as plt
R_est = 2.5 * (696.34e6)
def luminosity_integral(r, x):
T_est = 4000
termo1 = ((4 * pi * Planck * (x**4) ) / (c**2))
termo2 = ((Planck * x) / (k*T_est)) * (3*pi/2 * (r/R_est)**3)**0.25
termo3 = np.exp(-termo2)
return ((termo1 * r ) * termo3 / (1 - termo3))
freqs = np.logspace(6, 16)
y = np.zeros_like(freqs)
for i, nu in enumerate(freqs):
y[i] = quad(luminosity_integral, (6* R_est), (7e4 * R_est), args = (nu))[0]
plt.loglog(freqs, y)
plt.ylim([1e6, 1e25])
plt.show()
Related
This question already has answers here:
Using Sympy Equations for Plotting
(2 answers)
Closed 4 months ago.
I have figured out how to make a equation with SymPy, however, I am not sure how to plot the relationship between two values. I keep getting an TypeError: Cannot convert expression to float whenever I write plt.plot(Rho , T). I have a code like this so far:
import matplotlib as plt
from sympy import init_session
init_session()
rho, X, Y, Z, T_9, T, T_8, m, n, Gamma = symbols('rho X Y Z T_9 T T_8 m n Gamma')
q_pp = (2.4 * 10**(4) * rho * X**2 / T_9**(2/3)) * exp((-3.380/T_9**(1/3)))
q_CNO = (4.4 * 10**(25) * rho * X* Z/ T_9**(2/3)) * exp((-15.228/T_9**(1/3)))
q_min = q_pp + q_CNO
simplify(q_min)
T_9 = T / (10**9)
Rho = (10**3)*(T_9**(1/3) / (24000 * X * exp(15.228/T_9**(1/3)) + (4.4*10**25) * Z * exp(3.38/T_9**(1/3)))) * exp(-18.608/ T_9**(1/3))
simplify(Rho)
plot_implicit(T, Rho)
Updated: I used SymPy plot to get new error, I updated the code to reflect what I currently have, TypeError: object of type 'Mul' has no len()
You need to provide values for the independent variable(s). For example, to plot an expression like y = x**2 - 1, I would do this:
import numpy as np
import matplotlib.pyplot as plt
x = np.arange(0, 20) # Provide the range of the independent variable.
y = x**2 - 1 # Compute the dependent variable.
plt.plot(x, y)
In your case, you'll need to provide values for T I suppose, and it looks like there are several other unknowns too. Take a look at this question, answers to which show a SymPy plotting example.
I've tried a few formats and ideas, but the syntax is kind of confusing. Help is appreciated, danke.
Only with python built-in functios:
import math
r = math.e**(math.cos(theta)) - 2 * math.cos(4 * theta) + math.sin(theta/12)**5
With Sympy(for symbolic computation):
from sympy import Symbol, cos, sin, E
t = Symbol('Θ')
E**(cos(t)) - 2 * cos(4 * t) + sin(t/12)**5
Result:
from math import exp, cos, sin
theta = 0.1 # Just as an example
r = exp(cos(theta)) - 2 * cos(4 * theta) + sin(theta / 12) ** 5
How about something like this?
import matplotlib.pyplot as plt
import numpy as np
theta = np.linspace(-2*np.pi, 2*np.pi, 10)
r = np.exp(np.cos(theta)) - 2*np.cos(4*theta) + np.sin(theta/12)**5
plt.plot(theta,r)
plt.savefig('parametric.jpg')
A very straightforward, but naive approach would be to just use the math library, which is a standard library in python.
import math
def r(theta):
return math.pow(math.e, math.cos(theta)) - 2 * math.cos(4*theta) + math.pow(math.sin(theta/12), 5)
better results are possible with libraries for scientific computing, like numpy or other members of the scipy ecosystem.
I was trying to obtain the Mathieu characteristic values for a specific problem. I do not have any problem obtaining them, and I have read the documentation from Scipy regarding these functions. The problem is that I know for a fact that the points I am obtaining are not right. My script to obtain the characteristic values I need is below:
import numpy as np
import matplotlib.pyplot as plt
from scipy.special import mathieu_a, mathieu_b, mathieu_cem, mathieu_sem
M = 1.0
g = 1.0
l = 1.0
h = 0.06
U0 = M * g * l
q = 4 * M * l**2 * U0 / h**2
def energy(n, q):
if n % 2 == 0:
return (h**2 / (8 * M * l**2)) * mathieu_a(n, q) + U0
else:
return (h**2 / (8 * M * l**2)) * mathieu_b(n + 1, q) + U0
n_list = np.arange(0, 80, 1)
e_n = [energy(i, q) for i in n_list]
plt.plot(n_list, e_n, '.')
The resulting plot of these values is this one. There is a zone where it appears to be "noise" or a numerical error, and I know that those jumps must not occur. In reality, around x= 40 to x > 40, the points should behave like a staircase of two consecutive points, similar to what can be seen between 70 < x < 80. And the values that x can take for this case are only positive integers.
I saw that the implementation of the Mathieu function has some problems, see here. But this was six years ago! In the answer to this question they use the NAG Library for Python, but it is not exactly open-source.
Is there a way I can still use these functions from Scipy without having this problem? Or is it related to the precision I am using to obtain the Mathieu characteristic value?
I have some variables that are uncertain, these are
w_m = u.ufloat(0.1430, 0.0011)
z_rec = u.ufloat(1089.92, 0.25)
theta_srec = u.ufloat(0.0104110, 0.0000031)
r_srec = u.ufloat(144.43, 0.26)
and some constant values
c = 299792.458 # speed of light in [km/s]
N_eff = 3.046
w_r = 2.469 * 10**(-5) * (1 + (7/8)*(4/11)**(4/3) * N_eff)
My problem is I need to solve an integral defined by this functions
def D_zrec(z):
return (c/100) / sqrt(w_m * (1+z)**3 + w_r * (1+z)**4 + (h**2 - w_m - w_r))
This function is evaluated for dz but it also contains an unknown h that we need to find, with corresponding uncertainty. So I need to write a code that finds h.
Here is my full code
from numpy import sqrt, vectorize
from scipy.integrate import quad
import uncertainties as u
from uncertainties.umath import *
from scipy.optimize import fsolve
#### Important Parameters #####
c = 299792.458 # speed of light in [km/s]
N_eff = 3.046
w_r = 2.469 * 10**(-5) * (1 + (7/8)*(4/11)**(4/3) * N_eff)
w_m = u.ufloat(0.1430, 0.0011)
z_rec = u.ufloat(1089.92, 0.25)
theta_srec = u.ufloat(0.0104110, 0.0000031)
r_srec = u.ufloat(144.43, 0.26)
D_zrec_true = r_srec / theta_srec
#u.wrap
def D_zrec_finder(h, w_m, z_rec, D_zrec_true):
def D_zrec(z):
return (c/100) / sqrt(w_m * (1+z)**3 + w_r * (1+z)**4 + (h**2 - w_m - w_r))
result, error = quad(D_zrec, 0, z_rec)
return D_zrec_true - result
def h0_finder(w_m, z_rec, D_zrec_true):
vfunc = vectorize(D_zrec_finder)
sol = fsolve(vfunc, u.ufloat(0.6728, 0.01), args=(w_m, z_rec, D_zrec_true))[0]
return sol
print(h0_finder(w_m, z_rec, D_zrec_true))
So to summarize I have an integral named as D_zrec that is a function of z, but also contains an unknown number h that we need to find by using fsolve.
I have found 3 sites that might be useful for the coder. Please look at them if you want to help
https://kitchingroup.cheme.cmu.edu/blog/2013/03/07/Another-approach-to-error-propagation/
https://kitchingroup.cheme.cmu.edu/blog/2013/07/10/Uncertainty-in-an-integral-equation/
https://kitchingroup.cheme.cmu.edu/blog/2013/01/23/Solving-integral-equations-with-fsolve/
I have looked at them to write my code but no luck.
Thanks for the help
I have written this code to model the motion of a spring pendulum
import numpy as np
from scipy.integrate import odeint
from numpy import sin, cos, pi, array
import matplotlib.pyplot as plt
def deriv(z, t):
x, y, dxdt, dydt = z
dx2dt2=(0.415+x)*(dydt)**2-50/1.006*x+9.81*cos(y)
dy2dt2=(-9.81*1.006*sin(y)-2*(dxdt)*(dydt))/(0.415+x)
return np.array([x,y, dx2dt2, dy2dt2])
init = array([0,pi/18,0,0])
time = np.linspace(0.0,10.0,1000)
sol = odeint(deriv,init,time)
def plot(h,t):
n,u,x,y=h
n=(0.4+x)*sin(y)
u=(0.4+x)*cos(y)
return np.array([n,u,x,y])
init2 = array([0.069459271,0.393923101,0,pi/18])
time2 = np.linspace(0.0,10.0,1000)
sol2 = odeint(plot,init2,time2)
plt.xlabel("x")
plt.ylabel("y")
plt.plot(sol2[:,0], sol2[:, 1], label = 'hi')
plt.legend()
plt.show()
where x and y are two variables, and I'm trying to convert x and y to the polar coordinates n (x-axis) and u (y-axis) and then graph n and u on a graph where n is on the x-axis and u is on the y-axis. However, when I graph the code above it gives me:
Instead, I should be getting an image somewhat similar to this:
The first part of the code - from "def deriv(z,t): to sol:odeint(deriv..." is where the values of x and y are generated, and using that I can then turn them into rectangular coordinates and graph them. How do I change my code to do this? I'm new to Python, so I might not understand some of the terminology. Thank you!
The first solution should give you the expected result, but there is a mistake in the implementation of the ode.
The function you pass to odeint should return an array containing the solutions of a 1st-order differential equations system.
In your case what you are solving is
While instead you should be solving
In order to do so change your code to this
import numpy as np
from scipy.integrate import odeint
from numpy import sin, cos, pi, array
import matplotlib.pyplot as plt
def deriv(z, t):
x, y, dxdt, dydt = z
dx2dt2 = (0.415 + x) * (dydt)**2 - 50 / 1.006 * x + 9.81 * cos(y)
dy2dt2 = (-9.81 * 1.006 * sin(y) - 2 * (dxdt) * (dydt)) / (0.415 + x)
return np.array([dxdt, dydt, dx2dt2, dy2dt2])
init = array([0, pi / 18, 0, 0])
time = np.linspace(0.0, 10.0, 1000)
sol = odeint(deriv, init, time)
plt.plot(sol[:, 0], sol[:, 1], label='hi')
plt.show()
The second part of the code looks like you are trying to do a change of coordinate.
I'm not sure why you try to solve the ode again instead of just doing this.
x = sol[:,0]
y = sol[:,1]
def plot(h):
x, y = h
n = (0.4 + x) * sin(y)
u = (0.4 + x) * cos(y)
return np.array([n, u])
n,u = plot( (x,y))
As of now, what you are doing there is solving this system:
Which leads to x=e^t and y=e^t and n' = (0.4 + e^t) * sin(e^t) u' = (0.4 + e^t) * cos(e^t).
Without going too much into the details, with some intuition you could see that this will lead to an attractor as the derivative of n and u will start to switch sign faster and with greater magnitude at an exponential rate, leading to n and u collapsing onto an attractor as shown by your plot.
If you are actually trying to solve another differential equation I would need to see it in order to help you further
This is what happen if you do the transformation and set the time to 1000: