def calc_G_HEM_Zweiphasig_1(p_0, T_0, p_2, T_2, zeta_): #kritisch Massenstrom darstellen schritt = 1000 #wie viel Teile geteilt sind in der Gleichung B3.2-9 p = np.linspace(p_0, p_2, schritt) delta_p = (p_2 - p_0) / schritt state_0 = IAPWS97(T=T_0, P=p_0) s_0 = state_0.s # unterschiedlicher Zustand mit gleicher Entropie v_0 = state_0.v sigma_p = 0 sigma_v = 0 G = 0 G_List = [] for pressureVAL in p: # state_1 = IAPWS97(P = pressureVAL, s=s_0) # unterschiedlicher Zustand mit gleicher Entropie state_2 = IAPWS97( P=(pressureVAL + delta_p), s=s_0) # unterschiedlicher Zustand mit gleicher Entropie # v_1= state_1.v v_2 = state_2.v # delta_v=v_2-v_1 sigma_v = math.log(v_2 / v_0) sigma_p = sigma_p + delta_p / v_2 G = (((-2 * sigma_p) / (zeta_ + 2 * sigma_v))**0.5) * 1000 #kg/m^2/s G_List.append(G) plt.figure(1) #Diagramm zeichnen plt.xlabel("Austrittsdruck in MPa") plt.ylabel("G") plt.plot(p, G_List) return [round(G, 2), round(pressureVAL, 4)]
def calc_P_ein_mit_gleich_s( p_0, T_0, p_2, T_2, zeta_, A_ ): #beruecksichtigung des Eintrittsducks mit der Erweiterungen der klassischen Formulierung state_s_T_0 = IAPWS97(T=T_0, x=0) state_0 = IAPWS97(T=T_0, P=p_0) h_0 = state_0.h s_0 = state_0.s # p_s_0 = state_s_T_0.P # rho_0=state_0.rho #dichte kg/m^3 P_ein_List = np.linspace(max(p_s_0, p_0 - 1, p_2), p_0, 20) delta_G_List = [] for P_ein in P_ein_List: G_1 = calc_G_HEM_Zweiphasig(P_ein, T_0, p_2, T_2, zeta_)[0] state_1 = IAPWS97(P=P_ein, s=s_0) h_1 = state_1.h v_1 = state_1.v G_2 = math.sqrt(2 * (h_0 - h_1) * 1000 / v_1 / v_1) print(P_ein, G_1, G_2) delta_G = abs(G_1 - G_2) delta_G_List.append(delta_G) delta_G_min = min(delta_G_List) G_index = delta_G_List.index(delta_G_min) P_ein = P_ein_List[G_index] Zustand = calc_G_HEM_Zweiphasig(P_ein, T_0, p_2, T_2, zeta_) G = Zustand[0] P_aus = Zustand[1] kritisch = Zustand[2] V = G * A_ * 1000 #Massenstrom g/s print(p_0, round(G, 2), round(V, 2), P_ein, round(P_aus, 4), kritisch) return [round(G, 2), round(V, 2), P_ein, round(P_aus, 4), kritisch]
def solve_back_P(self, P_high, P_low, T21, length): P_guess = (P_high + P_low) / 2. # initial pressure guess S2 = IAPWS97(P=P_guess, T=T21) # create instance for guessed steam conditions V2 = self.calc_vel(self.m_dot2, self.D, S2.v) fd2 = self.calc_fric_coeff(S2.rho, V2, S2.mu) P_drop = self.calc_P_drop(length, fd2, S2.rho, V2, self.D) # iterate using bisection search until P_guess matches P_drop while abs(P_guess - P_drop) >= P_guess/100.: if P_guess > P_drop: P_high = P_guess P_guess = (P_high + P_low) / 2. elif P_guess < P_drop: P_low = P_guess P_guess = (P_high + P_low) / 2. try: print('P = %sMpa and T = %sK' %(P_guess, T21)) S2 = IAPWS97(P=P_guess, T=T21) # create instance for guessed steam conditions except ValueError: print('Pressure or temperature out of bounds') V2 = self.calc_vel(self.m_dot2, self.D, S2.v) fd2 = self.calc_fric_coeff(S2.rho, V2, S2.mu) P_drop = self.calc_P_drop(length, fd2, S2.rho, V2, self.D) return P_guess
def calc_P_ein_und_G_HEM_alt_nicht_genau( p_0, T_0, p_2, T_2, zeta_, A_): #beruecksichtigung des Eintrittsducks state_s_T_0 = IAPWS97(T=T_0, x=0) state_0 = IAPWS97(T=T_0, P=p_0) p_s_0 = state_s_T_0.P rho_0 = state_0.rho #dichte kg/m^3 P_ein_List = np.linspace(max(p_s_0, p_0 - 0.05, p_2), p_0, 21) #print(P_ein_List) delta_G_List = [] for P_ein_variable in P_ein_List: G_1 = calc_G_HEM_Zweiphasig_2(P_ein_variable, T_0, p_2, T_2, zeta_)[0] G_2 = math.sqrt(2 * (p_0 - P_ein_variable) * 1000000 * rho_0) delta_G = abs(G_1 - G_2) delta_G_List.append(delta_G) delta_G_min = min(delta_G_List) G_index = delta_G_List.index(delta_G_min) P_ein = P_ein_List[G_index] Zustand = calc_G_HEM_Zweiphasig_2(P_ein, T_0, p_2, T_2, zeta_) G = Zustand[0] P_aus = Zustand[1] kritisch = Zustand[2] V = G * A_ / 1000000 #Massenstrom kg/m^2/s state_2 = IAPWS97(T=T_2, P=p_2) rho_2 = state_2.rho # print(rho_2) v = G / rho_2 # m/s #print(p_0,round(G,2),round(V,6),P_ein,round(P_aus,4),kritisch) #print('v(m/s)=',v) #durchschnittliche Geschwindigkeit return [round(G, 2), round(V, 6), P_ein, round(P_aus, 4), kritisch] #G:Leckrate V:Massenstrom
def SteamVolume(steamtype, pressure, temperature): #Initialize the volume variable. volume = 0 #Convert pressure as in the SteamType function. pressure = (pressure + 14.7) * 0.006895 #Convert Temperature as in the SteamType function temperature = (((temperature - 32) / 1.8) + 273) temperature = int(round(temperature)) """ The logic below returns the specific volume attribute of the steam objects instatiated, while simultaneously converting them from MPa to psi. This is so that the returned value can be utilized correctly in the Valve Sizing Excel file. """ if steamtype == "Saturated Steam": volsatsteam = IAPWS97(P=pressure, x=1) volume = volsatsteam.v * 16.0185 elif steamtype == "Superheated Steam": volshsteam = IAPWS97(P=pressure, T=temperature) volume = volshsteam.v * 16.0185 elif steamtype == "Supercritical Steam": volscsteam = IAPWS97(P=pressure, T=temperature) volume = volscsteam.v * 16.0185 elif steamtype == "Water": volwater = IAPWS97(T=temperature, x=0) volume = volwater.v * 16.0185 return (volume)
def calc_G_HEM_Zweiphasig(p_0, T_0, p_2, T_2, zeta_): #zweiphasig genauiger als frueher schritt = 1000 #wie viel Teile geteilt sind in der Gleichung B3.2-9 p = np.linspace(p_0, p_2, schritt) delta_p = (p_2 - p_0) / schritt state_0 = IAPWS97(T=T_0, P=p_0) s_0 = state_0.s # unterschiedlicher Zustand mit gleicher Entropie v_0 = state_0.v sigma_p = 0 sigma_v = 0 G_alt = 0 G_neu = 0 kritisch = False for pressureVAL in p: # state_1 = IAPWS97(P = pressureVAL, s=s_0) # unterschiedlicher Zustand mit gleicher Entropie state_2 = IAPWS97( P=(pressureVAL + delta_p), s=s_0) # unterschiedlicher Zustand mit gleicher Entropie # v_1= state_1.v v_2 = state_2.v # delta_v=v_2-v_1 sigma_v = math.log(v_2 / v_0) sigma_p = sigma_p + delta_p / v_2 G_neu = ((-2 * sigma_p) / (zeta + 2 * sigma_v))**0.5 * 1000 #kg/m^2/s if G_neu > G_alt: G_alt = G_neu else: kritisch = True break return [round(G_alt, 2), round(pressureVAL, 4), kritisch]
def massflow2(L=1.4, K=5, d=0.0254, q_start=0, q_end=5, Tin=99.7, Pin=0.101325): A = np.pi * (d / 2)**2 g = 9.81 # m/s^2 #Subcooled inlet properties of water # Tin = 99.4 # deg C # m_dot = 0.0010 sc_liq = IAPWS97(P=Pin, T=Tin + 273.15) #Saturated properties of water sat_liq = IAPWS97(P=Pin, x=0) #Saturated properties of vapor sat_vap = IAPWS97(P=Pin, x=1) Hvap = sat_vap.h - sat_liq.h #kJ/kg h_in = sc_liq.h h_sat = sat_liq.h x_i = (h_in - h_sat) / Hvap x = lambda m_dot: (((q_dot) / m_dot) + h_in - h_sat) / Hvap - x_i * np.exp( (((((q_dot) / m_dot) + h_in - h_sat) / Hvap) / x_i) - 1) alpha = lambda m_dot: 1 / (1 + (((1 - x(m_dot)) / x(m_dot)) * (sat_vap.rho / sat_liq.rho))) Re = lambda m_dot: (((m_dot * d) / (A * (x(m_dot) * sat_vap.mu + ((1 - x(m_dot)) * sat_liq.mu))))) rhoH = lambda m_dot: (sat_liq.rho * (1 - alpha(m_dot)) + sat_vap.rho * alpha(m_dot)) left = lambda m_dot: (sc_liq.rho - rhoH(m_dot)) * g * L right = lambda m_dot: K * 2 * (0.079 / (Re(m_dot)**0.25)) * (L / d) * ( (m_dot**2) / (A**2)) * (1 / rhoH(m_dot)) mass_fun = lambda m_dot: left(m_dot) - right(m_dot) mass_flow = [] heat = [] heats = np.linspace(q_start, q_end, 100) for i in range(0, 100): q_dot = heats[i] heat.append(q_dot) if i < 5: mass_flow.append(float(optimize.fsolve(mass_fun, 0.01))) else: mass_flow.append(float(optimize.fsolve(mass_fun, mass_flow[-1]))) plt.plot(heat, mass_flow) return heat, mass_flow
def OutletCalc(Thi, Tci, Tho, Tco, DIAco, DIAci, DIAh, MDOTc, MDOTh, L): """ This function takes a bunch of inputs and outputs useful information """ Ks = 237 #Thermal conductivity of the center pipe DIAhyd = DIAco - DIAci #Hydraulic diameter Thm = (Thi + Tho) / 2 # Calculate average temp for hot water properties Tcm = (Tco + Tci) / 2 # ^^^ but for cold PROPh = IAPWS97(T=Thm, x=0) #Creates gets all the properties for the hot water PROPc = IAPWS97(T=Tcm, x=0) # ^^^ Same # The next two lines puts all the propeties into variables for ease of use RHOh, MUh, Kh, CPh, PRh = PROPh.rho, PROPh.mu, PROPh.k, PROPh.cp, PROPh.Prandt RHOc, MUc, Kc, CPc, PRc = PROPc.rho, PROPc.mu, PROPc.k, PROPc.cp, PROPc.Prandt #These two lines get the average velocity of the water in the pipes VELc = MDOTc / (RHOc * np.pi / 4 * (DIAco**2 - DIAci**2)) VELh = MDOTh / (RHOh * np.pi / 4 * DIAh**2) #Step 1 #Get the Reynold numbers for both flows #Step 2 #Get the Nusset numbers for both REYi, NUi = NumCalcs(RHOh, VELh, DIAh, MUh, PRh) REYo, NUo = NumCalcs(RHOc, VELc, DIAhyd, MUc, PRc) #Step3 #Calculate h from the NU nums Hh = Kh * NUi / DIAh Hc = Kc * NUo / (DIAhyd) #Step 4 #First calculate all the areas Ahyd = np.pi * (DIAhyd) * L #Hydraulic area Ao = np.pi * DIAci * L Ai = np.pi * DIAh * L U = 1 / Ai * (1 / (Hc * Ao) + np.log(DIAci / DIAh) / (2 * np.pi * Ks * L) + 1 / (Hh * Ahyd))**-1 #Step 5 Cc = MDOTc * CPc Ch = MDOTh * CPh Cmin = Ch Cmax = Cc if Cc < Ch: Cmin = Cc Cmax = Ch Cr = Cmin / Cmax NTU = U * Ai / Cmin eff = (1 - np.exp(-NTU * (1 - Cr))) / (1 - Cr * np.exp(-NTU * (1 - Cr))) Qmax = Cmin * (Thi - Tci) Tho = Thi - eff * Qmax / Ch Tco = Tci + eff * Qmax / Cc Q = eff * Qmax return Tho, Tco, Q, REYo, REYi, U * Ai, Hh, Hc, NUi, NUo
def workspec(inlet, outlet_IS, W_tar, eff_mech, **max): m_rat = max.get('m_rat', None) m_max = max.get('m_max', None) # Constants abc = f_abc(inlet.P * 10, outlet_IS.P * 10) # abc is calculated in bara a = abc[0] b = abc[1] c = abc[2] dh_IS = f_dh_IS(inlet, IAPWS97(P=outlet_IS.P, s=inlet.s)) # Initial guess for mass flowrate m_act = W_tar / (eff_mech * (inlet.h - outlet_IS.h)) h_out_i1 = f_h_2(inlet, W_tar, eff_mech, m_act) # initialise convergence parameters i = 0 tol = 1e-5 # Absolute tolerance h_err = tol + 10 # Make sure initial error > tol while h_err > tol: # Check loop number, not sure if this is the right exception i += 1 if i > 100: raise StopIteration("After 100 iteration turbine not converged.") # Set max flowrate if not m_rat == None: m_max = m_act * m_rat # Model turbine n = f_n(a, b, c, dh_IS, m_max) W_int = f_Wint(a, b, c, dh_IS, m_max) W_calc = f_W(m_act, n, W_int) # Comment in/out to track iteration # print(f"i={i}, W={W_calc:.2f}, h_2={h_out_i1:.2f}, m={m_act:.2f}") # Update convergence criteria h_out_i2 = f_h_2(inlet, W_calc, eff_mech, m_act) h_err = abs(h_out_i2 - h_out_i1) h_out_i1 = h_out_i2 # Set new flowrate m_act = W_tar / (eff_mech * (inlet.h - h_out_i2)) # comment in/out to show final figures # print(f"\nFinal Iteration\ni={i}, W={W_calc:.2f}, h_2={h_out_i1:.2f}, m={m_act:.2f}") return IAPWS97(P=outlet_IS.P, h=h_out_i2)
def calc_P_ein_und_G_HEM( p_0, T_0, p_2, T_2, zeta_, A_): #beruecksichtigung des Eintrittsducks mit Bisektionsverfahren state_s_T_0 = IAPWS97(T=T_0, x=0) state_0 = IAPWS97(T=T_0, P=p_0) p_s_0 = state_s_T_0.P rho_0 = state_0.rho #dichte kg/m^3 a = max(p_s_0, p_0 - 1, p_2) b = p_0 delta_G = calc_G_HEM_Zweiphasig(a, T_0, p_2, T_2, zeta_)[0] - math.sqrt( 2 * (p_0 - a) * 1000000 * rho_0) P_ein_List = [] G1_List = [] G2_list = [] while abs(delta_G) > 10: c = (a + b) / 2 delta_G = calc_G_HEM_Zweiphasig(c, T_0, p_2, T_2, zeta_)[0] - math.sqrt( 2 * (p_0 - c) * 1000000 * rho_0) if delta_G > 0: b = c else: a = c print(c, math.sqrt(2 * (p_0 - c) * 1000000 * rho_0)) P_ein_List.append(c) G1_List.append(calc_G_HEM_Zweiphasig(c, T_0, p_2, T_2, zeta_)[0]) G2_list.append(math.sqrt(2 * (p_0 - c) * 1000000 * rho_0)) P_ein = c Zustand = calc_G_HEM_Zweiphasig(P_ein, T_0, p_2, T_2, zeta_) G = Zustand[0] P_aus = Zustand[1] kritisch = Zustand[2] V = G * A_ / 1000000 #Massenstrom kg/m^2/s state_2 = IAPWS97(T=T_2, P=p_2) rho_2 = state_2.rho # print(rho_2) v = G / rho_2 # m/s #print(p_0,round(G,2),round(V,6),P_ein,round(P_aus,4),kritisch) #print('v(m/s)=',v) #durchschnittliche Geschwindigkeit # print(P_ein_List, G1_List, G2_list) # plt.figure(2) #Diagramm zeichnen # plt.xlabel("Eintrittsdruck in MPa") # plt.ylabel("G") # plt.plot(P_ein_List, G1_List) # plt.plot(P_ein_List, G2_list) # return [round(G, 2), round(V, 6), P_ein, round(P_aus, 4), kritisch] #G:Leckrate V:Massenstrom
def get_iapws(self): if self.T != None and self.P != None: return IAPWS97(T=self.T, P=self.P) elif self.P != None and self.x != None: return IAPWS97(x=self.x, P=self.P) elif self.P != None and self.s != None: return IAPWS97(s=self.s, P=self.P) elif self.T != None and self.s != None: return IAPWS97(s=self.s, T=self.T) elif self.P != None and self.h != None: return IAPWS97(P=self.P, h=self.h) else: return None
def turbine_output(p_in, t_in, p_exh, t_exh, flow): """ :param p_in: :param t_in: :param p_exh: :param t_exh: :param flow: :return: """ stm_in = IAPWS97(P=p_in, T=t_in + 273.15) stm_exh = IAPWS97(P=p_exh, T=t_exh + 273.15) turb_power = (stm_in.h - stm_exh.h) * flow / 1000 print("焓值%.2f %.2f" % (stm_in.h, stm_exh.h)) return turb_power
def calc_back_P(self, P11 = None): ''' calc_P_drop guesses a pressure upstream of the condenser and finds the corresponding density. It uses the density and an assumed backpressure of 0 to calculate a pressure drop through the sparger. The function iterates until the guess and the pressure drop match. All calculations in SI units. returns P21 - pressure upstream of condenser/back pressure for TBV in psia ''' if P11 == None: P11 = self.P11 T21 = self.T11 # upstream temperature for unknown conditions in K S = IAPWS97(P=P11, T=self.T11) # create instance for reference steam conditions V = self.calc_vel(self.m_dot1, self.D, S.v) # call function to return reference flow upstream velocity in m/s fd = self.calc_fric_coeff(S.rho, V, S.mu) # call function to return reference flow upstream Reynolds number # equivalent length of pipe to represent pressure drop through condenser sparger length = self.calc_length(fd, S.rho, V, self.P11-self.P12, self.D) if self.m_dot2 < self.m_dot1: # set initial guess bounds P_high = P11 P_low = 0 P_guess = self.solve_back_P(P_high, P_low, T21, length) elif self.m_dot2 == self.m_dot1: pass elif self.m_dot2 > self.m_dot1: # set initial guess bounds - P_high is an arbitrarily high number to avoid exceeding the upper bound P_high = 6894.76/100 P_low = P11 P_guess = self.solve_back_P(P_high, P_low, T21, length) return (P_guess+self.P22)/(6894.76/1000000) # return guess that gives matching P_drop in psia
def analytic_otemp(fluidInput, T_out_K, P_op_Mpa, temp_amb_K, DNI, IAM, Area, n_coll_loop, mdot_use_kgs, T_in_K, F_Rta_eq, F_RU_L_eq, mdot_test_permeter, **kwargs): #This calculates the outlet temperature for the collectors in the loop with a given flux T_av_K = 0.5 * (T_in_K + T_out_K) #[K] if fluidInput == 'water': #the average of temperatures is take and then twith help of IAPWS97 the Cp is obtained. Cp_av_JkgK = IAPWS97(P=P_op_Mpa, T=T_av_K).cp * 1000 #[J/kg·K] elif fluidInput == "oil": [rho_av, Cp_av_KJkgK, k_av, Dv_av, Kv_av, thermalDiff_av, Prant_av] = thermalOil(T_av_K) Cp_av_JkgK = Cp_av_KJkgK * 1000 elif fluidInput == "moltenSalt": [rho, Cp_av_KJkgK, k, Dv] = moltenSalt(T_av_K) Cp_av_JkgK = Cp_av_KJkgK * 1000 #Get the linear parameters for the whole loop of collectors depenent of radiation, Ti and Ta #F_Rta_eq,F_RU_L_eq,mdot_test_kgs = equiv_coll_series_o1(T_in_K,T_out_K,temp_amb_K,DNI,IAM,Area,Cp_av_JkgK,**coll_par) #Calculates the equivalent o1 parameters of an array of collectors connected in series using their o2 parameters. #Calculate nu for the linear efficiency equation nu_test = calc_nu_Ti_o1(F_Rta_eq, F_RU_L_eq, DNI, IAM, T_in_K, temp_amb_K) #Modify nu for the flux of use r = (mdot_use_kgs * Cp_av_JkgK * (1 - (1 - (F_RU_L_eq / (mdot_test_permeter * Cp_av_JkgK)))**( (Area * mdot_test_permeter) / mdot_use_kgs))) / (F_RU_L_eq * Area) nu_use = r * nu_test #Efficiency at use conditions #Calculates the outlet temperature T_outlet_K = T_in_K + DNI * Area * nu_use / (mdot_use_kgs * Cp_av_JkgK) Perd_termicas = (1 - nu_use) * DNI * Area #[W] Q_prod = (nu_use) * DNI * Area * .001 #[kW] return [T_outlet_K, Q_prod, Perd_termicas]
def IT_temp(T_in_K, P_op_Mpa, temp_amb_K, REC_type, theta_i_rad, DNI, Long, IAM, Area, n_coll_loop, flow_rate_rec, rho_optic_0): T_outlet_KX = 999 for jj in range(1, 202): if jj >= 200: #Si no llegamos a convergencia después de 200 iteraciones paramos break if jj == 1: err = 99 else: err = (T_outlet_KX - T_outlet_K) / T_outlet_K T_outlet_KX = T_outlet_K if abs( err ) <= 1e-4: #Si el error de convergencia es suficientemente bajo salimos del bucle break T_av_K = (T_outlet_KX + T_in_K) / 2 average = IAPWS97(P=P_op_Mpa, T=T_av_K) Cp_av_KJkgK = average.cp DELTA_T_loss = T_outlet_KX - temp_amb_K [Q_loss_rec] = Rec_loss(REC_type, DELTA_T_loss, theta_i_rad, DNI) if Q_loss_rec <= 0: Q_loss_rec = 0 gain = (DNI * Area * IAM * rho_optic_0 - Q_loss_rec * n_coll_loop * Long) / (flow_rate_rec * Cp_av_KJkgK * 1000) #In W if jj < 2 and gain < 0: #To avoid iteration errors at the very beigning gain = 0 T_outlet_K = T_in_K + gain Perd_termicas = Q_loss_rec * n_coll_loop * Long return [T_outlet_K, Perd_termicas]
def IT_flow(T_out_K, T_in_K, P_op_Mpa, temp_amb_K, REC_type, theta_i_rad, DNI, Long, IAM, Area, n_coll_loop): T_av_K = (T_in_K + T_out_K) / 2 average = IAPWS97(P=P_op_Mpa, T=T_av_K) Cp_av_KJkgK = average.cp Q_net_X = 0 for jj in range(1, 202): if jj >= 200: #Si no llegamos a convergencia después de 200 iteraciones paramos break if jj == 1: err = 99 else: err = (Q_net - Q_net_X) / Q_net_X Q_net_X = Q_net if abs( err ) <= 1e-4: #Si el error de convergencia es suficientemente bajo salimos del bucle break DELTA_T_loss = T_out_K - temp_amb_K [Q_loss_rec] = Rec_loss(REC_type, DELTA_T_loss, theta_i_rad, DNI) #W/m Q_net = DNI * IAM * Area - Q_loss_rec * n_coll_loop * Long #In W flow_rate_kgs = (DNI * IAM * Area) / ( (T_out_K - T_in_K) * Cp_av_KJkgK * 1000) T_out_K = T_in_K + Q_net / (flow_rate_kgs * Cp_av_KJkgK * 1000) return [flow_rate_kgs, T_out_K, Q_loss_rec]
def get_inputs(): print("---- SILENCER SIZE CALCULATOR -----\n") # steam_up_pres = (float(input("UPSTREAM STEAM PRESSURE(barA): "))) # steam_up_temp = float(input("UPSTREAM STEAM TEMPERATURE(°C): ")) # steam_flow_mass = float(input("STEAM FLOWRATE(kg/h): ")) # p_atm = float(input("ATMOSPHERIC PRESSURE(barA): ")) # # run this later steam_up_pres = 7 steam_up_temp = 165 steam_flow_mass = 5000 p_atm = 0 # diff_pres = float(input("DESIRED DIFFUSER PRESSURE(barA): ")) steam_cond = IAPWS97(P=steam_up_pres / 10, T=steam_up_temp + 273.15) hs1 = steam_cond.h vs_atm = iapws.iapws97._Backward3a_v_Ph(p_atm / 10, hs1) steam_flow_vol = vs_atm / steam_flow_mass * 3600 print("\nUpstream Steam Properties:\nPressure: ", steam_up_pres, " barA \nTemperature: ", steam_up_temp, " °C \nEnthalpy: ", steam_cond.h, "kJ/kg \nSpecific Volume: ", vs_atm, "m3/kg \nVolumetric Flow Rate through Silencer: ", steam_flow_vol, "m3/s")
def SteamType(pressure, temperature): #Convert psi to MPa; IAPWS97 object requires SI units pressure = (pressure + 14.7) * 0.006895 #Convert Fahrenheit to Kelvin; IAPWS97 object requires SI units temperature = (((temperature - 32) / 1.8) + 273) #Round the temperature to the nearest whole number. temperature = int(round(temperature)) #Establishes an empty string to fill with the return value. fluid = "" #Instantiation of the steam object; assumes saturated steam. steam = IAPWS97(P=pressure, x=1) #Determines the saturation temperature of the steam. satsteamtemp = int(round(steam.T)) """ The logic below is to define the type of steam being used in the customer's service. It assumes that the steam is saturated, and determines by the first if clause whether or not that is the case. It does so by comparing a ratio of the given line temperature to the saturation temperature determined above. If that ratio=1, then it is exactly the saturation temperature. The logic allows for a ratio right around one because customers are rarely going to give the perfect temperature for saturated steam at their pressure. """ if 0.999 < temperature / satsteamtemp and temperature / satsteamtemp < 1.01: fluid = "Saturated Steam" elif 1.01 < temperature / satsteamtemp: fluid = "Superheated Steam" elif pressure > 22: fluid = "Supercritical Steam" else: fluid = "Water" return (fluid)
def calc_G_modB_Einphasig(p_0, T_0, zeta_): #einphasig state_s_T_0 = IAPWS97(T=T_0, x=0) p_s_T_0 = state_s_T_0.P rho_s_T_0 = state_s_T_0.rho #Density, [kg/m³] G = math.pow(2 * (p_0 - p_s_T_0) * 1000000 * rho_s_T_0 / (1 + zeta_), 0.5) return round(G, 2)
def psat_IAPWS97(tsat, delta_tsat=0, delta_psat=0): ''' IAPWS 97 Formulas (input Kelvin, output MPa) Return P saturation function of T input - temperature in °c with 273.15°K ≤ T ≤ 647.096°K - delta_tsat in °c - delta_psat in bar abs ouput psat as an interger Psat in bar abs. -- Warning -- temperature above 647°K will return the critical point value It is incorrect and only done to prevent handling error and missing point. It is mostly for the Psat + 110 bar abs curve that quickly skyrocket. ''' # Convert to Kelvin, filter out of bound values and apply delta tsat. # I do like lambda function and generator/ tsat = [ celsius_to_kelvin(item - delta_tsat) if celsius_to_kelvin(item - delta_tsat) >= 273.15 and celsius_to_kelvin(item - delta_tsat) <= 647.096 else 647.096 # Set to critical point when out of bounds for item in tsat] pressure = [IAPWS97(T=temperature, x=0).P * 10 + delta_psat for temperature in tsat] return pressure
def calc_m_dot_total(self,P1 = None, m_dot = None): ''' Calculate spray water mass flow rate and total mass flow rate after attemperation. Inputs and output are in english units, but function converts to SI for all calculations. ''' if P1 == None: P1 = self.P1 if m_dot == None: m_dot = self.m_dot P1 = P1*6894.76/1000000 # convert P1 to metric stm1 = IAPWS97(P=P1, T=self.T1_SI) stm_s = IAPWS97(T=(self.T_s+491.67)*0.5555556,x=0) h2 = self.h2*1000/0.429923 # convert desired enthalpy to J/kg # Assume Joule-Thompson expansion through TBV - no change in enthalpy m_dot_s = m_dot*0.000125998*(h2-stm1.h)/(stm_s.h-h2) # calculate spray water flow rate (kg/s) m_dot_total = m_dot_s + m_dot*0.000125998 # Total flow rate after attemperation in kg/s return m_dot_total/0.000125998 # return total flow rate in lbm/hr
def calc_G_Benourlli(p_0, T_0, p_2, T_2, zeta_): #einphasig state_0 = IAPWS97(T=T_0, P=p_0) rho_0 = state_0.rho G = math.sqrt(2 * (p_0 - p_2) * 1000000 * rho_0 / (1 + zeta_)) return round(G, 2)
def thermo_table(): from iapws import IAPWS97 Ts = np.linspace(100+273.15, 300+273.15, 13) f = open('thermo_data.txt', 'w') s= ' T [K] P [MPa] h_l [kJ/kg] h_v [kJ/kg]\n' f.write(s) for i in range(len(Ts)): sat_steam = IAPWS97(T=Ts[i],x=0) sat_liquid = IAPWS97(T=Ts[i],x=1) T = Ts[i] P = sat_steam.P h_v = sat_liquid.h h_l = sat_steam.h s= "{:8.3f} {:6.3f} {:10.3f} {:10.3f}\n".format(T, P, h_v, h_l) print(s) f.write(s) f.close()
def parameter(self, pressure, temperature): # pressure: Input in bar # temperature: Input in degC steam = IAPWS97(P=pressure / 10., T=temperature + 273.15) # return: density (rho) [t/mm**3], kinematic viscosity (nu) [mm**2/s], Prandtl number (Pr) [-], # thermal conductivity (k) [W/(m*K)=(t*mm)/(s**3*K)] #print [steam.rho*10**-12, steam.nu*10**6, steam.Pr, steam.k, steam.P, steam.T] #raise Exception('exit') return [steam.rho * 10**-12, steam.nu * 10**6, steam.Pr, steam.k]
def cond_ttd(t, pc): """ :summary: 凝汽器端差:汽轮机背压下饱和温度与凝汽器出口循环水温度的差值. :param t: 凝汽器出口循环水温度,DegC. :param pc: 汽轮机背压,MPa.a :return: 凝汽器端差 """ ttd = IAPWS97(P=pc, x=1).T - t return ttd
def cond_wtr_sc(pc, tc): """ :summary: 凝结水过冷度:汽轮机背压下饱和温度与凝汽器热井水温度的差值. :param pc: 凝汽器背压.(kPa.a) :param tc: 凝汽器热井水温度.(DefC) :return: """ deltaT = IAPWS97(P=pc, x=1).T - tc return deltaT
def massflow(L=1.4, K=5, d=0.0005, q_start=0, q_end=5, Tin=99.7, Pin=0.101325): g = 9.81 # m/s^2 A = np.pi * (d / 2)**2 sc_liq = IAPWS97(P=Pin, T=Tin + 273.15) #Saturated properties of water sat_liq = IAPWS97(P=Pin, x=0) #Saturated properties of vapor sat_vap = IAPWS97(P=Pin, x=1) Hvap = sat_vap.h - sat_liq.h #kJ/kg h_in = sc_liq.h h_sat = sat_liq.h x_i = (h_in - h_sat) / Hvap x = lambda m_dot: (((q_dot) / m_dot) + h_in - h_sat) / Hvap - x_i * np.exp( (((((q_dot) / m_dot) + h_in - h_sat) / Hvap) / x_i) - 1) left = lambda m_dot: ((sc_liq.rho - sat_liq.rho) + (sat_liq.rho - sat_vap.rho) / (1 + (sat_vap.rho / sat_liq.rho) * ((1 - x(m_dot)) / x(m_dot)))) * g * L right = lambda m_dot: (1 + x(m_dot) * ((sat_liq.rho / sat_vap.rho) - 1) ) * K * (m_dot**2) / (2 * sat_liq.rho * A**2) mass_fun = lambda m_dot: left(m_dot) - right(m_dot) mass_flow = [] heat = [] heats = np.linspace(q_start, q_end, 100) for i in range(0, 100): q_dot = heats[i] heat.append(q_dot) if i < 5: mass_flow.append(float(optimize.fsolve(mass_fun, 0.01))) else: mass_flow.append(float(optimize.fsolve(mass_fun, mass_flow[-1]))) plt.plot(heat, mass_flow) return heat, mass_flow
def check_PT(request): [T, P] = [float(request.GET['T']), float(request.GET['P'])] try: x = IAPWS97(P=P * 0.1, T=T + 273).x if x == 0: resultado = True else: resultado = False except: resultado = False return HttpResponse(resultado)
def hydrocond2perm(K, p=101325, T=20.0): '''Calculates the hydraulic conductivity in m/s given the permeability in m2 and the pressure in Pa temperature in celcius. Defaults to atmospheric pressure and 20 C''' T = 273.15 + T S = IAPWS97( T=T, P=p / 1.e6 ) #temperature in Kelvin and pressure in MPa. This will only work for single phase conditions. mu = S.mu rho = S.rho g = 9.80665 k = K * (mu / (rho * g)) return k
def flow_calc_gen(fluidInput, T_out_K, P_op_Mpa, temp_amb_K, DNI, IAM, Area, T_in_K, F_Rta_eq, F_RU_L_eq, mdot_test_permeter, **kwargs): #This function uses the general efficiency equation. #This is used only for water and steam. #In order to calculate a specific heat at constant preassure (Cp) for water secific for the temperature changes #the average of temperatures is take and then twith help of IAPWS97 the Cp is obtained. T_av_K = 0.5 * (T_in_K + T_out_K) #[K] if fluidInput == 'water': #the average of temperatures is take and then twith help of IAPWS97 the Cp is obtained. Cp_av_JkgK = IAPWS97(P=P_op_Mpa, T=T_av_K).cp * 1000 #[J/kg·K] elif fluidInput == "oil": [rho_av, Cp_av_KJkgK, k_av, Dv_av, Kv_av, thermalDiff_av, Prant_av] = thermalOil(T_av_K) Cp_av_JkgK = Cp_av_KJkgK * 1000 #[J/kg·K] elif fluidInput == "moltenSalt": [rho, Cp_av_KJkgK, k, Dv] = moltenSalt(T_av_K) Cp_av_JkgK = Cp_av_KJkgK * 1000 #[J/kg·K] #So far a efficiency curve for the whole loop has been obtained at the test flow rate and now this curve equivalent to a huge collector with the sum of the areas has to be modified regarding the flux to obtain the desired temperature epsilon = T_out_K - T_in_K #This is the target jump in temperature. nu_test = calc_nu_Ti_o1( F_Rta_eq, F_RU_L_eq, DNI, IAM, T_in_K, temp_amb_K ) #This is the efficiency at the test flux for the design temperature jump. if ((F_RU_L_eq * epsilon) / (DNI * nu_test)) >= 1 or ( (F_RU_L_eq) / (mdot_test_permeter * Cp_av_JkgK) ) >= 1: #This is because in this case the ln_den is not defined because the argument of the logarithm is too near 0 or negative, in this case the result either is imaginary or inf and therefore is handeled harcoded resulting in a flux = 0 and all the radiation being lost. mdot_use_kgs = 0 Perd_termicas = DNI * Area #Originally the DNI is in [W/m2] else: #Obtained from eq 6.20.3, 6.20.4 and 10.5.2. Calculate the flux needed to obtain the desired jum taking into account the cahnges in the efficiency due the changes in the flux relative to the test flux. ln_num = np.log(1 - ((F_RU_L_eq) / (mdot_test_permeter * Cp_av_JkgK))) ln_den = np.log(1 - ((F_RU_L_eq * epsilon) / (DNI * nu_test))) mdot_use_kgs = mdot_test_permeter * Area * (ln_num / ln_den) #The proportionality factor "r" between the eficiency at test conditions and at use conditions by rearranging 6.20.3 and 6.20.4 from Duffie, J. 2013 r = (mdot_use_kgs * Cp_av_JkgK * (1 - (1 - (F_RU_L_eq / (mdot_test_permeter * Cp_av_JkgK)))** (mdot_test_permeter * Area / mdot_use_kgs))) / (F_RU_L_eq * Area) nu_use = r * nu_test #Efficiency at use conditions #It is needed to calculate the final jump in the temperature for this case to see if we are near enough to the target temperature #T_out_K_colln = T_in_K + DNI*Area*nu_use/(mdot_use_kgs*Cp_av_JkgK) #print(T_out_K_colln) Perd_termicas = (1 - nu_use) * DNI * Area Q_prod = DNI * Area * 0.001 - Perd_termicas * 0.001 #[kW] return [mdot_use_kgs, Q_prod, Perd_termicas]