Exemplo n.º 1
0
def residualsLiBr(T,P,x,deltaT=1e-4,deltaP=1e-4):
    TT = [T, T, T + deltaT]
    PP = [P, P + deltaP, P]
    hh = [0,0,0]
    vv = [0,0,0]
    for i in range(3):
        # TODO: make this a function
        h_liquid = libr_props.massSpecificEnthalpy(T,x)
        v_liquid = 1. / libr_props.massDensity(T,x) # m3/kg
        x_liquid = libr_props.massFraction(T,P)
        cp_liquid = libr_props.massSpecificHeat(T,x)
        # Now let's figure out the other thing
        Qu = 1. - x / x_liquid
        Q_vapor = 1
        h_vap = CP.PropsSI('H','T',T,'Q',Q_vapor,'Water')
        v_vap = CP.PropsSI('D','T',T,'Q',Q_vapor,'Water')
        cp_vap = CP.PropsSI('C','T',T,'Q',Q_vapor,'Water')
        h = (1.0 - Qu) * h_liquid + Qu * h_vap
        v = (1.0 - Qu) * v_liquid + Qu * v_vap
        hh[i] = h
        vv[i] = v
    dhdp_T = (hh[1] - hh[0]) / deltaP
    dvdT_p = (vv[2] - vv[0]) / deltaT
    a = dhdp_T - (vv[0] - T * dvdT_p)    
    dhdT_p = (state3.h - state1.h) / deltaT
    b = dhdT_p - cp
    print(state1)
    print(state2)
    print(state3)
    print("a = {}. b = {}".format(a,b))
    return a,b
Exemplo n.º 2
0
 def updateSHX_hot_side(self):
     DeltaT_max = self.T_gen_outlet - self.T_abs_outlet_max
     DeltaT_SHX_concentrate = self.Eff_SHX * DeltaT_max
     self.T_SHX_concentrate_outlet = self.T_gen_outlet \
         - DeltaT_SHX_concentrate
     self.h_SHX_concentrate_outlet = libr_props.massSpecificEnthalpy(
         C2K(self.T_SHX_concentrate_outlet), self.x2)
     self.Q_SHX = self.m_concentrate \
         * (self.h_gen_outlet - self.h_SHX_concentrate_outlet)
Exemplo n.º 3
0
 def update(self, P, m_in, T_in, x_in, x_out):
     self.P = P        
     self.m_in = m_in
     self.T_in = T_in
     self.x_in = x_in
     self.x_out = x_out
     
     # Find inlet enthalpy.
     # Find saturation point at inlet concentration.
     # Find ...
     self.T_sat = K2C(libr_props.temperature(self.P * 1e-5, self.x_in))
     self.T_out = K2C(libr_props.temperature(self.P * 1e-5, self.x_out))
     self.h_sat = libr_props.massSpecificEnthalpy(C2K(self.T_sat), self.x_in)
     self.h_out = libr_props.massSpecificEnthalpy(C2K(self.T_out),self.x_out)
     
     self.cp_in = libr_props.massSpecificHeat(C2K(self.T_in),self.x_in)
     # If h_in is an input:
     if False:
         preheat = (self.h_sat - self.h_in)/self.cp_in
         self.T_in = self.T_sat - preheat
     else:
         preheat = self.T_sat - self.T_in
         self.h_in = self.h_sat - preheat * self.cp_in
     
     pwater.update(CP.PT_INPUTS, self.P, C2K(self.T_sat))
     self.h_vapor_out = pwater.hmass() - h_w_ref
     
     # Mass balance on LiBr
     self.m_out = self.m_in * self.x_in / self.x_out
     # Mass balance on Water
     self.m_vapor_out = self.m_in - self.m_out
     self.m_total = self.m_out
     
     self.Q_preheat = self.m_in * (self.h_sat - self.h_in)
     self.Q_desorb = self.m_out * self.h_out \
             + self.m_vapor_out * self.h_vapor_out \
             - self.m_in * self.h_sat
     
     
     # Determine a reasonable limit for extending the domain.
     self.Tmax = K2C(libr_props.temperature(self.P*1e-5,libr_props.xmax))
