예제 #1
0
    def calculable(self):
        """Check in the class is fully defined"""
        # Check mix state
        self._multicomponent = False
        if len(self.kwargs["ids"]) > 1:
            self._multicomponent = True

        # Check supported fluid
        COOLPROP_available = True
        for id in self.kwargs["ids"]:
            if id not in __all__ and id not in noIds:
                COOLPROP_available = False
                if not COOLPROP_available:
                    raise(ValueError)

        # Check correct fluid definition
        if self._multicomponent:
            if self.kwargs["ids"] and len(self.kwargs["fraccionMolar"]) == \
                    len(self.kwargs["ids"]):
                self._definition = True
            else:
                self._definition = False
        elif self.kwargs["ids"]:
            self._definition = True
        else:
            self._definition = False

        # Update the kwargs with the special coolprop namespace
        if self.kwargs["x"] != CoolProp.kwargs["x"]:
            self.kwargs["Q"] = self.kwargs["x"]
        if self.kwargs["v"] != CoolProp.kwargs["v"]:
            self.kwargs["Dmass"] = 1/self.kwargs["v"]
        if self.kwargs["rho"] != CoolProp.kwargs["rho"]:
            self.kwargs["Dmass"] = self.kwargs["rho"]
        if self.kwargs["s"] != CoolProp.kwargs["s"]:
            self.kwargs["Smass"] = self.kwargs["s"]
        if self.kwargs["h"] != CoolProp.kwargs["h"]:
            self.kwargs["Hmass"] = self.kwargs["h"]
        if self.kwargs["u"] != CoolProp.kwargs["u"]:
            self.kwargs["Umass"] = self.kwargs["u"]

        # Check thermo definition
        self._thermo = ""
        for def_ in ["P-T", "Q-T", "P-Q", "Dmass-T", "Dmass-P", "Hmass-P",
                     "P-Smass", "Hmass-Smass", "Hmass-T", "T-Umass", "P-Umass",
                     "Dmass-Hmass", "Dmass-Smass", "Dmass-Umass",
                     "Hmass-Umass", "Smass-Umass"]:
            inputs = def_.split("-")
            if self.kwargs[inputs[0]] != CoolProp.kwargs[inputs[0]] and \
                    self.kwargs[inputs[1]] != CoolProp.kwargs[inputs[1]]:
                self._thermo = def_.replace("-", "")
                self._inputs = inputs
                self._par = CP.__getattribute__("%s_INPUTS" % self._thermo)
                break

        return self._definition and self._thermo
예제 #2
0
s_before_condenser = PropsSI('S', 'T', ihe_condenser.T.val + 273.15, 'P', ihe_condenser.p.val * 100000, working_fluid)
T_before_condenser = ihe_condenser.T.val

s_after_condenser = PropsSI('S', 'T', condenser_pump.T.val + 273.15, 'Q', 0, working_fluid)
T_after_condenser = condenser_pump.T.val

s_after_pump = PropsSI('S', 'T', pump_ihe.T.val + 273.15, 'P', pump_ihe.p.val * 100000, working_fluid)
T_after_pump = pump_ihe.T.val

s_after_ihe = PropsSI('S', 'T', ihe_wf_out.T.val + 273.15, 'P', ihe_wf_out.p.val * 100000, working_fluid)
T_after_ihe = ihe_wf_out.T.val

s_after_preheater = PropsSI('S', 'T', preheater_evaporator.T.val + 273.15, 'P', preheater_evaporator.p.val * 100000, working_fluid)
T_after_preheater = preheater_evaporator.T.val

state = CP.AbstractState('HEOS', working_fluid)
T_crit = state.trivial_keyed_output(CP.iT_critical)
df = pd.DataFrame(columns=['s_l', 's_g', 's_iso_P0', 's_iso_P1', 's_iso_P_top', 's_iso_P_bottom'])
P0 = condenser_pump.p.val * 100000
P1 = p_before_turbine * 100000
T_range = np.geomspace(273.15, T_crit, 1000)
for T in T_range:
    df.loc[T, 's_l'] = PropsSI('S', 'T', T, 'Q', 0, working_fluid)
    df.loc[T, 's_g'] = PropsSI('S', 'T', T, 'Q', 1, working_fluid)
    df.loc[T, 's_iso_P0'] = PropsSI('S', 'T', T, 'P', P0, working_fluid)
    df.loc[T, 's_iso_P1'] = PropsSI('S', 'T', T, 'P', P1, working_fluid)

T_range_evaporator = np.geomspace(preheater_evaporator.T.val + 273.15, evaporator_turbine.T.val + 273.15+0.1, 100)
for T in T_range_evaporator:
    df.loc[T, 's_iso_P_top'] = PropsSI('S', 'T', T, 'P', P1, working_fluid)
예제 #3
0
    def Calculate(self):
        """
        Calculate the PHE
        
        For now, only evaporation against glycol is possible
        Cold: Ref
        Hot: Glycol
        """
        #AbstractState
        if hasattr(self,'Backend_c'): #check if backend is given
            AS_c = CP.AbstractState(self.Backend_c, self.Ref_c)
            if hasattr(self,'MassFrac_c'):
                AS_c.set_mass_fractions([self.MassFrac_c])
            elif hasattr(self, 'VoluFrac_c'):
                AS_c.set_volu_fractions([self.VoluFrac_c])
        else: #otherwise, use the defualt backend
            AS_c = CP.AbstractState('HEOS', self.Ref_c)
        self.AS_c =AS_c
        if hasattr(self,'Backend_h'): #check if backend is given
            AS_h = CP.AbstractState(self.Backend_h, self.Ref_h)
            if hasattr(self,'MassFrac_h'):
                AS_h.set_mass_fractions([self.MassFrac_h])
            elif hasattr(self, 'VoluFrac_h'):
                AS_h.set_volu_fractions([self.VoluFrac_h])
        else: #otherwise, use the defualt backend
            AS_h = CP.AbstractState('HEOS', self.Ref_h)
        self.AS_h =AS_h
            
        # Allocate channels between hot and cold streams
        if not hasattr(self,'MoreChannels') or self.MoreChannels not in ['Hot','Cold']:
            raise KeyError("MoreChannels not found, options are 'Hot' or 'Cold'")
        #There are (Nplates - 1) gaps between the plates
        if self.MoreChannels=='Hot':
            #Hot stream gets the extra channel
            self.NgapsHot=(self.Nplates-1)//2+1
            self.NgapsCold=self.Nplates-1-self.NgapsHot
        else:
            #Cold stream gets the extra channel
            self.NgapsCold=(self.Nplates-1)//2+1
            self.NgapsHot=self.Nplates-1-self.NgapsCold
        
        #Saturation temperatures for cold fluid
        if 'IncompressibleBackend' in AS_c.backend_name():
            self.rhosatL_c= None
            self.rhosatV_c= None
            self.Tbubble_c = None
            self.Tdew_c = None
            self.Tsat_c = None
        else:
            AS_c.update(CP.PQ_INPUTS, self.pin_c, 0.0)
            self.Tbubble_c=AS_c.T() #[K]
            self.rhosatL_c=AS_c.rhomass() #[kg/m^3]
            AS_c.update(CP.PQ_INPUTS, self.pin_c, 1.0)
            self.Tdew_c=AS_c.T() #[K]
            self.rhosatV_c=AS_c.rhomass() #[kg/m^3]
            self.Tsat_c=(self.Tbubble_c+self.Tdew_c)/2.0
        
        if 'IncompressibleBackend' in AS_h.backend_name():
            self.Tbubble_h=None
            self.Tdew_h=None
            self.Tsat_h=None
            self.rhosatL_h=None
            self.rhosatV_h=None
        else:
            #Saturation temperatures for hot fluid
            AS_h.update(CP.PQ_INPUTS, self.pin_h, 0.0)
            self.Tbubble_h=AS_h.T() #[K]
            self.rhosatL_h=AS_h.rhomass() #[kg/m^3]
            AS_h.update(CP.PQ_INPUTS, self.pin_h, 1.0)
            self.Tdew_h=AS_h.T() #[K]
            self.rhosatV_h=AS_h.rhomass() #[kg/m^3]
            self.Tsat_h=(self.Tbubble_h+self.Tdew_h)/2.0
        
        #The rest of the inlet states
        self.Tin_h,self.rhoin_h=TrhoPhase_ph(self.AS_h,self.pin_h,self.hin_h,self.Tbubble_h,self.Tdew_h,self.rhosatL_h,self.rhosatV_h)[0:2]
        self.Tin_c,self.rhoin_c=TrhoPhase_ph(self.AS_c,self.pin_c,self.hin_c,self.Tbubble_c,self.Tdew_c,self.rhosatL_c,self.rhosatV_c)[0:2]
        
        if 'IncompressibleBackend' in AS_c.backend_name():
            AS_c.update(CP.PT_INPUTS, self.pin_c, self.Tin_c)
            self.sin_c=AS_c.smass() #[J/kg-K]
        else:
            AS_c.update(CP.DmassT_INPUTS, self.rhoin_c,self.Tin_c)
            self.sin_c=AS_c.smass() #[J/kg-K]
            
        if 'IncompressibleBackend' in AS_h.backend_name():
            AS_h.update(CP.PT_INPUTS, self.pin_h, self.Tin_h)
            self.sin_h=AS_h.smass() #[J/kg-K]
        else:
            AS_h.update(CP.DmassT_INPUTS, self.rhoin_h, self.Tin_h)
            self.sin_h=AS_h.smass() #[J/kg-K]
            
        # Find HT and Delta P on the hot side
        #---------------
        #Mean values for the hot side based on average of inlet temperatures
        HotPlateInputs={
            'PlateAmplitude': self.PlateAmplitude,
            'PlateWavelength' : self.PlateWavelength,
            'InclinationAngle': self.InclinationAngle,
            'Bp': self.Bp,
            'Lp': self.Lp
        }
        HotPlateOutputs=PHE_1phase_hdP(HotPlateInputs,JustGeo=True)
        #There are (Nplates-2) active plates (outer ones don't do anything)
        self.A_h_wetted=HotPlateOutputs['Ap']*(self.Nplates-2)
        self.V_h=HotPlateOutputs['Vchannel']*self.NgapsHot
        self.A_h_flow=HotPlateOutputs['Aflow']*self.NgapsHot
        self.Dh_h=HotPlateOutputs['Dh']
        
        # Find geometric parameters for cold side of plates
        ColdPlateInputs={
            'PlateAmplitude': self.PlateAmplitude,
            'PlateWavelength' : self.PlateWavelength,
            'InclinationAngle': self.InclinationAngle,
            'Bp': self.Bp,
            'Lp': self.Lp
        }
        ColdPlateOutputs=PHE_1phase_hdP(ColdPlateInputs,JustGeo=True)
        #There are (Nplates-2) active plates (outer ones don't do anything)
        self.A_c_wetted=ColdPlateOutputs['Ap']*(self.Nplates-2)
        self.V_c=ColdPlateOutputs['Vchannel']*self.NgapsCold
        self.A_c_flow=ColdPlateOutputs['Aflow']*self.NgapsCold
        self.Dh_c=ColdPlateOutputs['Dh']
        
        #Figure out the limiting rate of heat transfer
        self.Qmax=self.DetermineHTBounds()
        
        def GivenQ(Q):
            """
            In this function, the heat transfer rate is imposed.  Therefore the
            outlet states for both fluids are known, and each element can be solved
            analytically in one shot without any iteration.
            """
            
            EnthalpyList_c,EnthalpyList_h=self.BuildEnthalpyLists(Q)
                
