trying to solve differential equations simultaneously - python

I am trying to build a code for chemical reactor design which is able to solve for the pressure drop, conversion, and temperature of a reactor. All these parameters have differential equations, so i tried to define them inside a function to be able to integrate them using ODEINT. However it seems that the function i've built has an error which i can't figure out which held me back from integration it.
the error that i'm encountering:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-32-63c706e84be5> in <module>
1 X0=[0.05,1200,2]
----> 2 y=func(X0,0)
<ipython-input-27-6cfd4fef5ee2> in func(x, W)
8 kp=np.exp(((42311)/(R*T))-11.24)
9 deltah=-42471-1.563*(T-1260)+0.00136*(T**2 -1260**2)- 2,459*10e-7*(T**3-1260**3)
---> 10 ra=k*np.sqrt((1-X)/X)*((0.2-0.11*X)/(1-0.055*X)*(P/P0)-(x/(kp*(1-x)))**2)
11 summ = 57.23+0.014*T-1.94*10e-6*T**2
12 dcp=-1.5625+2.72*10e-3*T-7.38*10e-7*T**2
TypeError: unsupported operand type(s) for -: 'int' and 'list'
and here is the full code:
import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import odeint
fi = 0.45
gas_density = 0.054 #density
Pres0 = 2 #pressure
visc = 0.09
U = 10
Ac = 0.0422
T0 = 1400 #and 1200 also
gc = 4.17 * 10**8
bed_density = 33.8
Ta = 1264.6 #wall temp
fa0 = 0.188
def func(x,W):
X = x[0]
T = x[1]
P = x[2]
P0 = 2
R = 0.7302413
k = np.exp((-176008 / T) - (110.1 * np.log(T) + 912.8))
kp = np.exp(((42311) / (R * T)) - 11.24)
deltah = -42471 - 1.563 * (T - 1260) + 0.00136 * (T**2 - 1260**2) - 2,459 * 10e-7 * (T**3 - 1260**3)
ra = k * np.sqrt((1 - X) / X) * ((0.2 - 0.11 * X) / (1 - 0.055 * X) * (P / P0) - (x / (kp * (1 - x)))**2)
summ = 57.23 + 0.014 * T - 1.94 * 10e-6 * T**2
dcp = -1.5625 + 2.72 * 10e-3 * T - 7.38 * 10e-7 * T**2
dxdw = 5.31 * k * np.sqrt((1 - X) / X) * ((0.2 - 0.11 * X) / (1 - 0.055 * X) * (P / P0) - (x / (kp * (1 - x)))**2)
dpdw = (((-1.12 * 10**-8) * (1 - 0.55 * X) * T) / P) * (5500 * visc + 2288)
dtdw = (5.11 * (Ta - T) + (-ra) * deltah) / (fa0 * (summ + x * dcp))
return [dxdw, dpdw, dtdw]
X0 = [0.05, 1200, 2]
y = func(X0, 0)
thanks in advance

Inside line
ra=k*np.sqrt((1-X)/X)*((0.2-0.11*X)/(1-0.055*X)*(P/P0)-(x/(kp*(1-x)))**2)
you probably want to use ...X/(kp*(1-X))... instead of ...x/(kp*(1-x))... (i.e. use upper X), lower x is list type.
If you want to use some list variable l as multiple values somewhere then convert it to numpy array la = np.array(l) and use la in numpy vectorized expression.

Related

Solver Issue No Algorithm Found