Exemplo n.º 4
0
 def _qx(self,x_local):
     T = K2C(libr_props.temperature(self.P*1e-5,x_local))
     dx = self.x_in - x_local
     # TODO
     h_local = libr_props.massSpecificEnthalpy(C2K(T),x_local)
     # And calculate
     m_vapor = self.m_in * dx / x_local
     m_out = self.m_in + m_vapor
     # Heat is inbound.
     result = -self.m_in * self.h_in - m_vapor * self.h_vapor_inlet \
         + m_out * h_local
     return T,result
Exemplo n.º 5
0
 def _q_helper(self,T):
     x_local = libr_props.massFraction(C2K(T),self.P * 1e-5)
     # Could parametrize this by x, but libr_props.temperature also has an
     # implicit solve. Only P(T,x) is explicit.
     pwater.update(CP.PT_INPUTS, self.P, C2K(T))
     h_vapor_local = pwater.hmass() - h_w_ref
     h_solution_local = libr_props.massSpecificEnthalpy(C2K(T), x_local)
     # Mass balance on LiBr
     m_solution_local = self.m_in * self.x_in / x_local
     
     hlv1 = h_vapor_local - h_solution_local
     q1 = self.m_total * h_vapor_local - m_solution_local * hlv1
     return q1
Exemplo n.º 6
0
 def _q(self,T):
     """Provide process heat canonical curve for generator in various forms.
     Assumes that
     * inlet solution state is obtained from self,
     * generated vapor is flowing in reverse direction and
     * it is everywhere in local equilibrium with solution.
     
     Args
     ----
     T : Temperature (deg C)
         The local temperature
     
     Returns
     -------
     q : Local progress index
         Measured as cumulative heat flux (W).
     Q : Total heat flux (W)
         The total amount of heat transferred into the generator.
     """
     
     hlv0 = self.h_vapor_out - self.h_sat
     q0 = self.m_total * self.h_vapor_out - self.m_in * hlv0
     
     if T < self.T_in:
         raise "Generator outlet must be greater than pre-inlet temperature!"
     elif T < self.T_sat:
         # The state is either saturated or subcooled.
         # Use linear interpolation.
         q = self.m_in * self.cp_in * (T - self.T_in)
     else:
         x_local = libr_props.massFraction(C2K(T),self.P * 1e-5)
         pwater.update(CP.PT_INPUTS, self.P, C2K(T))
         h_vapor_local = pwater.hmass() - h_w_ref
         h_solution_local = libr_props.massSpecificEnthalpy(C2K(T), x_local)
         # Mass balance on LiBr
         m_solution_local = self.m_in * self.x_in / x_local
         
         hlv1 = h_vapor_local - h_solution_local
         q1 = self.m_total * h_vapor_local - m_solution_local * hlv1
         
         q = (q1 - q0) + self.Q_preheat
     # TODO
     # If q > Q (iff T > T_solution_outlet) then result is invalid.
     return q