#            #Plot temperature versus enthalpy profiles
#            for i in range(len(EnthalpyList_c)-1):
#                hc=np.linspace(EnthalpyList_c[i],EnthalpyList_c[i+1])
#                Tc=np.zeros_like(hc)
#                for j in range(len(hc)):
#                    Tc[j],r,Ph=TrhoPhase_ph(self.Ref_c,self.pin_c,hc[j],self.Tbubble_c,self.Tdew_c,self.rhosatL_c,self.rhosatV_c)
#                pylab.plot(self.mdot_c*(hc-EnthalpyList_c[0])/1000,Tc,'b')
#                
#            for i in range(len(EnthalpyList_h)-1):
#                hh=np.linspace(EnthalpyList_h[i],EnthalpyList_h[i+1])
#                Th=np.zeros_like(hh)
#                for j in range(len(hh)):
#                    Th[j],r,Ph=TrhoPhase_ph(self.Ref_h,self.pin_h,hh[j],self.Tbubble_h,self.Tdew_h,self.rhosatL_h,self.rhosatV_h)
#                pylab.plot(self.mdot_h*(hh-EnthalpyList_h[0])/1000,Th,'r')
#            pylab.show()
                
#            Ph(self.Ref_h)
#            pylab.plot(np.array(EnthalpyList_h)/1000,self.pin_h/1000*np.ones_like(EnthalpyList_h))
#            pylab.show()
            
            I_h=0
            I_c=0
            wList=[]
            cellList=[]
            while I_h<len(EnthalpyList_h)-1:
                #Try to figure out whether the next phase transition is on the hot or cold side     
                Qbound_h=self.mdot_h*(EnthalpyList_h[I_h+1]-EnthalpyList_h[I_h])
                Qbound_c=self.mdot_c*(EnthalpyList_c[I_c+1]-EnthalpyList_c[I_c])
                if Qbound_h<Qbound_c-1e-9:
                    # Minimum amount of heat transfer is on the hot side,
                    # add another entry to EnthalpyList_c 
                    Qbound=Qbound_h
                    EnthalpyList_c.insert(I_c+1, EnthalpyList_c[I_c]+Qbound/self.mdot_c)
                elif Qbound_h>Qbound_c+1e-9:
                    # Minimum amount of heat transfer is on the cold side,
                    # add another entry to EnthalpyList_h at the interface
                    Qbound=Qbound_c
                    EnthalpyList_h.insert(I_h+1, EnthalpyList_h[I_h]+Qbound/self.mdot_h)
                else:
                    Qbound=Qbound_h
                
                #Figure out the inlet and outlet enthalpy for this cell
                hout_h=EnthalpyList_h[I_h]
                hin_h=hout_h+Qbound/self.mdot_h
                hin_c=EnthalpyList_c[I_c]
                hout_c=hin_c+Qbound/self.mdot_c
                
                # Figure out what combination of phases you have:
                # -------------------------------------------------
                # Hot stream is either single phase or condensing (two phase)
                # Cold stream is either single phase or evaporating (two phase)
                
                #Use midpoint enthalpies to figure out the phase in the cell
                Phase_h=Phase_ph(self.AS_h,self.pin_h,(hin_h+hout_h)/2,self.Tbubble_h,self.Tdew_h,self.rhosatL_h,self.rhosatV_h)
                Phase_c=Phase_ph(self.AS_c,self.pin_c,(hin_c+hout_c)/2,self.Tbubble_c,self.Tdew_c,self.rhosatL_c,self.rhosatV_c)
                #Determine inlet and outlet temperatures to the cell ([0] gives the first element of the tuple which is temeperature)
                Tin_h=TrhoPhase_ph(self.AS_h,self.pin_h,hin_h,self.Tbubble_h,self.Tdew_h,self.rhosatL_h,self.rhosatV_h)[0]
                Tin_c=TrhoPhase_ph(self.AS_c,self.pin_c,hin_c,self.Tbubble_c,self.Tdew_c,self.rhosatL_c,self.rhosatV_c)[0]
                Tout_h=TrhoPhase_ph(self.AS_h,self.pin_h,hout_h,self.Tbubble_h,self.Tdew_h,self.rhosatL_h,self.rhosatV_h)[0]
                Tout_c=TrhoPhase_ph(self.AS_c,self.pin_c,hout_c,self.Tbubble_c,self.Tdew_c,self.rhosatL_c,self.rhosatV_c)[0]
                
                if Phase_h in ['Subcooled','Superheated'] and Phase_c in ['Subcooled','Superheated']:
                    # Both are single-phase
                    Inputs={
                        'Q':Qbound,
                        'cp_h':(hin_h-hout_h)/(Tin_h-Tout_h),
                        'cp_c':(hin_c-hout_c)/(Tin_c-Tout_c),
                        'Tmean_h':(Tin_h+Tout_h)/2,
                        'Tmean_c':(Tin_c+Tout_c)/2,
                        'Tin_h':Tin_h,
                        'Tin_c':Tin_c,
                        'pin_h':self.pin_h,
                        'pin_c':self.pin_c,
                        'Phase_c':Phase_c,
                        'Phase_h':Phase_h
                    }
                    Outputs=self._OnePhaseH_OnePhaseC_Qimposed(Inputs)
                    wList.append(Outputs['w'])
                    cellList.append(Outputs)
                    if self.Verbosity>6:
                        print('w[1-1]: ', Outputs['w'])
                elif Phase_h=='TwoPhase' and Phase_c in ['Subcooled','Superheated']:
                    # Hot stream is condensing, and cold stream is single-phase (SH or SC)
                    # TODO: bounding state can be saturated state if hot stream is condensing
                    #Must be two-phase so quality is defined
                    xin_h=(hin_h-self.hsatL_h)/(self.hsatV_h-self.hsatL_h)
                    xout_h=(hout_h-self.hsatL_h)/(self.hsatV_h-self.hsatL_h)
                    Inputs={
                        'Q':Qbound,
                        'xin_h':xin_h,
                        'xout_h':xout_h,
                        'Tsat_h':self.Tsat_h,
                        'Tmean_c':(Tin_c+Tout_c)/2,
                        'cp_c':(hin_c-hout_c)/(Tin_c-Tout_c),
                        'Tin_c':Tin_c,
                        'pin_h':self.pin_h,
                        'pin_c':self.pin_c,
                        'Phase_c':Phase_c,
                        'Phase_h':Phase_h
                    }
                    Outputs=self._TwoPhaseH_OnePhaseC_Qimposed(Inputs)
                    if self.Verbosity>6:
                        print('w[2-1]: ', Outputs['w'])
                    wList.append(Outputs['w'])
                    cellList.append(Outputs)
                elif Phase_c=='TwoPhase' and Phase_h in ['Subcooled','Superheated']:
                    # Cold stream is evaporating, and hot stream is single-phase (SH or SC)
                    
                    #Must be two-phase so quality is defined
                    xin_c=(hin_c-self.hsatL_c)/(self.hsatV_c-self.hsatL_c)
                    xout_c=(hout_c-self.hsatL_c)/(self.hsatV_c-self.hsatL_c)
                    
                    Inputs={
                        'Q':Qbound,
                        'xin_c':xin_c,
                        'xout_c':xout_c,
                        'Tsat_c':self.Tsat_c,
                        'cp_h':(hin_h-hout_h)/(Tin_h-Tout_h),
                        'Tmean_h':(Tin_h+Tout_h)/2,
                        'Tin_h':Tin_h,
                        'pin_h':self.pin_h,
                        'pin_c':self.pin_c,
                        'Phase_c':Phase_c,
                        'Phase_h':Phase_h
                    }
                    Outputs=self._OnePhaseH_TwoPhaseC_Qimposed(Inputs)
                    if self.Verbosity>6:
                        print('w[1-2]: ', Outputs['w'])
                    wList.append(Outputs['w'])
                    cellList.append(Outputs)
                    
                I_h+=1
                I_c+=1
                
            self.cellList=cellList
            if self.Verbosity>6:
                print('wsum:', np.sum(wList))
            return np.sum(wList)-1.0
        try:
            brentq(GivenQ,0.0000001*self.Qmax,0.999999999*self.Qmax,xtol=0.000001*self.Qmax)#,xtol=0.000001*self.Qmax) is commented
        except ValueError:
            print(GivenQ(0.0000001*self.Qmax),GivenQ(0.999999999*self.Qmax))
            raise
        # Collect parameters from all the pieces
        self.PostProcess(self.cellList)
