Plot Cstr equation - python

I need help getting the right plot for tau as a function of c (conversion).
Here's my code:
from __future__ import division, print_function
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
from math import *
from scipy.optimize import root
def tau(c,T = 298):
ci = 2
pw = 1000
Cp = 4
k0 = 0.01
e = 1000
Hr = (-3*10**4)
a = np.linspace(0,10000,10000)
t = np.zeros(len(a))
for i in range(len(a)):
t[i] = (ci * k0 * exp(e/298))/(ci - c[i])
plt.plot(t,c)
plt.show()
print(tau(np.linspace(0,1,10000)))
My plot is not correct.
How do I modify my equation to get the following kind of plot?

It's difficult to say why your plot of conversion is incorrect without knowing the original problem statement. Can you please provide more information? Your plot of conversion does increase with residence time (tau), which it should do. It looks like you've defined some constants that are unused, such as the enthalpy of reaction (Hr), pw, and the temperature. At any rate, it is apparent that your question is not about python or plotting, but rather about how to correctly solve a chemical engineering reactor design problem.

Related

Scipy solve_ivp not giving expected solutions

I need to solve a 2nd order ODE which I have decoupled into two first order ODEs. I've tried solving it using solve_ivp, but it doesn't seem to provide the solution I expect. I have provided the code below.
import numpy as np
import matplotlib.pyplot as plt
from scipy.misc import derivative
from scipy.integrate import solve_ivp
from matplotlib import rc
rc('text', usetex = True)
V0 = 2*10**-10
A = 0.130383
f = 0.129576
phi_i_USR2 = 6.1
phi_Ni_USR2 = 1.2
def V_USR2(phi):
return V0*(np.tanh(phi/np.sqrt(6)) + A*np.sin(1/f*np.tanh(phi/np.sqrt(6))))**2
def V_phi_USR2(phi):
return derivative(V_USR2, phi)
N = np.linspace(0,66,1000)
def USR2(N, X):
phi, g = X
return [g, (g**2/2 - 3)*(V_phi_USR2(phi)/V_USR2(phi) + g)]
X0 = [phi_i_USR2, phi_Ni_USR2]
sol = solve_ivp(USR2, (0,66), X0, method = 'LSODA', t_eval = N)
phi_USR2 = sol.y[0]
phi_N_USR2 = sol.y[1]
N_USR2 = sol.t
plt.plot(phi_USR2, phi_N_USR2)
plt.xlabel("$\phi$")
plt.ylabel("$\phi'$")
plt.title("Phase plot for USR2")
plt.show()
solve_ivp gives me the following plot:
The problem is that there is supposed to be an oscillation near the origin, which is not well captured by solve_ivp. However, for the same equation and initial conditions, Mathematica gives me exactly what I want:
I want the same plot in Python as well. I tried various methods in solve_ivp such as RK45, LSODA, Radau and BDF, but all of them show the same problem (LSODA tries to depict an oscillation but fails, but the other methods don't even move past the point where the oscillation starts). It would be great if someone can shed light on the problem. Thanks in advance.

How'd I use the Pyplot function in Python?

I'm having trouble trying to display my results after the program is finished. I'm expecting to see a velocity vs position graph, but for some reason, it's not showing up. Is there something wrong with my code.
import numpy
from matplotlib import pyplot
import time,sys
#specifying parameters
nx=41 # number of space steps
nt=25 #number of time steps
dt=0.025 #width between time intervals
dx=2/(nx-1) #width between space intervals
c=1 # the speed of the initial wave
#boundary conditions
u = numpy.ones(nx)
u[int(0.5/dx):int(1/(dx+1))] = 2
un = numpy.ones(nx)
#initializing the velocity function
for i in range(nt):
un= u.copy()
for i in range(1,nx):
u[i]= un[i] -c*(dt/dx)*(u[i]-u[i-1])
pyplot.xlabel('Position')
pyplot.ylabel('Velocity')
pyplot.plot(numpy.linspace(0,2,nx),u)
There are a few things going on here
You don't need to write out the full name of the packages you are importing. You can just use aliasing to call those packages and use them with those aliases later on. This, for example.
import numpy as np
Your dx value initalization will give you 0 beause you are dividing 2 by 40 which will give you a zero. You can initialize the value of dx by making one of the values in that expression a float, so something like this.
dx=float(2)/(nx-1) #width between space intervals
As Meowcolm Law in the comments suggested in the comments, add pyplot.show() to
show the graph. This is what the edited version of your code will like
import numpy as np
import matplotlib.pyplot as plt
import time,sys
#specifying parameters
nx=41 # number of space steps
nt=25 #number of time steps
dt=0.025 #width between time intervals
dx=float(2)/(nx-1) #width between space intervals
c=1 # the speed of the initial wave
#boundary conditions
u = np.ones(nx)
u[int(0.5/dx):int(1/(dx+1))] = 2
un = np.ones(nx)
#initializing the velocity function
for i in range(nt):
un= u.copy()
for i in range(1,nx):
u[i]= un[i] -c*(dt/dx)*(u[i]-u[i-1])
plt.xlabel('Position')
plt.ylabel('Velocity')
plt.plot(np.linspace(0,2,nx),u)
plt.show()
You can add
%matplotlib inline
in order to view the plot inside the notebook. I missed this step following the same guide.

Plancks Law, Frequency figures

I want to plot the frequency version of planck's law. I first tried to do this independently:
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
%matplotlib inline
# Planck's Law
# Constants
h = 6.62607015*(10**-34) # J*s
c = 299792458 # m * s
k = 1.38064852*(10**-23) # J/K
T = 20 # K
frequency_range = np.linspace(10**-19,10**19,1000000)
def plancks_law(nu):
a = (2*h*nu**3) / (c**2)
e_term = np.exp(h*nu/(k*T))
brightness = a /(e_term - 1)
return brightness
plt.plot(frequency_range,plancks_law(frequency_range))
plt.gca().set_xlim([1*10**-16 ,1*10**16 ])
plt.gca().invert_xaxis()
This did not work, I have an issue with scaling somehow. My next idea was to attempt to use this person's code from this question: Plancks Formula for Blackbody spectrum
import matplotlib.pyplot as plt
import numpy as np
h = 6.626e-34
c = 3.0e+8
k = 1.38e-23
def planck_f(freq, T):
a = 2.0*h*(freq**3)
b = h*freq/(k*T)
intensity = a/( (c**2 * (np.exp(b) - 1.0) ))
return intensity
# generate x-axis in increments from 1nm to 3 micrometer in 1 nm increments
# starting at 1 nm to avoid wav = 0, which would result in division by zero.
wavelengths = np.arange(1e-9, 3e-6, 1e-9)
frequencies = np.arange(3e14, 3e17, 1e14, dtype=np.float64)
intensity4000 = planck_f(frequencies, 4000.)
plt.gca().invert_xaxis()
This didn't work, because I got a divide by zero error. Except that I don't see where there is a division by zero, the denominator shouldn't ever be zero since the exponential term shouldn't ever be equal to one. I chose the frequencies to be the conversions of the wavelength values from the example code.
Can anyone help fix the problem or explain how I can get planck's law for frequency instead of wavelength?
You can not safely handle such large numbers; even for comparably "small" values of b = h*freq/(k*T) your float64 will overflow, e.g np.exp(709.)=8.218407461554972e+307 is ok, but np.exp(710.)=inf. You'll have to adjust your units (exponents) accordingly to avoid this!
Note that this is also the case in the other question you linked to, if you insert print( np.exp(b)[:10] ) within the definition of planck(), you can examine the first ten evaluated b's and you'll see the overflow in the first few occurrences. In any case, simply use the answer posted within the other question, but convert the x-axis in plt.plot(wavelengths, intensity) to frequency (i hope you know how to get from one to the other) :-)

