Source code for pytherm.gaseq
import numpy as np
[docs]
def find_eq(n0, r_mat, K, T, P, ftol=1e-12, fabs=1e-4, k_lim=10):
def get_n(ksi):
n = np.full(len(n0), 0.0)
for i in range(len(n0)):
n[i] = r_mat[:, i] @ ksi
return n0 + n
def get_pr(ksi):
pr = np.full(len(K), 0.0) # реакционные произведения
ni = get_n(ksi) # кол-ва вещества i
n = np.sum(ni) # общее кол-ва вещества
xi = ni / n # мольные доли i
for i in range(len(K)):
s = np.power(xi, r_mat[i])
pr[i] = np.prod(s) * P ** sum(r_mat[i])
return pr
def fi(ksi):
pr = get_pr(ksi)
# res = (pr - K) ** 2
res = np.abs(np.log(pr) - np.log(K))
return res
def get_rl(p_ksi, ri):
p_ksi[ri] = 0
n = get_n(p_ksi)
vals = []
for i in range(len(n0)):
if r_mat[ri][i] > 0:
buf = n[i] / r_mat[ri][i]
vals.append(- buf)
r_l = max(vals)
return r_l
def get_rr(p_ksi, ri):
p_ksi[ri] = 0
n = get_n(p_ksi)
vals = []
for i in range(len(n0)):
if r_mat[ri][i] < 0:
buf = n[i] / r_mat[ri][i]
vals.append(- buf)
r_r = min(vals)
return r_r
# пересчет К на давление
K = np.array(K)
for i in range(len(K)):
K[i] = K[i] * P ** np.sum(r_mat[i])
# заранее неравновесные реакции проводятся заранее
for i in range(len(K)):
if abs(K[i]) < 10 ** (- k_lim):
p_ksi = np.full(len(K), 0, dtype=float)
b = get_rl(p_ksi, i)
p_ksi[i] = b
n = get_n(p_ksi)
n0 = n
if abs(K[i]) > 10 ** k_lim:
p_ksi = np.full(len(K), 0, dtype=float)
b = get_rr(p_ksi, i)
p_ksi[i] = b
n = get_n(p_ksi)
n0 = n
# неравновесные реакции не нужно уравнивать
# is_optimize = np.full(len(K), True)
# for i in range(len(K)):
# if abs(K[i]) > 10 ** k_lim or abs(K[i]) < 10 ** (- k_lim):
# is_optimize[i] = False
ksi = np.full(len(K), 0, dtype=float)
while (1):
f = fi(ksi)
print("F = ", f)
print("ksi = ", ksi)
if np.sum(f) < fabs:
break
# поиск реакции с мах f
v = 0
ri = 0
for i in range(len(f)):
if f[i] > v:
v = f[i]
ri = i
# расчет n при ksi[i] = 0
p_ksi = ksi
p_ksi[ri] = 0
r_l = get_rl(p_ksi, ri)
r_r = get_rr(p_ksi, ri)
rs = np.array((r_l, 0, r_r))
# начало оптимизации
vals_u = np.array((0.0, 0.0))
while (1):
rs[1] = (rs[0] + rs[2]) / 2
p_ksi[ri] = rs[1]
# print("F = ", fi(p_ksi))
# print("Ksi = ", p_ksi)
res = (K - get_pr(p_ksi))
vals_u[1] = vals_u[0]
vals_u[0] = fi(p_ksi)[ri]
if res[ri] < 0:
rs[2] = rs[1]
else:
rs[0] = rs[1]
if vals_u[0] == 0:
ksi[ri] = rs[1]
break
if vals_u[0] < fabs / 10:
ksi[ri] = rs[1]
break
tol = np.abs((vals_u[0] - vals_u[1]) / vals_u[0])
if tol < ftol:
ksi[ri] = rs[1]
break
print("________________DONE__________________________")
print("KSI =\n", ksi)
print("F final =\n", fi(ksi))
print("K =\n", K)
print("PR final =\n", get_pr(ksi))
print("Ns =\n", get_n(ksi))
return get_n(ksi)