예제 #4
0
import CoolProp
import pandas
grouping = dict()
grouping2 = []
# Group aliases
for parameter in CoolProp.get('parameter_list').split(','):
    
    index = CoolProp.CoolProp.get_parameter_index(parameter)
    units = CoolProp.CoolProp.get_parameter_information(index, 'units').replace('-',' ')
    IO = CoolProp.CoolProp.get_parameter_information(index, 'IO')
    long = CoolProp.CoolProp.get_parameter_information(index, 'long')
    short = CoolProp.CoolProp.get_parameter_information(index, 'short')
    
    RHS = (units, IO, long)
    if RHS not in grouping:
        grouping[RHS] = [parameter]
    else:
        grouping[RHS].append(parameter)
    
for k, v in grouping.iteritems():
    grouping2.append([', '.join(['``'+_+'``' for _ in v])] + list(k))
    
headers = ['Parameter','Units','Input/Output','Description']

df3 = pandas.DataFrame(grouping2, columns = headers)
df4 = df3.sort_index(by = ['Input/Output', 'Parameter'])
grouping2 = [row for row in df4.values]

N = []
for i in range(len(grouping2[0])):
    N.append(max([len(el[i]) for el in grouping2]))
예제 #5
0
파일: setup.py 프로젝트: bansal16/pdsim
                                                              embedsignature = True),
                                       cython_c_in_temp=True
                                       )
                           )

package_data = package_pxd_files

setup(
  name = 'PDSim',
  version = version,
  author = "Ian Bell",
  author_email='*****@*****.**',
  url='http://pdsim.sourceforge.net',
  description = """A flexible open-source framework for the quasi-steady-state simulation of positive displacement machines including compressors and expanders""",
  packages = ['PDSim','PDSim.core','PDSim.flow','PDSim.plot','PDSim.scroll','PDSim.misc','PDSim.recip','PDSim.misc.clipper'],
  cmdclass={'build_ext': build_ext},
  ext_modules = ext_module_list,
  package_dir = {'PDSim':'PDSim',},
  package_data = package_data,
  include_dirs = [numpy.get_include(), CoolProp.get_include_directory(), "PDSim/misc/clipper"],

)

try:
    import quantities
    print('quantities package found, no need to install from source')
except ImportError:
    print('quantities package not found, will install from sources in externals/quantities.  Please hold on.')
    import subprocess
    subprocess.check_output('python setup.py install', shell = True, cwd=os.path.join('externals','quantities'))
    
예제 #6
0
        plt.savefig(fn + '_ORC_Ts_plot.png')
        # plt.show()


fluids = [
    'R600', 'R245fa', 'R245CA', 'R11', 'Isopentane', 'n-Pentane', 'R123',
    'R141B', 'R113'
]  # Isobutane
Td_bp_conds = [2, 4, 6, 8, 10]
for fluid in fluids:
    try:
        # for some testing
        print('+' * 75)
        PowerPlantWithIHE = PowerPlant(working_fluid=fluid)
        print('Working fluid:', fluid)
        state = CP.AbstractState('HEOS', fluid)
        T_crit = state.trivial_keyed_output(CP.iT_critical) - 273.15
        print('Critical temperature: {} °C'.format(round(T_crit, 4)))
        # for Td_bp_cond in Td_bp_conds:
        eff = PowerPlantWithIHE.calculate_efficiency(200, 0.1, 70, 2)
        if not np.isnan(eff):
            # PowerPlantWithIHE.generate_diagram()
            # PowerPlantWithIHE.plot_process(fn=fluid)
            PowerPlantWithIHE.print_result()
            PowerPlantWithIHE.plot_Ts(fn=fluid)
        else:
            print('+' * 75)
            print(fluid)
            print('+' * 75)
    except:
        print('+' * 75)