Avoiding divergent solutions with odeint? shooting method

I am trying to solve an equation in Python. Basically what I want to do is to solve the equation:
(1/x^2)*d(Gam*dL/dx)/dx)+(a^2*x^2/Gam-(m^2))*L=0
This is the Klein-Gordon equation for a massive scalar field in a Schwarzschild spacetime. It suppose that we know m and Gam=x^2-2*x. The initial/boundary condition that I know are L(2+epsilon)=1 and L(infty)=0. Notice that the asymptotic behavior of the equation is
L(x-->infty)-->Exp[(m^2-a^2)*x]/x and Exp[-(m^2-a^2)*x]/x
Then, if a^2>m^2 we will have oscillatory solutions, while if a^2 < m^2 we will have a divergent and a decay solution.
What I am interested is in the decay solution, however when I am trying to solve the above equation transforming it as a system of first order differential equations and using the shooting method in order to find the "a" that can give me the behavior that I am interested about, I am always having a divergent solution. I suppose that it is happening because odeint is always finding the divergent asymptotic solution. Is there a way to avoid or tell to odeint that I am interested in the decay solution? If not, do you know a way that I could solve this problem? Maybe using another method for solving my system of differential equations? If yes, which method?
Basically what I am doing is to add a new system of equation for "a"
(d^2a/dx^2=0, da/dx(2+epsilon)=0,a(2+epsilon)=a_0)
in order to have "a" as a constant. Then I am considering different values for "a_0" and asking if my boundary conditions are fulfilled.
Thanks for your time. Regards,
Luis P.
I am incorporating the value at infinity considering the assimptotic behavior, it means that I will have a relation between the field and its derivative. I will post the code for you if it is helpful:
from IPython import get_ipython
get_ipython().magic('reset -sf')
import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import odeint
from math import *
from scipy.integrate import ode
These are initial conditions for Schwarzschild. The field is invariant under reescaling, then I can use $L(2+\epsilon)=1$
def init_sch(u_sch):
om = u_sch[0]
return np.array([1,0,om,0]) #conditions near the horizon, [L_c,dL/dx,a,da/dx]
These are our system of equations
def F_sch(IC,r,rho_c,m,lam,l,j=0,mu=0):
L = IC[0]
ph = IC[1]
om = IC[2]
b = IC[3]
Gam_sch=r**2.-2.*r
dR_dr = ph
dph_dr = (1./Gam_sch)*(2.*(1.-r)*ph+L*(l*(l+1.))-om**2.*r**4.*L/Gam_sch+(m**2.+lam*L**2.)*r**2.*L)
dom_dr = b
db_dr = 0.
return [dR_dr,dph_dr,dom_dr,db_dr]
Then I try for different values of "om" and ask if my boundary conditions are fulfilled. p_sch are the parameters of my model. In general what I want to do is a little more complicated and in general I will need more parameters that in the just massive case. Howeve I need to start with the easiest which is what I am asking here
p_sch = (1,1,0,0) #[rho_c,m,lam,l], lam and l are for a more complicated case
ep = 0.2
ep_r = 0.01
r_end = 500
n_r = 500000
n_omega = 1000
omega = np.linspace(p_sch[1]-ep,p_sch[1],n_omega)
r = np.linspace(2+ep_r,r_end,n_r)
tol = 0.01
a = 0
for j in range(len(omega)):
print('trying with $omega =$',omega[j])
omeg = [omega[j]]
ini = init_sch(omeg)
Y = odeint(F_sch,ini,r,p_sch,mxstep=50000000)
print Y[-1,0]
#Here I ask if my asymptotic behavior is fulfilled or not. This should be basically my value at infinity
if abs(Y[-1,0]*((p_sch[1]**2.-Y[-1,2]**2.)**(1/2.)+1./(r[-1]))+Y[-1,1]) < tol:
print(j,'times iterations in omega')
print("R'(inf)) = ", Y[-1,0])
print("\omega",omega[j])
omega_1 = [omega[j]]
a = 10
break
if a > 1:
break
Basically what I want to do here is to solve the system of equations giving different initial conditions and find a value for "a=" (or "om" in the code) that should be near to my boundary conditions. I need this because after this I can give such initial guest to a secant method and try to fiend a best value for "a". However, always that I am running this code I am having divergent solutions that it is, of course, a behavior that I am not interested. I am trying the same but considering the scipy.integrate.solve_vbp, but when I run the following code:
from IPython import get_ipython
get_ipython().magic('reset -sf')
import numpy as np
import matplotlib.pyplot as plt
from math import *
from scipy.integrate import solve_bvp
def bc(ya,yb,p_sch):
m = p_sch[1]
om = p_sch[4]
tol_s = p_sch[5]
r_end = p_sch[6]
return np.array([ya[0]-1,yb[0]-tol_s,ya[1],yb[1]+((m**2-yb[2]**2)**(1/2)+1/r_end)*yb[0],ya[2]-om,yb[2]-om,ya[3],yb[3]])
def fun(r,y,p_sch):
rho_c = p_sch[0]
m = p_sch[1]
lam = p_sch[2]
l = p_sch[3]
L = y[0]
ph = y[1]
om = y[2]
b = y[3]
Gam_sch=r**2.-2.*r
dR_dr = ph
dph_dr = (1./Gam_sch)*(2.*(1.-r)*ph+L*(l*(l+1.))-om**2.*r**4.*L/Gam_sch+(m**2.+lam*L**2.)*r**2.*L)
dom_dr = b
db_dr = 0.*y[3]
return np.vstack((dR_dr,dph_dr,dom_dr,db_dr))
eps_r=0.01
r_end = 500
n_r = 50000
r = np.linspace(2+eps_r,r_end,n_r)
y = np.zeros((4,r.size))
y[0]=1
tol_s = 0.0001
p_sch= (1,1,0,0,0.8,tol_s,r_end)
sol = solve_bvp(fun,bc, r, y, p_sch)
I am obtaining this error: ValueError: bc return is expected to have shape (11,), but actually has (8,).
ValueError: bc return is expected to have shape (11,), but actually has (8,).

