예제 #1
0
    def getCp(self, T):

        if self.useConstantProperties:
            if self.constantCpIsSet == False:
                print(
                    "FATAL ERROR setConstartCp must be defined if constant properties are used"
                )
                sys.exit(0)
            else:
                return self.constantCp
        else:
            try:
                if newVersion == True:
                    return PropsSI("C", "T", T + 273.15, "P", self.pressure,
                                   self.name)
                else:
                    return Props("C", "T", T + 273.15, "P", self.pressure,
                                 self.name) * 1000.0

            except:
                if newVersion == True:
                    return PropsSI("C", "T", T + 0.01 + 273.15, "P",
                                   self.pressure, self.name)
                else:
                    try:
                        return Props("C", "T", T + 273.15, "P", self.pressure,
                                     self.name) * 1000.0
                    except:
                        return Props("C", "T", T + 0.01 + 273.15, "P",
                                     self.pressure, self.name) * 1000.0
예제 #2
0
파일: PHEHX.py 프로젝트: birdol/MCool
def WyattPHEHX():
        
    Tdew=Props('T','P',962.833,'Q',1.0,'R134a')
    params={
        'Ref_c':'R134a',
        'mdot_c':0.073,
        'pin_c':962.833,
        'hin_c':Props('H','T',Tdew,'Q',0.0,'R134a')*1000,
        'xin_c':0.0,
        
        'Ref_h':'Water',
        'mdot_h':100.017,
        'pin_h':Props('P','T',115.5+273.15,'Q',1,'Water'),
        'hin_h':Props('H','T',115.5+273.15,'Q',1,'Water')*1000,
        
        #Geometric parameters
        'Bp' : 0.119,
        'Lp' : 0.526, #Center-to-center distance between ports
        'Nplates' : 110,
        'PlateAmplitude' : 0.00102, #[m]
        'PlateThickness' : 0.0003, #[m]
        'PlateWavelength' : 0.0066, #[m]
        'InclinationAngle' : pi/3,#[rad]
        'PlateConductivity' : 15.0, #[W/m-K]
        'MoreChannels' : 'Hot', #Which stream gets the extra channel, 'Hot' or 'Cold'
    
        'Verbosity':10
    }
    PHE=PHEHXClass(**params)
    PHE.Calculate()
예제 #3
0
파일: PHEHX.py 프로젝트: birdol/MCool
def SWEPVariedmdot():
    Tin=8+273.15
    for mdot_h in [0.4176,0.5013,0.6267,0.8357,1.254,2.508]:
        params={
            'Ref_c':'R290',
            'mdot_c':0.03312,
            'pin_c':Props('P','T',Tin,'Q',1.0,'R290'),
            'hin_c':Props('H','T',Tin,'Q',0.15,'R290')*1000,
            
            'Ref_h':'Water',
            'mdot_h':mdot_h,
            'pin_h':200,
            'hin_h':Props('H','T',15+273.15,'P',200,'Water')*1000,
            
            #Geometric parameters
            'Bp' : 0.101,
            'Lp' : 0.455, #Center-to-center distance between ports
            'Nplates' : 46,
            'PlateAmplitude' : 0.00102, #[m]
            'PlateThickness' : 0.0003, #[m]
            'PlateWavelength' : 0.00626, #[m]
            'InclinationAngle' : 65/180*pi,#[rad]
            'PlateConductivity' : 15.0, #[W/m-K]
            'MoreChannels' : 'Hot', #Which stream gets the extra channel, 'Hot' or 'Cold'
        
            'Verbosity':0
        }
        PHE=PHEHXClass(**params)
        PHE.Calculate()
        print PHE.Q,',',PHE.h_subcooled_h,',',-PHE.DP_h/1000
예제 #4
0
    def getCp(self, T):

        if (self.useConstantProperties):
            if (self.constantCpIsSet == False):
                print(
                    "FATAL ERROR setConstartCp must be defined if constant properties are used"
                )
                sys.exit(0)
            else:
                return self.constantCp
        else:
            try:
                if (newVersion == True):
                    return (PropsSI('C', 'T', T + 273.15, 'P', self.pressure,
                                    self.name))
                else:
                    return (Props('C', 'T', T + 273.15, 'P', self.pressure,
                                  self.name) * 1000.)

            except:
                if (newVersion == True):
                    return (PropsSI('C', 'T', T + 0.01 + 273.15, 'P',
                                    self.pressure, self.name))
                else:
                    try:
                        return (Props('C', 'T', T + 273.15, 'P', self.pressure,
                                      self.name) * 1000.)
                    except:
                        return (Props('C', 'T', T + 0.01 + 273.15, 'P',
                                      self.pressure, self.name) * 1000.)
예제 #5
0
    def getLambda(self, T):

        if (self.useConstantProperties):
            if (self.constantMuIsSet == False):
                print(
                    "FATAL ERROR setConstartMu must be defined if constant properties are used"
                )
                sys.exit(0)
            else:
                return self.constantMu
        else:
            try:
                if (newVersion == True):
                    return (PropsSI('L', 'T', T + 273.15, 'P', self.pressure,
                                    self.name))
                else:
                    return (Props('L', 'T', T + 273.15, 'P', self.pressure,
                                  self.name))
            except:
                print("Error in Lambda T:%f" % T)
                if (newVersion == True):
                    return (PropsSI('L', 'T', T + 0.1 + 273.15, 'P',
                                    self.pressure, self.name) * 1000.)
                else:
                    return (Props('L', 'T', T + 0.1 + 273.15, 'P',
                                  self.pressure, self.name) * 1000.)
예제 #6
0
def TwoPhaseDensity(Ref, xmin, xmax, Tdew, Tbubble, slipModel='Zivi'):
    rhog = Props('D', 'T', Tdew, 'Q', 1, Ref)
    rhof = Props('D', 'T', Tbubble, 'Q', 0, Ref)

    if slipModel == 'Zivi':
        S = pow(rhof / rhog, 0.3333)
    elif slipModel == 'Homogeneous':
        S = 1
    else:
        raise ValueError("slipModel must be either 'Zivi' or 'Homogeneous'")
    C = S * rhog / rhof

    if xmin + 5 * machine_eps < 0 or xmax - 5 * machine_eps > 1.0:
        raise ValueError('Quality must be between 0 and 1')
    #Avoid the zero and one qualities (undefined integral)
    if xmin == xmax:
        alpha_average = 1 / (1 + C * (1 - xmin) / xmin)
    else:
        if xmin >= 1.0:
            alpha_average = 1.0
        elif xmax <= 0.0:
            alpha_average = 0.0
        else:
            alpha_average = -(C * (log(
                ((xmax - 1.0) * C - xmax) /
                ((xmin - 1.0) * C - xmin)) + xmax - xmin) - xmax + xmin) / (
                    C**2 - 2 * C + 1) / (xmax - xmin)
    return alpha_average * rhog + (1 - alpha_average) * rhof
예제 #7
0
    def getLambda(self, T):

        if self.useConstantProperties:
            if self.constantMuIsSet == False:
                print(
                    "FATAL ERROR setConstartMu must be defined if constant properties are used"
                )
                sys.exit(0)
            else:
                return self.constantMu
        else:
            try:
                if newVersion == True:
                    return PropsSI("L", "T", T + 273.15, "P", self.pressure,
                                   self.name)
                else:
                    return Props("L", "T", T + 273.15, "P", self.pressure,
                                 self.name)
            except:
                print("Error in Lambda T:%f" % T)
                if newVersion == True:
                    return PropsSI("L", "T", T + 0.1 + 273.15, "P",
                                   self.pressure, self.name) * 1000.0
                else:
                    return Props("L", "T", T + 0.1 + 273.15, "P",
                                 self.pressure, self.name) * 1000.0
예제 #8
0
 def __init__(self, Ref, IPF):
     self.Ref = Ref
     self.IPF = IPF
     self.RefString, self.N0, self.T0, self.D0, self.L0 = get_fluid_constants(Ref)
     self.Tc = Props(self.RefString,'Tcrit')
     self.rhoc = Props(self.RefString,'rhocrit')
     molemass = Props(self.RefString,'molemass')
     self.R = 8.314472/ molemass
예제 #9
0
def fit_hs(fluid):
    T = np.linspace(Props(fluid, 'Tmin'), Props(fluid, 'Tcrit') - 2)
    sL = Props('S', 'T', T, 'Q', 0, fluid)
    hL = Props('H', 'T', T, 'Q', 0, fluid)
    a = np.polyfit(sL, hL, 4)
    n = range(4, -1, -1)

    d = dict(a_hs_satL=list(a), n_hs_satL=list(n))
    return d