예제 #7
0
    def Calculate(self):
        #AbstractState
        if hasattr(self, 'Backend'):  #check if backend is given
            AS = CP.AbstractState(self.Backend, self.Ref)
        else:  #otherwise, use the defualt backend
            AS = CP.AbstractState('HEOS', self.Ref)
        self.AS = AS

        #Check that the length of lists of mdot_r and FinsTubes.Air.Vdot_ha
        #match the number of circuits or are all equal to 1 (standard evap)
        Ncircuits = int(self.Fins.Tubes.Ncircuits)

        # Make Ncircuits copies of evaporator classes defined
        #  by the inputs to the MCE superclass
        EvapDict = self.__dict__
        self.Evaps = []
        for i in range(Ncircuits):
            # Make a deep copy to break all the links between the Fins structs
            # of each of the evaporator instances
            ED = copy.deepcopy(EvapDict)
            #Create new evaporator instanciated with new deep copied dictionary
            E = EvaporatorClass(**ED)
            #Add to list of evaporators
            self.Evaps.append(E)

        #Upcast single values to lists, and convert numpy arrays to lists
        self.Fins.Air.Vdot_ha = np.atleast_1d(self.Fins.Air.Vdot_ha).tolist()
        self.mdot_r = np.atleast_1d(self.mdot_r).tolist()

        if Ncircuits != len(self.mdot_r) and len(self.mdot_r) > 1:
            print("Problem with length of vector for mdot_r for MCE")
        else:
            if len(self.mdot_r) == 1:  #Single value passed in for mdot_r
                if hasattr(self, 'mdot_r_coeffs'):
                    if len(self.mdot_r_coeffs) != Ncircuits:
                        raise AttributeError("Size of array mdot_r_coeffs: " +
                                             str(len(self.mdot_r_coeffs)) +
                                             " does not equal Ncircuits: " +
                                             str(Ncircuits))
                    elif abs(np.sum(self.mdot_r_coeffs) -
                             1) >= 100 * np.finfo(float).eps:
                        raise AttributeError(
                            "mdot_r_coeffs must sum to 1.0.  Sum *100000 is: "
                            + str(100000 * np.sum(self.mdot_r_coeffs)))
                    else:
                        # A vector of weighting factors multiplying the total mass flow rate is provided with the right length
                        for i in range(Ncircuits):
                            self.Evaps[i].mdot_r = self.mdot_r[
                                -1] * self.mdot_r_coeffs[i]
                else:
                    # Refrigerant flow is evenly distributed between circuits,
                    # give each evaporator an equal portion of the refrigerant
                    for i in range(Ncircuits):
                        self.Evaps[i].mdot_r = self.mdot_r[-1] / Ncircuits
            else:
                for i in range(Ncircuits):
                    self.Evaps[i].mdot_r = self.mdot_r[i]

        # Deal with the possibility that the quality might be varied among circuits
        if hasattr(self, 'mdot_v_coeffs'):
            if len(self.mdot_v_coeffs) != Ncircuits:
                raise AttributeError("Size of array mdot_v_coeffs: " +
                                     str(len(self.mdot_v_coeffs)) +
                                     " does not equal Ncircuits: " +
                                     str(Ncircuits))
            elif abs(np.sum(self.mdot_v_coeffs) -
                     1) >= 10 * np.finfo(float).eps:
                raise AttributeError(
                    "mdot_v_coeffs must sum to 1.0.  Sum is: " +
                    str(np.sum(self.mdot_v_coeffs)))
            else:
                AS.update(CP.PQ_INPUTS, self.psat_r, 0.0)
                hsatL = AS.hmass()  #[J/kg]
                AS.update(CP.PQ_INPUTS, self.psat_r, 1.0)
                hsatV = AS.hmass()  #[J/kg]
                x_inlet = (self.hin_r - hsatL) / (hsatV - hsatL)
                mdot_v = x_inlet * sum(self.mdot_r)
                for i in range(Ncircuits):
                    mdot_v_i = self.mdot_v_coeffs[i] * mdot_v
                    x_i = mdot_v_i / self.Evaps[i].mdot_r
                    AS.update(CP.PQ_INPUTS, self.psat_r, x_i)
                    self.Evaps[i].hin_r = AS.hmass()  #[J/kg]

        #For backwards compatibility, if the coefficients are provided in the FinInputs class, copy them to the base class
        if hasattr(self.Fins.Air, 'Vdot_ha_coeffs'):
            self.Vdot_ha_coeffs = self.Fins.Air.Vdot_ha_coeffs
            print(
                "Warning: please put the vector Vdot_ha_coeffs in the base MCE class, accesssed as MCE.Vdot_ha_coeffs"
            )

        if Ncircuits != len(self.Fins.Air.Vdot_ha) and len(
                self.Fins.Air.Vdot_ha) > 1:
            print("Problem with length of vector for Vdot_ha for MCE")
        else:
            if len(self.Fins.Air.Vdot_ha) == 1:
                if hasattr(self, 'Vdot_ha_coeffs'):
                    if len(self.Vdot_ha_coeffs) != Ncircuits:
                        raise AttributeError("Size of array Vdot_ha_coeffs: " +
                                             str(len(self.Vdot_ha_coeffs)) +
                                             " does not equal Ncircuits: " +
                                             str(Ncircuits))
                    elif abs(np.sum(self.Vdot_ha_coeffs) -
                             1) >= 10 * np.finfo(float).eps:
                        raise AttributeError(
                            "Vdot_ha_coeffs does not sum to 1.0! Sum is: " +
                            str(np.sum(self.Vdot_ha_coeffs)))
                    else:
                        # A vector of factors multiplying the total volume flow rate is provided
                        for i in range(Ncircuits):
                            self.Evaps[
                                i].Fins.Air.Vdot_ha = self.Fins.Air.Vdot_ha[
                                    -1] * self.Vdot_ha_coeffs[i]
                else:
                    # Air flow is evenly distributed between circuits,
                    # give each circuit an equal portion of the air flow
                    for i in range(Ncircuits):
                        self.Evaps[i].Fins.Air.Vdot_ha = self.Fins.Air.Vdot_ha[
                            -1] / Ncircuits
            else:
                for i in range(Ncircuits):
                    self.Evaps[i].Fins.Air.Vdot_ha = self.Fins.Air.Vdot_ha[i]

        # Distribute the tubes of the bank among the different circuits
        # If Tubes per bank is divisible by the number of circuits, all the
        # circuits have the same number of tubes per bank

        # The circuits are ordered from fewer to more if they are not evenly distributed
        NTubes_min = int(floor(self.Fins.Tubes.NTubes_per_bank / Ncircuits))
        NTubes_max = int(ceil(self.Fins.Tubes.NTubes_per_bank / Ncircuits))

        if NTubes_min == NTubes_max:
            #If evenly divisible, use the tubes per circuit from the division
            A = Ncircuits
        else:
            # Total number of tubes per bank is given by
            A = (self.Fins.Tubes.NTubes_per_bank -
                 Ncircuits * NTubes_max) / (NTubes_min - NTubes_max)

        for i in range(Ncircuits):
            if i + 1 <= A:
                self.Evaps[i].Fins.Tubes.NTubes_per_bank = NTubes_min
            else:
                self.Evaps[i].Fins.Tubes.NTubes_per_bank = NTubes_max

        for i in range(Ncircuits):
            self.Evaps[i].Fins.Tubes.Ncircuits = 1
            #Actually run each Evaporator
            self.Evaps[i].Calculate()

        #Collect the outputs from each of the evaporators individually
        #Try to mirror the outputs of each of the evaporators
        self.Q = np.sum([self.Evaps[i].Q for i in range(Ncircuits)])
        self.Charge = np.sum([self.Evaps[i].Charge for i in range(Ncircuits)])
        self.Charge_superheat = np.sum(
            [self.Evaps[i].Charge_superheat for i in range(Ncircuits)])
        self.Charge_2phase = np.sum(
            [self.Evaps[i].Charge_2phase for i in range(Ncircuits)])
        self.DP_r = np.mean([self.Evaps[i].DP_r
                             for i in range(Ncircuits)])  #simplified
        self.DP_r_superheat = np.mean([
            self.Evaps[i].DP_r_superheat for i in range(Ncircuits)
        ])  #simplified
        self.DP_r_2phase = np.mean(
            [self.Evaps[i].DP_r_2phase for i in range(Ncircuits)])  #simplified
        self.Tin_r = np.mean([self.Evaps[i].Tin_r
                              for i in range(Ncircuits)])  #simplified
        self.h_r_superheat = np.mean([
            self.Evaps[i].h_r_superheat for i in range(Ncircuits)
        ])  #simplified, really should consider flowrate
        self.h_r_2phase = np.mean([
            self.Evaps[i].h_r_2phase for i in range(Ncircuits)
        ])  #simplified, really should consider flowrate
        self.w_superheat = np.sum(
            [self.Evaps[i].w_superheat
             for i in range(Ncircuits)]) / float(Ncircuits)
        self.w_2phase = np.sum(
            [self.Evaps[i].w_2phase
             for i in range(Ncircuits)]) / float(Ncircuits)
        self.hout_r = 0.0
        for i in range(Ncircuits):
            self.hout_r += self.Evaps[i].hout_r * self.Evaps[i].mdot_r
        self.hout_r = (self.hout_r / sum(self.mdot_r))
        self.Tin_a = self.Evaps[
            0].Fins.Air.Tdb  #assuming equal temperature for all circuits
        self.Tout_a = 0.0
        for i in range(Ncircuits):
            self.Tout_a += self.Evaps[i].Tout_a * self.Evaps[i].Fins.Air.Vdot_ha
        self.Tout_a = (self.Tout_a / sum(self.Fins.Air.Vdot_ha))
        Pout_r = self.psat_r + self.DP_r / 1.0
        AS.update(CP.PQ_INPUTS, Pout_r, 1.0)
        hsatV_out = AS.hmass()  #[J/kg]
        AS.update(CP.PQ_INPUTS, Pout_r, 0.0)
        hsatL_out = AS.hmass()  #[J/kg]
        if self.hout_r > hsatV_out:
            AS.update(CP.HmassP_INPUTS, self.hout_r, Pout_r)
            self.Tout_r = AS.T()  #superheated temperature at outlet [K]
        else:
            xout_r = ((self.hout_r - hsatL_out) / (hsatV_out - hsatL_out))
            AS.update(CP.PQ_INPUTS, Pout_r, xout_r)
            self.Tout_r = AS.T()  #saturated temperature at outlet quality [K]
        self.Capacity = np.sum([self.Evaps[i].Q for i in range(Ncircuits)
                                ]) - self.Fins.Air.FanPower
        self.SHR = np.mean([self.Evaps[i].SHR for i in range(Ncircuits)])
        self.UA_a = np.sum([self.Evaps[i].UA_a for i in range(Ncircuits)])
        self.UA_r = np.sum([self.Evaps[i].UA_r for i in range(Ncircuits)])
        self.Q_superheat = np.sum(
            [self.Evaps[i].Q_superheat for i in range(Ncircuits)])
        self.Q_2phase = np.sum(
            [self.Evaps[i].Q_2phase for i in range(Ncircuits)])
        #Convert back to a single value for the overall evaporator
        self.Fins.Air.Vdot_ha = float(self.Fins.Air.Vdot_ha[-1])
        if self.Verbosity > 0:
            print(chr(127), end='')  #progress bar
예제 #8
0
matplotlib.use('Agg') # use a non-interactive backend
import CoolProp
import os.path

web_dir = os.path.abspath(os.path.join(os.path.dirname(__file__),'..'))
tar_fil = os.path.join(web_dir,'_static','CoolPropLogo.png')
tar_fil_long = os.path.join(web_dir,'_static','CoolPropLogoLong.png')

import matplotlib
import numpy as np
import CoolProp as CP
import matplotlib.pyplot as plt
import scipy.interpolate

# Prepare the constants
Water = CP.AbstractState("HEOS", "Water")
pc = Water.keyed_output(CP.iP_critical)
Tc = Water.keyed_output(CP.iT_critical)
T_min = 200
T_max = 1000
p_max = Water.keyed_output(CP.iP_max)
p_triple = 611.657
T_triple = 273.16

# Prepare the data for the melting line
steps = 2000

TT = []
PP = list(np.logspace(np.log10(p_triple), np.log10(p_max),steps))
for p in PP:
    TT.append(Water.melting_line(CP.iT, CP.iP, p))
예제 #9
0
import CoolProp
import CoolProp.CoolProp as CP
import matplotlib.pyplot as plt
import matplotlib.colors as colors
import matplotlib.cm as cmx
import matplotlib.ticker
import numpy as np
import random

fig = plt.figure(figsize=(10,5))
ax1 = fig.add_axes((0.08,0.1,0.32,0.83))
ax2 = fig.add_axes((0.50,0.1,0.32,0.83))

Ref = 'R245fa'

BICUBIC = CoolProp.AbstractState('BICUBIC&HEOS',Ref)
TTSE = CoolProp.AbstractState('TTSE&HEOS',Ref)
EOS = CoolProp.AbstractState('HEOS',Ref)
MM = EOS.molar_mass()
print MM

T = np.linspace(CP.PropsSI(Ref,'Tmin')+0.1, CP.PropsSI(Ref,'Tcrit')-0.01, 300)
pV = CP.PropsSI('P','T',T,'Q',1,Ref)
hL = CP.PropsSI('Hmolar','T',T,'Q',0,Ref)
hV = CP.PropsSI('Hmolar','T',T,'Q',1,Ref)

HHH1, PPP1, EEE1 = [], [], []
HHH2, PPP2, EEE2 = [], [], []