Exemplo n.º 7
0
 def generatorHeatCurveQ(self,T,x_out):
     """Provide process heat canonical curve for generator in various forms.
     Assumes that
     * inlet solution state is obtained from self,
     * generated vapor is flowing in reverse direction and
     * it is everywhere in local equilibrium with solution.
     
     Args
     ----
     T : Temperature (deg C)
         The local temperature
     x_out : Mass fraction (kg/kg)
         The outlet solution LiBr mass fraction
     
     Returns
     -------
     q : Local progress index
         Measured as cumulative heat flux (W).
     Q : Total heat flux (W)
         The total amount of heat transferred into the generator.
     """
     
     # We may need m_concentrate. It depends on Q -- solve from inlet.
     h_solution_inlet = self.h_gen_inlet
     h_vapor_outlet = self.h_gen_vapor_outlet
     T_solution_outlet = K2C(libr_props.temperature(self.P_cond * 1e-5,
                                            x_out))
     h_solution_outlet = libr_props.massSpecificEnthalpy(
         C2K(T_solution_outlet), x_out)
     # Mass balance on LiBr
     m_solution_outlet = self.m_pump * self.x1 / x_out
     # Mass balance on Water
     m_vapor_outlet = self.m_pump - m_solution_outlet
     m_total = m_solution_outlet
     
     hlv0 = h_vapor_outlet - h_solution_inlet
     q0 = m_total * h_vapor_outlet - self.m_pump * hlv0
     
     Q = m_solution_outlet * h_solution_outlet \
         + m_vapor_outlet * h_vapor_outlet \
         - self.m_pump * h_solution_inlet
     
     q = 0
     T0,T1,T2=self.genpoints[0][1],self.genpoints[1][1],self.genpoints[2][1]
     Q0,Q1,Q2=self.genpoints[0][0],self.genpoints[1][0],self.genpoints[2][0]
     if T < T0:
         raise "Generator outlet must be greater than pre-inlet temperature!"
     elif T < T1:
         # The state is either saturated or subcooled.
         # Use linear interpolation.
         q = (T - T0) / (T1 - T0) * (Q1 - Q0)
     else:
         x_local = libr_props.massFraction(C2K(T),self.P_cond * 1e-5)
         pwater.update(CP.PT_INPUTS, self.P_cond, C2K(T))
         h_vapor_local = pwater.hmass() - h_w_ref
         h_solution_local = libr_props.massSpecificEnthalpy(C2K(T), x_local)
         # Mass balance on LiBr
         m_solution_local = self.m_pump * self.x1 / x_local
         
         hlv1 = h_vapor_local - h_solution_local
         q1 = m_total * h_vapor_local - m_solution_local * hlv1
         
         q = (q1 - q0) + (Q1 - Q0)
     # TODO
     # If q > Q (iff T > T_solution_outlet) then result is invalid.
     return q, Q
Exemplo n.º 8
0
    def iterate1(self):
        """Update the internal parameters."""
        self.T_gen_inlet = K2C(libr_props.temperature(self.P_cond*1e-5,
                                                      self.x1))
        self.T_gen_outlet = K2C(libr_props.temperature(self.P_cond * 1e-5,
                                                   self.x2))
        self.T_abs_inlet_max = K2C(libr_props.temperature(self.P_evap * 1e-5,
                                                          self.x2))
        self.T_abs_outlet_max = K2C(libr_props.temperature(self.P_evap * 1e-5,
                                                           self.x1))
        
        self.h_gen_inlet = libr_props.massSpecificEnthalpy(
            C2K(self.T_gen_inlet), self.x1)
        self.h_gen_outlet = libr_props.massSpecificEnthalpy(
            C2K(self.T_gen_outlet), self.x2)
        self.h_abs_inlet = libr_props.massSpecificEnthalpy(
            C2K(self.T_abs_inlet_max), self.x2)
        self.h_abs_outlet = libr_props.massSpecificEnthalpy(
            C2K(self.T_abs_outlet_max), self.x1)
        
        # Mass balance on LiBr
        self.m_concentrate = self.m_pump * self.x1 / self.x2
        # Mass balance on Water
        self.m_refrig = self.m_pump - self.m_concentrate
        self.f = self.m_pump / self.m_refrig

        # Compute SHX outlets, assuming concentrate limits heat flow (C_min)
        # Neglect pump work for the present.
        DeltaT_max = self.T_gen_outlet - self.T_abs_outlet_max
        DeltaT_SHX_concentrate = self.Eff_SHX * DeltaT_max
        self.T_SHX_concentrate_outlet = self.T_gen_outlet \
            - DeltaT_SHX_concentrate
        self.h_SHX_concentrate_outlet = libr_props.massSpecificEnthalpy(
            C2K(self.T_SHX_concentrate_outlet), self.x2)
        self.Q_SHX = self.m_concentrate \
            * (self.h_gen_outlet - self.h_SHX_concentrate_outlet)
        
        # Expansion valve
        self.h_abs_pre = self.h_SHX_concentrate_outlet
        if self.h_abs_pre > self.h_abs_inlet:
            # Pre-cooling is required to reach saturation temperature
            self.Q_abs_pre_cool = self.m_concentrate \
                * (self.h_abs_pre - self.h_abs_inlet)
            q,t,xl = libr_props.twoPhaseProps(self.h_abs_pre,
                                              self.P_evap*1e-5,
                                              self.x2)
            self.T_abs_pre = K2C(t)
            self.x_abs_pre = xl
            # ignore vapor quality, q
            # Minimum vapor pressure for absorption to occur
            self.P_abs_pre = np.inf
        else:
            self.Q_abs_pre_cool = 0
            #self.T_abs_pre = K2C(CP.PropsSI('T',
            #    'H', self.h_abs_pre,
            #    'P', self.P_evap,
            #    librname(self.x2)))
            self.T_abs_pre = np.nan
            # Minimum vapor pressure for absorption to occur
