def initialize(self): """ Preparing for running problem by creating the fluid objects required instantiating arrays for storing time-dependent results, setting additional required class attributes. """ self.vol = self.diameter**2 / 4 * math.pi * self.length # m3 self.vol_tot = ((self.diameter + 2 * self.thickness)**2 / 4 * math.pi * (self.length + 2 * self.thickness)) # m3 self.vol_solid = self.vol_tot - self.vol self.surf_area_outer = ( self.diameter + 2 * self.thickness)**2 / 4 * math.pi * 2 + ( self.diameter + 2 * self.thickness) * math.pi * ( self.length + 2 * self.thickness) self.surf_area_inner = (self.diameter)**2 / 4 * math.pi * 2 + ( self.diameter) * math.pi * self.length self.fluid = CP.AbstractState("HEOS", self.comp) self.fluid.specify_phase(CP.iphase_gas) self.fluid.set_mole_fractions(self.molefracs) self.fluid.update(CP.PT_INPUTS, self.p0, self.T0) self.transport_fluid = CP.AbstractState("HEOS", self.compSRK) self.transport_fluid.specify_phase(CP.iphase_gas) self.transport_fluid.set_mole_fractions(self.molefracs) self.vent_fluid = CP.AbstractState("HEOS", self.comp) self.vent_fluid.specify_phase(CP.iphase_gas) self.vent_fluid.set_mole_fractions(self.molefracs) self.vent_fluid.update(CP.PT_INPUTS, self.p0, self.T0) self.res_fluid = CP.AbstractState("HEOS", self.comp) self.res_fluid.set_mole_fractions(self.molefracs) if self.input["valve"]["flow"] == "filling": self.res_fluid.update(CP.PT_INPUTS, self.p_back, self.T0) # data storage data_len = int(self.time_tot / self.tstep) self.rho = np.zeros(data_len) self.T_fluid = np.zeros(data_len) self.T_vent = np.zeros(data_len) self.T_vessel = np.zeros(data_len) self.Q_outer = np.zeros(data_len) self.Q_inner = np.zeros(data_len) self.h_inside = np.zeros(data_len) self.T_vent = np.zeros(data_len) self.H_mass = np.zeros(data_len) self.S_mass = np.zeros(data_len) self.U_mass = np.zeros(data_len) self.U_tot = np.zeros(data_len) self.U_res = np.zeros(data_len) self.P = np.zeros(data_len) self.mass_fluid = np.zeros(data_len) self.mass_rate = np.zeros(data_len) self.time_array = np.zeros(data_len) self.rho0 = self.fluid.rhomass( ) #PropsSI("D", "T", self.T0, "P", self.p0, self.species) self.m0 = self.rho0 * self.vol self.MW = self.fluid.molar_mass() #PropsSI("M", self.species)
def test_hinside_mixed(): mdot = 1e-10 D = 0.010 fluid = CP.AbstractState("HEOS", "air") Tboundary = (311 + 505.4) / 2 fluid.update(CP.PT_INPUTS, 1e5, Tboundary) h = tp.h_inside_mixed(0.305, 311, 505.4, fluid, mdot, D) assert h == pytest.approx(7, abs=0.1)
def __init__(self, fluid, backend="HEOS", **state_parameters): """ Available backends: HEOS (opensource), REFPROP. See http://www.coolprop.org/coolprop/REFPROP.html for details. """ self._AbstractState = CP.AbstractState(backend, fluid) if state_parameters: self.update_kw(**state_parameters)
def __init__(self, mole_frac_comp): # You're supposed to be able to set reference states in CoolProp, but # that functionality is broken for cubic EoSes at the moment for comp in self.component_list: self.Href[comp] = CP.PropsSI("HMOLAR", "T", standard_temp, "P", standard_pressure, "PR::" + comp) self.Sref[comp] = CP.PropsSI("SMOLAR", "T", standard_temp, "P", standard_pressure, "PR::" + comp) self.Href["NH3"] -= -45949 # Heat of formation in J/mol self.AS = CP.AbstractState("PR", "H2&N2&NH3") self.set_mole_frac_comp(mole_frac_comp) self.AS.update(CP.PT_INPUTS, 4E7, 573)
def draw_ts(): ''' simplified isolines for mixtures in which the calc_isolines() function does not work Returns ------- None. ''' states_sat = StateContainer() N = 100 sat_l = CP.AbstractState(library, fluid) sat_v = CP.AbstractState(library, fluid) Tsat = np.linspace(limits[2],T_crit-0.00001,N) s_l = np.zeros(N) s_v = np.zeros(N) if '&' in fluid: sat_l.set_mole_fractions([x_molar, 1 - x_molar]) sat_v.set_mole_fractions([x_molar, 1 - x_molar]) for i,T in enumerate(Tsat): sat_l.update(CP.QT_INPUTS,0,T) s_l[i] = sat_l.keyed_output(CP.iSmass) sat_v.update(CP.QT_INPUTS,1,T) s_v[i] = sat_v.keyed_output(CP.iSmass) for i in range(N): states_sat.append({'T':Tsat[i],'S':s_l[i]}) for i in range(N): states_sat.append({'T':Tsat[N-1-i],'S':s_v[N-1-i]}) with NoStdStreams(): pp.draw_process(states_sat,line_opts={'color':'black','linewidth':0.3}) for x in range(1,10): states_x = StateContainer() for i in range(3,N): s = x/10 * s_l[i] + (1-x/10) * s_v[i] states_x.append({'T':Tsat[i],'S':s}) with NoStdStreams(): pp.draw_process(states_x,line_opts={'color':'black','linewidth':0.1})
def coolantH(self): channelWidth = self.channelWidth channelHeight = self.channelHeight numberOfChannels = self.numberOfChannels massFlow = self.coolantMassFlow inletTemperature = self.coolantInletTemperature coolantPressure = self.coolantPressure x = 1 - self.coolant.waterFraction HEOS = CP.AbstractState('HEOS', 'Ethanol&Water') HEOS.set_mass_fractions([x, 1 - x]) HEOS.update(CP.PT_INPUTS, coolantPressure, inletTemperature) Pr = HEOS.Prandtl() k = HEOS.conductivity() rho = HEOS.rhomass() viscosity = HEOS.viscosity() #rho = self.coolant.getRho(coolantPressure, inletTemperature) #viscosity = self.coolant.getViscosity(coolantPressure, inletTemperature) #k = self.coolant.getK(coolantPressure, inletTemperature) #Pr = self.coolant.getPr(coolantPressure, inletTemperature) channelArea = channelWidth * channelHeight channelDiameter = 4 * channelArea / (2 * (channelHeight + channelWidth)) channelMassFlowRate = massFlow / numberOfChannels channelFlowRate = channelMassFlowRate / rho channelVelocity = channelFlowRate / channelArea reynolds = rho * channelVelocity * channelDiameter / viscosity if reynolds >= 10000: Nu = 0.023 * reynolds**(4 / 5) * Pr**(0.4) else: Nu = 4.36 h = Nu * k / channelDiameter self.coolant.h = h return h
def check_ancillaries(self, ancillaries, name, T, backend='REFPROP'): AS = CP.AbstractState(backend, name) AS.update(CP.QT_INPUTS, 0, T) rhoL = AS.rhomolar() rhoV = AS.saturated_vapor_keyed_output(CP.iDmolar) p = AS.p() try: rhoL_anc = self.ancillary_evaluator(anc['DL'], T) rhoV_anc = self.ancillary_evaluator(anc['DV'], T) p_anc = self.ancillary_evaluator(anc['PS'], T) def check_ok(k, err, thresh): if err > thresh: raise ValueError(name, k, err, thresh) check_ok('DL', abs(rhoL_anc - rhoL) / rhoL, 1e-3) check_ok('DV', abs(rhoV_anc - rhoV) / rhoV, 1e-3) check_ok('PS', abs(p_anc - p) / p, 1e-3) except BaseException as BE: print(BE)
def time_CoolProp(n, Nrep, backend): AS = CP.AbstractState(backend, 'METHANE') AS.specify_phase(CP.iphase_gas) if n == 0: f = lambda AS: AS.alphar() elif n == 1: f = lambda AS: AS.delta() * AS.dalphar_dDelta() elif n == 2: f = lambda AS: AS.delta()**2 * AS.d2alphar_dDelta2() elif n == 3: f = lambda AS: AS.delta()**3 * AS.d3alphar_dDelta3() else: raise ValueError(n) T = 300 rho = 3.0 tic = timeit.default_timer() for i in range(Nrep): AS.update(CP.DmolarT_INPUTS, rho + 1e-3 * i, T) f(AS) toc = timeit.default_timer() elap = (toc - tic) / Nrep return elap
def test_hinside(): fluid = CP.AbstractState("HEOS", "air") Tboundary = (311 + 505.4) / 2 fluid.update(CP.PT_INPUTS, 1e5, Tboundary) h = tp.h_inside(0.305, 311, 505.4, fluid) assert h == pytest.approx(7, abs=0.1)
#Evaporator chracteristics gas = 'Propane&IsoButane' isentropic_eff = 0.7 evaporation_temp = 0 + 273.15 # R290 condensation_temp = 55 + 273.15 # Estimation from Aeronamic ?? superheat = 5 # ambient temperature subcooling = 3.1 #D= CP.PropsSI('Dmass','T',300,'P',101325,'Propane[0.7]&IsoButane[0.3]') #C= CP.PropsSI('C','T',300,'P',101325,'Propane[0.7]&IsoButane[0.3]') #H= CP.PropsSI('H','T',300,'P',101325,'Propane[0.7]&IsoButane[0.3]') HEOS = CP.AbstractState('HEOS', 'Propane&IsoButane') #for x0 in [0.02, 0.2, 0.4, 0.6, 0.8, 0.98]: for x0 in [0.7]: HEOS.set_mole_fractions([x0, 1 - x0]) try: HEOS.build_phase_envelope("dummy") PE = HEOS.get_phase_envelope_data() PELabel = 'Propane, x = ' + str(x0) plt.plot(PE.T, PE.p, '-', label=PELabel) except ValueError as VE: print(VE) #T= CP.PropsSI('T','H',28627,'P',101325,'Propane[0.7]&IsoButane[0.3]') MapPT = [PE.T[0:-1], PE.p[0:-1]] # create PT database MapPTt = np.transpose(MapPT)
def flasher(sub: str, inputType1: str, inputValue1: float, inputType2: str, inputValue2: float, backend: str = "CP") -> dict: res = dict() errtext = "" extend_backend_req = False mode_refprop = False mixture = None outType = ("D", "H", "M", "S", "U", "V", "Z") # 检查REFPROP可用性 if backend == "REFPROP": if REFPROP_READY: mode_refprop = True else: errtext += "Warning: No REFPROP support on server!\n" res.update({"warning": True, "message": errtext}) mode_refprop = False # 将所有文本输入转化为大写 sub = sub.upper() backend = backend.upper() inputType1 = inputType1.upper() inputType2 = inputType2.upper() # 检查纯物质名字是否受到支持 # 2-检查混合物可用性 mixture = re.findall(MIXTURE_PATTERN, sub) if mixture: # get substance name sub = list(map(lambda x: x.split(":")[0], mixture)) # get substance fraction mixture = list(map(lambda x: float(x.split(":")[1]), mixture)) if set(sub) - set(SUBS_P.keys()): errtext += "Input Error: Not supported substance for mixture: " + ", ".join( sub) logger.error(errtext) res.update({"error": True, "message": errtext}) return {"result": res} else: if reduce(lambda acc, x: SUBS_P[x][2] or acc, sub, False): errtext += "Input Error: Building a mixture with a mixture..." logger.error(errtext) res.update({"error": True, "message": errtext}) return {"result": res} else: if backend in ("CP", "COOLPROP"): sub = "&".join([SUBS_P[i][0] for i in sub]) elif mode_refprop: sub = "&".join([SUBS_P[i][1] for i in sub]) if "N/A" in sub: errtext += "Input Error: Not supported substance for REFPROP is detected." logger.error(errtext) res.update({"error": True, "message": errtext}) return {"result": res} else: extend_backend_req = True # 检查混合组分输入是否均为正数 if not reduce(lambda acc, x: acc and (x > 0), mixture, True): errtext += "Input Error: Building a mixture with a mixture..." logger.error(errtext) res.update({"error": True, "message": errtext}) return {"result": res} mixture = [i / sum(mixture) for i in mixture] else: extend_backend_req = True if not mixture: errtext += "Input Error: Can not calculate flashing for pure component." logger.error(errtext) res.update({"error": True, "message": errtext}) return {"result": res} if type(sub) == str: res.update({"components": sub.split("&")}) if inputType1 == inputType2: errtext += "Input Error. Only one input Type [%s] is given." % inputType1 logger.error(errtext) res.update({"error": True, "message": errtext}) return {"result": res} if SequenceMatcher(None, inputType1, inputType2).find_longest_match(0, len(inputType1), 0, len(inputType2)).size: errtext += "Input Error. Input Type [%s&%s] is the same." % ( inputType1, inputType2) logger.error(errtext) res.update({"error": True, "message": errtext}) return {"result": res} if not {inputType1, inputType2}.issubset(ITYPE): errtext += "Input Error. Invalid input type combo [%s&%s]." % ( inputType1, inputType2) logger.error(errtext) res.update({"error": True, "message": errtext}) return {"result": res} for item in ("H", "S"): if item in inputType1 + inputType2: errtext += "Warning: Unexpected result due to [%s] using difference Reference point on different backend.\n" % item logger.warning(errtext) res.update({"warning": True, "message": errtext}) try: inputValue1 = float(inputValue1) inputValue2 = float(inputValue2) except: errtext += "Input Error. Invalid values are not numbers." logger.error(errtext) res.update({"error": True, "message": errtext}) return {"result": res} if backend in ("PENGROBINSON", "PENG-ROBINSON", "PR"): backend = "PR" elif backend in ("CP", "COOLPROP") or not mode_refprop: backend = "HEOS" elif backend == "REFPROP" and mode_refprop: backend = "REFPROP" if extend_backend_req: # todo: impletementing of mProp_extend() res.update(mProp_extend()) else: sub = cp.AbstractState(backend, sub) sub.set_mole_fractions(mixture) sub.update(**input_construct(inputType1, inputType2, inputValue1, inputValue2)) # Q = sub.keyed_output(getattr(cp, "iQ")) T = sub.T() P = sub.p() rtn = dict() for item in outType: try: rtn.update({item: sub.keyed_output(getattr(cp, OTYPE[item]))}) except Exception as e: errtext += "Calculation Error: Fail to cal [%s] for INFLOW:\n" % item errtext += str(e) res.update({"warning": True, "message": errtext}) rtn.update({"Fraction": mixture}) res.update({"IN": rtn, "T": T, "P": P, "Q": Q}) if not (0 < Q < 1): errtext += "Input Error: INFLOW is single phase" res.update({"warning": True, "message": errtext}) return {"result": res} for mix in OTYPE_MIX: _mixture = None sub.set_mole_fractions(mixture) try: _mixture = getattr(sub, OTYPE_MIX[mix])() except Exception as e: errtext += "Calculation Error: Fail to cal [%s]:\n" % mix errtext += str(e) res.update({"warning": True, "message": errtext}) continue sub.set_mole_fractions(_mixture) sub.specify_phase(cp.iphase_gas if mix == "VAPFRAC" else cp.iphase_liquid) sub.update(cp.PT_INPUTS, P, T) rtn = dict() for item in outType: try: rtn.update( {item: sub.keyed_output(getattr(cp, OTYPE[item]))}) except Exception as e: errtext += "Calculation Error: Fail to cal [%s] for INFLOW:\n" % item errtext += str(e) res.update({"warning": True, "message": errtext}) rtn.update({"Fraction": _mixture}) res.update({mix: rtn}) if {"message", "warning"} == set(res.keys()): errtext += "Fatal Calculation Error: No result calculated!" res.update({"warning": True, "message": errtext}) return {"result": res}
def mProp(sub: str, outType: list, inputType1: str, inputValue1: float, inputType2: str, inputValue2: float, backend: str = "CP") -> dict: res = dict() errtext = "" mode_refprop = False extend_backend_req = False mixture = None flash = [] # 检查REFPROP可用性 if backend == "REFPROP": if REFPROP_READY: mode_refprop = True else: errtext += "Warning: No REFPROP support on server!\n" res.update({"warning": True, "message": errtext}) mode_refprop = False # 转换输出关键字为list if type(outType) != list: if type(outType) == str: outType = re.findall(TYPE_PATTERN, outType) else: errtext += "Input Error: Invalid output type: " + str(outType) logger.error(errtext) res.update({"error": True, "message": errtext}) return {"result": res} # 将所有文本输入转化为大写 sub = sub.upper() backend = backend.upper() inputType1 = inputType1.upper() inputType2 = inputType2.upper() outType = set(list(map(str.upper, outType))) # 检查纯物质名字是否受到支持 # 1-检查REFPROPbackend可用性 if sub in SUBS_P: if mode_refprop: if SUBS_P[sub][1] == "N/A": errtext += "Input Error: Not a REFPROP supported substance " + str( sub) logger.error(errtext) res.update({"error": True, "message": errtext}) return {"result": res} else: sub = SUBS_P[sub][1] else: # 检查使用的backend类型 if backend in ("CP", "COOLPROP") or (not mode_refprop and backend == "REFPROP"): sub_ = SUBS_P[sub][0] elif backend in ("PENGROBINSON", "PENG-ROBINSON", "PR"): sub_ = SUBS_P[sub][0] else: errtext += "Input Error: Not supported backend [%s] requested." % backend logger.error(errtext) res.update({"error": True, "message": errtext}) return {"result": res} # todo: make extend pure backend avaible if sub_ == "N/A": # extend_backend_req = True errtext += "Input Error: Not a CoolProp supported substance " + str( sub) logger.error(errtext) res.update({"error": True, "message": errtext}) return {"result": res} sub = sub_ del sub_ else: # 2-检查混合物可用性 # 2.1-检查是否输入了混合物组分 # 2.2-检查是否在组成自定义混合物的物质名中包含了混合物名称 # 2.3-检查组成自定义混合物的物质是否都是物性数据库支持的物质 # 2.4-检查各物质份额是否均为正数 # 2.5-归一化混合物组成 mixture = re.findall(MIXTURE_PATTERN, sub) if mixture: # get substance name sub = list(map(lambda x: x.split(":")[0], mixture)) # get substance fraction mixture = list(map(lambda x: float(x.split(":")[1]), mixture)) if set(sub) - set(SUBS_P.keys()): errtext += "Input Error: Not supported substance for mixture: " + ", ".join( sub) logger.error(errtext) res.update({"error": True, "message": errtext}) return {"result": res} else: if reduce(lambda acc, x: SUBS_P[x][2] or acc, sub, False): errtext += "Input Error: Building a mixture with a mixture..." logger.error(errtext) res.update({"error": True, "message": errtext}) return {"result": res} else: if backend in ("CP", "COOLPROP"): sub = "&".join([SUBS_P[i][0] for i in sub]) elif mode_refprop: sub = "&".join([SUBS_P[i][1] for i in sub]) if "N/A" in sub: errtext += "Input Error: Not REFPROP supported substance is detected." logger.error(errtext) res.update({"error": True, "message": errtext}) return {"result": res} # 检查混合组分输入是否均为正数 if not reduce(lambda acc, x: acc and (x > 0), mixture, True): errtext += "Input Error: Building a mixture with a mixture..." logger.error(errtext) res.update({"error": True, "message": errtext}) return {"result": res} mixture = [i / sum(mixture) for i in mixture] else: extend_backend_req = True if not outType.issubset(QCTYPE): if inputType1 == inputType2: errtext += "Input Error. Only one input Type [%s] is given." % inputType1 logger.error(errtext) res.update({"error": True, "message": errtext}) return {"result": res} if SequenceMatcher(None, inputType1, inputType2).find_longest_match( 0, len(inputType1), 0, len(inputType2)).size: errtext += "Input Error. Input Type [%s&%s] is the same." % ( inputType1, inputType2) logger.error(errtext) res.update({"error": True, "message": errtext}) return {"result": res} if not {inputType1, inputType2}.issubset(ITYPE): errtext += "Input Error. Invalid input type combo [%s&%s]." % ( inputType1, inputType2) logger.error(errtext) res.update({"error": True, "message": errtext}) return {"result": res} for item in ("H", "S"): if item in inputType1 + inputType2: errtext += "Warning: Unexpected result due to [%s] using difference Reference point on different backend.\n" % item logger.warning(errtext) res.update({"warning": True, "message": errtext}) try: inputValue1 = float(inputValue1) inputValue2 = float(inputValue2) except: errtext += "Input Error. Invalid values are not numbers." logger.error(errtext) res.update({"error": True, "message": errtext}) return {"result": res} if backend in ("PENGROBINSON", "PENG-ROBINSON", "PR"): backend = "PR" elif backend in ("CP", "COOLPROP") or not mode_refprop: backend = "HEOS" elif backend == "REFPROP" and mode_refprop: backend = "REFPROP" # 处理输出项 # 构建闪蒸计算输出 flash = set(OTYPE_MIX.keys()) flash &= outType outType -= flash # 如果将进行闪蒸计算而目标组成不是混合物 if not mixture and flash: flash = [] errtext += "Input Error. Not support flash calculation for predefine mixture or pure component." logger.error(errtext) res.update({"error": True, "message": errtext}) # 构建组合输出 for item in set(OTYPE_COMBO.keys()).intersection(outType): outType.remove(item) outType = outType.union(OTYPE_COMBO[item]) # 构建普通输出 if outType - set(OTYPE.keys()): errtext += "Warning: Unsupported Output Type keywords: %s \n" % list( outType - set(OTYPE.keys())) logger.warning(errtext) res.update({"warning": True, "message": errtext}) outType = outType.intersection(OTYPE.keys()) if extend_backend_req: # todo: impletementing of mProp_extend() res.update(mProp_extend()) else: sub = cp.AbstractState(backend, sub) if mixture: sub.set_mole_fractions(mixture) sub.update(**input_construct(inputType1, inputType2, inputValue1, inputValue2)) for item in outType: try: res.update({item: sub.keyed_output(getattr(cp, OTYPE[item]))}) except Exception as e: errtext += "Calculation Error: Fail to cal [%s]:\n" % item errtext += str(e) res.update({"warning": True, "message": errtext}) for item in flash: try: res.update({item: getattr(sub, OTYPE_MIX[item])()}) except Exception as e: errtext += "Calculation Error: Fail to cal [%s]:\n" % item errtext += str(e) res.update({"warning": True, "message": errtext}) if {"message", "warning"} == set(res.keys()): errtext += "Fatal Calculation Error: No result calculated!" res.update({"warning": True, "message": errtext}) return {"result": res}
def hx_pinch(library, fluid, N, M_dot, CPstate_su, CPstate_ex, T_sf_su, pinch, T_sf_ex=None): ''' Descretized heat exchanger model with imposed pinch point temperature difference or with imposed secondary fluid outlet temperature Uses the CoolProp low-level interface Parameters ---------- fluid : String Primary working fluid. N : Int Number of discretization elements. M_dot : Float Primary working fluid mass flow rate. CPstate_su : CoolProp.CoolProp.AbstractState Inlet state of the primary working fluid. CPstate_ex : CoolProp.CoolProp.AbstractState Outlet stete of the primary working fluid. T_sf_su : Float Inlet temperature of the secondary working fluid. pinch : Fload Imposed pinch point temperature difference T_sf_ex : Float Secondary fluid outlet temperature (if specified, the pinch point is not imposed anymore) Returns ------- Temperature profiles ''' T_sf = np.zeros(N) Ti = np.zeros(N) si = np.zeros(N) h_su = CPstate_su.keyed_output(CP.iHmass) h_ex = CPstate_ex.keyed_output(CP.iHmass) p_su = CPstate_su.keyed_output(CP.iP) p_ex = CPstate_ex.keyed_output(CP.iP) CPstates = [] for i in range(N): CPstates.append(CP.AbstractState(library, fluid)) if '&' in fluid: CPstates[i].set_mole_fractions([x_molar, 1 - x_molar]) hi = h_su + (h_ex - h_su) / (N - 1) * i Pi = p_su + (p_su - p_ex) / (N - 1) * i CPstates[i].update(CP.HmassP_INPUTS, hi, Pi) Ti[i] = CPstates[i].keyed_output(CP.iT) si[i] = CPstates[i].keyed_output(CP.iSmass) def pinch_calc(C_dot): T_sf_ex = T_sf_su + M_dot / C_dot[0] * (h_su - h_ex) T_sf = np.linspace(T_sf_ex, T_sf_su, N) if T_sf[N - 1] > Ti[0]: DELTAT = np.min(T_sf - Ti) else: DELTAT = np.min(Ti - T_sf) return DELTAT - pinch if h_su > h_ex and Ti[ -1] - T_sf_su < pinch or h_su < h_ex and T_sf_su - Ti[-1] < pinch: print('The pinch point requirement cannot be respected') sys.exit(1) if T_sf_ex is not None: C_dot_sf = (T_sf_ex - T_sf_su) / (M_dot * (h_su - h_ex)) else: C_dot_sf = fsolve(pinch_calc, 10)[0] T_sf_ex = T_sf_su + M_dot / C_dot_sf * (h_su - h_ex) T_sf = np.linspace(T_sf_ex, T_sf_su, N) if T_sf[N - 1] > Ti[0]: DELTAT = np.min(T_sf - Ti) else: DELTAT = np.min(Ti - T_sf) print("The pinch temperature difference is %.2f K" % (DELTAT)) return si, Ti, T_sf, C_dot_sf, CPstates
import CoolProp.CoolProp as CP, timeit AS = CP.AbstractState('HEOS', 'n-Propane') tau = 0.8 delta = 1.3 rhomolar = delta * AS.rhomolar_reducing() T = AS.T_reducing() / tau s = 0 N = 10000 tic = timeit.default_timer() for i in range(N): AS.specify_phase(CP.iphase_gas) AS.update(CP.DmolarT_INPUTS, rhomolar, T) # s += 0 s += (AS.alphar() + AS.delta() * AS.dalphar_dDelta() + AS.tau() * AS.dalphar_dTau() + AS.tau()**2 * AS.d2alphar_dTau2() + AS.delta() * AS.tau() * AS.d2alphar_dDelta_dTau() + AS.delta()**2 * AS.d2alphar_dDelta2() + AS.delta()**3 * AS.d3alphar_dDelta3() + AS.delta() * AS.tau()**2 * AS.d3alphar_dDelta_dTau2() + AS.delta()**2 * AS.tau() * AS.d3alphar_dDelta2_dTau() + AS.tau()**3 * AS.d3alphar_dTau3()) toc = timeit.default_timer() print(s / N, (toc - tic) / N * 1e6)
def __init__(self, refrigerant_data): # Create instances of results self._T = numpy.zeros(10, dtype=numpy.float) # Temperature self._p = numpy.zeros(10, dtype=numpy.float) # Pressure self._h = numpy.zeros(10, dtype=numpy.float) # Enthlapy self._s = numpy.zeros(10, dtype=numpy.float) # Entropy self._d = numpy.zeros(10, dtype=numpy.float) # Density self._x = numpy.zeros(10, dtype=numpy.float) # Vapor mass quality self._h1k_is = 0 # Points of interest self._description = numpy.zeros(10, dtype=numpy.object) self._description[0] = 'After suction line/ Before compressor' self._description[1] = 'After compressor / Before discharge line' self._description[2] = 'After discharge line / Condenser inlet' self._description[3] = 'Condenser dew point' self._description[4] = 'Condenser bubble point' self._description[5] = 'Condenser outlet / Before liquid line' self._description[6] = 'After liquid line / Before expansion valve' self._description[7] = 'After expansion valve / Evaporator inlet' self._description[8] = 'Evaporator dew point' self._description[9] = 'Evaporator outlet / Before suction line' # Evaporator self._ev_temperature = 0 self._ev_super_heat = 0 self._ev_pressure_drop = 0 # Suction line self._sl_temperature_change = 0 self._sl_pressure_drop = 0 # Compressor self._capacity_volumetric = 0 self._efficiency_isentropic = 0 self._efficiency_volymetric = 0 # Retrieved from "Analysis based on EU Regulation No 517/2014 of new HFC/HFO mixtures # as alternatives of high GWP refrigerants in refrigeration and HVAC systems" self._volumetric_flow_rate = 0.00653 # Discharge line self._dl_temperature_change = 0 self._dl_pressure_drop = 0 # Condenser self._co_temperature = 0 self._co_sub_cooling = 0 self._co_pressure_drop = 0 # Liquid line self._ll_temperature_change = 0 self._ll_pressure_drop = 0 # Data changed self._recalculate_condenser = True self._recalculate_evaporator = True # Initiate CoolProp with AbstractState meaning low-level interface self._refrigerant = CoolProp.AbstractState(refrigerant_data[1], refrigerant_data[2]) # Set mole fractions self._refrigerant.set_mole_fractions(refrigerant_data[3]) # Build custom composition envelope self._refrigerant.build_phase_envelope(refrigerant_data[0]) # Instantiate compressor self._compressor = Compressor()
## State T_0 = 2922.58 # K P = 15e5 # Pa T_0 = 2000.0 # K # P = 10e5 # Pa ## Gas gas = create_solution_mechanism() gas.TPY = T_0, P, 'N2O: 1.0' # gas.TP = T_0, P # gas.set_equivalence_ratio(1.0, fuel='C2H5OH', oxidizer='N2O') # gas.equilibrate('TP') ## Liquid liquid = CoolProp.AbstractState("HEOS", "Ethanol") # &Water") # liquid.set_mass_fractions([0.92, 0.08]) liquid.update(CoolProp.PQ_INPUTS, gas.P, 0) liquid_density = liquid.rhomass() ## Intial conditions D_0 = 40.002 * 1e-6 # micro m D2_0 = (D_0 * 1e6)**2 ml_0 = 0.314 # kg/s mg_0 = 1.103 # kg/s # mg_0 = 1.417 # kg/s rho_g_0 = gas.density # kg/m3 v_d_0 = 93.75 # m/s phi_0 = 0.0 ## Geometry
# Heat sink parameters: T_w_su_cd =273.15 + 130 # cooling water inlet temperature /K DELTAT_cd=7.5 # pinch point temperature of cooling water /K Q_dot_cd=10000 # heat capacity flowrates of cooling water kW/K # Heat source parameters: T_w_su_ev =273.15+135 # cooling water inlet temperature /K DELTAT_ev=7.5 # pinch point temperature of cooling water /K T_w_ex_ev = 0 # set to 0 if the cf T profile is calculated with the pinch limits = [1.25,2,250,550] # limits for plotting cycle = [] for i in range(8): cycle.append(CP.AbstractState(library, fluid)) if '&' in fluid: cycle[i].set_mole_fractions([x_molar, 1 - x_molar]) # c.build_phase_envelope("dummy") T_crit = cycle[0].T_critical() p_crit = cycle[0].p_critical() impose_T = False # Set to true to impose the saturation temperatures and not the pressure if impose_T: T_ev = 273.15 + 100 T_cd = 273.15 + 160 # mid-evaporation and mid-condensation: ev_mid = CP.AbstractState(library, fluid) if '&' in fluid:
# Based on Cam's design p_psi = 20. # PSI p = p_psi * 6894.76 # Pa # What's the temperature at which the two-phase gas-liquid condition exists (saturated state) Tmax = CP.PropsSI('T', 'P', p, 'Q', 0, fluid) print(Tmax) # What's the temperature at which it solidifies? #p=101325 state = CP.AbstractState("", "Deuterium") print(state.has_melting_line()) # Conclusion: seems like CoolProp does not have this information. p_psi = 20. # PSI p = p_psi * 6894.76 # Pa T = 23.0 # K h1 = CP.PropsSI('H', 'T', T, 'P', p, fluid) phase = CP.PhaseSI('T', T, 'P', p, fluid) print(T, p, h1, phase) T = 24.0 # K h2 = CP.PropsSI('H', 'T', T, 'P', p, fluid) density = CP.PropsSI('D', 'T', T, 'P', p, fluid) phase = CP.PhaseSI('T', T, 'P', p, fluid)
import CoolProp.CoolProp as CP import matplotlib.pyplot as plt # Increase the starting pressure a bit, behavior at very low pressure is problematic CP.set_config_double(CP.PHASE_ENVELOPE_STARTING_PRESSURE_PA, 1e4) SRK = CP.AbstractState('SRK', 'Methane&Ethane') SRK.set_mole_fractions([0.5, 1 - 0.5]) for kij, c in zip([0.0, 0.1], ['r', 'b']): # Set the interaction parameter SRK.set_binary_interaction_double(0, 1, "kij", kij) # Some VLE calculations for p in [1e4, 1e5, 1e6]: SRK.update(CP.PQ_INPUTS, p, 0) plt.plot(SRK.T(), SRK.p(), '<', color=c) SRK.update(CP.PQ_INPUTS, p, 1) plt.plot(SRK.T(), SRK.p(), '>', color=c) # Phase envelope SRK.build_phase_envelope("") PE = SRK.get_phase_envelope_data() plt.plot(PE.T, PE.p, '-', label='$k_{ij} = $' + str(kij), color=c) # Critical point pts = SRK.all_critical_points() for pt in pts: plt.plot(pt.T, pt.p, '*', color=c)
A single effect LiBr absorption chiller model. """ import numpy as np import tabulate from scipy.optimize import fsolve from scipy.interpolate import PchipInterpolator from collections import namedtuple import CoolProp.CoolProp as CP from hw2_1 import CelsiusToKelvin as C2K from hw2_1 import KelvinToCelsius as K2C import libr_props, libr_props2 import HRHX_integral_model water = 'HEOS::Water' librname = lambda x: 'INCOMP::LiBr[{}]'.format(x) pwater = CP.AbstractState("HEOS","water") pointType = np.dtype(dict(names="name m x T p Q h D C".split(),formats=['S32']+['d']*8)) class ProcessPoint(object): def __init__(self,row): self.row = row def makeprop(i): def getx(self): return self.row[i] def setx(self,value): self.row[i]=value def delx(self): del self.row[i] return property(getx,setx,delx) for i in pointType.names: setattr(ProcessPoint,i,makeprop(i))
import numpy as np import random import CoolProp.CoolProp as CP import time random.seed("coolprop_test") p = 101325 # 1 atmosphere T = np.random.uniform( 120, 400, 10000) + 273.15 # Random points from 120 to 400 deg C, gas phase only # Make sure the objects exist and create tables if needed normal_state = CP.AbstractState("HEOS", "H2O") tabular_state = CP.AbstractState("BICUBIC&HEOS", "H2O") # Measure execution speed results = {} tmp = time.time() for Ti in T: rho = CP.PropsSI("Dmass", "P", p, "T", Ti, "H2O") results["1. PropsSI"] = time.time() - tmp tmp = time.time() for Ti in T: normal_state.update(CP.PT_INPUTS, p, Ti) rho = normal_state.keyed_output(CP.iDmass) results["2. HEOS"] = time.time() - tmp tmp = time.time() for Ti in T:
__author__ = 'Peter Eriksson @ KTH 2015' import numpy as numpy import CoolProp.CoolProp as CoolProp # Description: # This file illustrates the zeotropic behaviour of temperature glide # Initiate CoolProp with AbstractState meaning low-level interface refrigerant = CoolProp.AbstractState("REFPROP", "R125&R1234yf") pressure = 101.325e3 k = 273.15 x = numpy.linspace(0, 1, 25) # Open files file_1 = open('../../Report/LaTeX/data/zeotropic_bubble.dat', 'w+') file_2 = open('../../Report/LaTeX/data/zeotropic_dew.dat', 'w+') file_3 = open('../../Report/LaTeX/data/zeotropic_diff.dat', 'w+') file_1.write("mixture temperature\n") file_2.write("mixture temperature\n") file_3.write("mixture temperature\n") for i in range(0, len(x)): # Set mole fractions refrigerant.set_mole_fractions([x[i], 1 - x[i]]) refrigerant.update(CoolProp.PQ_INPUTS, pressure, 0) file_1.write(str("%f %f\n" % (x[i], refrigerant.T() - k)))
__author__ = 'Peter Eriksson @ KTH 2015' import numpy as numpy import CoolProp.CoolProp as CoolProp import vcc_input # Description: # This file illustrates the non-linear behaviour of temperature glide. refrigerant_data = vcc_input.refrigerant('R448A') # Initiate CoolProp with AbstractState meaning low-level interface refrigerant = CoolProp.AbstractState(refrigerant_data[1], refrigerant_data[2]) # Set mole fractions refrigerant.set_mole_fractions(refrigerant_data[3]) pressure = 4e5 k = 273.15 x = numpy.linspace(0,1,10) t = numpy.zeros(len(x), numpy.float) file_1 = open('../../Report/LaTeX/data/Glide-non-linear.dat', 'w+') file_2 = open('../../Report/LaTeX/data/Glide-linear.dat', 'w+') file_3 = open('../../Report/LaTeX/data/Glide-diff.dat', 'w+') file_1.write("vapormassquality temperature\n") file_2.write("vapormassquality temperature\n") file_3.write("vapormassquality temperature\n")
regulator_output_pressure, regulator_output_temperature) # # Initialise simulation # simulation = MortarSimulation( # Model inputs fill_function= fill_function, # Volume flow rate into the tank as a function of p1/p2 (m3/s) regulator_output_pressure= regulator_output_pressure, # Regulator output pressure (Pa) regulator_output_temperature= regulator_output_temperature, # Regulator output temperature (K) gas_model=CP.AbstractState("HEOS", "N2"), # Gas equation of state calculator radius_piston=0.0595, # Radius of the piston (m) cross_area_orifice=0.0595**2 * np.pi, # Cross sectional area of orifice (m2) volume_tank=0.0014, # Volume of the plenum/accumulator (m3) external_pressure=13032.0, # External pressure (Pa) shear_pin_force_limit=8800.0, # Force required to shear pins (N) piston_mass=0.57, # Mass of the piston (kg) parachute_mass=1.2, # Mass of the payload (kg) friction_factor=150.0, # Viscous friction factor coefficient (-) body_acceleration=0.0, # Acceleration of reference frame (m/s2) static_friction_force=100.0, # Static frictional force (N) maximum_compression=0.001, # Max expansion before shear pins break (m) initial_density=0.146, # Initial density in tank (kg/m3) initial_pressure=13032.0, # Initial pressure in tank (Pa) mortar_temperature=300.0, # Temperature of the mortar (K)
import CoolProp.CoolProp as CP import matplotlib.pyplot as plt HEOS = CP.AbstractState('HEOS', 'Methane&Ethane') for x0 in [0.02, 0.2, 0.4, 0.6, 0.8, 0.98]: HEOS.set_mole_fractions([x0, 1 - x0]) try: HEOS.build_phase_envelope("dummy") PE = HEOS.get_phase_envelope_data() PELabel = 'Methane, x = ' + str(x0) plt.plot(PE.T, PE.p, '-', label=PELabel) except ValueError as VE: print(VE) plt.xlabel('Temperature [K]') plt.ylabel('Pressure [Pa]') plt.yscale('log') plt.title('Phase Envelope for Methane/Ethane Mixtures') plt.legend(loc='lower right', shadow=True) plt.savefig('methane-ethane.pdf') plt.savefig('methane-ethane.png') plt.close()
def __init__(self, fluid1, x1, fluid2, x2=-1): """Class to hold and calculate thermodynamic properties of fluid mixtures. When a new object is created, a new card is also created to be used in rocketcea. Parameters ---------- fluid1 : Fluid x1 : float Weigth percentage (0 - 100). fluid2 : Fluid x2 : float, optional Weigth percentage (0 - 100). Defalut is 100 - x1. Returns ------- None Note ---- Both fluids should have the same storage pressure and temperature. TODO: check if above restriction is really necessary. Both fluids shoud be of the same type, either oxidizer or fuel. Does not support fluid blends wh """ # Save input data self.fluid1 = fluid1 self.fluid2 = fluid2 self.x1 = x1 self.x2 = x2 if x2 != -1 else (1 - x1) # Check if storage pressure and temperature and type is the same if self.fluid1.storage_pressure != self.fluid2.storage_pressure: raise ValueError("Fluid pressures do not match. " + "Fluid 1: {:.2f} K | Fluid 2: {:.2f} K".format( self.fluid1.storage_pressure, self.fluid2.storage_pressure)) if self.fluid1.storage_temperature != self.fluid2.storage_temperature: raise ValueError("Fluid temperatures do not match. " + "Fluid 1: {:.2f} K | Fluid 2: {:.2f} K".format( self.fluid1.storage_temperature, self.fluid2.storage_temperature)) if self.fluid1.fluid_type != self.fluid2.fluid_type: raise ValueError( "Fluid types are not the same! Must be two oxidizers or two fuels." ) # Save storage temperature, pressure and type self.fluid_type = self.fluid1.fluid_type self.storage_pressure = self.fluid1.storage_pressure self.storage_temperature = self.fluid1.storage_temperature # Create a new fluid name self.coolprop_name = self.fluid1.coolprop_name + "&" + self.fluid2.coolprop_name # Create a new rocketcea fluid blend if self.fluid_type == "fuel": self.name = blends.newFuelBlend( fuelL=[self.fluid1.name, self.fluid2.name], fuelPcentL=[self.x1, self.x2], ) else: self.name = blends.newOxBlend( oxL=[self.fluid1.name, self.fluid2.name], oxPcentL=[self.x1, self.x2], ) # Create HEOS CoolProp object self.HEOS = CoolProp.AbstractState("HEOS", self.coolprop_name) self.HEOS.set_mass_fractions([self.x1 / 100, self.x2 / 100]) self.HEOS.update(CoolProp.PT_INPUTS, self.storage_pressure, self.storage_temperature) self.storage_density = self.HEOS.rhomass()
def __init__(self, CP_BACKEND, FLUID): self.abst = CP.AbstractState(CP_BACKEND, FLUID) self.__get_PropLimits()