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.CoolingCoil = CoolingCoilClass() self.CoolingCoil.Fins = FinInputs() self.Pump = PumpClass() #Add both types of internal heat exchangers self.CoaxialIHX = CoaxialHXClass() self.PHEIHX = PHEHXClass() self.LineSetSupply = LineSetOptionClass() self.LineSetReturn = LineSetOptionClass() self.LineSetSuction = LineSetOptionClass() self.LineSetDischarge = LineSetOptionClass() self.LineSetLiquid = LineSetOptionClass() #Make IHX an empty class for holding parameters common to PHE and Coaxial IHX class struct: pass self.IHX = struct()
def __init__(self): """ Load up the necessary sub-structures to be filled with the code that follows """ self.Compressor = CompressorClass() self.CoolingCoil = CoolingCoilClass() self.CoolingCoil.Fins = FinInputs() self.PHEHX = PHEHXClass() self.Pump = PumpClass()
FinsTubes.Fins.Pd = 0.001 FinsTubes.Fins.xf = 0.001 FinsTubes.Fins.t = 0.00011 FinsTubes.Fins.k_fin = 237 FinsTubes.Air.Vdot_ha = 0.5663 FinsTubes.Air.Tmean = 299.8 FinsTubes.Air.Tdb = 299.8 FinsTubes.Air.p = 101325 #Air pressure in Pa FinsTubes.Air.RH = 0.51 FinsTubes.Air.RHmean = 0.51 FinsTubes.Air.FanPower = 438 #fan power in Watts # Here are two equivalent methods for setting parameters # 1. Create an empty instance of the class, then set parameters CC=CoolingCoilClass() CC = CoolingCoilClass() CC.Fins = FinsTubes CC.FinsType = 'WavyLouveredFins' #Choose fin Type: 'WavyLouveredFins' or 'HerringboneFins'or 'PlainFins' CC.Ref_g = 'Water' CC.mdot_g = 0.15 CC.Tin_g = 278 CC.pin_g = 300000 #Refrigerant vapor pressure in Pa CC.Verbosity = 3 CC.Calculate() print "Method 1:" print "Cooling Coil Q: " + str(CC.Q) + " W" print "Cooling Coil SHR: " + str(CC.SHR) + " " # 2. Build a dictionary of values, then use that to initialize the class kwds = {
class SecondaryCycleClass(): def __init__(self): """ Load up the necessary sub-structures to be filled with the code that follows """ self.Compressor = CompressorClass() self.CoolingCoil = CoolingCoilClass() self.CoolingCoil.Fins = FinInputs() self.PHEHX = PHEHXClass() self.Pump = PumpClass() def Update(self): ''' Update cycle class with selected HX type Update cyle class with Abstract State ''' if self.EvapSolver == 'Moving-Boundary': if self.EvapType == 'Fin-tube': self.Evaporator = EvaporatorClass() self.Evaporator.Fins = FinInputs() elif self.EvapType == 'Micro-channel': raise else: raise elif self.EvapSolver == 'Finite-Element': raise else: raise if self.CondSolver == 'Moving-Boundary': if self.CondType == 'Fin-tube': self.Condenser = CondenserClass() self.Condenser.Fins = FinInputs() elif self.CondType == 'Micro-channel': self.Condenser = MicroCondenserClass() self.Condenser.Fins = MicroFinInputs() else: raise elif self.CondSolver == 'Finite-Element': raise else: raise #Abstract State self.AS = CP.AbstractState(self.Backend, self.Ref) if hasattr(self, 'MassFrac'): self.AS.set_mass_fractions([self.MassFrac]) elif hasattr(self, 'VoluFrac'): self.AS.set_volu_fractions([self.VoluFrac]) #Abstract State for SecLoopFluid self.AS_SLF = CP.AbstractState(self.Backend_SLF, self.SecLoopFluid) if hasattr(self, 'MassFrac_SLF'): self.AS_SLF.set_mass_fractions([self.MassFrac_SLF]) elif hasattr(self, 'VoluFrac_SLF'): self.AS_SLF.set_volu_fractions([self.VoluFrac_SLF]) 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 AS = self.AS #AbstractState for SecLoopFluid AS_SLF = self.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, 'AS': AS, } self.Compressor.Update(**params) self.Compressor.Calculate() params = { 'mdot_r': self.Compressor.mdot_r, 'Tin_r': self.Compressor.Tout_r, 'psat_r': psat_cond, 'AS': AS, } 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, 'AS_c': AS, 'AS_h': AS_SLF, } 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, 'AS_g': AS_SLF, } self.CoolingCoil.Update(**params) self.CoolingCoil.Calculate() params = { 'DP_g': self.PHEHX.DP_h + self.CoolingCoil.DP_g, 'Tin_g': self.CoolingCoil.Tout_g, 'AS_g': AS_SLF, } 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.AS_g = self.AS_SLF 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)
FinsTubes.Fins.Pd=0.001 FinsTubes.Fins.xf=0.001 FinsTubes.Fins.t=0.00011 FinsTubes.Fins.k_fin=237 FinsTubes.Air.Vdot_ha=0.5663 FinsTubes.Air.Tmean=299.8 FinsTubes.Air.Tdb= 299.8 FinsTubes.Air.p=101325 #Air pressure in Pa FinsTubes.Air.RH=0.51 FinsTubes.Air.RHmean=0.51 FinsTubes.Air.FanPower=438 #fan power in Watts # Here are two equivalent methods for setting parameters # 1. Create an empty instance of the class, then set parameters CC=CoolingCoilClass() CC=CoolingCoilClass() CC.Fins = FinsTubes CC.FinsType = 'WavyLouveredFins' #Choose fin Type: 'WavyLouveredFins' or 'HerringboneFins'or 'PlainFins' CC.Ref_g = 'Water' CC.mdot_g = 0.15 CC.Tin_g = 278 CC.pin_g = 300000 #Refrigerant vapor pressure in Pa CC.Verbosity = 3 CC.Calculate() print "Method 1:" print "Cooling Coil Q: " + str(CC.Q) + " W" print "Cooling Coil SHR: " + str(CC.SHR) + " " # 2. Build a dictionary of values, then use that to initialize the class kwds={'Fins':FinsTubes,
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.CoolingCoil = CoolingCoilClass() self.CoolingCoil.Fins = FinInputs() self.Pump = PumpClass() #Add both types of internal heat exchangers self.CoaxialIHX = CoaxialHXClass() self.PHEIHX = PHEHXClass() self.LineSetSupply = LineSetOptionClass() self.LineSetReturn = LineSetOptionClass() self.LineSetSuction = LineSetOptionClass() self.LineSetDischarge = LineSetOptionClass() self.LineSetLiquid = LineSetOptionClass() #Make IHX an empty class for holding parameters common to PHE and Coaxial IHX class struct: pass self.IHX = struct() def Update(self): ''' Update cycle class with selected HX type Update cycle class with Abstract State ''' if self.EvapSolver == 'Moving-Boundary': if self.EvapType == 'Fin-tube': self.Evaporator = EvaporatorClass() self.Evaporator.Fins = FinInputs() elif self.EvapType == 'Micro-channel': raise else: raise elif self.EvapSolver == 'Finite-Element': raise else: raise if self.CondSolver == 'Moving-Boundary': if self.CondType == 'Fin-tube': self.Condenser = CondenserClass() self.Condenser.Fins = FinInputs() elif self.CondType == 'Micro-channel': self.Condenser = MicroCondenserClass() self.Condenser.Fins = MicroFinInputs() else: raise elif self.CondSolver == 'Finite-Element': raise else: raise #Abstract State self.AS = CP.AbstractState(self.Backend, self.Ref) if hasattr(self, 'MassFrac'): self.AS.set_mass_fractions([self.MassFrac]) elif hasattr(self, 'VoluFrac'): self.AS.set_volu_fractions([self.VoluFrac]) #Abstract State for SecLoopFluid self.AS_SLF = CP.AbstractState(self.Backend_SLF, self.SecLoopFluid) if hasattr(self, 'MassFrac_SLF'): self.AS_SLF.set_mass_fractions([self.MassFrac_SLF]) elif hasattr(self, 'VoluFrac_SLF'): self.AS_SLF.set_volu_fractions([self.VoluFrac_SLF]) 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)) #AbstractState AS = self.AS #AbstractState for SecLoopFluid AS_SLF = self.AS_SLF #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') #Evaporator and condeser saturation pressures 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] #Evaporator and condeser bubble temepratures AS.update(CP.PQ_INPUTS, psat_evap, 0.0) self.Tbubble_evap = AS.T() #[K] AS.update(CP.PQ_INPUTS, psat_cond, 0.0) self.Tbubble_cond = AS.T() #[K] #Cycle solver for 'AC' 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': self.Tdew_evap+self.DT_sh, 'AS': AS, } self.Compressor.Update(**params) self.Compressor.Calculate() #Calculate inlet enthalpy AS.update(CP.PT_INPUTS, psat_evap, self.Tdew_evap + self.DT_sh) h_in = AS.hmass() #[J/kg] params = { 'Tin': self.Tdew_evap + self.DT_sh, 'pin': psat_evap, 'hin': h_in, 'mdot': self.Compressor.mdot_r, 'AS': AS, 'Name': 'Suction Line' } self.LineSetSuction.Update(**params) self.LineSetSuction.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.AS, psat_evap, self.LineSetSuction.hout, self.Tbubble_evap, self.Tdew_evap)[0], 'AS': AS } self.Compressor.Update(**params) self.Compressor.Calculate() params = { 'Tin': self.Compressor.Tout_r, 'pin': psat_cond, 'hin': self.Compressor.hout_r, 'mdot': self.Compressor.mdot_r, 'AS': AS, 'Name': 'Discharge Line' } self.LineSetDischarge.Update(**params) self.LineSetDischarge.Calculate() params = { 'mdot_r': self.Compressor.mdot_r, 'Tin_r': self.Compressor.Tout_r, 'psat_r': psat_cond, 'AS': AS, #'Oil': self.Oil, #'shell_pressure':self.shell_pressure, } self.Condenser.Update(**params) self.Condenser.Calculate() params = { 'Tin': self.Condenser.Tout_r, 'pin': psat_cond, 'hin': self.Condenser.hout_r, 'mdot': self.Compressor.mdot_r, 'AS': AS, 'Name': 'Liquid Line' } self.LineSetLiquid.Update(**params) self.LineSetLiquid.Calculate() #Inlet enthalpy to LineSetSupply AS_SLF.update(CP.PT_INPUTS, self.Pump.pin_g, Tin_CC) h_in_LineSetSupply = AS_SLF.hmass() #[J/kg] params = { 'Tin': Tin_CC, 'mdot': self.Pump.mdot_g, 'hin': h_in_LineSetSupply, 'pin': self.Pump.pin_g, 'AS': AS_SLF, 'Name': 'Supply Line' } 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, 'pin_g': self.CoolingCoil.pin_g, 'AS_g': AS_SLF } self.CoolingCoil.Update(**params) self.CoolingCoil.Calculate() #Inlet enthalpy to LineSetReturn AS_SLF.update(CP.PT_INPUTS, self.Pump.pin_g, self.CoolingCoil.Tout_g) h_in_LineSetReturn = AS_SLF.hmass() #[J/kg] params = { 'Tin': self.CoolingCoil.Tout_g, 'mdot': self.Pump.mdot_g, 'hin': h_in_LineSetReturn, 'pin': self.CoolingCoil.pin_g, 'AS': AS_SLF, 'Name': 'Return Line' } 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_g': self.Pump.pin_g, 'AS_g': AS_SLF, 'pin_r': psat_evap, 'hin_r': self.LineSetLiquid.hout, 'AS_r': AS, '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.Tout_r = self.CoaxialIHX.Tout_r self.IHX.DP_r = self.CoaxialIHX.DP_r if hasattr(self, 'PHEIHX'): del self.PHEIHX elif self.IHXType == 'PHE': #Inlet enthalpy to PHEIHX AS_SLF.update(CP.PT_INPUTS, self.PHEIHX.pin_h, self.CoolingCoil.Tout_g) h_in_PHEIHX = AS_SLF.hmass() #[J/kg] params = { 'mdot_h': self.Pump.mdot_g, 'hin_h': h_in_PHEIHX, 'pin_h': self.PHEIHX.pin_h, 'AS_h': AS_SLF, 'mdot_c': self.Compressor.mdot_r, 'pin_c': psat_evap, 'hin_c': self.LineSetLiquid.hout, 'AS_c': AS } 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 self.IHX.Tout_r = self.PHEIHX.Tout_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, 'pin_g': self.Pump.pin_g, 'AS_g': AS_SLF, } self.Pump.Update(**params) self.Pump.Calculate() self.Charge = self.Compressor.Charge + self.Condenser.Charge + self.IHX.Charge_r + self.LineSetSuction.Charge + self.LineSetDischarge.Charge + self.LineSetLiquid.Charge self.EnergyBalance = self.Compressor.CycleEnergyIn + self.Condenser.Q + self.IHX.Q + self.LineSetSuction.Q + self.LineSetDischarge.Q + self.LineSetLiquid.Q #Calculate properties: AS.update(CP.QT_INPUTS, 0.0, self.Tbubble_cond) h_L = AS.hmass() #[J/kg] cp_L = AS.cpmass() #[J/kg-K] AS.update(CP.PT_INPUTS, psat_cond, self.Tbubble_cond - self.DT_sc_target) h_target = AS.hmass() #[J/kg] self.DT_sc = (h_L - self.Condenser.hout_r) / cp_L deltaH_sc = self.Compressor.mdot_r * (h_L - h_target) resid = np.zeros((3)) resid[0] = self.Compressor.mdot_r * (self.IHX.hout_r - self.LineSetSuction.hin) 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 + self.LineSetDischarge.DP + self.LineSetLiquid.DP #[Pa] self.DP_low_Model = self.IHX.DP_r + self.LineSetSuction.DP #[Pa] #Cycle solver for 'HP' mode 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) + ' Pa] - is low side pressure drop too high?') 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': self.Tdew_evap+self.DT_sh, 'AS': AS, } self.Compressor.Update(**params) self.Compressor.Calculate() #Calculate inlet enthalpy AS.update(CP.PT_INPUTS, psat_evap, self.Tdew_evap + self.DT_sh) h_in = AS.hmass() #[J/kg] params = { 'Tin': self.Tdew_evap + self.DT_sh, 'pin': psat_evap, 'hin': h_in, 'mdot': self.Compressor.mdot_r, 'AS': AS, 'Name': 'Suction Line' } self.LineSetSuction.Update(**params) self.LineSetSuction.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.AS, psat_evap, self.LineSetSuction.hout, self.Tbubble_evap, self.Tdew_evap)[0], 'AS': AS } self.Compressor.Update(**params) self.Compressor.Calculate() params = { 'Tin': self.Compressor.Tout_r, 'pin': psat_cond, 'hin': self.Compressor.hout_r, 'mdot': self.Compressor.mdot_r, 'AS': AS, 'Name': 'Discharge Line' } self.LineSetDischarge.Update(**params) self.LineSetDischarge.Calculate() #Inlet enthalpy to LineSetSupply AS_SLF.update(CP.PT_INPUTS, self.Pump.pin_g, Tin_CC) h_in_LineSetSupply = AS_SLF.hmass() #[J/kg] params = { 'Tin': Tin_CC, 'mdot': self.Pump.mdot_g, 'hin': h_in_LineSetSupply, 'AS': AS_SLF, 'Name': 'Supply Line' } 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, 'pin_g': self.PHEIHX.pin_c, 'AS_g': AS_SLF } self.CoolingCoil.Update(**params) self.CoolingCoil.Calculate() #Inlet enthalpy to LineSetReturn AS_SLF.update(CP.PT_INPUTS, self.Pump.pin_g, self.CoolingCoil.Tout_g) h_in_LineSetReturn = AS_SLF.hmass() #[J/kg] params = { 'Tin': self.CoolingCoil.Tout_g, 'mdot': self.Pump.mdot_g, 'hin': h_in_LineSetReturn, 'AS': AS_SLF, 'Name': 'Return Line' } self.LineSetReturn.Update(**params) self.LineSetReturn.Calculate() #Inlet enthalpy to PHEIHX AS_SLF.update(CP.PT_INPUTS, self.PHEIHX.pin_c, self.LineSetReturn.Tout) h_in_PHEIHX = AS_SLF.hmass() #[J/kg] params = { 'mdot_h': self.Compressor.mdot_r, 'hin_h': self.LineSetDischarge.hout, 'pin_h': psat_cond, 'AS_h': AS, 'mdot_c': self.Pump.mdot_g, 'hin_c': h_in_PHEIHX, 'pin_c': self.Pump.pin_g, 'AS_c': AS_SLF, } self.PHEIHX.Update(**params) self.PHEIHX.Calculate() params = { 'Tin': self.PHEIHX.Tout_h, 'pin': psat_cond, 'hin': self.PHEIHX.hout_h, 'mdot': self.Compressor.mdot_r, 'AS': AS, 'Name': 'Liquid Line' } self.LineSetLiquid.Update(**params) self.LineSetLiquid.Calculate() params = { 'mdot_r': self.Compressor.mdot_r, 'psat_r': psat_evap, 'hin_r': self.LineSetLiquid.hout, 'AS': AS, } self.Evaporator.Update(**params) self.Evaporator.Calculate() params = { 'DP_g': self.PHEIHX.DP_c + self.CoolingCoil.DP_g + self.LineSetSupply.DP + self.LineSetReturn.DP, 'Tin_g': self.CoolingCoil.Tout_g, 'pin_g': self.Pump.pin_g, 'AS_g': AS_SLF } self.Pump.Update(**params) self.Pump.Calculate() self.Charge = self.Compressor.Charge + self.Evaporator.Charge + self.PHEIHX.Charge_h + self.LineSetSuction.Charge + self.LineSetDischarge.Charge + self.LineSetLiquid.Charge #Calculate properties: AS.update(CP.QT_INPUTS, 0.0, self.Tbubble_cond) h_L = AS.hmass() #[J/kg] cp_L = AS.cpmass() #[J/kg-K] AS.update(CP.PT_INPUTS, psat_cond, self.Tbubble_cond - self.DT_sc_target) h_target = AS.hmass() #[J/kg] #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 #(PropsSI('H','T',self.Tbubble_cond,'Q',0,self.Ref)-self.PHEIHX.hout_h)/(PropsSI('C','T',self.Tbubble_cond,'Q',0,self.Ref)) #*1000 #*1000 deltaH_sc = self.Compressor.mdot_r * (h_L - h_target) resid = np.zeros((3)) resid[0] = self.Compressor.mdot_r * (self.Evaporator.hout_r - self.LineSetSuction.hin) 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 + self.LineSetDischarge.DP + self.LineSetLiquid.DP #[Pa] self.DP_low_Model = self.Evaporator.DP_r + self.LineSetSuction.DP #[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, 'Pa / Model calc:', self.DP_low_Model, 'Pa') print('DP_HP :: Input:', self.DP_high, 'Pa / Model calc:', self.DP_high_Model, 'Pa') #Some variables need to be initialized self.DP_low = 0 #The actual low-side pressure drop to be used in Pa self.DP_high = 0 #The actual low-side pressure drop to be used in Pa 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 - self.DP_low), abs(self.DP_high_Model - self.DP_high) ]) if self.Verbosity > 0: PrintDPs() print('Max pressure drop error [inner loop] is', max_error_DP, 'Pa') #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 - self.DP_low), abs(self.DP_high_Model - self.DP_high) ]) if self.Verbosity > 0: PrintDPs() print('Max pressure drop error [outer loop] is', max_error_DP, 'Pa') if self.Verbosity > 1: print('Capacity: ', self.Capacity) print('COP: ', self.COP) print('COP (w/ both fans): ', self.COSP) print('SHR: ', self.SHR) print('-------------------------------------') print(' Simulation Completed ') print('-------------------------------------') return