cNorm  = colors.LogNorm(vmin=1e-12, vmax=10)
scalarMap = cmx.ScalarMappable(norm = cNorm, cmap = plt.get_cmap('jet'))
예제 #10
0
    def calculo(self):
        fluido = self._name()
        args = self.args()
        estado = CP.AbstractState("HEOS", fluido)
        self.eq = self._limit(fluido, estado)
        if self._multicomponent:
            estado.set_mole_fractions(self.kwargs["fraccionMolar"])
        estado.update(self._par, *args)

        self.M = unidades.Dimensionless(estado.molar_mass() * 1000)

        if self._multicomponent:
            # Disabled CoolProp critical properties for multicomponent,
            # see issue #1087

            # Calculate critical properties with mezcla method
            # Coolprop for mixtures can fail and it's slow
            Cmps = [Componente(int(i)) for i in self.kwargs["ids"]]

            # Calculate critic temperature, API procedure 4B1.1 pag 304
            V = sum([
                xi * cmp.Vc
                for xi, cmp in zip(self.kwargs["fraccionMolar"], Cmps)
            ])
            k = [
                xi * cmp.Vc / V
                for xi, cmp in zip(self.kwargs["fraccionMolar"], Cmps)
            ]
            Tcm = sum([ki * cmp.Tc for ki, cmp in zip(k, Cmps)])
            self.Tc = unidades.Temperature(Tcm)

            # Calculate pseudocritic temperature
            tpc = sum([
                x * cmp.Tc
                for x, cmp in zip(self.kwargs["fraccionMolar"], Cmps)
            ])

            # Calculate pseudocritic pressure
            ppc = sum([
                x * cmp.Pc
                for x, cmp in zip(self.kwargs["fraccionMolar"], Cmps)
            ])

            # Calculate critic pressure, API procedure 4B2.1 pag 307
            sumaw = 0
            for xi, cmp in zip(self.kwargs["fraccionMolar"], Cmps):
                sumaw += xi * cmp.f_acent
            pc = ppc + ppc * (5.808 + 4.93 * sumaw) * (self.Tc - tpc) / tpc
            self.Pc = unidades.Pressure(pc)

            # Calculate critic volume, API procedure 4B3.1 pag 314
            sumaxvc23 = sum([
                xi * cmp.Vc**(2. / 3)
                for xi, cmp in zip(self.kwargs["fraccionMolar"], Cmps)
            ])
            k = [
                xi * cmp.Vc**(2. / 3) / sumaxvc23
                for xi, cmp in zip(self.kwargs["fraccionMolar"], Cmps)
            ]

            # TODO: Calculate C value from component type.
            # For now it suppose all are hidrycarbon (C=0)
            C = 0

            V = [[
                -1.4684 * abs((cmpi.Vc - cmpj.Vc) / (cmpi.Vc + cmpj.Vc)) + C
                for cmpj in Cmps
            ] for cmpi in Cmps]
            v = [[
                V[i][j] * (cmpi.Vc + cmpj.Vc) / 2.
                for j, cmpj in enumerate(Cmps)
            ] for i, cmpi in enumerate(Cmps)]
            suma1 = sum([ki * cmp.Vc for ki, cmp in zip(k, Cmps)])
            suma2 = sum([
                ki * kj * v[i][j] for j, kj in enumerate(k)
                for i, ki in enumerate(k)
            ])
            self.rhoc = unidades.Density((suma1 + suma2) * self.M)

        else:
            self.Tc = unidades.Temperature(estado.T_critical())
            self.Pc = unidades.Pressure(estado.p_critical())
            self.rhoc = unidades.Density(estado.rhomass_critical())

        self.R = unidades.SpecificHeat(estado.gas_constant() / self.M)
        self.Tt = unidades.Temperature(estado.Ttriple())
        estado2 = CP.AbstractState("HEOS", fluido)
        if self._multicomponent:
            estado2.set_mole_fractions(self.kwargs["fraccionMolar"])
        estado2.update(CP.PQ_INPUTS, 101325, 1)
        self.Tb = unidades.Temperature(estado2.T())
        self.f_accent = unidades.Dimensionless(estado.acentric_factor())

        # Dipole moment only available for REFPROP backend
        # self.momentoDipolar(estado.keyed_output(CP.idipole_moment))

        self.phase, x = self.getphase(estado)
        self.x = unidades.Dimensionless(x)
        if self._multicomponent:
            string = fluido.replace("&", " (%0.2f), ")
            string += " (%0.2f)"
            self.name = string % tuple(self.kwargs["fraccionMolar"])
            self.CAS = ""
            self.synonim = ""
            self.formula = ""
        else:
            self.name = fluido
            self.CAS = estado.fluid_param_string("CAS")
            self.synonim = estado.fluid_param_string("aliases")
            self.formula = estado.fluid_param_string("formula")

        self.P = unidades.Pressure(estado.p())
        self.T = unidades.Temperature(estado.T())
        self.Tr = unidades.Dimensionless(self.T / self.Tc)
        self.Pr = unidades.Dimensionless(self.P / self.Pc)
        self.rho = unidades.Density(estado.rhomass())
        self.v = unidades.SpecificVolume(1. / self.rho)

        cp0 = self._prop0(estado)
        self._cp0(cp0)

        self.Liquido = ThermoAdvanced()
        self.Gas = ThermoAdvanced()
        if self.x == 0:
            # liquid phase
            self.fill(self.Liquido, estado)
            self.fill(self, estado)
            self.fillNone(self.Gas)
        elif self.x == 1:
            # vapor phase
            self.fill(self.Gas, estado)
            self.fill(self, estado)
            self.fillNone(self.Liquido)
        else:
            # Two phase
            liquido = CP.AbstractState("HEOS", fluido)
            if self._multicomponent:
                xi = estado.mole_fractions_liquid()
                liquido.set_mole_fractions(xi)
            liquido.specify_phase(CP.iphase_liquid)
            liquido.update(CP.QT_INPUTS, 0, self.T)
            self.fill(self.Liquido, liquido)

            vapor = CP.AbstractState("HEOS", fluido)
            if self._multicomponent:
                yi = estado.mole_fractions_vapor()
                vapor.set_mole_fractions(yi)
            vapor.specify_phase(CP.iphase_gas)
            vapor.update(CP.QT_INPUTS, 1, self.T)
            self.fill(self.Gas, vapor)
            self.fill(self, estado)

        # Calculate special properties useful only for one phase
        if self._multicomponent:
            self.sigma = unidades.Tension(None)
        elif x < 1 and self.Tt <= self.T <= self.Tc:
            self.sigma = unidades.Tension(estado.surface_tension())
        else:
            self.sigma = unidades.Tension(None)

        self.virialB = unidades.SpecificVolume(estado.Bvirial())
        self.virialC = unidades.SpecificVolume_square(estado.Cvirial())
        self.invT = unidades.InvTemperature(-1 / self.T)

        if 0 < self.x < 1:
            self.Hvap = unidades.Enthalpy(self.Gas.h - self.Liquido.h)
            self.Svap = unidades.SpecificHeat(self.Gas.s - self.Liquido.s)
        else:
            self.Hvap = unidades.Enthalpy(None)
            self.Svap = unidades.SpecificHeat(None)
예제 #11
0
import CoolProp
import matplotlib.pyplot as plt
import math
from CoolProp.Plots import StateContainer

refrigerant = 'R600'

# setting the gasses
HEOS = CoolProp.AbstractState('HEOS', refrigerant)

# Setting the variables
evaporation_temp = 4 + 273.15
condensation_temp = 70 + 273.15
superheat_evap = 5
superheat_intercooler = 5

subcooling_intercooler = 23
isentropic_eff = 0.7
compressor_loss = 0.1
condensor_capacity = 50000

DP_sup = 2500
DP_cond = 5000
DP_sub = 5000
DP_evap = 500
DP_int = 5000
"""----Evaporation----"""

T1 = evaporation_temp
HEOS.update(CoolProp.QT_INPUTS, 1, T1)
HEOS.specify_phase(CoolProp.iphase_gas)
    return u':raw-html:`<span title="{1}">{0}</span>`'.format(short, long)


class Dossier:
    def __init__(self):
        self.data = {}

    def add(self, key, value):
        if key not in self.data:
            self.data[key] = []
        self.data[key].append(value)


d = Dossier()

pairs = CoolProp.get('mixture_binary_pairs_list')
print(len(pairs.split(',')))
for pair in pairs.split(','):
    CAS1, CAS2 = pair.split('&')
    d.add('CAS1', CAS1)
    d.add('CAS2', CAS2)
    for key in [
            'name1', 'name2', 'F', 'function', 'BibTeX', 'xi', 'zeta', 'betaT',
            'betaV', 'gammaT', 'gammaV'
    ]:
        try:
            d.add(
                key,
                CoolProp.CoolProp.get_mixture_binary_pair_data(
                    CAS1, CAS2, key))
        except BaseException as BE:
예제 #13
0
# -*- coding: utf-8 -*-
"""
Created on Thu Apr 23 15:27:45 2020

@author: TrungNguyen
"""
import CoolProp
from CoolProp.CoolProp import PropsSI
from CoolProp.Plots import PropertyPlot
from CoolProp.Plots import StateContainer


#Evaporator chracteristics
gas = 'R290'
HEOS = CoolProp.AbstractState('HEOS', 'Propane&IsoButane')
HEOS.set_mass_fractions([0.99999, 0.00001])

isentropic_eff=0.7
evaporation_temp = 0 + 273.15                # R290
condensation_temp = 55 + 273.15              # Estimation from Aeronamic
superheat = 5                                # ambient temperature
subcooling = 3.1                             # estimation from Aeronamic (how to know or calculate the value)

#Compressor characteristics
compressor_power = 4300                      #
massflow = 0.04506                           #