Trying to replace the function U2(x,y,z) with specified values of x,y,z. Not sure how to do that with sympy because they are as "x = arange.(-h,h,0.001)" as seen in the code below.
Below you will find my implementation with sympy. Additionally I am using PyCharm.
This implementation is based on Dr. Annabestani and Dr. Naghavis' paper: A 3D analytical ion transport model for ionic polymer metal composite actuators in large bending deformations
import sympy as sp
h = 0.1 # [mm] half of thickness
W: float = 6 # [mm] width
L: float = 28 # [mm] length
F: float = 96458 # [C/mol] Faraday's constant
k_e = 1.34E-6 # [F/m]
Y = 5.71E8 # [Pa]
d = 1.03 - 11 # [m^2/s] diffiusitivity coefficient
T = 293 # [K]
C_minus = 1200 # [mol/m^3] Cation concentration
C_plus = 1200 # [mol/m^3] anion concentration
R = 8.3143 # [J/mol*K] Gas constant
Vol = 2*h*W*L
#dVol = diff(Vol,x) + diff(Vol, y) + diff(Vol, z) # change in Volume
theta = 1 / W
x, y, z, m, n, p, t = sp.symbols('x y z m n p t')
V_1 = 0.5 * sp.sin(2 * sp.pi * t) # Voltage as a function of time
k_f = 0.5
t_f = 44
k_g = 4.5
t_g = 0.07
B_mnp = 0.003
b_mnp: float = B_mnp
gamma_hat_2 = 0.04
gamma_hat_5 = 0.03
gamma_hat_6 = 5E-3
r_M = 0.15 # membrane resistance
r_ew = 0.175 # transverse resistance of electrode
r_el = 0.11 # longitudinal resistance of electrode
mu = 2.4
sigma_not = 0.1
a_L: float = 1.0 # distrubuted surface attentuation
r_hat = sp.sqrt(r_M ** 2 + r_ew ** 2 + r_el ** 2)
lambda_1 = 0.0001
dVol = 1
K = (F ** 2 * C_minus * d * (1 - C_minus * dVol)) / (R * T * k_e) # also K = a
K_hat = (K-lambda_1)/d
gamma_1 = 1.0
gamma_2 = 1.0
gamma_3 = 1.0
gamma_4 = 1.0
gamma_5 = 1.0
gamma_6 = 1.0
gamma_7 = 1.0
small_gamma_1 = 1.0
small_gamma_2 = 1.0
small_gamma_3 = 1.0
psi = gamma_1*x + gamma_2*y + gamma_3*z + gamma_4*x*y + gamma_5*x*z + gamma_6*y*z + gamma_7*x*y*z + (small_gamma_1/2)*x**2 + (small_gamma_2/2)*y**2 + (small_gamma_3/2)*x*z**2
psi_hat_part = ((sp.sin(((m + 1) * sp.pi) / 2 * h)) * x) * ((sp.sin(((n + 1) * sp.pi) / W)) * y) * ((sp.sin(((p + 1) * sp.pi) / L)) * z)
psi_hat = psi * psi_hat_part # Eqn. 19
print(psi_hat)
x1: float = -h
x2: float = h
y1: float = 0
y2: float = W
z1: float = 0
z2: float = L
I = psi_hat.integrate((x, x1, x2), (y, y1, y2), (z, z1, z2)) # Integration for a_mnp Eqn. 18
A_mnp = ((8 * K_hat) / (2 * h * W * L)) * I
Partial = A_mnp * ((sp.sin(((m + 1) * sp.pi) / 2 * h)) * x) * ((sp.sin(((n + 1) * sp.pi) / W)) * y) * ((sp.sin(((p + 1) * sp.pi) / L)) * z)
start = Partial.integrate((p, 0 , 10E9), (n, 0, 10E9), (m, 0, 10E9)) #when using infinity it goes weird, also integrating leads to higher thresholds than summation
a_mnp_denom = (((sp.sin(((m + 1) * sp.pi) / 2 * h)) ** 2) * ((sp.sin(((n + 1) * sp.pi) / W)) ** 2) * (
(sp.sin(((p + 1) * sp.pi) / L)) ** 2) + K_hat)
a_mnp = A_mnp / a_mnp_denom # Eqn. 18
U2 = sp.Function("U2")
U2 = a_mnp * ((sp.sin(((m + 1) * sp.pi) / 2 * h)) * x) * ((sp.sin(((n + 1) * sp.pi) / W)) * y) * (
(sp.sin(((p + 1) * sp.pi) / L)) * z) # Eqn. 13
x = np.arange(-h, h, 0.001)
y = np.arange(-h, h, 0.001)
z = np.arange(-h, h, 0.001)
f= sp.subs((U2), (x ,y ,z))
I currently get the error message: ValueError: subs accepts either 1 or 2 arguments. So that means I can't use the subs() method and replace() also doesn't work too well. Are there any other methods one can use?
Any help will be grateful, thank you!
Oscar is right: you are trying to deal with too much of the problem at once. That aside, Numpy and SymPy do not work like you think they do. What were you hoping to see when you replaced 3 variables, each with a range?
You cannot replace a SymPy variable/Symbol with a Numpy arange object, but you can replace a Symbol with a single value:
>>> from sympy.abc import x, y
>>> a = 1.0
>>> u = x + y + a
>>> u.subs(x, 1)
y + 2.0
>>> u.subs([(x,1), (y,2)])
4.0
You might iterate over the arange values, creating values of f and then doing something with each value:
f = lambda v: u.subs(dict(zip((x,y),v)))
for xi in range(1,3): # replace range with your arange call
for yi in range(-4,-2):
fi = f((xi,yi))
print(xi,yi,fi)
Be careful about iterating and using x or y as your loop variable, however, since that will then lose the assignment of the Symbol to that variable,
for x in range(2):
print(u.subs(x, x)) # no change and x is no longer a Symbol, it is now an int