예제 #10
0
파일: PHEHX.py 프로젝트: birdol/MCool
 def _OnePhaseH_OnePhaseC_Qimposed(self,Inputs):
     """
     Single phase on both sides
     Inputs is a dict of parameters
     """
     
     #Calculate the mean temperature
     Tmean_h=Inputs['Tmean_h']
     Tmean_c=Inputs['Tmean_c']
     #Evaluate heat transfer coefficient for both fluids
     h_h,cp_h,PlateOutput_h=self.PlateHTDP(self.Ref_h, Tmean_h, Inputs['pin_h'],self.mdot_h/self.NgapsHot)
     h_c,cp_c,PlateOutput_c=self.PlateHTDP(self.Ref_c, Tmean_c, Inputs['pin_c'],self.mdot_c/self.NgapsCold)
     
     #Use cp calculated from delta h/delta T
     cp_h=Inputs['cp_h']
     cp_c=Inputs['cp_c']
     #Evaluate UA [W/K] if entire HX was in this section 
     UA_total=1/(1/(h_h*self.A_h_wetted)+1/(h_c*self.A_c_wetted)+self.PlateThickness/(self.PlateConductivity*(self.A_c_wetted+self.A_h_wetted)/2.))
     #Get Ntu [-]
     C=[cp_c*self.mdot_c,cp_h*self.mdot_h]
     Cmin=min(C)
     Cr=Cmin/max(C)
     
     #Effectiveness [-]
     Q=Inputs['Q']
     Qmax=Cmin*(Inputs['Tin_h']-Inputs['Tin_c'])
     epsilon = Q/Qmax
     
     #Pure counterflow with Cr<1 (Incropera Table 11.4)
     NTU=1/(Cr-1)*log((epsilon-1)/(epsilon*Cr-1))
     
     #Required UA value
     UA_req=Cmin*NTU
     
     #w is required part of heat exchanger for this duty
     w=UA_req/UA_total
     
     #Determine both charge components
     rho_h=Props('D','T',Tmean_h, 'P', self.pin_h, self.Ref_h)
     Charge_h = w * self.V_h * rho_h
     rho_c=Props('D','T',Tmean_c, 'P', self.pin_c, self.Ref_c)
     Charge_c = w * self.V_c * rho_c
     
     #Pack outputs
     Outputs={
         'w': w,
         'Tout_h': Inputs['Tin_h']-Q/(self.mdot_h*cp_h),
         'Tout_c': Inputs['Tin_c']-Q/(self.mdot_c*cp_c),
         'Charge_c': Charge_c,
         'Charge_h': Charge_h,
         'DP_h': -PlateOutput_h['DELTAP'],
         'DP_c': -PlateOutput_c['DELTAP'],
         'h_h':h_h,
         'h_c':h_c,
         
     }
     return dict(Inputs.items()+Outputs.items())
예제 #11
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,1e-6,100000),
                    ('Fins',IsFinsClass,None,None),
                    ('hin_r',float,-100000,10000000),
                    ('mdot_r',float,0.000001,10),
                    ]
         optFields=['Verbosity']
         d=self.__dict__ #Current fields in model
         ValidateFields(d,reqFields,optFields)
         self.IsValidated=True
         
     # Retrieve some parameters from nested structures 
     # for code compactness
     self.ID=self.Fins.Tubes.ID
     self.OD=self.Fins.Tubes.OD
     self.Ltube=self.Fins.Tubes.Ltube
     self.NTubes_per_bank=self.Fins.Tubes.NTubes_per_bank
     self.Nbank=self.Fins.Tubes.Nbank
     self.Ncircuits=self.Fins.Tubes.Ncircuits
     self.Tin_a=self.Fins.Air.Tdb
     
     # 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]
     
     """
     Tsat() is a relatively slow function since it does a Dekker solve
     over the full two-phase region.  So store the value in order to cut
     down on computational work. 
     """
     ## Bubble and dew temperatures (same for fluids without glide) 
     self.Tbubble_r=Props('T','P',self.psat_r,'Q',0,self.Ref)
     self.Tdew_r=Props('T','P',self.psat_r,'Q',1,self.Ref)
     ## Mean temperature for use in HT relationships
     self.Tsat_r=(self.Tbubble_r+self.Tdew_r)/2
     # Latent heat
     self.h_fg=(Props('H','T',self.Tdew_r,'Q',1.0,self.Ref)-Props('H','T',self.Tbubble_r,'Q',0.0,self.Ref))*1000. #[J/kg]
     
     self.Fins.Air.RHmean=self.Fins.Air.RH
     self.Fins.h_tp_tuning= self.h_tp_tuning #pass tuning factor
     WavyLouveredFins(self.Fins)
     self.mdot_ha=self.Fins.mdot_ha #[kg_ha/s]
     self.mdot_da=self.Fins.mdot_da #[kg_da/s]
예제 #12
0
    def _Superheat_Forward(self, w_superheat):
        self.w_superheat = w_superheat
        DWS = DWSVals()  #DryWetSegment structure

        # Store temporary values to be passed to DryWetSegment
        DWS.A_a = self.Fins.A_a * w_superheat
        DWS.cp_da = self.Fins.cp_da
        DWS.eta_a = self.Fins.eta_a
        DWS.h_a = self.Fins.h_a  #Heat transfer coefficient
        DWS.mdot_da = self.mdot_da * w_superheat
        DWS.pin_a = self.Fins.Air.p
        DWS.Fins = self.Fins

        # Inputs on the air side to two phase region are inlet air again
        DWS.Tin_a = self.Tin_a
        DWS.RHin_a = self.Fins.Air.RH

        DWS.Tin_r = self.Tdew_r
        DWS.A_r = self.A_r_wetted * w_superheat
        DWS.cp_r = Props(
            'C', 'T', self.Tdew_r + 2.5, 'P', self.psat_r, self.Ref
        ) * 1000  #Use a guess value of 6K superheat to calculate cp
        DWS.pin_r = self.psat_r
        DWS.mdot_r = self.mdot_r
        DWS.IsTwoPhase = False

        #Use a guess value of 6K superheat to calculate the properties
        self.f_r_superheat, self.h_r_superheat, self.Re_r_superheat = f_h_1phase_Tube(
            self.mdot_r / self.Ncircuits, self.ID, self.Tdew_r + 3,
            self.psat_r, self.Ref, "Single")

        # Average Refrigerant heat transfer coefficient
        DWS.h_r = self.h_r_superheat

        #Run DryWetSegment
        DryWetSegment(DWS)

        rho_superheat = Props('D', 'T', (DWS.Tout_r + self.Tdew_r) / 2.0, 'P',
                              self.psat_r, self.Ref)
        self.Charge_superheat = w_superheat * self.V_r * rho_superheat

        #Pressure drop calculations for subcooled refrigerant
        v_r = 1 / rho_superheat
        #Pressure gradient using Darcy friction factor
        dpdz_r = -self.f_r_superheat * v_r * self.G_r**2 / (
            2 * self.ID)  #Pressure gradient
        self.DP_r_superheat = dpdz_r * self.Lcircuit * self.w_superheat

        #Set values
        self.Q_superheat = DWS.Q
        self.Q_sensible_superheat = DWS.Q_sensible
        self.fdry_superheat = DWS.f_dry
        self.Tout_a_superheat = DWS.Tout_a
        self.Tout_r = DWS.Tout_r
예제 #13
0
 def __init__(self, Ref):
     self.Ref = Ref
     self.RefString, N0, T0, D0, L0 = get_fluid_constants(Ref)
     self.molemass = Props(self.RefString, 'molemass')
     self.Tc = Props(self.RefString, 'Tcrit')
     self.rhoc = Props(self.RefString, 'rhocrit')
     self.pc = Props(self.RefString, 'pcrit')
     self.T = np.linspace(100, 450, 200)
     self.tau = self.Tc / self.T
     self.C = Props('C', 'T', self.T, 'D', 1e-15, self.RefString)
     R = 8.314472 / self.molemass
     self.cp0_R = self.C / R
예제 #14
0
파일: PHEHX.py 프로젝트: birdol/MCool
    def DetermineHTBounds(self):
        # See if each phase could change phase if it were to reach the
        # inlet temperature of the opposite phase 
        
        #Inlet phases
        self.Tin_h,rhoin_h,Phasein_h=TrhoPhase_ph(self.Ref_h,self.pin_h,self.hin_h,self.Tbubble_h,self.Tdew_h,self.rhosatL_h,self.rhosatV_h)
        self.Tin_c,rhoin_c,Phasein_c=TrhoPhase_ph(self.Ref_c,self.pin_c,self.hin_c,self.Tbubble_c,self.Tdew_c,self.rhosatL_c,self.rhosatV_c)
        
        # Find the maximum possible rate of heat transfer as the minimum of 
        # taking each stream to the inlet temperature of the other stream
        hout_h=Props('H','T',self.Tin_c,'P',self.pin_h,self.Ref_h)*1000
        hout_c=Props('H','T',self.Tin_h,'P',self.pin_c,self.Ref_c)*1000
        Qmax=min([self.mdot_c*(hout_c-self.hin_c),self.mdot_h*(self.hin_h-hout_h)])
        if Qmax<0:
            raise ValueError('Qmax in PHE must be > 0')
        
        # Now we need to check for internal pinch points where the temperature
        # profiles would tend to overlap given the "normal" definitions of 
        # maximum heat transfer of taking each stream to the inlet temperature 
        # of the other stream
        #
        # First we build the same vectors of enthalpies like below
        EnthalpyList_c,EnthalpyList_h=self.BuildEnthalpyLists(Qmax)
        # Then we find the temperature of each stream at each junction
        TList_c=np.zeros_like(EnthalpyList_c)
        TList_h=np.zeros_like(EnthalpyList_h)

        if not len(EnthalpyList_h)==len(EnthalpyList_c):
            raise ValueError('Length of enthalpy lists for both fluids must be the same')
        
        #Make the lists of temperatures of each fluid at each cell boundary
        for i in range(len(EnthalpyList_h)):
            TList_c[i]=TrhoPhase_ph(self.Ref_c,self.pin_c,EnthalpyList_c[i],self.Tbubble_c,self.Tdew_c,self.rhosatL_c,self.rhosatV_c)[0]
            TList_h[i]=TrhoPhase_ph(self.Ref_h,self.pin_h,EnthalpyList_h[i],self.Tbubble_h,self.Tdew_h,self.rhosatL_h,self.rhosatV_h)[0]