#            self.P_abs_pre = CP.PropsSI('P',
#                'T', C2K(self.T_abs_pre),
#                'Q', 0,
#                librname(self.x2))
            self.P_abs_pre = np.nan
                
        # Heat rejection in absorber: energy balance
        pwater.update(CP.PQ_INPUTS, self.P_evap, 1)
        self.h_abs_vapor_inlet = pwater.hmass() - h_w_ref
        self.Q_abs_main = self.m_refrig * self.h_abs_vapor_inlet \
            + self.m_concentrate * self.h_abs_inlet \
            - self.m_pump * self.h_abs_outlet
        self.Q_abs_total = self.Q_abs_main + self.Q_abs_pre_cool
        
        # Energy balance in SHX, pump side
        D_in = CP.PropsSI('D',
            'T',C2K(self.T_abs_outlet_max),
            'Q',0,
            librname(self.x1))
        DeltaH_pump = (self.P_cond - self.P_evap) / D_in
        self.W_pump = self.m_pump * DeltaH_pump
        self.h_pump_outlet = self.h_abs_outlet + DeltaH_pump
        DeltaH_SHX_pumpside = self.Q_SHX / self.m_pump
        self.h_gen_pre = self.h_pump_outlet + DeltaH_SHX_pumpside
        if self.h_gen_pre > self.h_gen_inlet:
            # Flash steam
            self.T_gen_pre = np.nan
        else:
            # The state is either saturated or subcooled.
            # We need to calculate the temperature from specific heat.
            cp = libr_props.massSpecificHeat(C2K(self.T_gen_inlet),self.x1)
            deltaHsub = self.h_gen_inlet - self.h_gen_pre
            deltaT = deltaHsub / cp
            self.T_gen_pre = self.T_gen_inlet - deltaT
        
        self.Q_gen_pre_heat = self.m_pump * (self.h_gen_inlet - self.h_gen_pre)
        
        # Heat input to generator: energy balance
        pwater.update(CP.PT_INPUTS, self.P_cond, C2K(self.T_gen_inlet))
        self.h_gen_vapor_outlet = pwater.hmass() - h_w_ref
        self.vapor_superheat = self.T_gen_inlet - self.T_cond
        self.Q_gen_main = self.m_refrig * self.h_gen_vapor_outlet \
            + self.m_concentrate * self.h_gen_outlet \
            - self.m_pump * self.h_gen_inlet
        self.Q_gen_total = self.Q_gen_main + self.Q_gen_pre_heat
        
        # Condenser
        pwater.update(CP.PQ_INPUTS, self.P_cond, 0)
        self.h_condenser_outlet = pwater.hmass() - h_w_ref
        self.Q_condenser_reject = self.m_refrig * (self.h_gen_vapor_outlet
            - self.h_condenser_outlet)
        
        # Expansion valve
        self.h_evap_inlet = self.h_condenser_outlet
        
        # Evaporator
        self.h_evap_outlet = self.h_abs_vapor_inlet
        self.Q_evap_heat = self.m_refrig * (self.h_evap_outlet
            - self.h_evap_inlet)
        
        self.COP = self.Q_evap_heat / self.Q_gen_total