Numpy refuses to display vectorized function

I've got a code that runs as follows:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import pyXSteam.XSteam
from pyXSteam.XSteam import XSteam
steamTable = XSteam(XSteam.UNIT_SYSTEM_MKS) # m/kg/sec/°C/bar/W
A = 3000 #define the heat exchange area
d_in = 20 #define the inner diameter of HE tubes
CF = 0.85 #define the cleanliness factor of SC.
w = 2.26 #define the water velocity within the tubes
Dk=np.arange(27.418,301.598,27.418) #define the range of steam loads
dk = (Dk * 1000 / (A * 3.600)) #calculate the relative steam load
Tcwin=20
def Cp():
return steamTable.CpL_t(Tcwin)
Gw = 13000 #define the flow of CW, t/hr
e = 2.718281828
f_velocity = w * 1.1 / (20 ** 0.25)
f_w=0.12 * CF * (1 + 0.15 * Tcwin)
Ф_в = f_velocity ** f_w
K = CF * 4070 * ((1.1 * w / (d_in ** 0.25)) ** (0.12 * CF * (1 + 0.15 * Tcwin))) * (1 - (((35 - Tcwin) ** 2) * (0.52 - 0.0072 * dk) * (CF ** 0.5)) / 1000)
n = (K * A) / (Cp() * Gw * 1000)
Tcwout_theor = Tcwin + (Dk * 2225 / (Cp() * Gw))
Subcooling_theor = (Tcwout_theor - Tcwin) / (e ** (K * A / (Cp() * (Gw * 1000 / 3600) * 1000)))
TR_theor = (Tcwout_theor - Tcwin)
Tsat_theor = (Tcwout_theor + Subcooling_theor)
def Ts():
return np.vectorize(Tsat_theor)
def Psat_theor():
return steamTable.psat_t(Tsat_theor)
print(Dk)
print(Tsat_theor)
print(Psat_theor)
While it does calculate Tsat_theor, it fails to print Psat_theor.
The output goes like this:
<function Psat_theor at 0x000002A7C29F0D30>
How can I obtain the actual value of Psat_theor?
You need to call mentioned function, change
print(Psat_theor)
to
print(Psat_theor())

Solving a double integral with scipy dblquad