#        #Double-check that the edges are not pinched
#        if TList_c[0]-1e-9>TList_h[0] or TList_c[-1]-1e-9>TList_h[-1]:
#            raise ValueError('Outlet or inlet of PHE is pinching.  Why?')
        
        #TODO: could do with more generality if both streams can change phase
        #Check if any internal points are pinched
        if np.sum(TList_c>TList_h)>0:
            #Loop over the internal cell boundaries
            for i in range(1,len(TList_c)-1):
                #If cold stream is hotter than the hot stream
                if TList_c[i]-1e-9>TList_h[i]:
                    #Find new enthalpy of cold stream at the hot stream cell boundary
                    hpinch=Props('H','T',TList_h[i],'P',self.pin_c,self.Ref_c)*1000
                    #Find heat transfer of hot stream in right-most cell
                    Qextra=self.mdot_h*(EnthalpyList_h[i+1]-EnthalpyList_h[i])
                    Qmax=self.mdot_c*(hpinch-self.hin_c)+Qextra
        
        return Qmax
예제 #15
0
파일: LineSet.py 프로젝트: birdol/MCool
    def Calculate(self):
        if not IsFluidType(self.Ref, 'Brine'):
            #Figure out the inlet state
            self.Tbubble = Props('T', 'P', self.pin, 'Q', 0.0, self.Ref)
            self.Tdew = Props('T', 'P', self.pin, 'Q', 1.0, self.Ref)
        else:
            #It is a brine
            self.Tbubble = None
            self.Tdew = None
        self.Tin, self.rhoin, self.Phasein = TrhoPhase_ph(
            self.Ref, self.pin, self.hin, self.Tbubble, self.Tdew)
        self.f_fluid, self.h_fluid, self.Re_fluid = f_h_1phase_Tube(
            self.mdot, self.ID, self.Tin, self.pin, self.Ref)
        # Specific heat capacity [J/kg-K]
        cp = Props('C', 'T', self.Tin, 'P', self.pin, self.Ref) * 1000
        # Density [kg/m^3]
        rho = Props('D', 'T', self.Tin, 'P', self.pin, self.Ref)

        #Thermal resistance of tube
        R_tube = log(self.OD / self.ID) / (2 * pi * self.L * self.k_tube)
        #Thermal resistance of insulation
        R_insul = log((self.OD + 2.0 * self.t_insul) /
                      self.OD) / (2 * pi * self.L * self.k_insul)
        #Convective UA for inside the tube
        UA_i = pi * self.ID * self.L * self.h_fluid
        #Convective UA for the air-side
        UA_o = pi * (self.OD + 2 * self.t_insul) * self.L * self.h_air

        #Avoid the possibility of division by zero if h_air is zero
        if UA_o < 1e-12:
            UA_o = 1e-12

        #Overall UA value
        UA = 1 / (1 / UA_i + R_tube + R_insul + 1 / UA_o)

        #Outlet fluid temperature [K]
        self.Tout = self.T_air - exp(
            -UA / (self.mdot * cp)) * (self.T_air - self.Tin)
        #Overall heat transfer rate [W]
        self.Q = self.mdot * cp * (self.Tout - self.Tin)
        self.hout = self.hin + self.Q / self.mdot

        #Pressure drop calculations for superheated refrigerant
        v = 1. / rho
        G = self.mdot / (pi * self.ID**2 / 4.0)
        #Pressure gradient using Darcy friction factor
        dpdz = -self.f_fluid * v * G**2 / (2. * self.ID)  #Pressure gradient
        self.DP = dpdz * self.L

        #Charge in Line set [kg]
        self.Charge = pi * self.ID**2 / 4.0 * self.L * rho
예제 #16
0
def f_h_1phase_Channel(mdot, W, H, T, p, Fluid, Phase):

    if Phase == "SatVap":
        mu = Props('V', 'T', T, 'Q', 1, Fluid)  #kg/m-s
        cp = Props('C', 'T', T, 'Q', 1, Fluid) * 1000.  #J/kg-K
        k = Props('L', 'T', T, 'Q', 1, Fluid) * 1000.  #W/m-K
        rho = Props('D', 'T', T, 'Q', 1, Fluid)  #kg/m^3
    else:
        mu = Props('V', 'T', T, 'P', p, Fluid)
        ##kg/m-s
        cp = Props('C', 'T', T, 'P', p, Fluid) * 1000.  #J/kg-K
        k = Props('L', 'T', T, 'P', p, Fluid) * 1000.  #W/m-K
        rho = Props('D', 'T', T, 'P', p, Fluid)  #kg/m^3

    Pr = cp * mu / k  #[-]

    Dh = 2 * H * W / (H + W)
    Area = W * H
    u = mdot / (Area * rho)
    Re = rho * u * (Dh) / mu

    # Friction factor of Churchill (Darcy Friction factor where f_laminar=64/Re)
    e_D = 0
    A = ((-2.457 * log((7.0 / Re)**(0.9) + 0.27 * e_D)))**16
    B = (37530.0 / Re)**16
    f = 8 * ((8 / Re)**12.0 + 1 / (A + B)**(1.5))**(1 / 12)

    # Heat Transfer coefficient of Gnielinski for high Re,
    if Re > 1000:
        Nu = (f / 8) * (Re - 1000.) * Pr / (1 + 12.7 * sqrt(f / 8) *
                                            (Pr**(0.66666) - 1))  #[-]
    else:
        Nu = 3.66
    h = k * Nu / Dh  #W/m^2-K
    return (f, h, Re)
예제 #17
0
def f_h_1phase_Annulus(mdot, OD, ID, T, p, Fluid, Phase='Single'):
    """
    
    """
    if Phase == "SatVap":
        mu = Props('V', 'T', T, 'Q', 1, Fluid)  #kg/m-s
        cp = Props('C', 'T', T, 'Q', 1, Fluid) * 1000.  #J/kg-K
        k = Props('L', 'T', T, 'Q', 1, Fluid) * 1000.  #W/m-K
        rho = Props('D', 'T', T, 'Q', 1, Fluid)  #kg/m^3
    else:
        mu = Props('V', 'T', T, 'P', p, Fluid)  #kg/m-s
        cp = Props('C', 'T', T, 'P', p, Fluid) * 1000.  #J/kg-K
        k = Props('L', 'T', T, 'P', p, Fluid) * 1000.  #W/m-K
        rho = Props('D', 'T', T, 'P', p, Fluid)  #kg/m^3

    Pr = cp * mu / k  #[-]

    Dh = OD - ID
    Area = pi * (OD**2 - ID**2) / 4.0
    u = mdot / (Area * rho)
    Re = rho * u * Dh / mu

    # Friction factor of Churchill (Darcy Friction factor where f_laminar=64/Re)
    e_D = 0
    A = ((-2.457 * log((7.0 / Re)**(0.9) + 0.27 * e_D)))**16
    B = (37530.0 / Re)**16
    f = 8 * ((8 / Re)**12.0 + 1 / (A + B)**(1.5))**(1 / 12)

    # Heat Transfer coefficient of Gnielinski
    Nu = (f / 8) * (Re - 1000) * Pr / (1 + 12.7 * sqrt(f / 8) *
                                       (Pr**(0.66666) - 1))  #[-]
    h = k * Nu / Dh  #W/m^2-K
    return (f, h, Re)