#Aeronamic calculated values
Qdot_condensor_expected = 14.3e3
Expected_COP = 3.17
예제 #14
0
    def add_fluids(fluids, memorise_fluid_properties=True):
        r"""
        Add list of fluids to fluid memorisation class.

        - Generate arrays for fluid property lookup if memorisation is
          activated.
        - Calculate/set fluid property value ranges for convergence checks.

        Parameters
        ----------
        fluids : dict
            Dict of fluid and corresponding CoolProp back end for fluid
            property memorization.

        memorise_fluid_properties : boolean
            Activate or deactivate fluid property value memorisation. Default
            state is activated (:code:`True`).

        Note
        ----
        The Memorise class creates globally accessible variables for different
        fluid property calls as dictionaries:

        - T(p,h)
        - T(p,s)
        - v(p,h)
        - visc(p,h)
        - s(p,h)

        Each dictionary uses the list of fluids passed to the Memorise class as
        identifier for the fluid property memorisation. The fluid properties
        are stored as numpy array, where each column represents the mass
        fraction of the respective fluid and the additional columns are the
        values for the fluid properties. The fluid property function will then
        look for identical fluid property inputs (p, h, (s), fluid mass
        fraction). If the inputs are in the array, the first column of that row
        is returned, see example.

        Example
        -------
        T(p,h) for set of fluids ('water', 'air'):

        - row 1: [282.64527752319697, 10000, 40000, 1, 0]
        - row 2: [284.3140698256616, 10000, 47000, 1, 0]
        """
        # number of fluids
        num_fl = len(fluids)
        if memorise_fluid_properties and num_fl > 0:
            fl = tuple(fluids.keys())
            # fluid property tables
            Memorise.T_ph[fl] = np.empty((0, num_fl + 4), float)
            Memorise.T_ps[fl] = np.empty((0, num_fl + 5), float)
            Memorise.v_ph[fl] = np.empty((0, num_fl + 4), float)
            Memorise.visc_ph[fl] = np.empty((0, num_fl + 4), float)
            Memorise.s_ph[fl] = np.empty((0, num_fl + 4), float)

            msg = (
                'Added fluids ' + ', '.join(fl) +
                ' to memorise lookup tables.')
            logging.debug(msg)

        Memorise.water = None
        for f, back_end in fluids.items():

            # save name for water in memorise
            if f in get_aliases("H2O"):
                Memorise.water = f

            if f in Memorise.state:
                del Memorise.state[f]

            # create CoolProp.AbstractState object
            try:
                Memorise.state[f] = CP.AbstractState(back_end, f)
                Memorise.back_end[f] = back_end
            except ValueError:
                msg = (
                    'Could not find the fluid "' + f + '" in the fluid '
                    'property database.'
                )
                logging.warning(msg)
                continue

            msg = (
                'Created CoolProp.AbstractState object for fluid ' +
                f + ' with back end ' + back_end + '.')
            logging.debug(msg)
            # pressure range
            try:
                pmin = Memorise.state[f].trivial_keyed_output(CP.iP_min)
                pmax = Memorise.state[f].trivial_keyed_output(CP.iP_max)
            except ValueError:
                pmin = 1e4
                pmax = 1e8
                msg = (
                    'Could not find values for maximum and minimum '
                    'pressure.')
                logging.warning(msg)

            # temperature range
            Tmin = Memorise.state[f].trivial_keyed_output(CP.iT_min)
            Tmax = Memorise.state[f].trivial_keyed_output(CP.iT_max)

            # value range for fluid properties
            Memorise.value_range[f] = [pmin, pmax, Tmin, Tmax]

            try:
                molar_masses[f] = Memorise.state[f].molar_mass()
                gas_constants[f] = Memorise.state[f].gas_constant()
            except ValueError:
                try:
                    molar_masses[f] = CPPSI('M', f)
                    gas_constants[f] = CPPSI('GAS_CONSTANT', f)
                except ValueError:
                    molar_masses[f] = 1
                    gas_constants[f] = 1
                    msg = (
                        'Could not find values for molar mass and gas '
                        'constant.')
                    logging.warning(msg)

            msg = (
                'Specifying fluid property ranges for pressure and '
                'temperature for convergence check of fluid ' + f + '.')
            logging.debug(msg)
예제 #15
0
ts_plot.show()

#%%

from CoolProp.Plots import PropertyPlot
plot = PropertyPlot("REFPROP::ISOBUTAN[0.8]&PROPANE[0.2]",
                    'PH',
                    unit_system='EUR',
                    tp_limits='ACHP')
plot.calc_isolines()
plot.show()

#%%

import CoolProp
state = CoolProp.AbstractState("REFPROP", "ISOBUTAN&PROPANE")
state.set_mass_fractions([0.8, 0.2])
from CoolProp.Plots import PropertyPlot
plot = PropertyPlot(state, 'TS', unit_system='EUR', tp_limits='ACHP')
plot.calc_isolines()
plot.show()

#%%

#from __future__ import print_function
import CoolProp
from CoolProp.Plots import StateContainer

T0 = 300.000
p0 = 200000.000
h0 = 112745.749
예제 #16
0
import CoolProp as CP
from CoolProp.CoolProp import PropsSI
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt

state = CP.AbstractState('HEOS', 'Isopentane')
T_crit = state.trivial_keyed_output(CP.iT_critical)
df = pd.DataFrame(columns=['s_l', 's_g', 's_iso_P0', 's_iso_P1'])
P0 = 1000000
P1 = 200000
T_range = np.geomspace(273.15, T_crit, 1000)
for T in T_range:
    df.loc[T, 's_l'] = PropsSI('S', 'T', T, 'Q', 0, 'Isopentane')
    df.loc[T, 's_g'] = PropsSI('S', 'T', T, 'Q', 1, 'Isopentane')
    df.loc[T, 's_iso_P0'] = PropsSI('S', 'T', T, 'P', P0, 'Isopentane')
    df.loc[T, 's_iso_P1'] = PropsSI('S', 'T', T, 'P', P1, 'Isopentane')

print(df)
fig, ax = plt.subplots()
ax.plot(df['s_g'] / 1000, df.index - 273.15, color='black')
ax.plot(df['s_l'] / 1000, df.index - 273.15, color='black')
ax.plot(df['s_iso_P0'] / 1000, df.index - 273.15, color='green')
ax.plot(df['s_iso_P1'] / 1000, df.index - 273.15, color='green')
ax.set(xlabel='Specific entropy [kJ/kg K]',
       ylabel='Temperature [K]',
       title='T,s Graph for working fluid')
ax.grid()
plt.savefig('ts_plot_new.png')
plt.show()
예제 #17
0
    phi_g_square = 1 + C * sqrt(X_squared) + X_squared

    #Find Boiling pressure drop griendient
    if dpdz_g * phi_g_square > dpdz_f * phi_f_square:
        dpdz = dpdz_g * phi_g_square
    else:
        dpdz = dpdz_f * phi_f_square

    return dpdz


if __name__ == '__main__':
    DP_vals_acc = []
    DP_vals_fric = []
    x_vals = []
    import pylab
    AS = CP.AbstractState("HEOS", "R410A")
    for x in np.linspace(0.1, 1.0, 10):
        DP_vals_acc.append(AccelPressureDrop(x - 0.1, x, AS, 2, 250, 250))
        DP_vals_fric.append(
            LMPressureGradientAvg(x - 0.1, x, AS, 0.1, 0.01, 250, 250) * 1 * 1)
        x_vals.append(x)

    print("plot shows accelerational pressure drop as f(x) for 0.1 x segments")
    pylab.plot(x_vals, DP_vals_acc)
    pylab.show()
    print(
        "plot shows frictional pressure drop as f(x) for 0.1 x segments of a fictional tube with unit length"
    )
    pylab.plot(x_vals, DP_vals_fric)
    pylab.show()
예제 #18
0
 def Initialize(self):
     #Input validation the first call of Initialize
     if False:#not hasattr(self,'IsValidated'):
         self.Fins.Validate()
         reqFields=[
                    ('Ref',str,None,None),
                    ('psat_r',float,0.001,100000000),                        
                    ('Fins',IsFinsClass,None,None),
                    ('FinsType',str,None,None),
                    ('hin_r',float,-100000,10000000),
                    ('mdot_r',float,0.000001,10),
                    ]
         optFields=['Verbosity','Backend']
         d=self.__dict__ #Current fields in model
         ValidateFields(d,reqFields,optFields)
         self.IsValidated=True
     
     #AbstractState
     if hasattr(self,'Backend'): #check if backend is given
         AS = CP.AbstractState(self.Backend, self.Ref)
     else: #otherwise, use the defualt backend
         AS = CP.AbstractState('HEOS', self.Ref)
     self.AS = AS
         
     # 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
     
     # 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
     # Wetted area on the refrigerant side
     self.A_r_wetted=self.Ncircuits*pi*self.ID*self.Lcircuit
     self.V_r=self.Ncircuits*self.Lcircuit*pi*self.ID**2/4.0
     #Average mass flux of refrigerant in circuit
     self.G_r = self.mdot_r/(self.Ncircuits*pi*self.ID**2/4.0) #[kg/m^2-s]
     
     ## Bubble and dew temperatures (same for fluids without glide)
     AS.update(CP.PQ_INPUTS, self.psat_r, 0.0)
     self.Tbubble_r=AS.T() #[K]
     h_l = AS.hmass() #[J/kg]
     AS.update(CP.PQ_INPUTS, self.psat_r, 1.0)
     self.Tdew_r=AS.T() #[K]
     h_v = AS.hmass() #[J/kg]
     ## Mean temperature for use in HT relationships
     self.Tsat_r=(self.Tbubble_r+self.Tdew_r)/2
     # Latent heat
     self.h_fg=h_v - h_l #[J/kg]
     
     self.Fins.Air.RHmean=self.Fins.Air.RH
     
     #Update with user FinType
     if self.FinsType == 'WavyLouveredFins':
         WavyLouveredFins(self.Fins)
     elif self.FinsType == 'HerringboneFins':
         HerringboneFins(self.Fins)
     elif self.FinsType == 'PlainFins':
         PlainFins(self.Fins)
     
     self.mdot_ha=self.Fins.mdot_ha #[kg_ha/s]
     self.mdot_da=self.Fins.mdot_da #[kg_da/s]
예제 #19
0
#mu_axis.set_ylim([0,1])
#mu_axis.set_yscale("log")
cp_axis.set_xlabel("Temperature $T$ / deg C")
cp_axis.set_ylabel("Isobaric Heat Capacity $c_p$ / J/kg/K")
#cp_axis.set_ylim([0,5000])