I am trying to solve the double integral of this complicated function. The function contains 3 symbolic variables which are defined with sympy.symbols. My goal is to integrate the function with respect to only two of the variables. sym.integrate run for 2 hours with no results to show. I tried numerical integration with scipy.integrate.dblquad. But I am having troubles which I suspect is due to the third symbolic variable. Is there a way to do this.
Problem summarized.
sym.symbols('x y z')
My_function(x,y,z)
Integrate My_function with respect to x and y (Both from 0 to inf i.e. definite integral).
Thank you in advance
h, t, w, r, q = sym.symbols('h t w r q') # Define symbols
wn = 2.0
alpha = 1.76
beta = 1.59
a0 = 0.7
a1 = 0.282
a2 = 0.167
b0 = 0.07
b1 = 0.3449
b2 = -0.2073
psi = 0.05
F_H = 1.0 - sym.exp(-(h / alpha) ** beta)
mu_h = a0 + a1 * h ** a2
sig_h = b0 + b1 * sym.exp(b2 * h)
F_TIH = (1 / 2) * (1 + sym.erf((sym.log(t) - mu_h) / (sig_h * sym.sqrt(2))))
f_h = sym.diff(F_H, h)
f_tzIhs = sym.diff(F_TIH, t)
f_S = f_h * f_tzIhs
H = (1.0 - (w / wn) ** 2.0 + 1.0j * 2.0 * psi * w / wn) ** (-1.0)
S_eta_h_t = h ** 2.0 * t / (8.0 * pi ** 2.0) * (w * t / (2.0 * pi)) ** (-5.0) * sym.exp(-1.0 / pi * (w * t / (2.0 * pi)) ** (-4.0))
S_RIS_hu_tu = abs(H) ** 2.0 * S_eta_h_t
m0_s = sym.integrate((w ** 0 * S_RIS_hu_tu), (w, 0, np.inf))
m0_s.doit()
m2_s = sym.integrate((w ** 2 * S_RIS_hu_tu), (w, 0, np.inf))
m2_s.doit()
v_rIs = 1 / (2 * pi) * sym.sqrt(m2_s / m0_s) * sym.exp(-r ** 2 / (2 * m0_s))
fun = v_rIs * f_S
# The integral I am trying to solve is a function of h,t and r.
integ_ht = sym.integrate(fun,(h,0,np.inf),(t,0,np.inf))

Why the figure plotted by my code only shows the blank?

Here is the attachment of the python code:
from scipy.stats import norm
import matplotlib.pyplot as plt
import numpy as np
import math
def V(S0):
# nx = norm.cdf(x)
K = 1.5
T = 1
sigma = 0.1
rd = 0.03
ry = 0.02
e = math.e
d1 = (math.log((S0 * e ** ((rd - ry) * T)) / K) + (sigma ** 2 * T) / 2) / (sigma * math.sqrt(T))
d2 = (math.log((S0 * e ** ((rd - ry) * T)) / K) - (sigma ** 2 * T) / 2) / (sigma * math.sqrt(T))
nd1 = norm.cdf(d1)
nd2 = norm.cdf(d2)
V = e ** (-rd * T) * (S0 * e ** ((rd - ry) * T) * nd1 - K * nd2)
V2 = np.vectorize(V)
S0 = np.arange(1, 1000, 1)
plt.title('V as a function of S0')
plt.xlabel('S0')
plt.ylabel('V')
plt.plot(S0, V2(S0))
plt.show()
And the code with such a result:
How can I fix it?
There are two issues
math.log only accepts size-1 arrays
Removed the math module and switched to numpy methods
Nothing is returned by the function V
Added return V
from scipy.stats import norm
import matplotlib.pyplot as plt
import numpy as np
def V(S0):
# nx = norm.cdf(x)
K = 1.5
T = 1
sigma = 0.1
rd = 0.03
ry = 0.02
e = np.e
d1 = (np.log((S0 * e ** ((rd - ry) * T)) / K) + (sigma ** 2 * T) / 2) / (sigma * np.sqrt(T))
d2 = (np.log((S0 * e ** ((rd - ry) * T)) / K) - (sigma ** 2 * T) / 2) / (sigma * np.sqrt(T))
nd1 = norm.cdf(d1)
nd2 = norm.cdf(d2)
V = e ** (-rd * T) * (S0 * e ** ((rd - ry) * T) * nd1 - K * nd2)
return V # return V added
V2 = np.vectorize(V)
S0 = np.arange(1, 1000, 1)
plt.title('V as a function of S0')
plt.xlabel('S0')
plt.ylabel('V')
plt.plot(S0, V2(S0))
plt.show()

How do you iterate and update a numpy array to solve a system of linear equations of form Ax=B?