예제 #18
0
def LMPressureGradientAvg(x_min,
                          x_max,
                          Ref,
                          G,
                          D,
                          Tbubble,
                          Tdew,
                          C=None,
                          satTransport=None):
    """
    Returns the average pressure gradient between qualities of x_min and x_max.
    
    To obtain the pressure gradient for a given value of x, pass it in as x_min and x_max
    
    Required parameters:
    * x_min : The minimum quality for the range [-]
    * x_max : The maximum quality for the range [-]
    * Ref : String with the refrigerant name
    * G : Mass flux [kg/m^2/s]
    * D : Diameter of tube [m]
    * Tbubble : Bubblepoint temperature of refrigerant [K]
    * Tdew : Dewpoint temperature of refrigerant [K]
    
    Optional parameters:
    * C : The coefficient in the pressure drop
    * satTransport : A dictionary with the keys 'mu_f','mu_g,'v_f','v_g' for the saturation properties.  So they can be calculated once and passed in for a slight improvement in efficiency 
    """
    def LMFunc(x):
        dpdz, alpha = LockhartMartinelli(Ref, G, D, x, Tbubble, Tdew, C,
                                         satTransport)
        return dpdz

    ## Use Simpson's Rule to calculate the average pressure gradient
    ## Can't use adapative quadrature since function is not sufficiently smooth
    ## Not clear why not sufficiently smooth at x>0.9
    if x_min == x_max:
        return LMFunc(x_min)
    else:
        #Calculate the tranport properties once
        satTransport = {}
        satTransport['v_f'] = 1 / Props('D', 'T', Tbubble, 'Q', 0.0, Ref)
        satTransport['v_g'] = 1 / Props('D', 'T', Tdew, 'Q', 1.0, Ref)
        satTransport['mu_f'] = Props('V', 'T', Tbubble, 'Q', 0.0, Ref)
        satTransport['mu_g'] = Props('V', 'T', Tdew, 'Q', 1.0, Ref)

        xx = np.linspace(x_min, x_max, 30)
        DP = np.zeros_like(xx)
        for i in range(len(xx)):
            DP[i] = LMFunc(xx[i])
        return -simps(DP, xx) / (x_max - x_min)
예제 #19
0
def test_subcrit_twophase_consistency():

    for Fluid in reversed(sorted(CoolProp.__fluids__)):
        Tmin = Props(Fluid, 'Tmin')
        Tcrit = Props(Fluid, 'Tcrit')
        for T in [Tmin + 1, (Tmin + Tcrit) / 2.0, 0.95 * Tcrit]:
            for mode in modes:
                rhoL = Props('D', 'T', T, 'Q', 0, Fluid)
                rhoV = Props('D', 'T', T, 'Q', 1, Fluid)
                for Q in [0.0, 0.5, 1.0]:
                    rho = 1 / ((1 - Q) / rhoL + Q / rhoV)
                    for inputs in twophase_inputs:
                        for unit_system in ['kSI', 'SI']:
                            yield check_consistency, Fluid, mode, unit_system, T, rho, inputs
예제 #20
0
def LongoCondensation(x_avg, G, dh, Ref, TsatL, TsatV):
    rho_L = Props('D', 'T', TsatL, 'Q', 0, Ref)  #kg/m^3
    rho_V = Props('D', 'T', TsatV, 'Q', 1, Ref)  #kg/m^3
    mu_L = Props('V', 'T', TsatL, 'Q', 0, Ref)  #kg/m-s
    cp_L = Props('C', 'T', TsatL, 'Q', 0, Ref) * 1000  #J/kg-K
    k_L = Props('L', 'T', TsatV, 'Q', 0, Ref) * 1000  #W/m-K
    Pr_L = cp_L * mu_L / k_L  #[-]

    Re_eq = G * ((1 - x_avg) + x_avg * sqrt(rho_L / rho_V)) * dh / mu_L

    if Re_eq < 1750:
        Nu = 60 * Pr_L**(1 / 3)
    else:
        Nu = ((75 - 60) / (3000 - 1750) * (Re_eq - 1750) + 60) * Pr_L**(1 / 3)
    h = Nu * k_L / dh
    return h
예제 #21
0
def hsatVmax(fluid):
    Tmin = Props(fluid, 'Tmin')
    Tmax = Props(fluid, 'Tcrit')

    def OBJECTIVE(T):
        return -Props('H', 'T', T, 'Q', 1, fluid)

    T = scipy.optimize.minimize_scalar(OBJECTIVE,
                                       bounds=(Tmin, Tmax),
                                       method='Bounded').x

    h = Props('H', 'T', T, 'Q', 1, fluid)
    s = Props('S', 'T', T, 'Q', 1, fluid)
    rho = Props('D', 'T', T, 'Q', 1, fluid)

    return h * 1000, T, s * 1000, rho
예제 #22
0
 def _Superheat_Forward(self,w_superheat,T_inlet_r=-99):
     if T_inlet_r==-99:  #catch if default case is used
         T_inlet_r=self.Tdew_r
     self.w_superheat=w_superheat
     DWS=DWSVals() #DryWetSegment structure
 
     # Store temporary values to be passed to DryWetSegment
     DWS.A_a=self.Fins.A_a*w_superheat
     DWS.cp_da=self.Fins.cp_da
     DWS.eta_a=self.Fins.eta_a
     DWS.h_a=self.Fins.h_a  #Heat transfer coefficient
     DWS.mdot_da=self.mdot_da*w_superheat
     DWS.pin_a=self.Fins.Air.p
     DWS.Fins=self.Fins
 
     # Inputs on the air side to two phase region are inlet air again
     DWS.Tin_a=self.Tin_a
     DWS.RHin_a=self.Fins.Air.RH
 
     DWS.Tin_r=T_inlet_r  #default is dew temperature; can change to consider for initial superheat
     DWS.A_r=self.A_r_wetted*w_superheat
     DWS.cp_r=self.cp_r
     DWS.pin_r=self.psat_r
     DWS.mdot_r=self.mdot_r
     DWS.IsTwoPhase=False
     
     #Use a guess value of 6K superheat to calculate the properties
     self.f_r_superheat, self.h_r_superheat, self.Re_r_superheat=f_h_1phase_Tube(self.mdot_r / self.Ncircuits, self.ID, 
         self.Tdew_r+3, self.psat_r, self.Ref, "Single");
     
     # Average Refrigerant heat transfer coefficient
     DWS.h_r=self.h_r_superheat
     
     #Run DryWetSegment
     DryWetSegment(DWS)
     try:
         rho_superheat=Props('D','T',(DWS.Tout_r+self.Tdew_r)/2.0, 'P', self.psat_r, self.Ref)
         #members = [attr for attr in dir(DWS()) if not callable(attr) and not attr.startswith("__")]
         #print members
     except:
         print "error in Evaporator, unreasonable inputs?","Inputs to calculate density are DWS.Tout_r,self.Tdew_r,self.psat_r",DWS.Tout_r,self.Tdew_r,self.psat_r,"<<"
         print "DWS values are", 'DWS.A_a',DWS.A_a,'DWS.Tin_r',DWS.Tin_r,'DWS.mdot_da',DWS.mdot_da,"DWS.mdot_r",DWS.mdot_r,'DWS.mdot_da',DWS.mdot_da,'DWS.mdot_r',DWS.mdot_r
         print "plot DWS vals to figure out what is going on"
         raise()
     self.Charge_superheat = w_superheat * self.V_r * rho_superheat
     
     #Pressure drop calculations for subcooled refrigerant
     v_r=1/rho_superheat
     #Pressure gradient using Darcy friction factor
     dpdz_r=-self.f_r_superheat*v_r*self.G_r**2/(2*self.ID)  #Pressure gradient
     self.DP_r_superheat=dpdz_r*self.Lcircuit*self.w_superheat
     
     #Set values
     self.Q_superheat=DWS.Q
     self.Q_sensible_superheat=DWS.Q_sensible
     self.fdry_superheat=DWS.f_dry
     self.Tout_a_superheat=DWS.Tout_a
     self.Tout_r=DWS.Tout_r
     self.omega_out_superheat=DWS.omega_out
예제 #23
0
    def getTemperature(self, h):

        if newVersion == True:
            return PropsSI("T", "H", h / 1000.0, "P", self.pressure,
                           self.name) - 273.15
        else:
            return Props("T", "H", h / 1000.0, "P", self.pressure,
                         self.name) - 273.15
예제 #24
0
파일: genetic.py 프로젝트: lgpage/coolprop
 def __init__(self,
            num_samples = 80, # Have 60 chromos in the sample group
            num_selected = 20, # Have 10 chromos in the selected group
            mutation_factor = 2, # Randomly mutate 1/n of the chromosomes
            num_powers = 4, # How many powers in the fit
            Ref = 'REFPROP-R134a',
            value = 'rhoV',
            addTr = False
             ):
     self.num_samples = num_samples
     self.num_selected = num_selected
     self.mutation_factor = mutation_factor
     self.num_powers = num_powers
     self.addTr = addTr
     self.value = value
     self.Ref = Ref 
     
     #THermodynamics
     from CoolProp.CoolProp import Props
     self.Tc = Props(Ref,'Tcrit')
     self.pc = Props(Ref,'pcrit')
     self.rhoc = Props(Ref,'rhocrit')
     self.Tmin = Props(Ref,'Tmin')
     
     self.T = np.linspace(self.Tmin+1e-6, self.Tc-0.000001,200)
     self.p = [Props('P','T',T,'Q',0,Ref) for T in self.T]
     self.rhoL = [Props('D','T',T,'Q',0,Ref) for T in self.T]
     self.rhoV = [Props('D','T',T,'Q',1,Ref) for T in self.T]
     self.logppc = (np.log(self.p)-np.log(self.pc))
     self.rhoLrhoc = np.array(self.rhoL)/self.rhoc
     self.rhoVrhoc = np.array(self.rhoV)/self.rhoc
     self.logrhoLrhoc = np.log(self.rhoL)-np.log(self.rhoc)
     self.logrhoVrhoc = np.log(self.rhoV)-np.log(self.rhoc)
