def ventflow(self, T, P_discharge, D, Kd): """ Calculates the vent flow rate for all vapour venting scenarios. """ Mw = self.H2O.y * cc.MH2O + self.H2O2.y * cc.MH2O2 + self.O2.y * cc.MO2 Z = self.H2O.Z * self.H2O.y + self.H2O2.Z * self.H2O2.y + self.O2.Z * self.O2.y if self.critical_flow is True: C = 520 * np.sqrt(self.cp.k * ((2 / (self.cp.k + 1)) ** ((self.cp.k + 1) / (self.cp.k - 1)))) self.m_vent_vap = ((A_relief(D) * 1000000 * C * Kd * self.cp.P / 13160) * np.sqrt( Mw / (c2k(T) * Z)) * 1000 / 3600) elif self.critical_flow is False: r = self.cp.P / P_discharge F2 = np.sqrt((self.cp.k / (self.cp.k - 1)) * r ** (2 / self.cp.k) * ((1 - r ** ((self.cp.k - 1) / self.cp.k)) / (1 - r))) self.m_vent_vap = (((A_relief(D) * 1000000 * F2 * Kd / 17.9) * np.sqrt( Mw * self.cp.P * (self.cp.P - P_discharge) / (Z * c2k(T)))) * 1000 / 3600) self.n_vent_vap = self.m_vent_vap / Mw
def surface_tension(self, T): """ Calculate surface tension of liquid water in N/m. """ B = 235.8E-3 b = -0.625 u = 1.256 self.st = B * (((cc.TcH2O - c2k(T)) / cc.TcH2O) ** u) * (1 + b * (cc.TcH2O - c2k(T)) / cc.TcH2O)
def reduced_tempertaure(self, T, Tc): """ Calculate the reduced temperature. For use in estimating compressibility factors of non-ideal vapours using RK-EOS. """ return c2k(T) / Tc
def equilibrate(self, data): """ Works with VLE to calculate thermodynamically stable vessel conditions given data. Arguments: data: list containing best initial guess for vessel thermodynamic conditions contains: [ xH2O (mol fraction water in liquid phase), xH2O2 (mol fraction hydrogen peroxide in liquid phase), yH2O (mol fraction water in vapour phase), yH2O2 (mol fraction hydrogen peroxide in vapour phase), yO2 (mol fraction oxygen in vapour phase), nL (total moles of liquid in vessel), nG (total moles of vapour in vessel), P (total vessel pressure), PH2O (water partial pressure), PH2O2 (hydrogen peroxide partial pressure), VL (liquid volume), ZO2 (oxygen compressibility factor) ] """ initvals = np.asarray(data) (self.xH2O, self.xH2O2, self.yH2O, self.yH2O2, self.yO2, self.nL, self.nG, self.P, self.PH2O, self.PH2O2, self.VL, ZO2) = opt.fsolve(self.VLE, initvals) self.VG = self.VR - self.VL self.xO2 = 0 self.PO2 = self.nO2 * cc.R * c2k(self.T) / self.VG
def initial_conditions(self): """ Calculates thermodynamically stable starting conditions for the reactor. """ H2O = pl.Water(self.T) H2O2 = pl.Hydrogen_Peroxide(self.T) self.mH2O2 = self.mR * self.XH2O2 self.mH2O = self.mR * (1 - self.XH2O2) self.nH2O2 = self.mH2O2 * 1000 / cc.MH2O2 self.nH2O = self.mH2O * 1000 / cc.MH2O VG = self.VR - self.mH2O / H2O.density - self.mH2O2 / H2O2.density VL = self.mH2O / H2O.density - self.mH2O2 / H2O2.density self.nO2 = self.P0 * VG / (cc.R * c2k(self.T)) self.mO2 = self.nO2 * cc.MO2 self.ntotal = self.nH2O + self.nH2O2 + self.nO2 self.zH2O = self.nH2O / self.ntotal self.zH2O2 = self.nH2O2 / self.ntotal self.zO2 = self.nO2 / self.ntotal data = [ self.zH2O, self.zH2O2, self.zH2O, self.zH2O2, self.zO2, self.ntotal, self.nO2, self.P0, H2O.Psat, H2O2.Psat, VL, 0.95 ] self.equilibrate(data)
def VLE(self, z): """ Solver for calculating thermodynamically stable equilibrium conditions given overall composition, temperature, and quantity of material. """ xH2O = z[0] xH2O2 = z[1] yH2O = z[2] yH2O2 = z[3] yO2 = z[4] nL = z[5] nG = z[6] P = z[7] PH2O = z[8] PH2O2 = z[9] VL = z[10] ZO2 = z[11] H2O = pl.Water(self.T, P) H2O2 = pl.Hydrogen_Peroxide(self.T, P) O2 = pl.Oxygen(self.T, P) A = 0.42748 * O2.Pr / O2.Tr**2.5 B = 0.08664 * O2.Pr / O2.Tr F = np.empty(12) F[0] = nL * xH2O + nG * yH2O - self.ntotal * self.zH2O F[1] = nL * xH2O2 + nG * yH2O2 - self.ntotal * self.zH2O2 F[2] = nL + nG - self.ntotal F[3] = PH2O + PH2O2 + (ZO2 * self.nO2 * cc.R * c2k(self.T)) / (self.VR - VL) - P F[4] = PH2O - xH2O * H2O.Psat * H2O.gamma F[5] = PH2O2 - xH2O2 * H2O2.Psat * H2O2.gamma F[6] = yH2O - PH2O / P F[7] = yH2O2 - PH2O2 / P F[8] = yO2 - (ZO2 * self.nO2 * cc.R * c2k(self.T)) / ( (self.VR - VL) * P) F[9] = xH2O + xH2O2 - yH2O - yH2O2 - yO2 F[10] = VL - nL * ((xH2O * cc.MH2O / (H2O.density * 1000)) + (xH2O2 * cc.MH2O2 / (H2O2.density * 1000))) F[11] = ZO2**3 - ZO2**2 + (A - B - B**2) * ZO2 - A * B return F
def activity(self, T, xH2O): """ Calculate the activity coefficient for hydrogen peroxide (H2O). """ Ca0 = -999.883 Ca1 = -2499.584 Ca2 = 8.261924 Ca3 = 327.4487 P10 = 17418.34 P11 = -109.9125 P12 = 0.1663847 P20 = -6110.401 P21 = 28.08669 P22 = -0.03587408 Ca01 = 126.7385 Ca11 = -2558.776 Ca21 = 12.33364 Ca31 = 343.105 Ca02 = 63.18354 Ca12 = -149.9278 Ca22 = 0.4745954 Ca32 = 348.1642 Ca03 = 59.42228 Ca13 = -199.2644 Ca23 = 0.8321514 Ca33 = 346.2121 T_K = c2k(T) if T_K > 0 and T_K <= 317.636: Ba = Ca0 + ((Ca1 * Ca2) / (np.pi * (Ca2 ** 2 + (T_K - Ca3) ** 2))) elif T_K > 317.636 and T_K <= 348.222: Ba = ((Ca0 + ((Ca1 * Ca2) / (np.pi * (Ca2 ** 2 + ((T_K - Ca3) ** 2))))) + ( P12 * T_K ** 2 + P11 * T_K + P10)) / 2 elif T_K > 348.222 and T_K <= 391.463: Ba = P22 * T_K ** 2 + P21 * T_K + P20 else: Ba = -612.9613 Bb = Ca01 + ((Ca11 * Ca21) / (np.pi * (Ca21 ** 2 + ((T_K - Ca31) ** 2)))) Bc = Ca02 + (Ca12 / (1 + np.exp(Ca22 * (T_K - Ca32)))) Bd = Ca03 + (Ca13 / (1 + np.exp(Ca23 * (T_K - Ca33)))) self.gamma = np.exp((xH2O ** 2 / (cc.R * T_K)) * ( Ba + Bb * (3 - 4 * xH2O) + Bc * (1 - 2 * xH2O) * (5 - 6 * xH2O) + Bd * ((1 - 2 * xH2O) ** 2) * ( 7 - 8 * xH2O)))
def heat_capacity_G(self, T): """ Calculate the constant pressure heat capacity of water vapour in J/(g*K). """ A = 30.09200 B = 6.832514 C = 6.793435 D = -2.534480 E = 0.082139 Tref = c2k(T) / 1000 self.cpg = (A + B * Tref + C * Tref ** 2 + D * Tref ** 3 + E / Tref ** 2) / cc.MH2O
def heat_capacity_G(self, T): """ Calculate the constant pressure heat capacity of oxygen gas in J/(g*K). """ K = 31.32234 L = -20.23531 M = 57.86644 N = -36.50624 O = -0.007374 Tref = c2k(T) / 1000 self.cpg = (K + L * Tref + M * Tref ** 2 + N * Tref ** 3 + O / Tref ** 2) / cc.MO2
def heat_capacity_G(self, T): """ Calculate the constant pressure heat capacity of hydrogen peroxide vapour in J/(g*K). """ F = 34.25667 G = 55.18445 H = -35.15443 I = 9.087440 J = -0.422157 Tref = c2k(T) / 1000 self.cpg = (F + G * Tref + H * Tref ** 2 + I * Tref ** 3 + J / Tref ** 2) / cc.MH2O2
def heat_capacity_L(self, T): """ Calculate the constant pressure heat capacity of liquid water in J/(g*K). """ A = -203.606 B = 1523.290 C = -3196.413 D = 2474.455 E = 3.855326 Tref = c2k(T) / 1000 self.cpl = (A + B * Tref + C * Tref ** 2 + D * Tref ** 3 + E / Tref ** 2) / cc.MH2O
def kinetics(self, T, kf): self.rate = cc.A_ar * kf * np.exp(-cc.Ea / c2k(T))
def coupling(self, z, X, T): vt = (1 - X) * self.vL + X * self.vG * z[0] ** (-1 / self.cp.k) F = np.empty(1) F[0] = (2 * self.cp.P / vt ** 2) * ( (1 - X) * self.vL * (1 - z[0]) + X * self.vG * (self.cp.k / (self.cp.k - 1)) * (1 - z[0] ** ((self.cp.k - 1) / self.cp.k))) - 1 / ( (X * self.vG / (self.cp.k * self.cp.P)) + ((self.vG - self.vL) * self.cp.dHvap) ** 2 * self.CpL * c2k(T)) return F
def rxn_vent_ode(self, t, Y, k): """ Main ODE funtion for integration of both venting, nonventing, and BPR enabled scenarios. Arguments: k: Integration iteration number. Used for indexing current data set. """ T, Tj, nH2O, nH2O2, nO2 = Y # Total reaction mass (g) mR = nH2O * cc.MH2O + nH2O2 * cc.MH2O2 + nO2 * cc.MO2 # Update VLE conditions in reactor system and generate compound objects/kinetic data uc = VLE.Update_Conditions(self.scenario, T, nH2O, nH2O2, nO2, self.data, k) self.H2O = pl.Water(T, uc.P, uc) self.H2O2 = pl.Hydrogen_Peroxide(T, uc.P, uc) self.O2 = pl.Oxygen(T, uc.P, uc) self.cp = pl.Common_Properties(T, uc, self.H2O, self.H2O2, self.O2) kin = pl.Kinetics(T, self.scenario.kf) # Mass fraction vapour in vessel x = self.cp.nG * (self.H2O.y * cc.MH2O + self.H2O2.y * cc.MH2O2 + self.O2.y * cc.MO2) / \ (self.cp.nG * (self.H2O.y * cc.MH2O + self.H2O2.y * cc.MH2O2 + self.O2.y * cc.MO2) + self.cp.nL * (self.H2O.x * cc.MH2O + self.H2O2.x * cc.MH2O2)) # Average phase and vessel properties self.CpL = self.H2O.x * self.H2O.cpl + self.H2O2.x * self.H2O2.cpl # Average liquid constant pressure heat capacity (J/(g*K)) self.CpG = self.H2O.y * self.H2O.cpg + self.H2O2.y * self.H2O2.cpg + self.O2.y * self.O2.cpg # Average vapour constant pressure heat capacity (J/(g*K)) self.Cp = x * self.CpG + ( 1 - x) * self.CpL # Average heat capacity in vessel (J/(g*K)) self.pG = (1 / (cc.R * c2k(T) * 1000)) * ( self.H2O.P * cc.MH2O + self.H2O2.P * cc.MH2O2 + self.O2.P * cc.MO2 ) # Average vapour density (kg/L) self.pL = self.H2O.density * self.H2O.x + self.H2O2.density * self.H2O2.x # Average liquid density (kg/L) self.vL = 1 / self.pL # Average specific gravity (L/kg) self.vG = 1 / self.pG vfg = self.vG - self.vL # Change in specific volume upon vaporization (L/kg) # Calculate vent flow rate self.vent_calc(T) self.aux = pl.Aux_Properties(self.m_vent, self.xe) # Differential equations for change in molar amount of components (mol/s) dnH2O_dt = kin.rate * nH2O2 - (self.H2O.y * self.xe + self.H2O.x * (1 - self.xe)) * self.n_vent dnH2O2_dt = -kin.rate * nH2O2 - (self.H2O2.y * self.xe + self.H2O2.x * (1 - self.xe)) * self.n_vent dnO2_dt = kin.rate * nH2O2 / 2 - self.O2.y * self.xe * self.n_vent # Vessel thermodynamics dTj_dt = self.ramp_rate / 60 Q_rxn = dnH2O2_dt * cc.MH2O2 * cc.dH_rxn Q_HEx = self.scenario.Ux * A_wet(self.cp.VL, self.scenario.D) * (T - Tj) Q_vap = ((self.vL / vfg) + 1) * self.cp.dhvap * self.n_vent * ( self.H2O.y + self.H2O2.y) * cc.MH2O Xp = ((self.cp.dhvap - self.cp.P * vfg) / (vfg * self.Cp * 1000)) * (x * self.cp.dvGdt / 1000 + (1 - x) * self.cp.dvLdt / 1000) dT_dt = (Q_rxn - Q_HEx - Q_vap) / (mR * self.Cp * (1 - Xp)) return [dT_dt, dTj_dt, dnH2O_dt, dnH2O2_dt, dnO2_dt]