for fluid in CoolProp.__incompressibles_pure__ + CoolProp.__incompressibles_solution__:
    #for fluid in CoolProp.__incompressibles_solution__:
    #for fluid in CoolProp.__incompressibles_pure__:
    skip_fluid = False
    for ignored in ["example", "iceea", "icena", "icepg"]:
        if ignored in fluid.lower():
            skip_fluid = True
    if skip_fluid:
        continue
    state = CoolProp.AbstractState("INCOMP", fluid)
    error = ""
    for frac in [0.5, 0.2, 0.8, 0.1, 0.9]:
        error = ""
        try:
            state.set_mass_fractions([frac])
            state.update(CoolProp.PT_INPUTS, p, state.Tmax())
            break
        except Exception as e:
            error = e.message
            try:
                state.set_volu_fractions([frac])
                state.update(CoolProp.PT_INPUTS, p, state.Tmax())
                break
            except Exception as e:
                error = e.message
    Nominal compressor power consumption: 3.4 kW
    Evaporating temperature (K): 247-274
    Condensing temperature (K): 316-342
    Suction temperature (K): 290-292
    Discharge temperature (K): 364-415
    Refrigerant type: R22
    'a_etav':[1.35,-0.2678,-0.0106,0.7195], #Volumetric eff. coeff.
    'a_etais':[1,0.0753,0.2183,0.0015,0.0972], #Isentropic eff. coeff.
    'a_etaoi':[1,-0.1642,0.2050,0.0659,0.7669], #Overall eff. coeff.    
    
    """
    
    #Abstract State 
    Ref = 'R134a'
    Backend = 'HEOS' #choose between: 'HEOS','TTSE&HEOS','BICUBIC&HEOS','REFPROP','SRK','PR'
    AS = CP.AbstractState(Backend, Ref)
    
    Tsat_ev = 270 #[K]
    DT_sh = 7 + 8 #[K]
    
    AS.update(CP.QT_INPUTS, 1, Tsat_ev)
    pin_r = AS.p() #[Pa]
    
    Tsat_cd = 320 #[K]
    DT_sc = 8 #[K]

    AS.update(CP.QT_INPUTS, 1, Tsat_cd)
    pout_r = AS.p() #[Pa]
    
    # Compressor inlet temperature
    Tin_r = Tsat_ev + DT_sh
예제 #21
0
def get_speed_data():

    H_TP = 350e3
    P_TP = 400e3

    H_SP = 250e3
    P_SP = 1000e3

    P_PT = 101325
    T_PT = 300

    fluid = 'R245fa'
    number = 50000
    repeat = 3
    version = CoolProp.__version__

    if int(CoolProp.__version__[0]) > 4:
        loaded = 5
        print("Loaded CoolProp version 5")
        from CoolProp.CoolProp import generate_update_pair, get_parameter_index, set_debug_level
        TTSE = CoolProp.AbstractState('TTSE&HEOS', fluid)
        BICUBIC = CoolProp.AbstractState('BICUBIC&HEOS', fluid)
        HEOS = CoolProp.AbstractState('HEOS', fluid)

        def two_phase_TTSE():
            TTSE.update(CoolProp.HmassP_INPUTS, H_TP, P_TP)
            TTSE.rhomolar()

        def single_phase_TTSE():
            TTSE.update(CoolProp.HmassP_INPUTS, H_SP, P_SP)
            TTSE.rhomolar()

        def single_phase_pT_TTSE():
            TTSE.update(CoolProp.PT_INPUTS, P_PT, T_PT)
            TTSE.rhomolar()

        def two_phase_BICUBIC():
            BICUBIC.update(CoolProp.HmassP_INPUTS, H_TP, P_TP)
            BICUBIC.rhomolar()

        def single_phase_BICUBIC():
            BICUBIC.update(CoolProp.HmassP_INPUTS, H_SP, P_SP)
            BICUBIC.rhomolar()

        def single_phase_pT_BICUBIC():
            BICUBIC.update(CoolProp.PT_INPUTS, P_PT, T_PT)
            BICUBIC.rhomolar()

        def two_phase_HEOS():
            HEOS.update(CoolProp.HmassP_INPUTS, H_TP, P_TP)
            HEOS.rhomolar()

        def single_phase_HEOS():
            HEOS.update(CoolProp.HmassP_INPUTS, H_SP, P_SP)
            HEOS.rhomolar()

        def single_phase_pT_HEOS():
            HEOS.update(CoolProp.PT_INPUTS, P_PT, T_PT)
            HEOS.rhomolar()

    else:
        loaded = 4
        print("Loaded CoolProp version 4")
        #from CoolProp.CoolProp import set_debug_level,set_standard_unit_system,enable_TTSE_LUT,disable_TTSE_LUT
        CoolProp.CoolProp.set_standard_unit_system(CoolProp.UNIT_SYSTEM_SI)
        state = CoolProp.State.State(fluid, {"H": H_TP * 2, "P": P_TP})

        def two_phase_HP():
            state.update({"H": H_TP, "P": P_TP})
            state.get_rho()

        def single_phase_HP():
            state.update({"H": H_SP, "P": P_SP})
            state.get_rho()

        def single_phase_PT():
            state.update({"P": P_PT, "T": T_PT})
            state.get_rho()

    if loaded == 4:
        CoolProp.CoolProp.disable_TTSE_LUT(fluid)
        two_phase_hp_heos = min(
            timeit.Timer(two_phase_HP).repeat(repeat=repeat,
                                              number=number)) / number * 1e6
        single_phase_hp_heos = min(
            timeit.Timer(single_phase_HP).repeat(repeat=repeat,
                                                 number=number)) / number * 1e6
        single_phase_pt_heos = min(
            timeit.Timer(single_phase_PT).repeat(repeat=repeat,
                                                 number=number)) / number * 1e6
        CoolProp.CoolProp.enable_TTSE_LUT(fluid)
        two_phase_hp_ttse = min(
            timeit.Timer(two_phase_HP).repeat(repeat=repeat,
                                              number=number)) / number * 1e6
        single_phase_hp_ttse = min(
            timeit.Timer(single_phase_HP).repeat(repeat=repeat,
                                                 number=number)) / number * 1e6
        single_phase_pt_ttse = min(
            timeit.Timer(single_phase_PT).repeat(repeat=repeat,
                                                 number=number)) / number * 1e6
        CoolProp.CoolProp.disable_TTSE_LUT(fluid)
    elif loaded == 5:
        two_phase_hp_heos = min(
            timeit.Timer(two_phase_HEOS).repeat(repeat=repeat,
                                                number=number)) / number * 1e6
        single_phase_hp_heos = min(
            timeit.Timer(single_phase_HEOS).repeat(
                repeat=repeat, number=number)) / number * 1e6
        single_phase_pt_heos = min(
            timeit.Timer(single_phase_pT_HEOS).repeat(
                repeat=repeat, number=number)) / number * 1e6
        two_phase_hp_ttse = min(
            timeit.Timer(two_phase_TTSE).repeat(repeat=repeat,
                                                number=number)) / number * 1e6
        single_phase_hp_ttse = min(
            timeit.Timer(single_phase_TTSE).repeat(
                repeat=repeat, number=number)) / number * 1e6
        single_phase_pt_ttse = min(
            timeit.Timer(single_phase_pT_TTSE).repeat(
                repeat=repeat, number=number)) / number * 1e6
        two_phase_hp_bicubic = min(
            timeit.Timer(two_phase_BICUBIC).repeat(
                repeat=repeat, number=number)) / number * 1e6
        single_phase_hp_bicubic = min(
            timeit.Timer(single_phase_BICUBIC).repeat(
                repeat=repeat, number=number)) / number * 1e6
        single_phase_pt_bicubic = min(
            timeit.Timer(single_phase_pT_BICUBIC).repeat(
                repeat=repeat, number=number)) / number * 1e6
    else:
        raise ValueError("Unknown CoolProp version.")

    return locals()
예제 #22
0
# ts_plot_water = PropsPlot('Water', 'Ts')
# ts_plot_water.title('Ts Graph for Water')
# ts_plot_water.xlabel(r's $[{kJ}/{kg K}]$')
# ts_plot_water.ylabel(r'T $[K]$')
# ts_plot_water.grid()
# ts_plot_water.savefig('images/Water_Ts.pdf')

# ph_plot_water = PropsPlot('Water', 'Ph')
# ax = ph_plot_water.axis
# ax.set_yscale('log')
# ax.text(400, 5500, 'Saturated Liquid', fontsize=15, rotation=40)
# ax.text(2700, 3500, 'Saturated Vapour', fontsize=15, rotation=-100)
# ph_plot_water.savefig('images/Water_Ph.pdf')

# ref_fluid = 'R600a'
# fig = pyplot.figure(1, figsize=(10, 10), dpi=100)
# for i, gtype in enumerate(['PT', 'PD', 'PS', 'PH', 'TD', 'TS', 'HS']):
#     ax = pyplot.subplot(4, 2, i+1)
#     if gtype.startswith('P'):
#         ax.set_yscale('log')
#     props_plot = PropsPlot(ref_fluid, gtype, axis=ax)
#     props_plot.title(gtype)
#     props_plot._draw_graph()
# fig.set_tight_layout(True) #pyplot.tight_layout()
# fig.savefig('images/comined_R600a.pdf') #pyplot.savefig('images/comined_R600a.pdf')

print CP.PropsSI("P","T",306.3265564,"Q",0,"R407C")
print CP.PhaseSI("T",306.3265564,"P",100000,"R407C")
print CP.PropsSI('I', 'T', 200, 'Q', 0, "R407C")
print CP.saturation_ancillary("R407C",'I',1,'T', 200)
print get_svn_revision(sys.path)
예제 #23
0
import CoolProp
import pandas
grouping = dict()
grouping2 = []
# Group aliases
for parameter in CoolProp.get('parameter_list').split(','):

    index = CoolProp.CoolProp.get_parameter_index(parameter)
    units = CoolProp.CoolProp.get_parameter_information(index,
                                                        'units').replace(
                                                            '-', ' ')
    IO = CoolProp.CoolProp.get_parameter_information(index, 'IO')
    long = CoolProp.CoolProp.get_parameter_information(index, 'long')
    short = CoolProp.CoolProp.get_parameter_information(index, 'short')
    trivial = str(CoolProp.CoolProp.is_trivial_parameter(index))

    RHS = (units, IO, trivial, long)
    if RHS not in grouping:
        grouping[RHS] = [parameter]
    else:
        grouping[RHS].append(parameter)

for k, v in grouping.iteritems():
    grouping2.append([', '.join(['``' + _ + '``' for _ in v])] + list(k))

headers = ['Parameter', 'Units', 'Input/Output', 'Trivial', 'Description']

df3 = pandas.DataFrame(grouping2, columns=headers)
df4 = df3.sort_values(by=['Input/Output', 'Parameter'])
grouping2 = [row for row in df4.values]
예제 #24
0
 def Calculate(self):
     #AbstractState
     if hasattr(self,'Backend'): #check if backend is given
         AS = CP.AbstractState(self.Backend, self.Ref)
     else: #otherwise, use the defualt backend
         AS = CP.AbstractState('HEOS', self.Ref)
     self.AS = AS
     
     #Local copies of coefficients
     P=self.P
     M=self.M
     
     #Calculate suction superheat and dew temperatures
     AS.update(CP.PQ_INPUTS, self.pin_r, 1.0)
     self.Tsat_s_K=AS.T() #[K]
     
     AS.update(CP.PQ_INPUTS, self.pout_r, 1.0)
     self.Tsat_d_K=AS.T() #[K]
     self.DT_sh_K=self.Tin_r-self.Tsat_s_K
     
     #Convert saturation temperatures in K to F
     Tsat_s = self.Tsat_s_K * 9/5 - 459.67
     Tsat_d = self.Tsat_d_K * 9/5 - 459.67
 
     #Apply the 10 coefficient ARI map to saturation temps in F
     power_map = P[0] + P[1] * Tsat_s + P[2] * Tsat_d + P[3] * Tsat_s**2 + P[4] * Tsat_s * Tsat_d + P[5] * Tsat_d**2 + P[6] * Tsat_s**3 + P[7] * Tsat_d * Tsat_s**2 + P[8] * Tsat_d**2*Tsat_s + P[9] * Tsat_d**3
     mdot_map = M[0] + M[1] * Tsat_s + M[2] * Tsat_d + M[3] * Tsat_s**2 + M[4] * Tsat_s * Tsat_d + M[5] * Tsat_d**2 + M[6] * Tsat_s**3 + M[7] * Tsat_d * Tsat_s**2 + M[8] * Tsat_d**2*Tsat_s + M[9] * Tsat_d**3
 
     # Convert mass flow rate to kg/s from lbm/h
     mdot_map *= 0.000125998 
 
     # Add more mass flow rate to scale
     mdot_map*=self.Vdot_ratio
     power_map*=self.Vdot_ratio
 
     P1 = self.pin_r
     P2 = self.pout_r
     T1_actual = self.Tsat_s_K + self.DT_sh_K
     T1_map = self.Tsat_s_K + 20 * 5 / 9
 
     AS.update(CP.PT_INPUTS, P1, T1_map)
     v_map = 1 / AS.rhomass() #[m^3/kg]
     s1_map = AS.smass() #[J/kg-K]
     h1_map = AS.hmass() #[J/kg]
     
     AS.update(CP.PT_INPUTS, P1, T1_actual)
     s1_actual = AS.smass() #[J/kg-K]
     h1_actual = AS.hmass() #[J/kg]
     v_actual = 1 / AS.rhomass() #[m^3/kg]
     F = 0.75
     mdot = (1 + F * (v_map / v_actual - 1)) * mdot_map
     
     AS.update(CP.PSmass_INPUTS, P2, s1_map)
     h2s_map = AS.hmass() #[J/kg]        
     
     AS.update(CP.PSmass_INPUTS, P2, s1_actual)
     h2s_actual = AS.hmass() #[J/kg]
 
     #Shaft power based on 20F superheat calculation from fit overall isentropic efficiency
     power = power_map * (mdot / mdot_map) * (h2s_actual - h1_actual) / (h2s_map - h1_map)
 
     h2 = power * (1 - self.fp) / mdot + h1_actual
     self.eta_oi=mdot*(h2s_actual-h1_actual)/(power)
     
     AS.update(CP.HmassP_INPUTS, h2, P2)
     self.Tout_r = AS.T() #[K]
     self.sout_r = AS.smass() #[J/kg-K]        
     
     self.sin_r = s1_actual
     self.hout_r = h2
     self.hin_r = h1_actual
     self.mdot_r=mdot
     self.W=power
     self.CycleEnergyIn=power*(1-self.fp)
     self.Vdot_pumped= mdot*v_actual
     self.Q_amb=-self.fp*power
예제 #25
0
import CoolProp as CP
import pylab, numpy as np

from ACHP.Correlations import ShahEvaporation_Average

x = np.linspace(0, 1, 1000)
h = np.zeros_like(x)
TsatL, TsatV = 300., 300.
AS = CP.AbstractState('HEOS', 'R134a')
AS.update(CP.QT_INPUTS, 0.0, TsatL)
p = AS.p()  #[Pa]
for i in range(len(x)):
    h[i] = ShahEvaporation_Average(x[i], x[i], AS, 300, 0.01, p, 200, TsatL,
                                   TsatV)

havg = np.trapz(h, x=x)
pylab.figure(figsize=(7, 5))
pylab.axhline(havg, ls='--')
pylab.text(0.2, havg, r'$\alpha_{avg}$', ha='center', va='bottom')
pylab.text(
    0.7, 1300,
    'R134a\nG=300 kg/m$^2$\nD=0.01 m\nq\"=200 W/m$^2$\np=%0.1f kPa' %
    (p / 1000))
pylab.gca().set_xlabel('x [-]')
pylab.gca().set_ylabel(r'$\alpha$ [W/m$^2$/K]')
pylab.plot(x, h)
pylab.title('Shah Evaporation HTC as a function of quality')
pylab.show()
예제 #26
0
    number = float(number)
    short = "{0:.4e}".format(number)
    long  = "{0:.14e}".format(number)
    return u':raw-html:`<span title="{1}">{0}</span>`'.format(short,long)

class Dossier:
    def __init__(self):
        self.data = {}
    def add(self, key, value):
        if key not in self.data:
            self.data[key] = []
        self.data[key].append(value)

d = Dossier()

pairs = CoolProp.get('mixture_binary_pairs_list')
for pair in pairs.split(','):
    CAS1, CAS2 = pair.split('&')
    d.add('CAS1', CAS1)
    d.add('CAS2', CAS2)
    for key in ['name1','name2','F','function','BibTeX','xi','zeta','betaT','betaV','gammaT','gammaV']:
        try:
            d.add(key, CoolProp.CoolProp.get_mixture_binary_pair_data(CAS1, CAS2, key))
        except BaseException as BE:
            d.add(key, '')

import pandas
df = pandas.DataFrame(d.data)
df = df.sort(['BibTeX','name1'], ascending = [0, 1])

bibtexer = getBibtexParser()#filename = '../../../CoolPropBibTeXLibrary.bib')
예제 #27
0
    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),
                         ('FinsType', str, None, None),
                         ('mdot_r', float, 0.00001, 20),
                         ('Tin_r', float, 200, 500),
                         ('psat_r', float, 0.01, 20000000)]
            optFields = ['Verbosity', 'Backend']
            ValidateFields(self.__dict__, reqFields, optFields)
            self.IsValidated = True

        #AbstractState
        if hasattr(self, 'Backend'):  #check if backend is given
            AS = CP.AbstractState(self.Backend, self.Ref)
        else:  #otherwise, use the defualt backend
            AS = CP.AbstractState('HEOS', self.Ref)
        self.AS = AS

        # 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)
        AS.update(CP.PQ_INPUTS, self.psat_r, 0.0)
        self.Tbubble = AS.T()  #[K]
        self.h_l = AS.hmass()  #[J/kg]
        self.cp_satL = AS.cpmass()  #[J/kg-K]

        AS.update(CP.PQ_INPUTS, self.psat_r, 1.0)
        self.Tdew = AS.T()  #[K]
        self.h_v = AS.hmass()  #[J/kg]

        # 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)

        #define known parameters
        AS.update(CP.PT_INPUTS, self.psat_r, self.Tin_r)
        self.hin_r = AS.hmass()  #[J/kg]
        self.sin_r = AS.smass()  #[J/kg-K]

        #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

        if self.existsSubcooled == True:
            AS.update(CP.PT_INPUTS, self.psat_r, self.Tout_r)
            self.hout_r = AS.hmass()  #[J/kg]
            self.sout_r = AS.smass()  #[J/kg-K]
        else:
            self.Tout_r = self.xout_2phase * self.Tdew + (
                1 - self.xout_2phase) * self.Tbubble
            AS.update(CP.QT_INPUTS, 0.0, self.Tout_r)
            h_l = AS.hmass()  #[J/kg]
            s_l = AS.smass()  #[J/kg-K]
            AS.update(CP.QT_INPUTS, 1.0, self.Tout_r)
            h_v = AS.hmass()  #[J/kg]
            s_v = AS.smass()  #[J/kg-K]
            self.hout_r = h_l + self.xout_2phase * (h_v - h_l)
            self.sout_r = s_l + self.xout_2phase * (s_v - s_l)
            #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