예제 #25
0
    def getTemperature(self, h):

        if (newVersion == True):
            return (
                PropsSI('T', 'H', h / 1000., 'P', self.pressure, self.name) -
                273.15)
        else:
            return (Props('T', 'H', h / 1000., 'P', self.pressure, self.name) -
                    273.15)
예제 #26
0
 def evaluate_REFPROP(self, Ref, T, rho):
     
     p,cp,cv,w = [],[],[],[]
     R = 8.314472/Props(Ref,'molemass')
     for _T,_rho in zip(T, rho):
         p.append(Props("P",'T',_T,'D',_rho,Ref))
         cp.append(Props("C",'T',_T,'D',_rho,Ref))
         cv.append(Props("O",'T',_T,'D',_rho,Ref))
         w.append(Props("A",'T',_T,'D',_rho,Ref))
         
     class stub: pass
     PPF = stub()
     PPF.p = np.array(p, ndmin = 1).T 
     PPF.cp = np.array(cp, ndmin = 1).T 
     PPF.cv = np.array(cv, ndmin = 1).T 
     PPF.w = np.array(w, ndmin = 1).T 
     
     return PPF
예제 #27
0
def AccelPressureDrop(x_min,
                      x_max,
                      Ref,
                      G,
                      Tbubble,
                      Tdew,
                      rhosatL=None,
                      rhosatV=None,
                      slipModel='Zivi'):
    """
    Accelerational pressure drop
    
    From -dpdz|A=G^2*d[x^2v_g/alpha+(1-x)^2*v_f/(1-alpha)^2]/dz
    
    Integrating over z from 0 to L where x=x_1 at z=0 and x=x_2 at z=L
    
    Maxima code:
        alpha:1/(1+S*rho_g/rho_f*(1-x)/x)$
        num1:x^2/rho_g$
        num2:(1-x)^2/rho_f$
        subst(num1/alpha+num2/(1-alpha),x,1);
        subst(num1/alpha+num2/(1-alpha),x,0);
    """
    if rhosatL == None or rhosatV == None:
        rhosatL = Props('D', 'T', Tbubble, 'Q', 0.0, Ref)
        rhosatV = Props('D', 'T', Tdew, 'Q', 1.0, Ref)

    def f(x, rhoL, rhoV):
        if abs(x) < 1e-12:
            return 1 / rhosatL
        elif abs(1 - x) < 1e-12:
            return 1 / rhosatV
        else:
            if slipModel == 'Zivi':
                S = pow(rhoL / rhoV, 1 / 3)
            elif slipModel == 'Homogeneous':
                S = 1
            else:
                raise ValueError(
                    "slipModel must be either 'Zivi' or 'Homogeneous'")
            alpha = 1 / (1 + S * rhoV / rhoL * (1 - x) / x)
            return x**2 / rhoV / alpha + (1 - x)**2 / rhoL / (1 - alpha)

    return G**2 * (f(x_min, rhosatL, rhosatV) - f(x_max, rhosatL, rhosatV))
예제 #28
0
def saturation_pressure_brute(Ref, ClassName):

    Tc = Props(Ref, 'Tcrit')
    pc = Props(Ref, 'pcrit')
    rhoc = Props(Ref, 'rhocrit')
    Tmin = Props(Ref, 'Tmin')

    TT = np.linspace(Tmin + 1e-6, Tc - 0.00001, 300)
    p = np.array([Props('P', 'T', T, 'Q', 0, Ref) for T in TT])
    rhoL = np.array([Props('D', 'T', T, 'Q', 0, Ref) for T in TT])
    rhoV = np.array([Props('D', 'T', T, 'Q', 1, Ref) for T in TT])

    Np = 10

    max_abserror = 99999
    bbest = []

    x = 1.0 - TT / Tc
    y = (np.log(rhoL) - np.log(rhoc)) * TT / Tc

    def f_p(B, x):
        # B is a vector of the parameters.
        # x is an array of the current x values.
        return sum([_B * x**(_n) for _B, _n in zip(B, b)])

    linear = Model(f_p)
    mydata = Data(x, y)

    for attempt in range(300):

        n = [i / 6.0 for i in range(1, 100)] + [
            0.35 + i / 200.0 for i in range(1, 70)
        ] + [0.05 + 0.01 * i for i in range(1, 70)]
        b = []
        for _ in range(6):
            i = random.randint(0, len(n) - 1)
            b.append(n.pop(i))

        myodr = ODR(mydata, linear, beta0=[1] * len(b))
        myoutput = myodr.run()

        b = np.array(b)

        keepers = np.abs(myoutput.sd_beta / myoutput.beta) < 0.1
        if any(keepers):
            b = b[keepers]

        myodr = ODR(mydata, linear, beta0=[1] * len(b))
        myoutput = myodr.run()

        rho_fit = np.exp(f_p(myoutput.beta, x) * Tc / TT) * rhoc
        abserror = np.max(np.abs(rho_fit / rhoL - 1)) * 100
        print('.')
        if abserror < max_abserror:
            max_abserror = abserror
            bbest = b
            betabest = myoutput.beta
            print("%s %s %s" % (abserror, myoutput.sum_square,
                                myoutput.sd_beta / myoutput.beta))
예제 #29
0
def check_consistency(Fluid, mode, unit_system, T, rho, inputs):

    if unit_system == 'SI':
        set_standard_unit_system(unit_systems_constants.UNIT_SYSTEM_SI)
    elif unit_system == 'kSI':
        set_standard_unit_system(unit_systems_constants.UNIT_SYSTEM_KSI)
    else:
        raise ValueError('invalid unit_system:' + str(unit_system))

    if get_REFPROPname(Fluid) == 'N/A':
        return

    if mode == 'REFPROP':
        Fluid = 'REFPROP-' + get_REFPROPname(Fluid)

    if mode == 'pure' and not IsFluidType(Fluid, 'PureFluid'):
        return

    #  Evaluate the inputs; if inputs is ('T','P'), calculate the temperature and the pressure
    Input1 = Props(inputs[0], 'T', T, 'D', rho, Fluid)
    Input2 = Props(inputs[1], 'T', T, 'D', rho, Fluid)

    #  Evaluate using the inputs given --> back to T,rho
    TEOS = Props('T', inputs[0], Input1, inputs[1], Input2, Fluid)
    DEOS = Props('D', inputs[0], Input1, inputs[1], Input2, Fluid)

    print 'T', inputs[0], Input1, inputs[1], Input2, Fluid
    #  Check they are consistent
    if abs(TEOS - T) > 1e-1 or abs(DEOS / rho - 1) > 0.05:
        raise AssertionError(
            "{T:g} K {D:g} kg/m^3 inputs: \"D\",'{ins1:s}',{in1:.12g},'{ins2:s}',{in2:.12g},\"{fluid:s}\"  || T: {TEOS:g} D: {DEOS:g}"
            .format(T=T,
                    D=rho,
                    TEOS=TEOS,
                    DEOS=DEOS,
                    inputs=str(inputs),
                    in1=Input1,
                    in2=Input2,
                    ins1=inputs[0],
                    ins2=inputs[1],
                    fluid=Fluid))
