Source code for Condenser

from __future__ import division #Make integer 3/2 give 1.5 in python 2.x
from math import pi,log,exp
from CoolProp.CoolProp import Props
from Correlations import f_h_1phase_Tube,ShahCondensation_Average,LMPressureGradientAvg,TwoPhaseDensity,AccelPressureDrop 
from FinCorrelations import WavyLouveredFins,FinInputs,IsFinsClass
from scipy.optimize import brentq
from ACHPTools import ValidateFields
class FinVals():
    def __init__(self):
        pass
    
[docs]class CondenserClass(): def __init__(self,**kwargs): #Load the parameters passed in # using the dictionary self.__dict__.update(kwargs)
[docs] def OutputList(self): """ Return a list of parameters for this component for further output It is a list of tuples, and each tuple is formed of items: [0] Description of value [1] Units of value [2] The value itself """ return [ ('Volumetric flow rate of humid air','m^3/s',self.Fins.Air.Vdot_ha), ('Inlet Dry bulb temp','K',self.Tin_a), ('Inlet Air pressure','kPa',self.Fins.Air.p), ('Inlet Air Relative Humidity','-',self.Fins.Air.RH), ('Tubes per bank','-',self.Fins.Tubes.NTubes_per_bank), ('Number of banks','-',self.Fins.Tubes.Nbank), ('Number circuits','-',self.Fins.Tubes.Ncircuits), ('Length of tube','m',self.Fins.Tubes.Ltube), ('Tube OD','m',self.OD), ('Tube ID','m',self.ID), ('Tube Long. Pitch','m',self.Fins.Tubes.Pl), ('Tube Transverse Pitch','m',self.Fins.Tubes.Pt), ('Fins per inch','1/in',self.Fins.Fins.FPI), ('Fin waviness pd','m',self.Fins.Fins.Pd), ('Fin waviness xf','m',self.Fins.Fins.xf), ('Fin thickness','m',self.Fins.Fins.t), ('Fin Conductivity','W/m-K',self.Fins.Fins.k_fin), ('Q Total','W',self.Q), ('Q Superheat','W',self.Q_superheat), ('Q Two-Phase','W',self.Q_2phase), ('Q Subcool','W',self.Q_subcool), ('Inlet Temp','K',self.Tin_r), ('Outlet Temp','K',self.Tout_r), ('Pressure Drop Total','Pa',self.DP_r), ('Pressure Drop Superheat','Pa',self.DP_r_superheat), ('Pressure Drop Two-Phase','Pa',self.DP_r_2phase), ('Pressure Drop Subcool','Pa',self.DP_r_subcool), ('Charge Total','kg',self.Charge), ('Charge Superheat','kg',self.Charge_superheat), ('Charge Two-Phase','kg',self.Charge_2phase), ('Charge Subcool','kg',self.Charge_subcool), ('Mean HTC Superheat','W/m^2-K',self.h_r_superheat), ('Mean HTC Two-phase','W/m^2-K',self.h_r_2phase), ('Mean HTC Subcool','W/m^2-K',self.h_r_subcool), ('Wetted Area Fraction Superheat','-',self.w_superheat), ('Wetted Area Fraction Two-phase','-',self.w_2phase), ('Wetted Area Fraction Subcool','-',self.w_subcool), ('Mean Air HTC','W/m^2-K',self.Fins.h_a), ('Surface Effectiveness','-',self.Fins.eta_a), ('Air-side area (fin+tubes)','m^2',self.Fins.A_a), ('Mass Flow rate of Dry Air','kg/s',self.Fins.mdot_da), ('Mass Flow rate of Humid Air','kg/s',self.Fins.mdot_ha), ('Pressure Drop Air-side','Pa',self.Fins.dP_a), ('Subcooling','K',self.DT_sc) ]
[docs] def Update(self,**kwargs): #Update the parameters passed in # using the dictionary self.__dict__.update(kwargs)
[docs] def Calculate(self): #Only validate the first time if not hasattr(self,'IsValidated'): self.Fins.Validate() reqFields=[ ('Ref',str,None,None), ('Fins',IsFinsClass,None,None), ('mdot_r',float,0.00001,20), ('Tin_r',float,200,500), ('psat_r',float,0.00001,20000) ] optFields=['Verbosity'] ValidateFields(self.__dict__,reqFields,optFields) self.IsValidated=True # Retrieve some parameters from nested structures # for code compactness self.ID=self.Fins.Tubes.ID self.OD=self.Fins.Tubes.OD self.Ltube=self.Fins.Tubes.Ltube self.NTubes_per_bank=self.Fins.Tubes.NTubes_per_bank self.Nbank=self.Fins.Tubes.Nbank self.Ncircuits=self.Fins.Tubes.Ncircuits self.Tin_a=self.Fins.Air.Tdb ## Bubble and dew temperatures (same for fluids without glide) self.Tbubble=Props('T','P',self.psat_r,'Q',0.0,self.Ref) self.Tdew=Props('T','P',self.psat_r,'Q',1.0,self.Ref) # Calculate an effective length of circuit if circuits are # not all the same length TotalLength=self.Ltube*self.NTubes_per_bank*self.Nbank self.Lcircuit=TotalLength/self.Ncircuits self.V_r = pi * self.ID**2 / 4.0 * self.Lcircuit * self.Ncircuits self.A_r_wetted = pi * self.ID * self.Ncircuits * self.Lcircuit self.G_r = self.mdot_r/(self.Ncircuits*pi*self.ID**2/4.0) #Definitely have a superheated portion self._Superheat_Forward() #Maybe have a full two-phase section #First try to run with a full two-phase section from quality of 1 to quality of 0 self._TwoPhase_Forward() #If we have already used too much of the HX (max possible sum of w is 1.0) if self.w_2phase+self.w_superheat>1: #There is no subcooled portion, solve for outlet quality brentq(self._TwoPhase_Forward,0.0000001,0.9999999) #Zero out all the subcooled parameters self.Q_subcool=0.0 self.DP_r_subcool=0.0 self.Charge_subcool=0.0 self.w_subcool=0.0 self.h_r_subcool=0.0 self.existsSubcooled=False else: #By definition then we have a subcooled portion, solve for it self.existsSubcooled=True self._Subcool_Forward() #Overall calculations self.Q=self.Q_superheat+self.Q_2phase+self.Q_subcool self.DP_r=self.DP_r_superheat+self.DP_r_2phase+self.DP_r_subcool self.Charge=self.Charge_2phase+self.Charge_subcool+self.Charge_superheat self.sin_r=Props('S','T',self.Tin_r,'P',self.psat_r,self.Ref)*1000 if self.existsSubcooled==True: self.hout_r=Props('H','T',self.Tout_r,'P',self.psat_r,self.Ref)*1000 self.sout_r=Props('S','T',self.Tout_r,'P',self.psat_r,self.Ref)*1000 else: self.Tout_r=self.xout_2phase*self.Tdew+(1-self.xout_2phase)*self.Tbubble self.hout_r=Props('H','T',self.Tout_r,'Q',self.xout_2phase,self.Ref)*1000 self.sout_r=Props('S','T',self.Tout_r,'Q',self.xout_2phase,self.Ref)*1000 #Use the effective subcooling self.DT_sc=self.DT_sc_2phase #Calculate the mean outlet air temperature [K] self.Tout_a=self.Tin_a-self.Q/(self.Fins.cp_da*self.Fins.mdot_da) self.hmean_r=self.w_2phase*self.h_r_2phase+self.w_superheat*self.h_r_superheat+self.w_subcool*self.h_r_subcool self.UA_r=self.hmean_r*self.A_r_wetted self.UA_a=self.Fins.h_a*self.Fins.A_a*self.Fins.eta_a
def _Superheat_Forward(self): # ********************************************************************** # SUPERHEATED PART # ********************************************************************** #Dew temperature for constant pressure cooling to saturation Tdew=self.Tdew # Average fluid temps are used for the calculation of properties # Average temp of refrigerant is average of sat. temp and outlet temp # Secondary fluid is air over the fins self.f_r_superheat, self.h_r_superheat, self.Re_r_superheat=f_h_1phase_Tube(self.mdot_r / self.Ncircuits, self.ID, (Tdew+self.Tin_r)/2.0, self.psat_r, self.Ref, "Single"); cp_r = Props('C', 'T', (Tdew+self.Tin_r)/2, 'P', self.psat_r, self.Ref)*1000. #//[J/kg-K] WavyLouveredFins(self.Fins) self.mdot_da=self.Fins.mdot_da # Cross-flow in the superheated region. # Using effectiveness-Ntu relationships for cross flow with non-zero Cr. UA_overall = 1. / (1. / (self.Fins.eta_a * self.Fins.h_a * self.Fins.A_a) + 1. / (self.h_r_superheat * self.A_r_wetted) ) epsilon_superheat=(Tdew-self.Tin_r)/(self.Tin_a-self.Tin_r) Ntu=UA_overall/(self.mdot_da*self.Fins.cp_da) if epsilon_superheat>1.0: epsilon_superheat=1.0-1e-12 self.w_superheat=-log(1-epsilon_superheat)*self.mdot_r*cp_r/((1-exp(-Ntu))*self.mdot_da*self.Fins.cp_da) # Positive Q is heat input to the refrigerant, negative Q is heat output from refrigerant. # Heat is removed here from the refrigerant since it is being cooled self.Q_superheat = self.mdot_r * cp_r * (Tdew-self.Tin_r) rho_superheat=Props('D','T',(self.Tin_r+Tdew)/2.0, 'P', self.psat_r, self.Ref) #Pressure drop calculations for superheated refrigerant v_r=1./rho_superheat; #Pressure gradient using Darcy friction factor dpdz_r=-self.f_r_superheat*v_r*self.G_r**2/(2.*self.ID) #Pressure gradient self.DP_r_superheat=dpdz_r*self.Lcircuit*self.w_superheat self.Charge_superheat = self.w_superheat * self.V_r * rho_superheat #Latent heat needed for pseudo-quality calc Tbubble=Props('T','P',self.psat_r,'Q',0,self.Ref) Tdew=Props('T','P',self.psat_r,'Q',1,self.Ref) h_fg = (Props('H', 'T', Tdew, 'Q', 1, self.Ref) - Props('H', 'T', Tbubble, 'Q', 0, self.Ref))*1000 #J/kg self.hin_r=Props('H','T',self.Tin_r,'P',self.psat_r,self.Ref)*1000 self.xin_r=1.0+cp_r*(self.Tin_r-Tdew)/h_fg def _TwoPhase_Forward(self,xout_r_2phase=0.0): """ xout_r_2phase: quality of refrigerant at end of two-phase portion default value is 0.0 (full two phase region) """ ## Bubble and dew temperatures (same for fluids without glide) Tbubble=self.Tbubble Tdew=self.Tdew ## Mean temperature for use in HT relationships Tsat_r=(Tbubble+Tdew)/2 h_fg = (Props('H', 'T', Tdew, 'Q', 1, self.Ref) - Props('H', 'T', Tbubble, 'Q', 0, self.Ref))*1000 #J/kg # This block calculates the average refrigerant heat transfer coefficient by # integrating the local heat transfer coefficient between # a quality of 1.0 and the outlet quality self.h_r_2phase=ShahCondensation_Average(xout_r_2phase,1.0,self.Ref,self.G_r,self.ID,self.psat_r,Tbubble,Tdew); UA_overall = 1 / (1 / (self.Fins.eta_a * self.Fins.h_a * self.Fins.A_a) + 1 / (self.h_r_2phase * self.A_r_wetted)); self.epsilon_2phase=1-exp(-UA_overall/(self.mdot_da*self.Fins.cp_da)); self.w_2phase=-self.mdot_r*h_fg*(1.0-xout_r_2phase)/(self.mdot_da*self.Fins.cp_da*(self.Tin_a-Tsat_r)*self.epsilon_2phase); #Positive Q is heat input to the refrigerant, negative Q is heat output from refrigerant. #Heat is removed here from the refrigerant since it is condensing self.Q_2phase = self.epsilon_2phase * self.Fins.cp_da* self.mdot_da * self.w_2phase * (self.Tin_a-Tsat_r); self.xout_2phase=xout_r_2phase # Frictional pressure drop component DP_frict=LMPressureGradientAvg(self.xout_2phase,1.0,self.Ref,self.G_r,self.ID,Tbubble,Tdew)*self.Lcircuit*self.w_2phase #Accelerational pressure drop component DP_accel=-AccelPressureDrop(self.xout_2phase,1.0,self.Ref,self.G_r,Tbubble,Tdew) # Total pressure drop is the sum of accelerational and frictional components (neglecting gravitational effects) self.DP_r_2phase=DP_frict+DP_accel rho_average=TwoPhaseDensity(self.Ref,self.xout_2phase,1.0,self.Tdew,self.Tbubble,slipModel='Zivi') self.Charge_2phase = rho_average * self.w_2phase * self.V_r if self.Verbosity>7: print '2phase cond resid', self.w_2phase-(1-self.w_superheat) print 'h_r_2phase',self.h_r_2phase #Calculate an effective pseudo-subcooling based on the equality # cp*DT_sc=-dx*h_fg cp_satL=Props('C','T',self.Tbubble,'Q',0.0,self.Ref)*1000 self.DT_sc_2phase=-self.xout_2phase*h_fg/(cp_satL) #If the quality is being solved for, the length of the two-phase and subcooled # sections should add to the length of the HX. Return the residual return self.w_2phase-(1-self.w_superheat) def _Subcool_Forward(self): self.w_subcool=1-self.w_2phase-self.w_superheat if self.w_subcool<0: raise ValueError('w_subcool in Condenser cannot be less than zero') # Bubble temperature Tbubble=Props('T','P',self.psat_r,'Q',0.0,self.Ref) # Based on the the construction of the cycle model there is guaranteed to be a # two-phase portion of the heat exchanger A_a_subcool = self.Fins.A_a * self.w_subcool mdot_da_subcool = self.mdot_da * self.w_subcool A_r_subcool = self.A_r_wetted * self.w_subcool # Friction factor and HTC in the refrigerant portions. # Average fluid temps are used for the calculation of properties # Average temp of refrigerant is average of sat. temp and outlet temp # Secondary fluid is air over the fins self.f_r_subcool, self.h_r_subcool, self.Re_r_subcool=f_h_1phase_Tube( self.mdot_r / self.Ncircuits, self.ID, Tbubble-1.0, self.psat_r, self.Ref, "Single") cp_r = Props('C', 'T', Tbubble-1, 'P', self.psat_r, self.Ref)*1000 #[J/kg-K] # Cross-flow in the subcooled region. R_a=1. / (self.Fins.eta_a * self.Fins.h_a * self.Fins.A_a) R_r=1. / (self.h_r_subcool * self.A_r_wetted) UA_subcool = self.w_subcool / (R_a + R_r) Cmin=min([self.mdot_da*self.Fins.cp_da*self.w_subcool,self.mdot_r*cp_r]) Cmax=max([self.mdot_da*self.Fins.cp_da*self.w_subcool,self.mdot_r*cp_r]) Cr=Cmin/Cmax NTU=UA_subcool/Cmin if(self.mdot_da*self.Fins.cp_da*self.w_subcool>self.mdot_r*cp_r): #Minimum capacitance rate on refrigerant side epsilon_subcool = 1. - exp(-1. / Cr * (1. - exp(-Cr * NTU))) else: #Minimum capacitance rate on air side epsilon_subcool = 1 / Cr * (1 - exp(-Cr * (1 - exp(-NTU)))) # Positive Q is heat input to the refrigerant, negative Q is heat output from refrigerant. # Heat is removed here from the refrigerant since it is condensing self.Q_subcool=-epsilon_subcool*Cmin*(Tbubble-self.Tin_a) self.DT_sc=-self.Q_subcool/(self.mdot_r*cp_r) self.Tout_r=Tbubble-self.DT_sc rho_subcool=Props('D', 'T', (Tbubble + self.Tout_r) / 2, 'P', self.psat_r, self.Ref) self.Charge_subcool = self.w_subcool * self.V_r * rho_subcool #Pressure drop calculations for subcooled refrigerant v_r=1/rho_subcool #Pressure gradient using Darcy friction factor dpdz_r=-self.f_r_subcool*v_r*self.G_r**2/(2*self.ID) #Pressure gradient self.DP_r_subcool=dpdz_r*self.Lcircuit*self.w_subcool
def SampleCondenser(T=41.37): Fins=FinInputs() Fins.Tubes.NTubes_per_bank=41 #number of tubes per bank=row Fins.Tubes.Nbank=1 #number of baks/rows Fins.Tubes.Ncircuits=5 #number of baks/rows Fins.Tubes.Ltube=2.286 Fins.Tubes.OD=0.007 Fins.Tubes.ID=0.0063904 Fins.Tubes.Pl=0.0191 #distance between center of tubes in flow direction Fins.Tubes.Pt=0.0222 #distance between center of tubes orthogonal to flow direction Fins.Fins.FPI=25 #Number of fins per inch Fins.Fins.Pd=0.001 #2* amplitude of wavy fin Fins.Fins.xf=0.001 #1/2 period of fin Fins.Fins.t=0.00011 #Thickness of fin material Fins.Fins.k_fin=237 #Thermal conductivity of fin material Fins.Air.Vdot_ha=1.7934 #rated volumetric flowrate Fins.Air.Tmean=308.15 Fins.Air.Tdb=308.15 #Dry Bulb Temperature Fins.Air.p=101.325 #Air pressure Fins.Air.RH=0.51 #Relative Humidity Fins.Air.RHmean=0.51 Fins.Air.FanPower=160 params={ 'Ref': 'R410A', 'mdot_r': 0.0708, 'Tin_r': T+20+273.15, 'psat_r': Props('P','T',T+273.15,'Q',1.0,'R410A'), 'Fins':Fins, 'Verbosity':0 } Cond=CondenserClass(**params) Cond.Calculate() return Cond if __name__=='__main__': #This runs if you run this file directly Cond=SampleCondenser(43.3) print Cond.OutputList()