Exemplo n.º 9
0
    def __init__(self,P,m_in,h_in,x_in,h_vapor_inlet,debug=False):
        self.P=P
        self.m_in=m_in
        self.h_in=h_in
        self.x_in=x_in
        self.h_vapor_inlet = h_vapor_inlet
        
        self.T_sat = K2C(libr_props.temperature(self.P * 1e-5,
                                                          self.x_in))
        self.h_sat = libr_props.massSpecificEnthalpy(C2K(self.T_sat),self.x_in)
        
        if self.h_in > self.h_sat:
            q,t,xl = libr_props.twoPhaseProps(self.h_in,self.P*1e-5,self.x_in)
            # Pre-cooling is required to reach saturation temperature
            self.Q_pre_cool = self.m_in * (self.h_sat - self.h_in)
            self.T_in = K2C(t)
            prepoints_x = np.linspace(xl,self.x_in,20,endpoint=False)
            prepoints_T = np.zeros_like(prepoints_x)
            prepoints_q = np.zeros_like(prepoints_x)
            
            for i,x in enumerate(prepoints_x):
                #q,t,xl = libr_props.twoPhaseProps(h,self.P*1e-5,self.x_in)
                t = libr_props.temperature(self.P * 1e-5, x)
                h = libr_props.massSpecificEnthalpy(t,x)
                prepoints_T[i] = K2C(t)
                prepoints_q[i] = self.m_in * (h - self.h_in)
                prepoints_x[i] = x
        else:
            self.Q_pre_cool = 0
            self.T_in = K2C(libr_props.temperature(self.P * 1e-5, self.x_in))
            prepoints_T = []
            prepoints_q = []
            prepoints_x = []
        
        # Set up bounds and points for interpolation.
        # Absorber limit is liquid water.
        pwater.update(CP.PQ_INPUTS,P,0)
        self.Tmin = pwater.T()
        x_points = np.linspace(x_in,0.1,100)
        T_points = np.zeros_like(x_points)
        q_points = np.zeros_like(x_points)
        #q_func = np.vectorize(self._q)
        #q_points = q_func(T_points)
        for i,x in enumerate(x_points):
            T_points[i],q_points[i] = self._qx(x)

        x_points = np.concatenate([prepoints_x,x_points])
        T_points = np.concatenate([prepoints_T,T_points])
        q_points = np.concatenate([prepoints_q,q_points])
        
        # Forward function
        T_points1 = np.resize(T_points,len(T_points)+1)
        q_points1 = np.resize(q_points,len(T_points)+1)
        T_points1[-1] = T_points[-1] - 5
        q_points1[-1] = q_points[-1]
        
        # Inverse function
        T_points2 = np.resize(T_points,len(T_points)+1)
        q_points2 = np.resize(q_points,len(T_points)+1)
        T_points2[-1] = T_points[-1]
        q_points2[-1] = q_points[-1] * 1.05
        
        if debug:        
            import matplotlib.pyplot as plt
            import tabulate
            xmod = np.resize(x_points,len(x_points)+1)
            print(tabulate.tabulate(zip(xmod,T_points1,q_points1,
                                    T_points2,q_points2),
                                    headers=['x','T1','q1','T2','q2']))
            plt.figure(); plt.plot(T_points1,q_points1); plt.title("q(T)")
            plt.figure(); plt.plot(q_points2,T_points2); plt.title("T(q)")
        # Interpolate data must be in increasing order, so we reverse it
        # compared to reaction direction.
        self.q = PchipInterpolator(T_points1[::-1], q_points1[::-1])
        self.T = PchipInterpolator(q_points2[::-1], T_points2[::-1])