예제 #30
0
파일: Condenser.py 프로젝트: birdol/MCool
    def _Superheat_Forward(self):

        # **********************************************************************
        #                      SUPERHEATED PART
        # **********************************************************************
        #Dew temperature for constant pressure cooling to saturation
        Tdew = self.Tdew

        # Average fluid temps are used for the calculation of properties
        # Average temp of refrigerant is average of sat. temp and outlet temp
        # Secondary fluid is air over the fins
        self.f_r_superheat, self.h_r_superheat, self.Re_r_superheat = f_h_1phase_Tube(
            self.mdot_r / self.Ncircuits, self.ID, (Tdew + self.Tin_r) / 2.0,
            self.psat_r, self.Ref, "Single")

        cp_r = Props('C', 'T', (Tdew + self.Tin_r) / 2, 'P', self.psat_r,
                     self.Ref) * 1000.  #//[J/kg-K]

        WavyLouveredFins(self.Fins)
        self.mdot_da = self.Fins.mdot_da

        # Cross-flow in the superheated region.
        # Using effectiveness-Ntu relationships for cross flow with non-zero Cr.
        UA_overall = 1. / (1. /
                           (self.Fins.eta_a * self.Fins.h_a * self.Fins.A_a) +
                           1. / (self.h_r_superheat * self.A_r_wetted))
        epsilon_superheat = (Tdew - self.Tin_r) / (self.Tin_a - self.Tin_r)
        Ntu = UA_overall / (self.mdot_da * self.Fins.cp_da)
        if epsilon_superheat > 1.0:
            epsilon_superheat = 1.0 - 1e-12
        self.w_superheat = -log(1 - epsilon_superheat) * self.mdot_r * cp_r / (
            (1 - exp(-Ntu)) * self.mdot_da * self.Fins.cp_da)

        # Positive Q is heat input to the refrigerant, negative Q is heat output from refrigerant.
        # Heat is removed here from the refrigerant since it is being cooled
        self.Q_superheat = self.mdot_r * cp_r * (Tdew - self.Tin_r)

        rho_superheat = Props('D', 'T', (self.Tin_r + Tdew) / 2.0, 'P',
                              self.psat_r, self.Ref)
        #Pressure drop calculations for superheated refrigerant
        v_r = 1. / rho_superheat
        #Pressure gradient using Darcy friction factor
        dpdz_r = -self.f_r_superheat * v_r * self.G_r**2 / (
            2. * self.ID)  #Pressure gradient
        self.DP_r_superheat = dpdz_r * self.Lcircuit * self.w_superheat
        self.Charge_superheat = self.w_superheat * self.V_r * rho_superheat

        #Latent heat needed for pseudo-quality calc
        Tbubble = Props('T', 'P', self.psat_r, 'Q', 0, self.Ref)
        Tdew = Props('T', 'P', self.psat_r, 'Q', 1, self.Ref)
        h_fg = (Props('H', 'T', Tdew, 'Q', 1, self.Ref) -
                Props('H', 'T', Tbubble, 'Q', 0, self.Ref)) * 1000  #J/kg
        self.hin_r = Props('H', 'T', self.Tin_r, 'P', self.psat_r,
                           self.Ref) * 1000
        self.xin_r = 1.0 + cp_r * (self.Tin_r - Tdew) / h_fg
예제 #31
0
파일: genetic.py 프로젝트: EVT1982/coolprop
    def __init__(
        self,
        num_samples=100,  # Have this many chromos in the sample group
        num_selected=20,  # Have this many chromos in the selected group
        mutation_factor=2,  # Randomly mutate 1/n of the chromosomes
        num_powers=5,  # How many powers in the fit
        Ref="R407C",
        value="rhoV",
        addTr=True,
        values=None,
        Tlims=None,
    ):
        self.num_samples = num_samples
        self.num_selected = num_selected
        self.mutation_factor = mutation_factor
        self.num_powers = num_powers
        self.addTr = addTr
        self.value = value
        self.Ref = Ref

        # Thermodynamics
        from CoolProp.CoolProp import Props

        if values is None:
            self.Tc = Props(Ref, "Tcrit")
            self.pc = Props(Ref, "pcrit")
            self.rhoc = Props(Ref, "rhocrit")
            self.Tmin = Props(Ref, "Tmin")
            if Tlims is None:
                self.T = np.append(
                    np.linspace(self.Tmin + 1e-14, self.Tc - 1, 150),
                    np.logspace(np.log10(self.Tc - 1), np.log10(self.Tc) - 1e-15, 40),
                )
            else:
                self.T = np.linspace(Tlims[0], Tlims[1])
            self.pL = Props("P", "T", self.T, "Q", 0, Ref)
            self.pV = Props("P", "T", self.T, "Q", 1, Ref)
            self.rhoL = Props("D", "T", self.T, "Q", 0, Ref)
            self.rhoV = Props("D", "T", self.T, "Q", 1, Ref)
        else:
            self.Tc = values["Tcrit"]
            self.pc = values["pcrit"]
            self.rhoc = values["rhocrit"]
            self.Tmin = values["Tmin"]
            self.T = values["T"]
            self.p = values["p"]
            self.rhoL = values["rhoL"]
            self.rhoV = values["rhoV"]

        self.logpLpc = np.log(self.pL) - np.log(self.pc)
        self.logpVpc = np.log(self.pV) - np.log(self.pc)
        self.rhoLrhoc = np.array(self.rhoL) / self.rhoc
        self.rhoVrhoc = np.array(self.rhoV) / self.rhoc
        self.logrhoLrhoc = np.log(self.rhoL) - np.log(self.rhoc)
        self.logrhoVrhoc = np.log(self.rhoV) - np.log(self.rhoc)

        self.x = 1.0 - self.T / self.Tc

        MM = Props(Ref, "molemass")
        self.T_r = self.Tc

        if self.value == "pL":
            self.LHS = self.logpLpc.copy()
            self.EOS_value = self.pL.copy()
            if self.addTr == False:
                self.description = "p' = pc*exp(sum(n_i*theta^t_i))"
            else:
                self.description = "p' = pc*exp(Tc/T*sum(n_i*theta^t_i))"
            self.reducing_value = self.pc * 1000
        elif self.value == "pV":
            self.LHS = self.logpVpc.copy()
            self.EOS_value = self.pV.copy()
            if self.addTr == False:
                self.description = "p'' = pc*exp(sum(n_i*theta^t_i))"
            else:
                self.description = "p'' = pc*exp(Tc/T*sum(n_i*theta^t_i))"
            self.reducing_value = self.pc * 1000
        elif self.value == "rhoL":
            self.LHS = self.logrhoLrhoc.copy()
            self.EOS_value = self.rhoL
            if self.addTr == False:
                self.description = "rho' = rhoc*exp(sum(n_i*theta^t_i))"
            else:
                self.description = "rho' = rhoc*exp(Tc/T*sum(n_i*theta^t_i))"
            self.reducing_value = self.rhoc / MM * 1000
        elif self.value == "rhoV":
            self.LHS = self.logrhoVrhoc.copy()
            self.EOS_value = self.rhoV
            if self.addTr == False:
                self.description = "rho'' = rhoc*exp(sum(n_i*theta^t_i))"
            else:
                self.description = "rho'' = rhoc*exp(Tc/T*sum(n_i*theta^t_i))"
            self.reducing_value = self.rhoc / MM * 1000
        elif self.value == "rhoLnoexp":
            self.LHS = (self.rhoLrhoc - 1).copy()
            self.EOS_value = self.rhoL
            self.description = "rho' = rhoc*(1+sum(n_i*theta^t_i))"
            self.reducing_value = self.rhoc / MM * 1000
        else:
            raise ValueError

        if self.value == "rhoLnoexp" and self.addTr:
            raise ValueError("Invalid combination")

        if self.addTr:
            self.LHS *= self.T / self.Tc
예제 #32
0
def saturation_pressure(Ref, ClassName, fName=None, LV=None):

    if fName is None:
        Tc = Props(Ref, 'Tcrit')
        pc = Props(Ref, 'pcrit')
        rhoc = Props(Ref, 'rhocrit')
        Tmin = Props(Ref, 'Tmin')

        TT = np.linspace(Tmin + 1e-6, Tc - 0.00001, 300)
        pL = Props('P', 'T', TT, 'Q', 0, Ref)
        pV = Props('P', 'T', TT, 'Q', 1, Ref)
        rhoL = Props('D', 'T', TT, 'Q', 0, Ref)
        rhoV = Props('D', 'T', TT, 'Q', 1, Ref)
    else:
        Tc = 423.27
        pc = 3533
        rhoc = 470
        Tmin = 273
        lines = open(fName, 'r').readlines()
        TT, p, rhoL, rhoV = [], [], [], []
        for line in lines:
            _T, _p, _rhoL, _rhoV = line.split(' ')
            TT.append(float(_T))
            p.append(float(_p))
            rhoL.append(float(_rhoL))
            rhoV.append(float(_rhoV))

        TT = np.array(TT)

    Np = 60
    n = range(1, Np)
    max_abserror = 0
    while len(n) > 3:

        def f_p(B, x):
            # B is a vector of the parameters.
            # x is an array of the current x values.
            return sum([_B * x**(_n / 2.0) for _B, _n in zip(B, n)])

        x = 1.0 - TT / Tc
        if LV == 'L':
            y = (np.log(pL) - np.log(pc)) * TT / Tc
        elif LV == 'V' or LV is None:
            y = (np.log(pV) - np.log(pc)) * TT / Tc

        linear = Model(f_p)
        mydata = Data(x, y)
        myodr = ODR(mydata, linear, beta0=[0] * len(n))
        myoutput = myodr.run()

        beta = myoutput.beta
        sd = myoutput.sd_beta

        p_fit = np.exp(f_p(myoutput.beta, x) * Tc / TT) * pc
        if LV == 'L':
            max_abserror = np.max(np.abs((p_fit / pL) - 1) * 100)
        elif LV == 'V' or LV is None:
            max_abserror = np.max(np.abs((p_fit / pV) - 1) * 100)

        print(max_abserror)
        psat_error = max_abserror

        dropped_indices = [i for i in range(len(n)) if abs(sd[i]) < 1e-15]
        if dropped_indices:
            # for i in reversed(dropped_indices):
            # randomly drop one of them
            n.pop(random.choice(dropped_indices))
            continue

        if max_abserror < 0.5:  # Max error is 0.5%
            Ncoeffs = str(list(myoutput.beta)).lstrip('[').rstrip(']')
            tcoeffs = str(n).lstrip('[').rstrip(']')
            maxerror = max_abserror
            N = len(n)
        else:
            break

        # Find the least significant entry (the one with the largest standard error)
        # and remove it
        n.pop(np.argmax(sd))

        # Remove elements that are not
    import textwrap
    template = textwrap.dedent(
    """
    double {name:s}Class::psat{LV:s}(double T)
    {{
        // Maximum absolute error is {psat_error:f} % between {Tmin:f} K and {Tmax:f} K
        const double t[]={{0, {tcoeffs:s}}};
        const double N[]={{0, {Ncoeffs:s}}};
        double summer=0,theta;
        theta=1-T/reduce.T;
        for (int i=1;i<={N:d};i++)
        {{
            summer += N[i]*pow(theta,t[i]/2);
        }}
        return reduce.p.Pa*exp(reduce.T/T*summer);
    }}
    """)
    the_string = template.format(N=len(n) + 1,
                            tcoeffs=tcoeffs,
                            Ncoeffs=Ncoeffs,
                            name=ClassName,
                            Tmin=Tmin,
                            Tmax=TT[-1],
                            psat_error=maxerror,
                            LV=LV if LV in ['L', 'V'] else ''
                            )

    f = open('anc.txt', 'a')
    f.write(the_string)
    f.close()
    return the_string