So I am looking to solve a system of equations in python 3.7 with numpy. However, I need to solve the system of equations at the end of each iteration. During the iterations, it will solve some equations that will make up the contents of A and B to find x in the form of Ax=B. Upon solving for x I need to save these values to then solve the underlying equations for the following iteration to be reimplemented in A and B.
I have tried a more linear approach to solving the problem but it is not good for my end goal of solving the equation attached in the image. What I have done so far has also been attached below:
i = 0
while (y[i] >= 0 ): #Object is above water
t[i+1] = t[i] + dt
vx[i+1] = vx[i] + dt * ax[i] #Update the velocities
vy[i+1] = vy[i] + dt * ay[i]
v_ax[i+1] = (vx[i]*np.sin(phi/180*np.pi)) - (vy[i]*np.cos(phi/180*np.pi))
v_nor[i+1] = (vx[i]*np.cos(phi/180*np.pi)) + (vy[i]*np.sin(phi/180*np.pi))
F_wnor[i+1] = (Cd_a * A_da * rho_air * (v_nor[i] - v_wind*np.sin(phi/180*np.pi)) * abs(v_nor[i] - v_wind*np.sin(phi/180*np.pi)))/2
F_wax[i+1] = (Cd_a * A_da * rho_air * (v_ax[i] - v_wind*np.sin(phi/180*np.pi)) * abs(v_ax[i] - v_wind*np.sin(phi/180*np.pi)))/2
F_wx[i+1] = (-F_wax[i] * np.sin(phi/180*np.pi)) - (F_wnor[i] * np.cos(phi/180*np.pi))
F_wy[i+1] = (F_wax[i] * np.cos(phi/180*np.pi)) - (F_wnor[i] * np.sin(phi/180*np.pi))
ax[i+1] = F_wx[i]/M
ay[i+1] = (F_wx[i]/M) - g
y[i+1] = (y[i]+dt*vy[i])
x[i+1] = (x[i]+dt*vx[i])
i = i + 1
j = i
#under water velocities
# if y(t)>0: M*z'' = M.g - Fb + Fd + Fm
while (y[j] <= 0 and y[j] > -10):
if (abs(y[j]/r)< 2):
theta_degree = 2 * np.arccos(1 - (abs(y[j])/r))
theta = theta_degree/180*np.pi
m = ((rho_water * r**2)/2) * (((2*(np.pi)**3*(1-np.cos(theta))) / ( 3 * (2*np.pi-theta)**2)) \
+ (np.pi * (1-np.cos(theta)*1/3)) + (np.sin(theta)) - (theta))
dm_dz = ((rho_water * r)/np.sin(theta/2)) * (((2 * (np.pi)**3 / 3) * ((np.sin(theta) / (2*np.pi - theta)**2) \
+ (2 * (1-np.cos(theta)) / (2*np.pi - theta )**3))) + (np.pi * np.sin(theta) / 3) + np.cos(theta) - 1)
A_i = (r**2)/2 * (theta - np.sin(theta))
F_m[j] = - m * ay[j] - dm_dz * np.max(vy)*vy[j]
F_uwater[j] = (M * g) - (rho_water * A_i * g) - (Cd_y * rho_water * r * vy[j] * abs(vy[j]))
else:
m = np.pi * rho_water * r**2
dm_dz = 0
A_i = np.pi * r**2
F_m[j] = - m * ay[j] - dm_dz * vy[j]**2
F_uwater[j] = (M * g) - (rho_water * A_i * g) - (Cd_y * rho_water * r * vy[j] * abs(vy[j]))
print("Fully submerged")
t[j+1] = t[j] + dt
vx[j+1] = vx[j] + dt * ax[j] #Update the velocities
vy[j+1] = vy[j] + dt * ay[j]
ax[j+1] = F_wx[j]/M
ay[j+1] = (F_uwater[j] + F_m[j]/M)
y[j+1] = (y[j]+dt*vy[j])
x[j+1] = (x[j]+dt*vx[j])
print(y[j])
j = j + 1
I do not know how to go about this and help for getting started would be greatly appreciated!.
The problem I am trying to solve can be seen more clearly in the picture attached. System of equations I am trying to solve

Categories