class DXCycleClass(): def __init__(self): """ Load up the necessary sub-structures to be filled with the code that follows """ self.Compressor=CompressorClass() self.Condenser=CondenserClass() self.Condenser.Fins=FinInputs() self.Evaporator=EvaporatorClass() self.Evaporator.Fins=FinInputs() self.LineSetSupply=LineSetClass() self.LineSetReturn=LineSetClass() 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 """ Output_List=[] #append optional parameters, if applicable if hasattr(self,'TestName'): Output_List.append(('Name','N/A',self.TestName)) if hasattr(self,'TestDescription'): Output_List.append(('Description','N/A',self.TestDescription)) if hasattr(self,'TestDetails'): Output_List.append(('Details','N/A',self.TestDetails)) Output_List_default=[ #default output list ('Charge','kg',self.Charge), ('Condensation temp (dew)','K',self.Tdew_cond), ('Evaporation temp (dew)','K',self.Tdew_evap), ('Condenser Subcooling','K',self.DT_sc), ('Primary Ref.','-',self.Ref), ('COP','-',self.COP), ('COSP','-',self.COSP), ('Net Capacity','W',self.Capacity), ('Net Power','W',self.Power), ('SHR','-',self.SHR), ('Imposed Variable','-',self.ImposedVariable), ] for i in range(0,len(Output_List_default)): #append default parameters to output list Output_List.append(Output_List_default[i]) return Output_List def Calculate(self,DT_evap,DT_cond): """ Inputs are differences in temperature [K] between HX air inlet temperature and the dew temperature for the heat exchanger. Required Inputs: DT_evap: Difference in temperature [K] between evaporator air inlet temperature and refrigerant dew temperature DT_cond: Difference in temperature [K] between condenser air inlet temperature and refrigeant dew temperature """ if self.Verbosity>1: print 'DTevap %7.4f DTcond %7.4f,' %(DT_evap,DT_cond) Tdew_cond=self.Condenser.Fins.Air.Tdb+DT_cond#the values (Tin_a,..) come from line 128ff Tdew_evap=self.Evaporator.Fins.Air.Tdb-DT_evap psat_cond=Props('P','T',Tdew_cond,'Q',1,self.Ref) psat_evap=Props('P','T',Tdew_evap,'Q',1,self.Ref) Tbubble_evap=Props('T','P',psat_evap,'Q',0,self.Ref) self.Tdew_cond=Tdew_cond self.Tdew_evap=Tdew_evap #If the user doesn't include the Mode, fail assert hasattr(self,'Mode') if self.Mode=='AC': if not hasattr(self.Compressor,'mdot_r') or self.Compressor.mdot_r<0.00001: # The first run of model, run the compressor just so you can get a preliminary value # for the mass flow rate for the line set params={ #dictionary -> key:value, e.g. 'key':2345, 'pin_r': psat_evap, 'pout_r': psat_cond, 'Tin_r': Tdew_evap+self.Evaporator.DT_sh, 'Ref': self.Ref } self.Compressor.Update(**params) self.Compressor.Calculate() params={ 'pin': psat_evap, 'hin': Props('H','T',Tdew_evap+self.Evaporator.DT_sh,'P',psat_evap,self.Ref)*1000, 'mdot': self.Compressor.mdot_r, 'Ref': self.Ref } self.LineSetReturn.Update(**params) self.LineSetReturn.Calculate() params={ #dictionary -> key:value, e.g. 'key':2345, 'pin_r': psat_evap-self.DP_low, 'pout_r': psat_cond+self.DP_high, 'Tin_r': TrhoPhase_ph(self.Ref,psat_evap,self.LineSetReturn.hout,Tbubble_evap,Tdew_evap)[0], 'Ref': self.Ref } self.Compressor.Update(**params) self.Compressor.Calculate() if self.Verbosity>1: print 'Comp DP H L',self.DP_low,self.DP_high params={ 'mdot_r': self.Compressor.mdot_r, 'Tin_r': self.Compressor.Tout_r, 'psat_r': psat_cond, 'Ref': self.Ref } self.Condenser.Update(**params) self.Condenser.Calculate() params={ 'pin':psat_cond, 'hin':self.Condenser.hout_r, 'mdot':self.Compressor.mdot_r, 'Ref':self.Ref } self.LineSetSupply.Update(**params) self.LineSetSupply.Calculate() params={ 'mdot_r': self.Compressor.mdot_r, 'psat_r': psat_evap, 'hin_r': self.LineSetSupply.hout, 'Ref': self.Ref } self.Evaporator.Update(**params) self.Evaporator.Calculate() self.Charge=self.Condenser.Charge+self.Evaporator.Charge+self.LineSetSupply.Charge+self.LineSetReturn.Charge self.EnergyBalance=self.Compressor.CycleEnergyIn+self.Condenser.Q+self.Evaporator.Q resid=np.zeros((2)) self.DP_HighPressure=self.Condenser.DP_r+self.LineSetSupply.DP self.DP_LowPressure=self.Evaporator.DP_r+self.LineSetReturn.DP resid[0]=self.Compressor.mdot_r*(self.LineSetReturn.hin-self.Evaporator.hout_r) if self.ImposedVariable=='Subcooling': resid[1]=self.Condenser.DT_sc-self.DT_sc_target elif self.ImposedVariable=='Charge': resid[1]=self.Charge-self.Charge_target if self.Verbosity>1: print resid self.Capacity=self.Evaporator.Capacity self.Power=self.Compressor.W+self.Evaporator.Fins.Air.FanPower+self.Condenser.Fins.Air.FanPower self.COP=self.Evaporator.Q/self.Compressor.W self.COSP=self.Evaporator.Capacity/self.Power self.SHR=self.Evaporator.SHR self.DT_sc=self.Condenser.DT_sc elif self.Mode=='HP': params={ #dictionary -> key:value, e.g. 'key':2345, 'pin_r': psat_evap-self.DP_low*1, 'pout_r': psat_cond+self.DP_high*1, 'Tin_r': Tdew_evap+self.Evaporator.DT_sh, 'Ref': self.Ref } self.Compressor.Update(**params) self.Compressor.Calculate() params={ 'pin': psat_cond, 'hin': self.Compressor.hout_r, 'mdot': self.Compressor.mdot_r, 'Ref': self.Ref } self.LineSetSupply.Update(**params) self.LineSetSupply.Calculate() params={ 'mdot_r': self.Compressor.mdot_r, 'Tin_r': self.Compressor.Tout_r, 'psat_r': psat_cond, 'Ref': self.Ref } self.Condenser.Update(**params) self.Condenser.Calculate() params={ 'pin': psat_cond, 'hin': self.Condenser.hout_r, 'mdot': self.Compressor.mdot_r, 'Ref': self.Ref } self.LineSetReturn.Update(**params) self.LineSetReturn.Calculate() params={ 'mdot_r': self.Compressor.mdot_r, 'psat_r': psat_evap, 'hin_r': self.LineSetReturn.hout, 'Ref': self.Ref } self.Evaporator.Update(**params) self.Evaporator.Calculate() self.Charge=self.Condenser.Charge+self.Evaporator.Charge+self.LineSetSupply.Charge+self.LineSetReturn.Charge self.EnergyBalance=self.Compressor.CycleEnergyIn+self.Condenser.Q+self.Evaporator.Q resid=np.zeros((2)) resid[0]=self.Compressor.mdot_r*(self.Compressor.hin_r-self.Evaporator.hout_r) if self.ImposedVariable=='Subcooling': resid[1]=self.Condenser.DT_sc-self.DT_sc_target elif self.ImposedVariable=='Charge': resid[1]=self.Charge-self.Charge_target self.Capacity=-self.Condenser.Q+self.Condenser.Fins.Air.FanPower self.DT_sc=self.Condenser.DT_sc self.Power=self.Compressor.W+self.Evaporator.Fins.Air.FanPower+self.Condenser.Fins.Air.FanPower self.COP=-self.Condenser.Q/self.Compressor.W self.COSP=self.Capacity/self.Power self.SHR=self.Evaporator.SHR self.DP_HighPressure=self.Condenser.DP_r+self.LineSetSupply.DP self.DP_LowPressure=self.Evaporator.DP_r+self.LineSetReturn.DP else: ValueError("DX Cycle mode must be 'AC', or 'HP'") if self.Verbosity>1: print 'DTevap %7.4f DTcond %7.4f Qres % 12.6e DTsc: % 12.6e Charge %10.4f SC: %8.4f' %(DT_evap,DT_cond,resid[0],resid[1],self.Charge,self.Condenser.DT_sc) self.DT_evap=DT_evap self.DT_cond=DT_cond return resid def PreconditionedSolve(self): """ Solver that will precondition by trying a range of DeltaT until the model can solve, then will kick into 2-D Newton Raphson solve The two input variables for the system solver are the differences in temperature between the inlet air temperature of the heat exchanger and the dew temperature of the refrigerant. This is important for refrigerant blends with temperature glide during constant-pressure evaporation or condensation. Good examples of common working fluid with glide would be R404A or R410A. """ def OBJECTIVE_DXCycle(x): """ A wrapper function to convert input vector for fsolve to the proper form for the solver """ try: resids=self.Calculate(DT_evap=float(x[0]),DT_cond=float(x[1]))#,DP_low=float(x[2]),DP_high=float(x[3])) except ValueError: raise return resids # Use the preconditioner to determine a reasonably good starting guess DT_evap_init,DT_cond_init=DXPreconditioner(self) GoodRun=False while GoodRun==False: try: self.DP_low=0 self.DP_high=0 DP_converged=False while DP_converged==False: #Actually run the Newton-Raphson solver to get the solution x=Broyden(OBJECTIVE_DXCycle,[DT_evap_init,DT_cond_init]) delta_low=abs(self.DP_low-abs(self.DP_LowPressure)/1000) delta_high=abs(self.DP_high-abs(self.DP_HighPressure)/1000) self.DP_low=abs(self.DP_LowPressure)/1000 self.DP_high=abs(self.DP_HighPressure)/1000 #Update the guess values based on last converged values DT_evap_init=self.DT_evap DT_cond_init=self.DT_cond if delta_low<1 and delta_high<1: DP_converged=True if self.Verbosity>4: print self.DP_HighPressure/1000,self.DP_LowPressure/1000,'DPHP' GoodRun=True except AttributeError: # This will be a fatal error !! Should never have attribute error raise except: print "-------------- Exception Caught ---------------- " print "Error of type",sys.exc_info()[0]," is: " + sys.exc_info()[1].message raise if self.Verbosity>0: print 'Capacity: ', self.Capacity print 'COP: ',self.COP print 'COP (w/ both fans): ',self.COSP print 'SHR: ',self.SHR print 'UA_r_evap',self.Evaporator.UA_r print 'UA_a_evap',self.Evaporator.UA_a print 'UA_r_cond',self.Condenser.UA_r print 'UA_a_cond',self.Condenser.UA_a
class SecondaryCycleClass(): def __init__(self): """ Load up the necessary sub-structures to be filled with the code that follows """ self.Compressor=CompressorClass() self.Condenser=CondenserClass() self.Condenser.Fins=FinInputs() self.CoolingCoil=CoolingCoilClass() self.CoolingCoil.Fins=FinInputs() self.PHEHX=PHEHXClass() self.Pump=PumpClass() def Calculate(self,DT_evap,DT_cond,Tin_IHX): """ Inputs are differences in temperature [K] between HX air inlet temperature and the dew temperature for the heat exchanger. Required Inputs: DT_evap: Difference in temperature [K] between cooling coil air inlet temperature and refrigerant dew temperature DT_cond: Difference in temperature [K] between condenser air inlet temperature and refrigeant dew temperature Tin_IHX: Inlet "glycol" temperature to IHX """ if self.Verbosity>1: print 'Inputs: DTevap %7.4f DTcond %7.4f fT_IHX %7.4f'%(DT_evap,DT_cond,Tin_IHX) #AbstractState if hasattr(self,'Backend'): #check if backend is given AS = CP.AbstractState(self.Backend, self.Ref) if hasattr(self,'MassFrac'): AS.set_mass_fractions([self.MassFrac]) else: #otherwise, use the defualt backend AS = CP.AbstractState('HEOS', self.Ref) self.Backend = 'HEOS' self.AS = AS #AbstractState for SecLoopFluid if hasattr(self,'Backend_SLF'): #check if backend_SLF is given AS_SLF = CP.AbstractState(self.Backend_SLF, self.SecLoopFluid) if hasattr(self,'MassFrac_SLF'): AS_SLF.set_mass_fractions([self.MassFrac_SLF]) else: #otherwise, use the defualt backend AS_SLF = CP.AbstractState('HEOS', self.SecLoopFluid) self.Backend_SLF = 'HEOS' self.AS_SLF = AS_SLF """ The coldest the glycol entering the cooling coil could be would be the """ self.Tdew_cond=self.Condenser.Fins.Air.Tdb+DT_cond self.Tdew_evap=self.CoolingCoil.Fins.Air.Tdb-DT_evap AS.update(CP.QT_INPUTS,1.0,self.Tdew_cond) psat_cond=AS.p() #[Pa] AS.update(CP.QT_INPUTS,1.0,self.Tdew_evap) psat_evap=AS.p() #[Pa] AS.update(CP.PQ_INPUTS,psat_evap,0.0) self.Tbubble_evap=AS.T() #[K] params={ #dictionary -> key:value, e.g. 'key':2345, 'pin_r': psat_evap, 'pout_r': psat_cond, 'Tin_r': self.Tdew_evap+self.Compressor.DT_sh, 'Ref': self.Ref, 'Backend': self.Backend } self.Compressor.Update(**params) self.Compressor.Calculate() params={ 'mdot_r': self.Compressor.mdot_r, 'Tin_r': self.Compressor.Tout_r, 'psat_r': psat_cond, 'Ref': self.Ref, 'Backend': self.Backend } self.Condenser.Update(**params) self.Condenser.Calculate() AS.update(CP.QT_INPUTS,0.0,self.Tbubble_evap) hL=AS.hmass() #[J/kg] AS.update(CP.QT_INPUTS,1.0,self.Tdew_evap) hV=AS.hmass() #[J/kg] xin_r=(self.Condenser.hout_r-hL)/(hV-hL) AS_SLF.update(CP.PT_INPUTS,300000,Tin_IHX) h_in = AS_SLF.hmass() #[J/kg] params={ 'mdot_h': self.Pump.mdot_g, 'hin_h': h_in, 'hin_c': self.Condenser.hout_r, 'mdot_c': self.Compressor.mdot_r, 'pin_c': psat_evap, 'xin_c': xin_r } self.PHEHX.Update(**params) self.PHEHX.Calculate() #Now run CoolingCoil to predict inlet glycol temperature to IHX params={ 'mdot_g': self.Pump.mdot_g, 'Tin_g': self.PHEHX.Tout_h, } self.CoolingCoil.Update(**params) self.CoolingCoil.Calculate() params={ 'DP_g': self.PHEHX.DP_h+self.CoolingCoil.DP_g, 'Tin_g': self.CoolingCoil.Tout_g } self.Pump.Update(**params) self.Pump.Calculate() self.Charge=self.Condenser.Charge+self.PHEHX.Charge_c self.EnergyBalance=self.Compressor.CycleEnergyIn+self.Condenser.Q+self.PHEHX.Q resid=np.zeros((3)) resid[0]=self.EnergyBalance if self.ImposedVariable=='Subcooling': resid[1]=self.Condenser.DT_sc-self.DT_sc_target elif self.ImposedVariable=='Charge': resid[1]=self.Charge-self.Charge_target resid[2]=self.PHEHX.Q-self.CoolingCoil.Q if self.Verbosity>1: print 'Qres % 12.6e Resid2: % 12.6e ResSL %10.4f Charge %10.4f SC: %8.4f' %(resid[0],resid[1],resid[2],self.Charge,self.Condenser.DT_sc) self.Capacity=self.CoolingCoil.Capacity self.COP=self.CoolingCoil.Q/self.Compressor.W self.COSP=self.CoolingCoil.Capacity/(self.Compressor.W+self.Pump.W+self.CoolingCoil.Fins.Air.FanPower+self.Condenser.Fins.Air.FanPower) self.SHR=self.CoolingCoil.SHR return resid def PreconditionedSolve(self): # Takes the place of a lambda function since lambda functions do not # bubble the error up properly def OBJECTIVE(x): return self.Calculate(x[0],x[1],x[2]) # Increase DT_evap in increments of 0.5 K until the system solves, and # two steps cause a sign change in cycle energy balance # Should give a starting point quite close to the "right" soluton oldDT_evap=None oldQresid=None Tin_IHX=None for DT_evap in np.linspace(12,25,21): try: #Run the cooler to get a good starting inlet temperature for IHX self.CoolingCoil.mdot_g=self.Pump.mdot_g self.CoolingCoil.Tin_g=self.CoolingCoil.Fins.Air.Tdb-DT_evap self.CoolingCoil.Calculate() Tin_IHX=self.CoolingCoil.Tout_g resid=self.Calculate(DT_evap,8,Tin_IHX) except Exception,e: if self.Verbosity>1: print 'Failed: ',e.__str__() raise pass else: #Not set yet, first one that works if oldQresid==None: oldQresid=resid[0] oldDT_evap=DT_evap #Has been set, and sign changes, use average of old and new DT elif oldQresid*resid[0]<0: DT_evap=(DT_evap+oldDT_evap)/2 break #Run the Newton-Raphson solver to solve the system x=fsolve(OBJECTIVE,[DT_evap,20,Tin_IHX]) if self.Verbosity>1: print 'Capacity: ', self.Capacity print 'COP: ',self.COP print 'COP (w/ both fans): ',self.COSP print 'SHR: ',self.SHR
class SecondaryCycleClass(): def __init__(self): """ Load up the necessary sub-structures to be filled with the code that follows """ self.Compressor=CompressorClass() #Outdoor coil is a Condenser in cooling mode and evaporator in heating mode self.Condenser=CondenserClass() self.Condenser.Fins=FinInputs() self.Evaporator=EvaporatorClass() self.Evaporator.Fins=FinInputs() self.CoolingCoil=CoolingCoilClass() self.CoolingCoil.Fins=FinInputs() self.Pump=PumpClass() #Add both types of internal heat exchangers self.CoaxialIHX=CoaxialHXClass() self.PHEIHX=PHEHXClass() self.LineSetSupply=LineSetClass() self.LineSetReturn=LineSetClass() #Make IHX an empty class for holding parameters common to PHE and Coaxial IHX class struct: pass self.IHX=struct() 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 [ ('Charge','kg',self.Charge), ('Condenser Subcooling','K',self.DT_sc), ('Primary Ref.','-',self.Ref), ('Secondary Ref.','-',self.SecLoopFluid), ('Imposed Variable','-',self.ImposedVariable), ('IHX Type','-',self.IHXType), ('COP','-',self.COP), ('COSP','-',self.COSP), ('Net Capacity','W',self.CoolingCoil.Capacity), ('Net Power','W',self.Power), ('SHR','-',self.SHR), ('Condensation temp (dew)','K',self.Tdew_cond), ('Evaporation temp (dew)','K',self.Tdew_evap), ] def Calculate(self,DT_evap,DT_cond,Tin_CC): """ Inputs are differences in temperature [K] between HX air inlet temperature and the dew temperature for the heat exchanger. Required Inputs: DT_evap: Difference in temperature [K] between cooling coil air inlet temperature and refrigerant dew temperature DT_cond: Difference in temperature [K] between condenser air inlet temperature and refrigerant dew temperature Tin_CC: Inlet "glycol" temperature to line set feeding cooling coil """ if self.Verbosity>1: print 'Inputs: DTevap %7.4f DTcond %7.4f fT_IHX %7.4f'%(DT_evap,DT_cond,Tin_CC) #Store the values to save on computation for later self.DT_evap=DT_evap self.DT_cond=DT_cond self.Tin_CC=Tin_CC #If the user doesn't include the Mode, set it to Air Conditioning if not hasattr(self,'Mode'): self.Mode='AC' if self.Mode=='AC': self.Tdew_cond=self.Condenser.Fins.Air.Tdb+DT_cond self.Tdew_evap=self.CoolingCoil.Fins.Air.Tdb-DT_evap elif self.Mode=='HP': self.Tdew_cond=Tin_CC+DT_cond self.Tdew_evap=self.Evaporator.Fins.Air.Tdb-DT_evap else: raise ValueError('Mode must be AC or HP') psat_cond=Props('P','T',self.Tdew_cond,'Q',1,self.Ref) psat_evap=Props('P','T',self.Tdew_evap,'Q',1,self.Ref) self.Tbubble_evap=Props('T','P',psat_evap,'Q',0,self.Ref) self.Tbubble_cond=Props('T','P',psat_cond,'Q',0,self.Ref) if self.Mode=='AC': params={ #dictionary -> key:value, e.g. 'key':2345, 'pin_r': psat_evap+self.DP_low, 'pout_r': psat_cond-self.DP_high, 'Tin_r': self.Tdew_evap+self.PHEIHX.DT_sh, # TrhoPhase_ph(self.Ref,psat_evap,self.LineSetReturn.hout,self.Tbubble_evap,self.Tdew_evap)[0], 'Ref': self.Ref } self.Compressor.Update(**params) self.Compressor.Calculate() params={ 'mdot_r': self.Compressor.mdot_r, 'Tin_r': self.Compressor.Tout_r, 'psat_r': psat_cond, 'Ref': self.Ref } self.Condenser.Update(**params) self.Condenser.Calculate() params={ 'mdot': self.Pump.mdot_g, 'hin': Props('H','T',Tin_CC,'P',self.Pump.pin_g,self.SecLoopFluid)*1000, } self.LineSetSupply.Update(**params) self.LineSetSupply.Calculate() #Now run CoolingCoil to predict inlet glycol temperature to IHX params={ 'mdot_g': self.Pump.mdot_g, 'Tin_g': self.LineSetSupply.Tout, } self.CoolingCoil.Update(**params) self.CoolingCoil.Calculate() params={ 'mdot': self.Pump.mdot_g, 'hin': Props('H','T',self.CoolingCoil.Tout_g,'P',self.Pump.pin_g,self.SecLoopFluid)*1000, } self.LineSetReturn.Update(**params) self.LineSetReturn.Calculate() if self.IHXType=='Coaxial': params={ 'mdot_g': self.Pump.mdot_g, 'Tin_g': self.CoolingCoil.Tout_g, 'pin_r': psat_evap, 'hin_r': self.Condenser.hout_r, 'Ref_r': self.Ref, 'mdot_r': self.Compressor.mdot_r, } self.CoaxialIHX.Update(**params) self.CoaxialIHX.Calculate() self.IHX.Charge_r=self.CoaxialIHX.Charge_r self.IHX.Q=self.CoaxialIHX.Q self.IHX.Tout_g=self.CoaxialIHX.Tout_g self.IHX.DP_g=self.CoaxialIHX.DP_g self.IHX.hout_r=self.CoaxialIHX.hout_r self.IHX.DP_r=self.CoaxialIHX.DP_r if hasattr(self,'PHEIHX'): del self.PHEIHX elif self.IHXType=='PHE': params={ 'mdot_h': self.Pump.mdot_g, 'hin_h': Props('H','T',self.CoolingCoil.Tout_g,'P',self.PHEIHX.pin_h,self.SecLoopFluid)*1000, 'mdot_c': self.Compressor.mdot_r, 'pin_c': psat_evap, 'hin_c': self.Condenser.hout_r, } self.PHEIHX.Update(**params) self.PHEIHX.Calculate() self.IHX.Charge_r=self.PHEIHX.Charge_c self.IHX.Q=self.PHEIHX.Q self.IHX.Tout_g=self.PHEIHX.Tout_h self.IHX.DP_g=self.PHEIHX.DP_h self.IHX.DP_r=self.PHEIHX.DP_c self.IHX.hout_r=self.PHEIHX.hout_c if hasattr(self,'CoaxialIHX'): del self.CoaxialIHX params={ 'DP_g': self.IHX.DP_g+self.CoolingCoil.DP_g+self.LineSetSupply.DP+self.LineSetReturn.DP, 'Tin_g': self.CoolingCoil.Tout_g } self.Pump.Update(**params) self.Pump.Calculate() self.Charge=self.Condenser.Charge+self.IHX.Charge_r self.EnergyBalance=self.Compressor.CycleEnergyIn+self.Condenser.Q+self.IHX.Q self.DT_sc=(Props('H','T',self.Tbubble_cond,'Q',0,self.Ref)*1000-self.Condenser.hout_r)/(Props('C','T',self.Tbubble_cond,'Q',0,self.Ref)*1000) deltaH_sc=self.Compressor.mdot_r*(Props('H','T',self.Tbubble_cond,'Q',0,self.Ref)*1000-Props('H','T',self.Tbubble_cond-self.DT_sc_target,'P',psat_cond,self.Ref)*1000) # ## Plot a p-h plot # Ph(self.Ref,hbounds=(100,500)) # pylab.plot([self.Compressor.hin_r/1000,self.Compressor.hout_r/1000,self.Condenser.hout_r/1000,self.PHEIHX.hin_c/1000,self.Compressor.hin_r/1000],[psat_evap,psat_cond,psat_cond,psat_evap,psat_evap]) # pylab.show() resid=np.zeros((3)) resid[0]=self.Compressor.mdot_r*(self.Compressor.hin_r-self.IHX.hout_r) if self.ImposedVariable=='Subcooling': resid[1]=self.Condenser.DT_sc-self.DT_sc_target elif self.ImposedVariable=='Charge': resid[1]=self.Charge-self.Charge_target # resid[2]=self.IHX.Q-self.CoolingCoil.Q+self.Pump.W self.residSL=self.IHX.Q-self.CoolingCoil.Q+self.Pump.W+self.LineSetSupply.Q+self.LineSetReturn.Q resid[2]=self.residSL if self.Verbosity>7: print 'Wcomp % 12.6e Qcond: % 12.6e QPHE %10.4f ' %(self.Compressor.W,self.Condenser.Q,self.IHX.Q) if self.Verbosity>1: print 'Qres % 12.6e Resid2: % 12.6e ResSL %10.4f Charge %10.4f SC: %8.4f' %(resid[0],resid[1],self.residSL,self.Charge,self.Condenser.DT_sc) self.Capacity=self.CoolingCoil.Capacity self.COP=self.CoolingCoil.Q/self.Compressor.W self.COSP=self.CoolingCoil.Capacity/(self.Compressor.W+self.Pump.W+self.CoolingCoil.Fins.Air.FanPower+self.Condenser.Fins.Air.FanPower) self.SHR=self.CoolingCoil.SHR self.Power=self.Compressor.W+self.Pump.W+self.CoolingCoil.Fins.Air.FanPower+self.Condenser.Fins.Air.FanPower self.DP_high_Model=self.Condenser.DP_r #[Pa] self.DP_low_Model=self.IHX.DP_r #[Pa] elif self.Mode=='HP': if psat_evap+self.DP_low<0: raise ValueError('Compressor inlet pressure less than zero ['+str(psat_evap+self.DP_low)+' kPa] - is low side pressure drop too high?') params={ #dictionary -> key:value, e.g. 'key':2345, 'pin_r': psat_evap+self.DP_low, 'pout_r': psat_cond-self.DP_high, 'Tin_r': self.Tdew_evap+self.Evaporator.DT_sh, # TrhoPhase_ph(self.Ref,psat_evap,self.LineSetReturn.hout,self.Tbubble_evap,self.Tdew_evap)[0], 'Ref': self.Ref } self.Compressor.Update(**params) self.Compressor.Calculate() params={ 'mdot': self.Pump.mdot_g, 'hin': Props('H','T',Tin_CC,'P',self.Pump.pin_g,self.SecLoopFluid)*1000, } self.LineSetSupply.Update(**params) self.LineSetSupply.Calculate() #Now run CoolingCoil to predict inlet glycol temperature to IHX params={ 'mdot_g': self.Pump.mdot_g, 'Tin_g': self.LineSetSupply.Tout, } self.CoolingCoil.Update(**params) self.CoolingCoil.Calculate() params={ 'mdot': self.Pump.mdot_g, 'hin': Props('H','T',self.CoolingCoil.Tout_g,'P',self.Pump.pin_g,self.SecLoopFluid)*1000, } self.LineSetReturn.Update(**params) self.LineSetReturn.Calculate() params={ 'mdot_h': self.Compressor.mdot_r, 'hin_h': self.Compressor.hout_r, 'pin_h': psat_cond, 'mdot_c': self.Pump.mdot_g, 'hin_c': Props('H','T',self.LineSetReturn.Tout,'P',self.PHEIHX.pin_c,self.SecLoopFluid)*1000, } self.PHEIHX.Update(**params) self.PHEIHX.Calculate() params={ 'mdot_r': self.Compressor.mdot_r, 'psat_r': psat_evap, 'hin_r': self.PHEIHX.hout_h, 'Ref': self.Ref } self.Evaporator.Update(**params) self.Evaporator.Calculate() params={ 'DP_g': self.PHEIHX.DP_c+self.CoolingCoil.DP_g, 'Tin_g': self.CoolingCoil.Tout_g } self.Pump.Update(**params) self.Pump.Calculate() self.Charge=self.Evaporator.Charge+self.PHEIHX.Charge_h #Calculate an effective subcooling amount by deltah/cp_satL #Can be positive or negative (negative is quality at outlet self.DT_sc=self.PHEIHX.DT_sc_h#(Props('H','T',self.Tbubble_cond,'Q',0,self.Ref)*1000-self.PHEIHX.hout_h)/(Props('C','T',self.Tbubble_cond,'Q',0,self.Ref)*1000) deltaH_sc=self.Compressor.mdot_r*(Props('H','T',self.Tbubble_cond,'Q',0,self.Ref)*1000-Props('H','T',self.Tbubble_cond-self.DT_sc_target,'P',psat_cond,self.Ref)*1000) resid=np.zeros((3)) resid[0]=self.Compressor.mdot_r*(self.Compressor.hin_r-self.Evaporator.hout_r) if self.ImposedVariable=='Subcooling': resid[1]=self.DT_sc-self.DT_sc_target elif self.ImposedVariable=='Charge': resid[1]=self.Charge-self.Charge_target self.residSL=self.PHEIHX.Q+self.CoolingCoil.Q+self.Pump.W+self.LineSetSupply.Q+self.LineSetReturn.Q resid[2]=self.residSL if self.Verbosity>1: print 'Qres % 12.6e Resid2: % 12.6e ResSL %10.4f Charge %10.4f SC: %8.4f' %(resid[0],resid[1],self.residSL,self.Charge,self.DT_sc) self.Capacity=-self.CoolingCoil.Q+self.CoolingCoil.Fins.Air.FanPower self.COP=-self.CoolingCoil.Q/self.Compressor.W self.COSP=self.Capacity/(self.Compressor.W+self.Pump.W+self.CoolingCoil.Fins.Air.FanPower+self.Evaporator.Fins.Air.FanPower) self.Power=self.Compressor.W+self.Pump.W+self.CoolingCoil.Fins.Air.FanPower+self.Evaporator.Fins.Air.FanPower self.SHR=-self.CoolingCoil.SHR self.DP_high_Model=self.PHEIHX.DP_h #[Pa] self.DP_low_Model=self.Evaporator.DP_r #[Pa] self.DT_evap=DT_evap self.DT_cond=DT_cond return resid def PreconditionedSolve(self,PrecondValues=None): ''' PrecondValues = dictionary of values DT_evap, DT_cond and Tin_CC ''' def OBJECTIVE(x): """ Takes the place of a lambda function since lambda functions do not bubble error properly """ return self.Calculate(x[0],x[1],x[2]) def OBJECTIVE2(x,Tin): """ Takes the place of a lambda function since lambda functions do not bubble error properly """ return self.Calculate(x[0],x[1],Tin) def OBJECTIVE_SL(Tin_CC): """ Objective function for the inner loop of the vapor compression system Using the MultiDimNewtRaph function will re-evaluate the Jacobian at every step. Slower, but more robust since the solution surfaces aren't smooth enough Note: This function is not currently used! """ x=MultiDimNewtRaph(OBJECTIVE2,[self.DT_evap,self.DT_cond],args=(Tin_CC,)) # Update the guess values for Delta Ts starting # at the third step (after at least one update away # from the boundaries) if self.OBJ_SL_counter>=0: self.DT_evap=x[0] self.DT_cond=x[1] pass self.OBJ_SL_counter+=1 return self.residSL def PrintDPs(): print 'DP_LP :: Input:',self.DP_low,'kPa / Model calc:',self.DP_low_Model/1000,'kPa' print 'DP_HP :: Input:',self.DP_high,'kPa / Model calc:',self.DP_high_Model/1000,'kPa' #Some variables need to be initialized self.DP_low=0 #The actual low-side pressure drop to be used in kPa self.DP_high=0 #The actual low-side pressure drop to be used in kPa self.OBJ_SL_counter=0 #Run the preconditioner to get guess values for the temperatures if PrecondValues is None: self.DT_evap,self.DT_cond,Tin_CC=SecondaryLoopPreconditioner(self) else: self.DT_evap=PrecondValues['DT_evap'] self.DT_cond=PrecondValues['DT_cond'] Tin_CC=PrecondValues['Tin_CC'] #Remove the other, non-used IHX class if found if self.IHXType=='PHE': if hasattr(self,'CoaxialIHX'): del self.CoaxialIHX else: if hasattr(self,'PHEIHX'): del self.PHEIHX #Remove the condenser if in heating mode and condenser found if self.Mode=='HP': if hasattr(self,'Condenser'): del self.Condenser iter=1 max_error_DP=999 #Outer loop with a more relaxed convergence criterion while max_error_DP>0.5: iter_inner=1 #Inner loop to determine pressure drop for high and low sides while max_error_DP>0.05 and iter_inner<10: #Run to calculate the pressure drop as starting point OBJECTIVE([self.DT_evap,self.DT_cond,Tin_CC]) #Calculate the max error max_error_DP=max([abs(self.DP_low_Model/1000-self.DP_low),abs(self.DP_high_Model/1000-self.DP_high)]) if self.Verbosity>0: PrintDPs() print 'Max pressure drop error [inner loop] is',max_error_DP,'kPa' #Update the pressure drop terms self.DP_low=self.DP_low_Model/1000 self.DP_high=self.DP_high_Model/1000 iter_inner+=1 if self.Verbosity > 0: print "Done with the inner loop on pressure drop" # Use Newton-Raphson solver (self.DT_evap,self.DT_cond,Tin_CC)=MultiDimNewtRaph(OBJECTIVE,[self.DT_evap,self.DT_cond,Tin_CC],dx=0.1) #Calculate the error max_error_DP=max([abs(self.DP_low_Model/1000-self.DP_low),abs(self.DP_high_Model/1000-self.DP_high)]) if self.Verbosity>0: PrintDPs() print 'Max pressure drop error [outer loop] is',max_error_DP,'kPa' if self.Verbosity>1: print 'Capacity: ', self.Capacity print 'COP: ',self.COP print 'COP (w/ both fans): ',self.COSP print 'SHR: ',self.SHR return
from Compressor import CompressorClass from CoolProp.CoolProp import Props kwds = { 'M': [ 217.3163128, 5.094492028, -0.593170311, 4.38E-02, -2.14E-02, 1.04E-02, 7.90E-05, -5.73E-05, 1.79E-04, -8.08E-05 ], 'P': [ -561.3615705, -15.62601841, 46.92506685, -0.217949552, 0.435062616, -0.442400826, 2.25E-04, 2.37E-03, -3.32E-03, 2.50E-03 ], 'Ref': 'R134a', 'Tin_r': 280, 'pin_r': Props('P', 'T', 279, 'Q', 1, 'R134a'), 'pout_r': Props('P', 'T', 315, 'Q', 1, 'R134a'), 'fp': 0.15, #Fraction of electrical power lost as heat to ambient 'Vdot_ratio': 1.0 #Displacement Scale factor } Comp = CompressorClass(**kwds) Comp.Calculate() print 'Electrical power is: ' + str(Comp.W) + ' W' print 'Actual mass flow rate is: ' + str(Comp.mdot_r) + ' kg/s'