예제 #33
0
def saturation_density(Ref, ClassName, form='A', LV='L', perc_error_allowed=0.3, fName=None, add_critical=True):
    """

    Parameters
    ----------
    Ref : string
        The fluid name for the fluid that will be used to generate the saturation data
    ClassName : The name of the class that will be used in the C++ code
    form : string
        If ``'A'``, use a term of the form
    """

    if fName is None:
        Tc = Props(Ref, 'Tcrit')
        pc = Props(Ref, 'pcrit')
        rhoc = Props(Ref, 'rhocrit')
        Tmin = Props(Ref, 'Tmin')
        print("%s %s %s" % (Ref, Tmin, Props(Ref, 'Ttriple')))

        TT = np.linspace(Tmin, Tc - 1, 1000)
        TT = list(TT)
        # Add temperatures around the critical temperature
        if add_critical:
            for dT in [1e-10, 1e-9, 1e-8, 1e-7, 1e-6, 1e-5, 1e-4, 1e-3, 1e-2, 1e-1]:
                TT.append(Tc - dT)
        TT = np.array(sorted(TT))

        p = Props('P', 'T', TT, 'Q', 0, Ref)
        rhoL = Props('D', 'T', TT, 'Q', 0, Ref)
        rhoV = Props('D', 'T', TT, 'Q', 1, Ref)
    else:
        Tc = 423.27
        pc = 3533
        rhoc = 470
        Tmin = 273
        lines = open(fName, 'r').readlines()
        TT, p, rhoL, rhoV = [], [], [], []
        for line in lines:
            _T, _p, _rhoL, _rhoV = line.split(' ')
            TT.append(float(_T))
            p.append(float(_p))
            rhoL.append(float(_rhoL))
            rhoV.append(float(_rhoV))

        TT = np.array(TT)

    # Start with a large library of potential powers
    n = [i / 6.0 for i in range(1, 200)]  # +[0.35+i/200.0 for i in range(1,70)]+[0.05+0.01*i for i in range(1,70)]

    x = 1.0 - TT / Tc

    if LV == 'L':
        rho_EOS = rhoL
    elif LV == 'V':
        rho_EOS = rhoV
    else:
        raise ValueError

    if form == 'A':
        y = np.array(rho_EOS) / rhoc - 1
    elif form == 'B':
        y = (np.log(rho_EOS) - np.log(rhoc)) * TT / Tc
    else:
        raise ValueError

    max_abserror = 0
    while len(n) > 3:
        print("%s %s" % (max_abserror, len(n)))

        def f_p(B, x):
            # B is a vector of the parameters.
            # x is an array of the current x values.
            return sum([_B * x**(_n) for _B, _n in zip(B, n)])

        linear = Model(f_p)
        mydata = Data(x, y)
        myodr = ODR(mydata, linear, beta0=[0] * len(n))
        myoutput = myodr.run()

        beta = myoutput.beta
        sd = myoutput.sd_beta

        if form == 'A':
            rho_fit = (f_p(myoutput.beta, x) + 1) * rhoc
        elif form == 'B':
            rho_fit = np.exp(f_p(myoutput.beta, x) * Tc / TT) * rhoc
        else:
            raise ValueError

        print('first,last %s %s %s %s %s %s' % (TT[0], TT[-1], rho_fit[0], rho_fit[-1], rho_EOS[0], rho_EOS[-1]))

        max_abserror = np.max(np.abs(rho_fit / rho_EOS - 1)) * 100

        dropped_indices = [i for i in range(len(n)) if abs(sd[i]) < 1e-15]
        if dropped_indices:
            for i in reversed(sorted(dropped_indices)):
                n.pop(i)
            print('popping... %s terms remaining' % len(n))
            continue

        if max_abserror > perc_error_allowed:
            break  # The last good run will be used
        else:
            print(max_abserror)
            Ncoeffs = str(list(myoutput.beta)).lstrip('[').rstrip(']')
            tcoeffs = str(n).lstrip('[').rstrip(']')
            maxerror = max_abserror
            if form == 'A':
                code_template = textwrap.dedent(
                """
                for (int i=1; i<={count:d}; i++)
                {{
                    summer += N[i]*pow(theta,t[i]);
                }}
                return reduce.rho*(summer+1);
                """.format(count=len(n))
                )
            elif form == 'B':
                code_template = textwrap.dedent(
                """
                for (int i=1; i<={count:d}; i++)
                {{
                    summer += N[i]*pow(theta,t[i]);
                }}
                return reduce.rho*exp(reduce.T/T*summer);
                """.format(count=len(n))
                )
            else:
                raise ValueError

        # Find the least significant entry (the one with the largest relative standard error)
        # and remove it
        n.pop(np.argmax(np.abs(sd / beta)))

        # Remove elements that are not
    template = textwrap.dedent(
    """
    double {name:s}Class::rhosat{LV:s}(double T)
    {{
        // Maximum absolute error is {error:f} % between {Tmin:f} K and {Tmax:f} K
        const double t[] = {{0, {tcoeffs:s}}};
        const double N[] = {{0, {Ncoeffs:s}}};
        double summer=0,theta;
        theta=1-T/reduce.T;
        \t{code:s}
    }}
    """)
    the_string = template.format(tcoeffs=tcoeffs,
                            Ncoeffs=Ncoeffs,
                            name=ClassName,
                            Tmin=Tmin,
                            Tmax=TT[-1],
                            error=maxerror,
                            code=code_template,
                            LV=LV
                            )
    f = open('anc.txt', 'a')
    f.write(the_string)
    f.close()
    return the_string
