I get an error when I try to use a numpy array inside mpmath function, this example fails when it reaches the line:
C = (f*L/D) + 2*mp.log(P1/P2)
Where P1 is an array.
With the error:
cannot create mpf from array([**P1_array**])
I'm aware of this and this treads, which are related. But I cant get my code to work. Can someone help me to correct this mistake?
import numpy as np
import mpmath as mp
mp.mp.dps = 20
# State equation --> pV = nZRT
P1 = np.linspace(101325,10*101325,100)
P2 = 101325
T = 300
D = 0.0095
A = mp.power(D,2)*mp.pi/4
L = 300
R = 8.31446
f = 0.05
Z1 = 0.9992
Z2 = 0.9999
Zm = 0.5*(Z1+Z2)
C = (f*L/D) + 2*mp.log(P1/P2)
w2 = (mp.power(P1,2)-mp.power(P2,2))*mp.power(A,2)/(Zm*R*T*C)
w = mp.power(w2,0.5)
You'll need to broadcast the function you want (log and power here) on your numpy array using np.frompyfunc:
import numpy as np
import mpmath as mp
mp.mp.dps = 20
# State equation --> pV = nZRT
P1 = np.linspace(101325,10*101325,100)
P2 = 101325
T = 300
D = 0.0095
A = mp.power(D,2)*mp.pi/4
L = 300
R = 8.31446
f = 0.05
Z1 = 0.9992
Z2 = 0.9999
Zm = 0.5*(Z1+Z2)
log_array = np.frompyfunc(mp.log, 1, 1) #to evaluate mpmath log function on a numpy array
pow_array = np.frompyfunc(mp.power, 2, 1) #to evaluate mpmath power function on a numpy array
C = (f*L/D) + 2*log_array(P1/P2)
w2 = (pow_array(P1,2)-pow_array(P2,2))*pow_array(A,2)/(Zm*R*T*C)
w = pow_array(w2,0.5)
Related
I need to solve the attached equation for "theta2" given the attached values. There should be 56 results because there are 7 different insulation thicknesses(Linsluation/d2/hc), 4 different temperatures (theta1), and 2 e values (em, ec) which must be tested.
Given data:
k = .5
d1 = 20/12
Linsulation = [2/12,3/12,4/12,5/12,6/12,7/12,8/12]
em = .09
ec = .9
sigma = .171*10**(-8)
theta1 = [800, 900, 1000, 1100]
theta3 = 70
d2 = []
for i in range(len(Linsulation)):
di = (d1+(2*Linsulation[i]))
d2.append(di)
pi=math.pi
theta2 = sym.symbols("theta2")
hc=[]
for i in range(len(d2)):
hi = .270*((theta2-theta3)**(.25))*(d2[i]**(-.25))
hc.append(hi)
[enter image description here](https://i.stack.imgur.com/MgBrp.png)
I tried:
import math
import sympy as sym
from sympy import symbols, Eq, solve
import scipy
from scipy.optimize import fsolve
from math import pi
k = .5
d1 = 20/12
Linsulation = [2/12,3/12,4/12,5/12,6/12,7/12,8/12]
em = .09
ec = .9
sigma = .171*10**(-8)
theta1 = [800, 900, 1000, 1100]
theta3 = 70
d2 = []
for i in range(len(Linsulation)):
di = (d1+(2*Linsulation[i]))
d2.append(di)
pi=math.pi
theta2 = sym.symbols("theta2")
hc=[]
for i in range(len(d2)):
hi = .270*((theta2-theta3)**(.25))*(d2[i]**(-.25))
hc.append(hi)
def fun(e):
for i in range(len(Linsulation)):
for j in range(len(theta1)):
return (pi)*d2[i]*hc[i]*(theta2-theta3)+(pi)*d2[i]*e*sigma*(((theta2+460)**4)-((theta3+460)**4))-(2*(pi)*k*(theta1[j]-theta2))/ln(d2[i]/d1)
theta2 = fsolve(fun(em))
print(theta2)
I don't understand how fsolve should work in this context. What is the best way I can solve the equation for multiple values and when the variables cannot be separated?
Attempt 2:
import math
import sympy as sym
from sympy import symbols, Eq, solve
import scipy
from scipy.optimize import fsolve
from math import pi
k = .5
d1 = 20/12
Linsulation = [2/12,3/12,4/12,5/12,6/12,7/12,8/12]
em = .09
ec = .9
sigma = .171*10**(-8)
theta1 = [800, 900, 1000, 1100]
theta3 = 70
d2 = []
for i in range(len(Linsulation)):
di = (d1+(2*Linsulation[i]))
d2.append(di)
pi=math.pi
theta2 = sym.symbols("theta2")
hc=[]
for i in range(len(d2)):
hi = .270*((theta2-theta3)**(.25))*(d2[i]**(-.25))
hc.append(hi)
def fcn(theta2):
for i in range(len(Linsulation)):
for j in range(len(theta1)):
LHS = (pi)*d2[i]*hc[i]*(theta2-theta3)+(pi)*d2[i]*em*sigma*(((theta2+460)**4)-((theta3+460)**4))-(2*(pi)*k*(theta1[j]-theta2))/ln(d2[i]/d1)
return LHS
theta2_initial = 300 # Your inital guess
result = fsolve(fcn, [theta2_initial,])
Resulted in:
error: Result from function call is not a proper array of floats.
If you look at the documentation https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.fsolve.html you see that fsolve has two required arguments. The first is a callable, i.e. a function, or a function handle. The second is an initial "guess" for the variable you want to solve for.
So to use fsolve you would first define a function that will return 0 for the correct value of its input:
def fcn(theta2):
# rewrite your equation as LHS(theta2) = 0
LHS = # Some expression depending on theta2
return [LHS,] # fsolve requires input and output to be the same shape.
# Now call fsolve
theta2_initial = # Your inital guess
result = fsolve(fcn, [theta2_initial,]) # Note fsolve expects an array in general as it can solve multivariable equations.
See the documentation page for a complete example.
currently I am trying to think about how to speedup odeint for a simulation I am running. Actually its only a primitive second order ode with a friction term and a discontinuous force. The model I am using to describe the dynamics is defined in a seperate function. Trying to solve the ode results in an error or extremely high computation times (talking about days).
Here is my code mostly hardcoded:
import numpy as np
import pandas as pd
from scipy.integrate import odeint
import matplotlib.pyplot as plt
def create_ref(tspan):
if tspan>2 and tspan<8:
output = np.sin(tspan)
elif tspan>=20:
output = np.sin(tspan*10)
else:
output = 0.5
return output
def model(state,t):
def Fs(x):
pT = 0
pB = 150
p0 = 200
pA = 50
kein = 0.25
kaus = 0.25
if x<0:
pA = pT
Fsres = -kaus*x*pA-kein*x*(p0-pB)
else:
pB = pT
Fsres = -kaus*x*pB-kein*x*(p0-pA)
return Fsres
x,dx = state
refnow = np.interp(t,xref.index.values,xref.values.squeeze())
refprev = np.interp(t-dt,xref.index.values,xref.values.squeeze())
drefnow = (refnow-refprev)/dt
x_meas = x
dx_meas = dx
errnow = refnow-x_meas
errprev = refprev-(x_meas-dx_meas*dt)
intrefnow = dt*(errnow-errprev)
kp = 10
kd = 0.1
ki = 100
sigma = kp*(refnow-x_meas)+kd*(drefnow-dx_meas)+ki*intrefnow
tr0 = 5
FricRed = (1.5-0.5*np.tanh(0.1*(t-tr0)))
kpu = 300
fr = 0.1
m = 0.01
d = 0.01
k = 10
u = float(kpu*np.sqrt(np.abs(sigma))*np.sign(sigma))
ddx = 1/m*(Fs(x)+FricRed*fr*np.sign(dx)-d*dx-k*x + u )
return [dx,ddx]
dt = 1e-3
tspan = np.arange(start=0, stop=50, step=dt)
steplim = tspan[-1]*0.1
reffunc = np.vectorize(create_ref)
xrefvals = reffunc(tspan)
xref = pd.DataFrame(data=xrefvals,index=tspan,columns=['xref'])
x0 = [-0.5,0]
simresult = odeint(model, x0, tspan)
plt.figure(num=1)
plt.plot(tspan,simresult[:,0],label='ispos')
plt.plot(tspan,xref['xref'].values,label='despos')
plt.legend()
plt.show()
I change the code according to Pranav Hosangadi s comments. Thanks for the hints. I didn't know that and learned something new and didn't expect dictionaries to have such a high impact on computation time. But now its much faster.
I have an exponential function with two known variables, x, and y. I need to find the value of y when I input an x. However, my code could not go through and solve the problem.
My function and all relevant constants are given below:
import math
import numpy as np
import scipy.optimize as optimize
x1=np.array([0,20])
Vt = 0.026
Io = 23*math.pow(10,-10)
Iph = 2.282
idf = 1
Ns = 60
Nm = 1
Rse = 0.5
Rsh = 1000
x = np.linspace(x1.min(),x1.max(),300)
def equation(x,Iph,Io,Rse,Rsh,Ns,Nm,Vt):
return y - Iph + Io*(np.exp((x+y*Rse)/(Ns*Nm*idf*Vt))-1) + x/Rsh + y*Rse/Rsh
y = optimize.newton(equation(10,Iph,Io,Rse,Rsh,Ns,Nm,Vt), 7)
Present output:
File "<ipython-input-172-93ede88c9b49>", line 16, in ivcurve_equation
return y - Iph + Io*(np.exp((x+y*Rse)/(Ns*Nm*idf*Vt))-1) + v/Rsh + I*Rse/Rsh
TypeError: can't multiply sequence by non-int of type 'float'
Expected output:
y = a real and positive value # >0
Have a quick look at the docs and try to do some 'pattern matching'. The parameters of equation should only be variables and not constants. Here is a working version of your code, that you should tailor to your needs:
import math
import numpy as np
import scipy.optimize as optimize
x1=np.array([0,20])
Vt = 0.026
Io = 23*math.pow(10,-10)
Iph = 2.282
idf = 1
Ns = 60
Nm = 1
Rse = 0.5
Rsh = 1000
x_arr = np.linspace(x1.min(),x1.max(),300)
x = x_arr[0]
def equation(y):
return y - Iph + Io*(np.exp((x+y*Rse)/(Ns*Nm*idf*Vt))-1) + x/Rsh + y*Rse/Rsh
result = optimize.newton(equation, 7)
print(result)
Now if you want the output for an array of x's try this:
def equation(y,x):
return y - Iph + Io*(np.exp((x+y*Rse)/(Ns*Nm*idf*Vt))-1) + x/Rsh + y*Rse/Rsh
result = [optimize.newton(equation, 7, args = (a,)) for a in x_arr]
print(result)
Hope this helps!
I Want to solve a system of three differential equation, changes the initial conditions
import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import solve_ivp
#__________________________Condiciones Problema ________________________
#Constants that are use in the problem
Yxs = 0.06
Yxp = 0.06
Umax = 0.24
Ks = 1.6
Cpm = 100
n = 2
#Function to solve de ODE
def fermentation_process(C,t):
Cx , Cs , Cp = C
U = (Umax*((Cs/(Ks+Cs))*(1-(Cp/Cpm)))**n)
rx = U*Cx
rs = -(1/Yxs)*(rx)
rp = (1/Yxp)*(rx)
dCx_dt = rx
dCs_dt = rs
dCp_dt = rp
return [dCx_dt,dCs_dt,dCp_dt]
#________________________Initial condition_____________________
Cx0 = 0.1
Cp0 = 0
#________________________Iterable intial Condition______
I save the initial conditions in a function to use this function in a bucle for
#Fuction to save the inintial conditions
def ini(Cs0):
return np.array([Cx0,Cs0,Cp0])
t_lim = (0,60)
Cs0 = 0
Bucle for evaluate the variable inintial condition Cs0
for i in range(5):
Cs0 += 10
sol = solve_ivp(fermentation_process, ini(Cs0), t_lim)
Tiempo = sol.t
concentraciones = sol.y
figure, axis = plt.subplots()
plt.plot(Tiempo, concentraciones[0])
plt.plot(Tiempo, concentraciones[2])
plt.show()
The error that I obtain is:
File "C:/Users/Paula/.spyder-py3/Sin tÃtulo0.py", line 50, in
fermentation_process Cx , Cs , Cp = C
TypeError: cannot unpack non-iterable float object
Please update the below function (as we cannot assign an array to multiple variables)
def fermentation_process(C,t):
Cx , Cs , Cp = C[0], C[1], C[2]
(or)
def fermentation_process(C,t):
Cx = C[0]
Cs = C[1]
Cp = C[2]
I've written a code for my school project. The u and v matrices are generated already. I've made a 2D contour, but I wish to plot u and v in 3D.
import numpy as np
#import matplotlib.pyplot as plt
#inputs
m = 40
n = 20
Uinf = 2
delX = 0.05
delY = 0.05
nu = 0.8e-2
u= np.zeros((m+1,n))
v= np.zeros((m+1,n))
#intializing boundry conditions
u[:,0] = v[:,0] = v[:,n-1] = v[0,:] = 0
u[:,n-1] = u[0,:] = Uinf
#main program
for i in range(0,m):
for j in range(1,n-1):
a = (nu*delX) / (u[i,j]*delY**2)
b = (v[i,j]*delX) / (2*u[i,j]*delY)
u[i+1,j] = (a-b)*u[i,j+1]+(1-2*a)*u[i,j]+(a+b)*u[i,j-1]
v[i+1,j] = v[i+1,j-1]-(delY/(2*delX))*(u[i+1,j]-u[i,j]+u[i+1,j-1]-u[i,j-1])
I have to mention that I don't wanna generate an arbitrary function; u[i,j] and v[i,j] are present.
Thanks!