Exemple #1
0
    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()
Exemple #2
0
 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()
Exemple #3
0
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
Exemple #4
0
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