예제 #34
0
파일: genetic.py 프로젝트: EVT1982/coolprop
class GeneticAncillaryFitter(object):
    def __init__(
        self,
        num_samples=100,  # Have this many chromos in the sample group
        num_selected=20,  # Have this many chromos in the selected group
        mutation_factor=2,  # Randomly mutate 1/n of the chromosomes
        num_powers=5,  # How many powers in the fit
        Ref="R407C",
        value="rhoV",
        addTr=True,
        values=None,
        Tlims=None,
    ):
        self.num_samples = num_samples
        self.num_selected = num_selected
        self.mutation_factor = mutation_factor
        self.num_powers = num_powers
        self.addTr = addTr
        self.value = value
        self.Ref = Ref

        # Thermodynamics
        from CoolProp.CoolProp import Props

        if values is None:
            self.Tc = Props(Ref, "Tcrit")
            self.pc = Props(Ref, "pcrit")
            self.rhoc = Props(Ref, "rhocrit")
            self.Tmin = Props(Ref, "Tmin")
            if Tlims is None:
                self.T = np.append(
                    np.linspace(self.Tmin + 1e-14, self.Tc - 1, 150),
                    np.logspace(np.log10(self.Tc - 1), np.log10(self.Tc) - 1e-15, 40),
                )
            else:
                self.T = np.linspace(Tlims[0], Tlims[1])
            self.pL = Props("P", "T", self.T, "Q", 0, Ref)
            self.pV = Props("P", "T", self.T, "Q", 1, Ref)
            self.rhoL = Props("D", "T", self.T, "Q", 0, Ref)
            self.rhoV = Props("D", "T", self.T, "Q", 1, Ref)
        else:
            self.Tc = values["Tcrit"]
            self.pc = values["pcrit"]
            self.rhoc = values["rhocrit"]
            self.Tmin = values["Tmin"]
            self.T = values["T"]
            self.p = values["p"]
            self.rhoL = values["rhoL"]
            self.rhoV = values["rhoV"]

        self.logpLpc = np.log(self.pL) - np.log(self.pc)
        self.logpVpc = np.log(self.pV) - np.log(self.pc)
        self.rhoLrhoc = np.array(self.rhoL) / self.rhoc
        self.rhoVrhoc = np.array(self.rhoV) / self.rhoc
        self.logrhoLrhoc = np.log(self.rhoL) - np.log(self.rhoc)
        self.logrhoVrhoc = np.log(self.rhoV) - np.log(self.rhoc)

        self.x = 1.0 - self.T / self.Tc

        MM = Props(Ref, "molemass")
        self.T_r = self.Tc

        if self.value == "pL":
            self.LHS = self.logpLpc.copy()
            self.EOS_value = self.pL.copy()
            if self.addTr == False:
                self.description = "p' = pc*exp(sum(n_i*theta^t_i))"
            else:
                self.description = "p' = pc*exp(Tc/T*sum(n_i*theta^t_i))"
            self.reducing_value = self.pc * 1000
        elif self.value == "pV":
            self.LHS = self.logpVpc.copy()
            self.EOS_value = self.pV.copy()
            if self.addTr == False:
                self.description = "p'' = pc*exp(sum(n_i*theta^t_i))"
            else:
                self.description = "p'' = pc*exp(Tc/T*sum(n_i*theta^t_i))"
            self.reducing_value = self.pc * 1000
        elif self.value == "rhoL":
            self.LHS = self.logrhoLrhoc.copy()
            self.EOS_value = self.rhoL
            if self.addTr == False:
                self.description = "rho' = rhoc*exp(sum(n_i*theta^t_i))"
            else:
                self.description = "rho' = rhoc*exp(Tc/T*sum(n_i*theta^t_i))"
            self.reducing_value = self.rhoc / MM * 1000
        elif self.value == "rhoV":
            self.LHS = self.logrhoVrhoc.copy()
            self.EOS_value = self.rhoV
            if self.addTr == False:
                self.description = "rho'' = rhoc*exp(sum(n_i*theta^t_i))"
            else:
                self.description = "rho'' = rhoc*exp(Tc/T*sum(n_i*theta^t_i))"
            self.reducing_value = self.rhoc / MM * 1000
        elif self.value == "rhoLnoexp":
            self.LHS = (self.rhoLrhoc - 1).copy()
            self.EOS_value = self.rhoL
            self.description = "rho' = rhoc*(1+sum(n_i*theta^t_i))"
            self.reducing_value = self.rhoc / MM * 1000
        else:
            raise ValueError

        if self.value == "rhoLnoexp" and self.addTr:
            raise ValueError("Invalid combination")

        if self.addTr:
            self.LHS *= self.T / self.Tc

    def generate_random_chromosomes(self,):
        """ 
        Create a list of random chromosomes to seed our alogrithm.
        """
        chromos = []
        while len(chromos) < self.num_samples:
            chromos.append(Sample(sorted(random.sample(LIBRARY, self.num_powers))))
        return chromos

    def fitness(self, chromo):
        """ 
        Fitness of a chromo is the sum of the squares of the error of the correlation
        """

        # theta^t where the i-th row is equal to theta^t[i]
        # We need these terms later on to build the A and b matrices
        theta_t = (self.x.reshape(-1, 1) ** chromo.v).T

        # TODO: more numpy broadcasting should speed this up even more
        # Another few times faster ought to be possible
        I = len(chromo.v)
        A = np.zeros((I, I))
        b = np.zeros((I, 1))
        for i in range(I):
            for j in range(I):
                A[i, j] = np.sum(theta_t[i] * theta_t[j])
            b[i] = np.sum(theta_t[i] * self.LHS)

        # If you end up with a singular matrix, quit this run
        try:
            n = np.linalg.solve(A, b).T
        except np.linalg.linalg.LinAlgError as E:
            chromo.fitness = 1e99
            return

        chromo.beta = n
        RHS = np.sum(n * self.x.reshape(-1, 1) ** chromo.v, axis=1)

        if self.addTr:
            RHS *= self.Tc / self.T

        if self.value in ["pL", "pV"]:
            fit_value = np.exp(RHS) * self.pc
        elif self.value in ["rhoL", "rhoV"]:
            fit_value = np.exp(RHS) * self.rhoc
        elif self.value == "rhoLnoexp":
            fit_value = self.rhoc * (1 + RHS)
        else:
            raise ValueError

        max_abserror = np.max(np.abs((fit_value / self.EOS_value) - 1) * 100)

        chromo.fitness = max_abserror
        chromo.fit_value = fit_value
        chromo.max_abserror = max_abserror

        return chromo.fitness

    def tourny_select_chromo(self, samples):
        """ 
        Randomly select two chromosomes from the samples, then return the one
        with the best fitness.
        """
        a = random.choice(samples)
        b = random.choice(samples)
        if a.fitness < b.fitness:
            return a
        else:
            return b

    def breed(self, a, b):
        """ 
        Breed two chromosomes by splicing them in a random spot and combining
        them together to form two new chromos.
        """
        splice_pos = random.randrange(len(a.v))
        new_a = a.v[:splice_pos] + b.v[splice_pos:]
        new_b = b.v[:splice_pos] + a.v[splice_pos:]
        return Sample(sorted(new_a)), Sample(sorted(new_b))

    def mutate(self, chromo):
        """ 
        Mutate a chromosome by changing one of the parameters, but only if it improves the fitness
        """
        v = chromo.v
        if hasattr(chromo, "fitness"):
            old_fitness = chromo.fitness
        else:
            old_fitness = self.fitness(chromo)

        for i in range(10):
            pos = random.randrange(len(chromo.v))
            chromo.v[pos] = random.choice(LIBRARY)
            new_fitness = self.fitness(chromo)
            if new_fitness < old_fitness:
                return chromo
            else:
                return Sample(sorted(v))

    def run(self):
        # Create a random sample of chromos
        samples = self.generate_random_chromosomes()

        # Calculate the fitness for the initial chromosomes
        for chromo in samples:
            self.fitness(chromo)
        #         print '#'

        decorated = [(sample.fitness, sample) for sample in samples]
        decorated.sort()
        samples = [s for sv, s in decorated]
        values = [sv for sv, s in decorated]
        plt.plot(values[0 : len(values) // 2])
        plt.close()

        # Main loop: each generation select a subset of the sample and breed from
        # them.
        generation = -1
        while generation < 0 or samples[0].fitness > 0.02 or (generation < 3 and generation < 15):
            generation += 1

            # Generate the selected group from sample- take the top 10% of samples
            # and tourny select to generate the rest of selected.
            ten_percent = int(len(samples) * 0.1)
            selected = samples[:ten_percent]
            while len(selected) < self.num_selected:
                selected.append(self.tourny_select_chromo(samples))

            # Generate the solution group by breeding random chromos from selected
            solution = []
            while len(solution) < self.num_samples:
                solution.extend(self.breed(random.choice(selected), random.choice(selected)))

            # Apply a mutation to a subset of the solution set
            mutate_indices = random.sample(range(len(solution)), len(solution) // self.mutation_factor)
            for i in mutate_indices:
                solution[i] = self.mutate(solution[i])

            for chromo in solution:
                self.fitness(chromo)
            #             print '#'

            decorated = [(sample.fitness, sample) for sample in solution]
            decorated.sort()
            samples = [s for sv, s in decorated]

            #             print '------------------  Top 10 values  ---------------'
            #             for sample in samples[0:10]:
            #                 print sample.v, sample.fitness, sample.max_abserror

            #             print '// Max error is ',samples[0].max_abserror,'% between',np.min(self.T),'and',np.max(self.T),'K'
            #             print str(samples[0].v), samples[0].beta.tolist()

            # Print useful stats about this generation
            (min, median, max) = [samples[0].fitness, samples[len(samples) // 2].fitness, samples[-1].fitness]
            #             print("{0} best value: {1}. fitness: best {2}, median {3}, worst {4}".format(generation, samples[0].v, min, median, max))

            # If the string representations of all the chromosomes are the same, stop
            if len(set([str(s.v) for s in samples[0:5]])) == 1:
                break

        self.fitness(samples[0])

        print self.value
        print "// Max error is ", samples[0].max_abserror, "% between", np.min(self.T), "and", np.max(self.T), "K"
        #         print str(samples[0].v), samples[0].beta.tolist()

        j = dict()
        j["n"] = samples[0].beta.squeeze().tolist()
        j["t"] = samples[0].v
        j["Tmin"] = np.min(self.T)
        j["Tmax"] = np.max(self.T)
        j["type"] = self.value
        j["using_tau_r"] = self.addTr
        j["reducing_value"] = self.reducing_value
        j["T_r"] = self.Tc

        # Informational, not used
        j["max_abserror_percentage"] = samples[0].max_abserror
        j["description"] = self.description

        return j