Plotting 2D integral function in python

Here is my first steps within the NumPy world.
As a matter of fact the target is plotting below 2-D function as a 3-D mesh:
N = \frac{n}{2\sigma\sqrt{\pi}}\exp^{-\frac{n^{2}x^{2}}{4\sigma^{2}}}
That could been done as a piece a cake in Matlab with below snippet:
[x,n] = meshgrid(0:0.1:20, 1:1:100);
mu = 0;
sigma = sqrt(2)./n;
f = normcdf(x,mu,sigma);
mesh(x,n,f);
But the bloody result is ugly enough to drive me trying Python capabilities to generate scientific plots.
I searched something and found that the primary steps to hit above mark in Pyhton might be acquired by below snippet:
from matplotlib.patches import Polygon
import numpy as np
from scipy.integrate import quad
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
sigma = 1
def integrand(x,n):
return (n/(2*sigma*np.sqrt(np.pi)))*np.exp(-(n**2*x**2)/(4*sigma**2))
t = np.linespace(0, 20, 0.01)
n = np.linespace(1, 100, 1)
lower_bound = -100000000000000000000 #-inf
upper_bound = t
tt, nn = np.meshgrid(t,n)
real_integral = quad(integrand(tt,nn), lower_bound, upper_bound)
Axes3D.plot_trisurf(real_integral, tt,nn)
Edit: With due attention to more investigations on Greg's advices, above code is the most updated snippet.
Here is the generated exception:
RuntimeError: infinity comparisons don't work for you
It is seemingly referring to the quad call...
Would you please helping me to handle this integrating-plotting problem?!...
Best
Just a few hints to get you in the right direction.
numpy.meshgrid can do the same as MatLABs function:
http://docs.scipy.org/doc/numpy/reference/generated/numpy.meshgrid.html
When you have x and n you can do math just like in matlab:
sigma = numpy.sqrt(2)/n
(in python multiplication/division is default index by index - no dot needed)
scipy has a lot more advanced functions, see for example How to calculate cumulative normal distribution in Python for a 1D case.
For plotting you can use matplotlibs pcolormesh:
import matplotlib.pyplot as plt
plt.pcolormesh(x,n,real_integral)
Hope this helps until someone can give you a more detailed answer.

Categories