コード例 #1
0
def chartA(t,
           wv,
           A,
           t_range=np.arange(-10, 50, 5),
           w_range=np.arange(0, 0.030, 0.01)):
    """
    Parameters
    ----------
    t : np.array, no. equal to no. points in the psy-chart
        temperatures, °C
    wv: np.array, wv.shape = t.shape
        weight vapor, kg/kg_da
    A : np.array [no. processes, no. points = no. temperatures]
        adjancy matrix: -1 flow our of node, 1 flow in node, 0 no connection
    t_range : np.arange
        range of temperature
        the default is np.arange(-10, 50, 0.1).
        temperature vector t = np.arange(-10, 50, 0.1)
    w_range : np.arange
        humidity ration vector
        The default is np.arange(0, 0.030, 0.01).

    Returns
    -------
    None.

    """
    import matplotlib.pyplot as plt
    import psychro as psy

    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.yaxis.tick_right()
    plt.xlabel(r'Temperature $\theta$ [°C]')
    ax.yaxis.set_label_position("right")
    plt.ylabel(r'Humidity ratio w [kg/kg]')
    plt.grid(True)
    plt.plot(t_range, psy.w(t_range, 1), linewidth=2)  # saturation curve

    # Plot relative humidity curves
    for phi in np.arange(0, 1, 0.2):
        w4t = psy.w(t_range, phi)
        plt.plot(t_range, w4t, linewidth=0.5)
        phi100 = phi * 100
        s_phi = "%3.0f" % phi100
        ax.annotate(s_phi + ' %', xy=(t_range[-1] - 3, w4t[-1]))

    for k in range(0, A.shape[0]):
        tk = np.nonzero(A[k, :])
        wk = np.nonzero(A[k, :])
        plt.plot(t[tk], wv[wk], linewidth=3)  # processes
        # plot no. point
        for j in range(0, np.shape(tk)[1]):
            plt.text(t[tk][j], wv[tk][j], str(tk[0][j]))
    return None
コード例 #2
0
    def psy_chart(self, x, θo, φo):
        """
        Plot results on psychrometric chart.

        Parameters
        ----------
        x : θM, wM, θs, ws, θC, wC, θS, wS, θI, wI,
            QtCC, QsCC, QlCC, QsHC, QsTZ, QlTZ
                    results of self.solve_lin or self.m_ls
        θo, φo      outdoor point

        Returns
        -------
        None.

        """
        # Processes on psychrometric chart
        wo = psy.w(θo, φo)
        # Points: O, s, S, I
        θ = np.append(θo, x[0:10:2])
        w = np.append(wo, x[1:10:2])
        # Points       O   s   S   I     Elements
        A = np.array([
            [-1, 1, 0, 0, 0, 1],  # MX1
            [0, -1, 1, 0, 0, 0],  # CC
            [0, 0, -1, 1, -1, 0],  # MX2
            [0, 0, 0, -1, 1, 0],  # HC
            [0, 0, 0, 0, -1, 1]
        ])  # TZ
        psy.chartA(θ, w, A)

        θ = pd.Series(θ)
        w = 1000 * pd.Series(w)  # kg/kg -> g/kg
        P = pd.concat([θ, w], axis=1)  # points
        P.columns = ['θ [°C]', 'w [g/kg]']

        output = P.to_string(formatters={
            'θ [°C]': '{:,.2f}'.format,
            'w [g/kg]': '{:,.2f}'.format
        })
        print()
        print(output)

        Q = pd.Series(x[10:],
                      index=['QtCC', 'QsCC', 'QlCC', 'QsHC', 'QsTZ', 'QlTZ'])
        # Q.columns = ['kW']
        pd.options.display.float_format = '{:,.2f}'.format
        print()
        print(Q.to_frame().T / 1000, 'kW')
        return None
コード例 #3
0
def chart(t,
          w,
          t_range=np.arange(-10, 50, 0.1),
          w_range=np.arange(0, 0.030, 0.0001)):
    """
    Parameters
    ----------
    t_range : temperature vector t = np.arange(-10, 50, 0.1)
    w_range : humidity ration vector w = np.arange(0, 0.030, 0.0001)

    Returns
    -------
    None. Psycrometric chart

    """

    import matplotlib.pyplot as plt
    import psychro as psy

    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.yaxis.tick_right()
    plt.xlabel(r'Temperature $\theta$ [°C]')
    ax.yaxis.set_label_position("right")
    plt.ylabel(r'Humidity ratio w [kg/kg]')
    plt.grid(True)
    plt.plot(t_range, psy.w(t_range, 100), linewidth=2)  # saturation curve

    # Plot relative humidity curves
    for phi in np.arange(0, 100, 20):
        w4t = psy.w(t_range, phi)
        plt.plot(t_range, w4t, linewidth=0.5)
        s_phi = "%3.0f" % phi
        ax.annotate(s_phi + ' %', xy=(t_range[-1] - 3, w4t[-1]))

    plt.plot(t, w, linewidth=3)  # processes
    return None
コード例 #4
0
    def solve_lin(self, θs0):
        """
        Finds saturation point on saturation curve ws = f(θs).
            Solves iterativelly *lin_model(θs0)*:
            θs -> θs0 until ws = psy(θs, 1).

        Parameters
        ----------
        θs0     initial guess saturation temperature

        Method from object
        ---------------------
        *self.lin_model(θs0)*

        Returns (16 unknowns)
        ---------------------
        x of *self.lin_model(self, θs0)*
        """
        Δ_ws = 10e-3  # kg/kg, initial difference to start the iterations
        while Δ_ws > 0.01e-3:
            x = self.lin_model(θs0)
            Δ_ws = abs(psy.w(x[2], 1) - x[3])  # psy.w(θs, 1) = ws
            θs0 = x[2]  # actualize θs0
        return x
コード例 #5
0
ファイル: winter_AdHum.py プロジェクト: cmg-git/ClimTest
def RecAirCAV(alpha=1, beta=0.1,
              tS=30, tIsp=18, phiIsp=0.49, tO=-1, phiO=1,
              Qsa=0, Qla=0, mi=2.18, UA=935.83):
    """
    Model:
        Heating and adiabatic humidification
        Recycled air
        CAV Constant Air Volume:
            mass flow rate calculated for design conditions
            maintained constant in all situations

    INPUTS:
        alpha   mixing ratio of outdoor air, -
        beta    by-pass factor of the adiabatic humidifier, -
        tS      supply air, °C
        tIsp    indoor air setpoint, °C
        phiIsp  indoor relative humidity set point, -
        tO      outdoor temperature for design, °C
        phiO    outdoor relative humidity for design, -
        Qsa     aux. sensible heat, W
        Qla     aux. latente heat, W
        mi      infiltration massflow rate, kg/s
        UA      global conductivity bldg, W/K

    System:
        MX1:    Mixing box
        HC1:    Heating Coil
        AH:     Adiabatic Humidifier
        MX2:    Mixing in humidifier model
        HC2:    Reheating coil
        TZ:     Thermal Zone
        BL:     Building
        Kw:     Controller - humidity
        Kt:     Controller - temperature
        o:      outdoor conditions
        0..5    6 unknown points (temperature, humidity ratio)

        <----|<-------------------------------------------|
             |                                            |
             |              |-------|                     |
        -o->MX1--0->HC1--1->|       MX2--3->HC2--4->TZ--5-|
                    |       |       |        |      ||    |
                    |       |->AH-2-|        |      BL    |
                    |                        |            |
                    |                        |<-----Kt----|<-t5
                    |<------------------------------Kw----|<-w5

    16 Unknowns
        0..5: 2*6 points (temperature, humidity ratio)
        QsHC1, QsHC2, QsTZ, QlTZ
    Returns
    -------
    None
    """
    plt.close('all')
    wO = psy.w(tO, phiO)            # hum. out

    # Mass flow rate for design conditions
    # Supplay air mass flow rate
    # QsZ = UA*(tO - tIsp) + mi*c*(tO - tIsp)
    # m = - QsZ/(c*(tS - tIsp)
    # where
    # tO, wO = -1, 3.5e-3           # outdoor
    # tS = 30                       # supply air
    # mid = 2.18                     # infiltration
    QsZ = UA*(tOd - tIsp) + mid*c*(tOd - tIsp)
    m = - QsZ/(c*(tS - tIsp))
    print(f'm = {m: 5.3f} kg/s constant for design conditions:')
    print(f'    [tSd = {tS: 3.1f} °C, mi = 2.18 kg/S, tO = -1°C, phi0 = 100%]')

    # Model
    x = ModelRecAir(m, alpha, beta,
                    tS, tIsp, phiIsp, tO, phiO, Qsa, Qla, mi, UA)

    t = np.append(tO, x[0:12:2])
    w = np.append(wO, x[1:12:2])

    # Adjancy matrix
    # Points      o    0    1   2   3   4   5    Elements
    A = np.array([[-1, 1,  0,  0,  0,  0, -1],  # MX1
                 [0,  -1,  1,  0,  0,  0,  0],  # HC1
                 [0,   0, -1,  1,  0,  0,  0],  # AH
                 [0,   0, -1, -1,  1,  0,  0],  # MX2
                 [0,   0,  0,  0, -1,  1,  0],  # HC2
                 [0,   0,  0,  0,  0, -1,  1]]) # TZ

    psy.chartA(t, w, A)

    t = pd.Series(t)
    w = 1000*pd.Series(w)
    P = pd.concat([t, w], axis=1)       # points
    P.columns = ['t [°C]', 'w [g/kg]']

    output = P.to_string(formatters={
        't [°C]': '{:,.2f}'.format,
        'w [g/kg]': '{:,.2f}'.format
    })
    print()
    print(output)

    Q = pd.Series(x[12:], index=['QsHC1', 'QsHC2', 'QsTZ', 'QlTZ'])
    # Q.columns = ['kW']
    pd.options.display.float_format = '{:,.2f}'.format
    print()
    print(Q.to_frame().T/1000, 'kW')

    return None
コード例 #6
0
    def β_ls(self, value, sp):
        """
        Bypass β controls supply temperature θS or indoor humidity wI.
            Finds β which solves value = sp, i.e. minimizes ε = value - sp.
            Uses *scipy.optimize.least_squares* to solve the non-linear system.

        Parameters
        ----------
        value   string: 'θS' od 'wI' type of controlled variable
        sp      float: value of setpoint

        Calls
        -----
        *ε(m)*  gives (value - sp) to be minimized for m

        Returns (16 unknowns)
        ---------------------
        x           given by *self.lin_model(self, θs0)*
        """
        from scipy.optimize import least_squares

        def ε(β):
            """
            Gives difference ε = (values - sp) function of β
                ε  calculated by self.solve_lin(ts0)
                β   bounds=(0, 1)

            Parameters
            ----------
            β : by-pass factor of the cooling coil

            From object
                Method: self.solve.lin(θs0)
                Variables: self.actual <- m (used in self.solve.lin)
            Returns
            -------
            ε = value - sp: difference between value and its set point
            """
            self.actual[2] = β
            x = self.solve_lin(θs_0)
            if value == 'θS':
                θS = x[6]  # supply air
                return abs(sp - θS)
            elif value == 'φI':
                wI = x[9]  # indoor air
                return abs(sp - wI)
            else:
                print('ERROR in ε(β): value not in {"θS", "wI"}')

        β0 = self.actual[2]  # initial guess
        β0 = 0.1
        if value == 'φI':
            self.actual[4] = 0
            sp = psy.w(self.actual[7], sp)
        # gives m for min(θSsp - θS); θs_0 is the initial guess of θs
        res = least_squares(ε, β0, bounds=(0, 1))

        if res.cost < 1e-5:
            β = float(res.x)
            # print(f'm = {m: 5.3f} kg/s')
        else:
            print('RecAirVBP: No solution for β')

        self.actual[2] = β
        x = self.solve_lin(θs_0)
        return x
コード例 #7
0
    def m_ls(self, value, sp):
        """
        Mass flow rate m controls supply temperature θS or indoor humidity wI.
            Finds m which solves value = sp, i.e. minimizes ε = value - sp.
            Uses *scipy.optimize.least_squares* to solve the non-linear system.

        Parameters
        ----------
        value   string: 'θS' od 'wI' type of controlled variable
        sp      float: value of setpoint

        Calls
        -----
        *ε(m)*  gives (value - sp) to be minimized for m

        Returns (16 unknowns)
        ---------------------
        x           given by *self.lin_model(self, θs0)*
        """
        from scipy.optimize import least_squares

        def ε(m):
            """
            Gives difference ε = (values - sp) function of m
                ε  calculated by self.solve_lin(ts0)
                m   bounds=(0, m_max); m_max hard coded (global variable)

            Parameters
            ----------
            m : mass flow rate of dry air

            From object
                Method: self.solve.lin(θs0)
                Variables: self.actual <- m (used in self.solve.lin)
            Returns
            -------
            ε = value - sp: difference between value and its set point
            """
            self.actual[0] = m
            x = self.solve_lin(θs_0)
            if value == 'θS':
                θS = x[6]  # supply air
                return abs(sp - θS)
            elif value == 'φI':
                wI = x[9]  # indoor air
                return abs(sp - wI)
            else:
                print('ERROR in ε(m): value not in {"θS", "wI"}')

        m0 = self.actual[0]  # initial guess
        if value == 'φI':
            self.actual[4] = 0
            sp = psy.w(self.actual[7], sp)
        # gives m for min(θSsp - θS); θs_0 is the initial guess of θs
        res = least_squares(ε, m0, bounds=(0, m_max))

        if res.cost < 0.1e-3:
            m = float(res.x)
            # print(f'm = {m: 5.3f} kg/s')
        else:
            print('RecAirVAV: No solution for m')

        self.actual[0] = m

        x = self.solve_lin(θs_0)
        return x
コード例 #8
0
def AllOutAirVAV(tSsp=30,
                 tIsp=18,
                 phiIsp=0.5,
                 tO=-1,
                 phiO=1,
                 Qsa=0,
                 Qla=0,
                 mi=2.12,
                 UA=935.83):
    """
    All out air
    Heating & Vapor humidification
    VAV Variable Air Volume:
        mass flow rate calculated to have const. supply temp.

    INPUTS:
        tS    supply air °C
        tIsp  indoor air setpoint °C
        phiIsp -
        tO    outdoor temperature for design °C
        phiO  outdoor relative humidity for design -
        Qsa   aux. sensible heat W
        Qla   aux. latente heat W
        mi    infiltration massflow rate kg/s
        UA    global conductivity bldg W/K

    System:
        HC:     Heating Coil
        VH:     Vapor Humidifier
        TZ:     Thermal Zone
        BL:     Building
        Kw:     Controller - humidity
        Kt:     Controller - temperature
        o:      outdoor conditions

    10 Unknowns
        0, 1, 2 points (temperature, humidity ratio)
        QsHC, QlVH, QsTZ, QlTZ

    --o->HC--0->VH--F-----1-->TZ--2-->
         /       /  |     |   ||  |
         |       |  |     |   BL  |
         |       |  |_Kt1_|       |
         |       |                |
         |       |<----Kw---------|-w2
         |<------------Kt---------|-t2

        Mass-flow rate (VAV) I-controller:
        start with m = 0
        measure the supply temperature
        while -(tSsp - tS)>0.01, increase m (I-controller)
    """
    plt.close('all')
    wO = psy.w(tO, phiO)  # outdoor mumidity ratio

    # Mass flow rate
    DtS, m = 2, 0  # initial temp; diff; flow rate
    while DtS > 0.01:
        m = m + 0.01  # mass-flow rate I-controller
        # Model
        x = ModelAllOutAir(m, tSsp, tIsp, phiIsp, tO, phiO, Qsa, Qla, mi, UA)
        tS = x[2]
        DtS = -(tSsp - tS)
    print('Winter All_out_air VAV')
    print(f'm = {m: 5.3f} kg/s')
    # Processes on psychrometric chart
    t = np.append(tO, x[0:5:2])
    w = np.append(wO, x[1:6:2])
    # Points       o    0   1   2       Elements
    A = np.array([
        [-1, 1, 0, 0],  # HC
        [0, -1, 1, 0],  # VH
        [0, 0, 1, -1]
    ])  # TZ

    psy.chartA(t, w, A)

    t = pd.Series(t)
    w = 1000 * pd.Series(w)
    P = pd.concat([t, w], axis=1)  # points
    P.columns = ['t [°C]', 'w [g/kg]']

    output = P.to_string(formatters={
        't [°C]': '{:,.2f}'.format,
        'w [g/kg]': '{:,.2f}'.format
    })
    print()
    print(output)

    Q = pd.Series(x[6:], index=['QsHC', 'QlVH', 'QsTZ', 'QlTZ'])
    # Q.columns = ['kW']
    pd.options.display.float_format = '{:,.2f}'.format
    print()
    print(Q.to_frame().T / 1000, 'kW')

    return None
コード例 #9
0
    def lin_model(self, θs0):
        """
        Linearized model.
            Solves a set of 16 linear equations.
            Saturation curve is linearized in θs0.

        s-point (θs, ws):

        - is on a tangent to φ = 100 % in θs0;

        - is **not** on the saturation curve (Apparatus Dew Point ADP).


        Parameter from function call
        ----------------------------
        θs0     °C, temperature for which the saturation curve is liniarized

        Parameters from object
        ---------------------
        m, mo, θo, φo, θIsp, φIsp, β, mi, UA, Qsa, Qla = self.actual

        Equations (16)
        -------------
        +-------------+-----+----+-----+----+----+----+----+----+
        | Element     | MX1 | CC | MX2 | HC | TZ | BL | Kθ | Kw |
        +=============+=====+====+=====+====+====+====+====+====+
        | N° equations|  2  | 4  |  2  |  2 | 2  | 2  |  1 |  1 |
        +-------------+-----+----+-----+----+----+----+----+----+

        Returns (16 unknowns)
        ---------------------
        x : θM, wM, θs, ws, θC, wC, θS, wS, θI, wI,
            QtCC, QsCC, QlCC, QsHC, QsTZ, QlTZ
        """
        """
        <=4================================m==========================
               ||                                                   ||
               4 (m-mo) =======0=======                             ||
               ||       ||  (1-β)m   ||                             ||
       θo,φo=>[MX1]==0==||          [MX2]==2==[HC]==F==3==>[TZ]==4==||
         mo             ||           ||        /   /       //       |
                        ===0=[CC]==1===       s   m       sl        |
                             /\\   βm         |           ||        |
                            t  sl             |          [BL]<-mi   |
                            |                 |          //         |
                            |                 |         sl          |
                            |                 |                     |
                            |                 |<------[K]-----------+<-wI
                            |<------------------------[K]-----------+<-θI
        """
        m, mo, β, Kθ, Kw, θo, φo, θIsp, φIsp, mi, UA, Qsa, Qla = self.actual
        wo = psy.w(θo, φo)  # hum. out

        A = np.zeros((16, 16))  # coefficents of unknowns
        b = np.zeros(16)  # vector of inputs
        # MX1
        A[0, 0], A[0, 8], b[0] = m * c, -(m - mo) * c, mo * c * θo
        A[1, 1], A[1, 9], b[1] = m * l, -(m - mo) * l, mo * l * wo
        # CC
        A[2, 0], A[2, 2], A[2, 11], b[2] = (1 - β) * m * c, -(1 - β) * m * c,\
            1, 0
        A[3, 1], A[3, 3], A[3, 12], b[3] = (1 - β) * m * l, -(1 - β) * m * l,\
            1, 0
        A[4, 2], A[4, 3], b[4] = psy.wsp(θs0), -1,\
            psy.wsp(θs0) * θs0 - psy.w(θs0, 1)
        A[5, 10], A[5, 11], A[5, 12], b[5] = -1, 1, 1, 0
        # MX2
        A[6, 0], A[6, 2], A[6, 4], b[6] = β * m * c, (1 - β) * m * c,\
            - m * c, 0
        A[7, 1], A[7, 3], A[7, 5], b[7] = β * m * l, (1 - β) * m * l,\
            - m * l, 0
        # HC
        A[8, 4], A[8, 6], A[8, 13], b[8] = m * c, -m * c, 1, 0
        A[9, 5], A[9, 7], b[9] = m * l, -m * l, 0
        # TZ
        A[10, 6], A[10, 8], A[10, 14], b[10] = m * c, -m * c, 1, 0
        A[11, 7], A[11, 9], A[11, 15], b[11] = m * l, -m * l, 1, 0
        # BL
        A[12, 8], A[12, 14], b[12] = (UA + mi * c), 1, (UA + mi * c) * θo + Qsa
        A[13, 9], A[13, 15], b[13] = mi * l, 1, mi * l * wo + Qla
        # Kθ indoor temperature controller
        A[14, 8], A[14, 10], b[14] = Kθ, 1, Kθ * θIsp
        # Kw indoor humidity ratio controller
        A[15, 9], A[15, 13], b[15] = Kw, 1, Kw * psy.w(θIsp, φIsp)
        x = np.linalg.solve(A, b)
        return x
コード例 #10
0
            m=self.actual[0], mo=self.actual[1], β=self.actual[2]))
        self.psy_chart(x, θo, φo)

        return x


# TESTS: uncomment
# Recyclage p. 6/19
Kθ, Kw = 1e10, 0  # Kw can be 0
β = 0

m, mo = 3.093, 0.94179
θo, φo = 32, 0.5
θIsp, φIsp = 26, 0.5

mi = 15e3 / (l * (psy.w(θo, φo) - psy.w(θIsp, φIsp)))  # kg/s
UA = 45e3 / (θo - θIsp) - mi * c  # W/K
Qsa, Qla = 0, 0  # W

print(f'QsTZ = {(UA + mi * c) * (θo - θIsp): ,.1f} W')
print(f'QlTZ = {mi * l * (psy.w(θo, φo) - psy.w(θIsp, φIsp)): ,.1f} W')

parameters = m, mo, β, Kθ, Kw
inputs = θo, φo, θIsp, φIsp, mi, UA, Qsa, Qla
cool = MxCcRhTzBl(parameters, inputs)

# # 1. CAV
# print('\nCAV: m given')
# cool.CAV_wd()
# cool.CAV_wd(θo, φo, θIsp, φIsp, mi, UA, Qsa, Qla)
# # 2.
コード例 #11
0
ファイル: cool_loads.py プロジェクト: cmg-git/ClimTest
length = 20  # m
width = 30  # m
height = 3.5  # m
persons = 100  # m

sens_heat_person = 60  # W / person
latent_heat_person = 40  # W / person
load_m2 = 20  # W/m2
solar_m2 = 150  # W/m2 of window area
ACH = 1  # Air Cnhnages per Hour
U_wall = 0.4  # W/K, overall heat transfer coeff. walls
U_window = 3.5  # W/K, overall heat transfer coeff. windows

θo, φo = 32, 0.5  # outdoor temperature & relative humidity
θI, φI = 26, 0.5  # indoor temperature & relative humidity
wo = psy.w(θo, φo)
wI = psy.w(θI, φI)

floor_area = length * width
surface_envelope = 2 * (length + width) * height + floor_area
surface_wall = 0.9 * surface_envelope
surface_window = surface_envelope - surface_wall

# building conductance, W/K
UA = U_wall * surface_wall + U_window * surface_window

# infiltration mass flow rate, kg/s
mi = ACH * surface_envelope * height / 3600 * ρ

# gains, W
solar_gains = solar_m2 * surface_window
コード例 #12
0
def RecAirVAV(alpha=0.5,
              tSsp=30,
              tIsp=18,
              phiIsp=0.5,
              tO=-1,
              phiO=1,
              Qsa=0,
              Qla=0,
              mi=2.12,
              UA=935.83):
    """
    CAV Variable Air Volume:
    mass flow rate calculated s.t.
    he supply temp. is maintained constant in all situations
    INPUTS:
    INPUTS:
        m     mass flow of supply dry air kg/s
        alpha mixing ratio of outdoor air
        tS    supply air °C
        tIsp  indoor air setpoint °C
        phiIsp -
        tO    outdoor temperature for design °C
        phiO  outdoor relative humidity for design -
        Qsa   aux. sensible heat W
        Qla   aux. latente heat W
        mi    infiltration massflow rate kg/s
        UA    global conductivity bldg W/K

    System (CAV & m introduced by the Fan is cotrolled by tS )
        HC:     Heating Coil
        VH:     Vapor Humidifier
        TZ:     Thermal Zone
        F:      Supply air fan
        Kw:     Controller - humidity
        Kt:     Controller - temperature
        o:      outdoor conditions

    12 Unknowns
        0, 1, 2, 3 points (temperature, humidity ratio)
        QsHC, QlVH, QsTZ, QlTZ

    <----|<--------------------------------|
         |                                 |
    -o->MX--0->HC--1->VH--F-----2-->TZ--3-->
               /       /  |     |   ||  |
               |       |  |     |   BL  |
               |       |  |     |       |
               |       |  |_Kt2_|_t2    |
               |       |                |
               |       |_____Kw_________|_w3
               |_____________Kt_________|_t3

    Mass-flow rate (VAV) I-controller:
        start with m = 0
        measure the supply temperature
        while -(tSsp - tS)>0.01, increase m (I-controller)
    """
    plt.close('all')
    wO = psy.w(tO, phiO)  # hum. out

    # Mass flow rate
    DtS, m = 2, 0  # initial temp; diff; flow rate
    while DtS > 0.01:
        m = m + 0.01

        # Model
        x = ModelRecAir(m, alpha, tSsp, tIsp, phiIsp, tO, phiO, Qsa, Qla, mi,
                        UA)
        tS = x[4]
        DtS = -(tSsp - tS)

    print('Winter Rec_air VAV')
    print(f'm = {m: 5.3f} kg/s')

    # Processes on psychrometric chart
    # Points      o    0    1   2   3       Elements
    A = np.array([
        [-1, 1, 0, 0, -1],  # MX
        [0, -1, 1, 0, 0],  # HC
        [0, 0, -1, 1, 0],  # VH
        [0, 0, 0, -1, 1]
    ])  # TZ
    t = np.append(tO, x[0:8:2])
    print(f'wO = {wO:6.5f}')
    w = np.append(wO, x[1:8:2])
    psy.chartA(t, w, A)

    t = pd.Series(t)
    w = 1000 * pd.Series(w)
    P = pd.concat([t, w], axis=1)  # points
    P.columns = ['t [°C]', 'w [g/kg]']

    output = P.to_string(formatters={
        't [°C]': '{:,.2f}'.format,
        'w [g/kg]': '{:,.2f}'.format
    })
    print()
    print(output)

    Q = pd.Series(x[8:], index=['QsHC', 'QlVH', 'QsTZ', 'QlTZ'])
    pd.options.display.float_format = '{:,.2f}'.format
    print()
    print(Q.to_frame().T / 1000, 'kW')

    return None
コード例 #13
0
def ModelAllOutAir(m, tS, tIsp, phiIsp, tO, phiO, Qsa, Qla, mi, UA):
    """
    Model:
        All outdoor air
        CAV Constant Air Volume:
            mass flow rate given
            control of indoor condition (t2, w2)
    INPUTS:
        m     mass flow of supply dry air kg/s
        tS    supply air °C
        tIsp  indoor air setpoint °C
        phiIsp -
        tO    outdoor temperature for design °C
        phiO  outdoor relative humidity for design -
        Qsa   aux. sensible heat W
        Qla   aux. latente heat W
        mi    infiltration massflow rate kg/s
        UA    global conductivity bldg W/K

    OUTPUTS:
        x     vector 10 elements:
            t0, w0, t1, w1, t2, w2, QsHC, QlVH, QsTZ, QlTZ

    System:
        HC:     Heating Coil
        VH:     Vapor Humidifier
        TZ:     Thermal Zone
        BL:     Building
        Kw:     Controller - humidity
        Kt:     Controller - temperature
        o:      outdoor conditions
    
    10 Unknowns
        0, 1, 2 points (temperature, humidity ratio)
        QsHC, QlVH, QsTZ, QlTZ

    --o->HC--0->VH--1->TZ--2-->
         |       |     ||  |
         |       |     BL  |
         |       |         |
         |       |<----Kw--|-w2
         |<------------Kt--|-t2
    """
    Kt, Kw = 1e10, 1e10  # controller gain
    wO = psy.w(tO, phiO)  # outdoor mumidity ratio
    wIsp = psy.w(tIsp, phiIsp)  # indoor mumidity ratio

    # Model
    A = np.zeros((10, 10))  # coefficents of unknowns
    b = np.zeros(10)  # vector of inputs
    # HC heating coil
    A[0, 0], A[0, 6], b[0] = m * c, -1, m * c * tO
    A[1, 1], b[1] = m * l, m * l * wO
    # VA vapor humidifier
    A[2, 0], A[2, 2], b[2] = -m * c, m * c, 0
    A[3, 1], A[3, 3], A[3, 7], b[3] = -m * l, m * l, -1, 0
    # TZ thermal zone
    A[4, 2], A[4, 4], A[4, 8], b[4] = -m * c, m * c, -1, 0
    A[5, 3], A[5, 5], A[5, 9], b[5] = -m * l, m * l, -1, 0
    # BL building
    A[6, 4], A[6, 8], b[6] = UA + mi * c, 1, (UA + mi * c) * tO + Qsa
    A[7, 5], A[7, 9], b[7] = mi * l, 1, mi * l * wO + Qla
    # Kt indoor temperature controller
    A[8, 4], A[8, 8], b[8] = Kt, 1, Kt * tIsp
    # Kw indoor hum.ratio controller
    A[9, 5], A[9, 9], b[9] = Kw, 1, Kw * wIsp

    # Solution
    x = np.linalg.solve(A, b)
    return x
コード例 #14
0
def RecAirCAV(alpha=0.5,
              tS=30,
              tIsp=18,
              phiIsp=0.5,
              tO=-1,
              phiO=1,
              Qsa=0,
              Qla=0,
              mi=2.12,
              UA=935.83):
    """
    CAV Constant Air Volume:
    mass flow rate calculated for design conditions
    maintained constant in all situations
    INPUTS:
        alpha mixing ratio of outdoor air
        tS    supply air °C
        tIsp  indoor air setpoint °C
        phiIsp -
        tO    outdoor temperature for design °C
        phiO  outdoor relative humidity for design -
        Qsa   aux. sensible heat W
        Qla   aux. latente heat W
        mi    infiltration massflow rate kg/s
        UA    global conductivity bldg W/K

    System:
        HC:     Heating Coil
        VH:     Vapor Humidifier
        TZ:     Thermal Zone
        Kw:     Controller - humidity
        Kt:     Controller - temperature
        o:      outdoor conditions

    12 Unknowns
        0, 1, 2, 3 points (temperature, humidity ratio)
        QsHC, QlVH, QsTZ, QlTZ

    <-3--|<-------------------------|
         |                          |
    -o->MX--0->HC--1->VH--2->TZ--3-->
               /       /     ||  |
               |       |     BL  |
               |       |         |
               |       |_____Kw__|_w3
               |_____________Kt__|_t3
    """
    plt.close('all')
    wO = psy.w(tO, phiO)  # hum. out

    # Mass flow rate for design conditions
    # Supplay air mass flow rate
    # QsZ = UA*(tO - tIsp) + mi*c*(tO - tIsp)
    # m = - QsZ/(c*(tS - tIsp)
    # where
    # tOd, wOd = -1, 3.5e-3           # outdoor
    # tS = 30                       # supply air
    # mid = 2.18                     # infiltration
    QsZ = UA * (tOd - tIsp) + mid * c * (-1 - tIsp)
    m = -QsZ / (c * (tS - tIsp))
    print('Winter Recirculated_air CAV')
    print(f'm = {m: 5.3f} kg/s constant (from design conditions)')
    print(f'Design conditions tS = {tS: 3.1f} °C,'
          f'mi = {mid:3.1f} kg/s, tO = {tOd:3.1f} °C, '
          f'tI = {tIsp:3.1f} °C')

    # Model
    x = ModelRecAir(m, alpha, tS, tIsp, phiIsp, tO, phiO, Qsa, Qla, mi, UA)
    # (m, tS, mi, tO, phiO, alpha)

    # Processes on psychrometric chart
    # Points      o    0    1   2   3       Elements
    A = np.array([
        [-1, 1, 0, 0, -1],  # MX
        [0, -1, 1, 0, 0],  # HC
        [0, 0, -1, 1, 0],  # VH
        [0, 0, 0, -1, 1]
    ])  # TZ
    t = np.append(tO, x[0:8:2])

    print(f'wO = {wO:6.5f}')
    w = np.append(wO, x[1:8:2])
    psy.chartA(t, w, A)

    t = pd.Series(t)
    w = 1000 * pd.Series(w)
    P = pd.concat([t, w], axis=1)  # points
    P.columns = ['t [°C]', 'w [g/kg]']

    output = P.to_string(formatters={
        't [°C]': '{:,.2f}'.format,
        'w [g/kg]': '{:,.2f}'.format
    })
    print()
    print(output)

    Q = pd.Series(x[8:], index=['QsHC', 'QlVH', 'QsTZ', 'QlTZ'])
    pd.options.display.float_format = '{:,.2f}'.format
    print()
    print(Q.to_frame().T / 1000, 'kW')

    return None
コード例 #15
0
def ModelRecAir(m, alpha, tS, tIsp, phiIsp, tO, phiO, Qsa, Qla, mi, UA):
    """
    Model:
        Heating and vapor humidification
        Recycled air
        CAV Constant Air Volume:
            mass flow rate calculated for design conditions
            maintained constant in all situations
    INPUTS:
        m     mass flow of supply dry air kg/s
        alpha mixing ratio of outdoor air
        tS    supply air °C
        tIsp  indoor air setpoint °C
        phiIsp -
        tO    outdoor temperature for design °C
        phiO  outdoor relative humidity for design -
        Qsa   aux. sensible heat W
        Qla   aux. latente heat W
        mi    infiltration massflow rate kg/s
        UA    global conductivity bldg W/K

    OUTPUTS:
        x     vector 12 elements:
            t0, w0, t1, w1, t2, w2, t3, w3, QsHC, QlVH, QsTZ, QlTZ

    System:
        MX:     Mixing Box
        HC:     Heating Coil
        VH:     Vapor Humidifier
        TZ:     Thermal Zone
        BL:     Buildings
        Kw:     Controller - humidity
        Kt:     Controller - temperature
        o:      outdoor conditions

    12 Unknowns
        0, 1, 2, 3 points (temperature, humidity ratio)
        QsHC, QlVH, QsTZ, QlTZ

    <-3--|<-------------------------|
         |                          |
    -o->MX--0->HC--1->VH--2->TZ--3-->
               /       /     ||  |
               |       |     BL  |
               |       |         |
               |       |<----Kw--|-w3
               |<------------Kt--|-t3
    """
    Kt, Kw = 1e10, 1e10  # controller gain
    wO = psy.w(tO, phiO)  # hum. out
    wIsp = psy.w(tIsp, phiIsp)  # hum. in set point

    # Model
    A = np.zeros((12, 12))  # coefficents of unknowns
    b = np.zeros(12)  # vector of inputs
    # MX mixing box
    A[0, 0], A[0, 6], b[0] = m * c, -(1 - alpha) * m * c, alpha * m * c * tO
    A[1, 1], A[1, 7], b[1] = m * l, -(1 - alpha) * m * l, alpha * m * l * wO
    # HC hearing coil
    A[2, 0], A[2, 2], A[2, 8], b[2] = m * c, -m * c, 1, 0
    A[3, 1], A[3, 3], b[3] = m * l, -m * l, 0
    # VH vapor humidifier
    A[4, 2], A[4, 4], b[4] = m * c, -m * c, 0
    A[5, 3], A[5, 5], A[5, 9], b[5] = m * l, -m * l, 1, 0
    # TZ thermal zone
    A[6, 4], A[6, 6], A[6, 10], b[6] = m * c, -m * c, 1, 0
    A[7, 5], A[7, 7], A[7, 11], b[7] = m * l, -m * l, 1, 0
    # BL building
    A[8, 6], A[8, 10], b[8] = (UA + mi * c), 1, (UA + mi * c) * tO + Qsa
    A[9, 7], A[9, 11], b[9] = mi * l, 1, mi * l * wO + Qla
    # Kt indoor temperature controller
    A[10, 6], A[10, 8], b[10] = Kt, 1, Kt * tIsp
    # Kw indoor humidity controller
    A[11, 7], A[11, 9], b[11] = Kw, 1, Kw * wIsp

    # Solution
    x = np.linalg.solve(A, b)
    return x
コード例 #16
0
ファイル: winter_AdHum.py プロジェクト: cmg-git/ClimTest
def RecAirVAV(alpha=1, beta=0.1,
              tSsp=30, tIsp=18, phiIsp=0.49, tO=-1, phiO=1,
              Qsa=0, Qla=0, mi=2.18, UA=935.83):
    """
    Created on Fri Apr 10 13:57:22 2020
    Heating & Adiabatic humidification & Re-heating
    Recirculated air
    VAV Variable Air Volume:
        mass flow rate calculated to have const. supply temp.

    INPUTS:
        alpha   mixing ratio of outdoor air, -
        beta    by-pass factor of the adiabatic humidifier, -
        tS      supply air, °C
        tIsp    indoor air setpoint, °C
        phiIsp  indoor relative humidity set point, -
        tO      outdoor temperature for design, °C
        phiO    outdoor relative humidity for design, -
        Qsa     aux. sensible heat, W
        Qla     aux. latente heat, W
        mi      infiltration massflow rate, kg/s
        UA      global conductivity bldg, W/K

    System:
        MX1:    Mixing box
        HC1:    Heating Coil
        AH:     Adiabatic Humidifier
        MX2:    Mixing in humidifier model
        HC2:    Reheating coil
        TZ:     Thermal Zone
        BL:     Building
        Kw:     Controller - humidity
        Kt:     Controller - temperature
        o:      outdoor conditions
        0..5    unknown points (temperature, humidity ratio)

        <----|<-------------------------------------------------|
             |                                                  |
             |              |-------|                           |
        -o->MX1--0->HC1--1->|       MX2--3->HC2--F-----4->TZ--5-|
                    |       |->AH-2-|        |   |     |  ||    |
                    |                        |   |-Kt4-|  BL    |
                    |                        |                  |
                    |                        |<-----Kt----------|<-t5
                    |<------------------------------Kw----------|<-w5

    16 Unknowns
        0..5: 2*6 points (temperature, humidity ratio)
        QsHC1, QsHC2, QsTZ, QlTZ
    """
    from scipy.optimize import least_squares

    def Saturation(m):
        """
        Used in VAV to find the mass flow which solves tS = tSsp
        Parameters
        ----------
            m : mass flow rate of dry air

        Returns
        -------
            tS - tSsp: difference between supply temp. and its set point

        """
        x = ModelRecAir(m, alpha, beta,
                        tSsp, tIsp, phiIsp, tO, phiO, Qsa, Qla, mi, UA)
        tS = x[8]
        return (tS - tSsp)

    plt.close('all')
    wO = psy.w(tO, phiO)            # hum. out

    # Mass flow rate
    res = least_squares(Saturation, 5, bounds=(0, 10))
    if res.cost < 1e-10:
        m = float(res.x)
    else:
        print('RecAirVAV: No solution for m')

    print(f'm = {m: 5.3f} kg/s')
    x = ModelRecAir(m, alpha, beta,
                    tSsp, tIsp, phiIsp, tO, phiO, Qsa, Qla, mi, UA)

    # DtS, m = 2, 1                   # initial temp; diff; flow rate
    # while DtS > 0.01:
    #     m = m + 0.01
    #     # Model
    #     x = ModelRecAir(m, tSsp, mi, tO, phiO, alpha, beta)
    #     tS = x[8]
    #     DtS = -(tSsp - tS)

    t = np.append(tO, x[0:12:2])
    w = np.append(wO, x[1:12:2])

    # Adjancy matrix
    # Points      o    0    1   2   3   4   5       Elements
    A = np.array([[-1, 1,   0,  0,  0,  0, -1],     # MX1
                 [0,  -1,   1,  0,  0,  0,  0],     # HC1
                 [0,   0,  -1,  1,  0,  0,  0],     # AH
                 [0,   0,  -1, -1,  1,  0,  0],     # MX2
                 [0,   0,   0,  0, -1,  1,  0],     # HC2
                 [0,   0,   0,  0,  0, -1,  1]])    # TZ

    psy.chartA(t, w, A)

    t = pd.Series(t)
    w = 1000*pd.Series(w)
    P = pd.concat([t, w], axis=1)       # points
    P.columns = ['t [°C]', 'w [g/kg]']

    output = P.to_string(formatters={
        't [°C]': '{:,.2f}'.format,
        'w [g/kg]': '{:,.2f}'.format
    })
    print()
    print(output)

    Q = pd.Series(x[12:], index=['QsHC1', 'QsHC2', 'QsTZ', 'QlTZ'])
    # Q.columns = ['kW']
    pd.options.display.float_format = '{:,.2f}'.format
    print()
    print(Q.to_frame().T/1000, 'kW')

    return None
コード例 #17
0
ファイル: winter_AdHum.py プロジェクト: cmg-git/ClimTest
def ModelRecAir(m, alpha, beta, tS, tIsp, phiIsp, tO, phiO, Qsa, Qla, mi, UA):
    """
    Model:
        Heating and adiabatic humidification
        Recycled air
        CAV Constant Air Volume:
            mass flow rate calculated for design conditions
            maintained constant in all situations

    INPUTS:
        m       mass flow of supply dry air, kg/s
        alpha   mixing ratio of outdoor air, -
        beta    by-pass factor of the adiabatic humidifier, -
        tS      supply air, °C
        tIsp    indoor air setpoint, °C
        phiIsp  indoor relative humidity set point, -
        tO      outdoor temperature for design, °C
        phiO    outdoor relative humidity for design, -
        Qsa     aux. sensible heat, W
        Qla     aux. latente heat, W
        mi      infiltration massflow rate, kg/s
        UA      global conductivity bldg, W/K

    System:
        MX1:    Mixing box
        HC1:    Heating Coil
        AH:     Adiabatic Humidifier
        MX2:    Mixing in humidifier model
        HC2:    Reheating coil
        TZ:     Thermal Zone
        BL:     Building
        Kw:     Controller - humidity
        Kt:     Controller - temperature
        o:      outdoor conditions
        0..5    unknown points (temperature, humidity ratio)

        <----|<-------------------------------------------|
             |                                            |
             |              |-------|                     |
        -o->MX1--0->HC1--1->|       MX2--3->HC2--4->TZ--5-|
                    /       |       |        /      ||    |
                    |       |->AH-2-|        |      BL    |
                    |                        |            |
                    |                        |<-----Kt----|<-t5
                    |<------------------------------Kw----|<-w5


    Returns
    -------
    x       vector 16 elem.:
            t0, w0, t1, w1, t2, w2, t3, w3, t4, w4, t5, w5,...
                QHC1, QHC2, QsTZ, QlTZ

    """
    Kt, Kw = 1e10, 1e10             # controller gain
    wO = psy.w(tO, phiO)            # hum. out
    wIsp = psy.w(tIsp, phiIsp)      # indoor mumidity ratio

    # Model
    ts0, Del_ts = tS, 2             # initial guess saturation temp.

    A = np.zeros((16, 16))          # coefficents of unknowns
    b = np.zeros(16)                # vector of inputs
    while Del_ts > 0.01:
        # MX1
        A[0, 0], A[0, 10], b[0] = m*c, -(1 - alpha)*m*c, alpha*m*c*tO
        A[1, 1], A[1, 11], b[1] = m*l, -(1 - alpha)*m*l, alpha*m*l*wO
        # HC1
        A[2, 0], A[2, 2], A[2, 12], b[2] = m*c, -m*c, 1, 0
        A[3, 1], A[3, 3], b[3] = m*l, -m*l, 0
        # AH
        A[4, 2], A[4, 3], A[4, 4], A[4, 5], b[4] = c, l, -c, -l, 0
        A[5, 4], A[5, 5] = psy.wsp(ts0), -1
        b[5] = psy.wsp(ts0)*ts0 - psy.w(ts0, 1)
        # MX2
        A[6, 2], A[6, 4], A[6, 6], b[6] = beta*m*c, (1-beta)*m*c, -m*c, 0
        A[7, 3], A[7, 5], A[7, 7], b[7] = beta*m*l, (1-beta)*m*l, -m*l, 0
        # HC2
        A[8, 6], A[8, 8], A[8, 13], b[8] = m*c, -m*c, 1, 0
        A[9, 7], A[9, 9], b[9] = m*l, -m*l, 0
        # TZ
        A[10, 8], A[10, 10], A[10, 14], b[10] = m*c, -m*c, 1, 0
        A[11, 9], A[11, 11], A[11, 15], b[11] = m*l, -m*l, 1, 0
        # BL
        A[12, 10], A[12, 14], b[12] = (UA+mi*c), 1, (UA+mi*c)*tO + Qsa
        A[13, 11], A[13, 15], b[13] = mi*l, 1, mi*l*wO + Qla
        # Kt & Kw
        A[14, 10], A[14, 12], b[14] = Kt, 1, Kt*tIsp
        A[15, 11], A[15, 13], b[15] = Kw, 1, Kw*wIsp

        x = np.linalg.solve(A, b)
        Del_ts = abs(ts0 - x[4])
        ts0 = x[4]
    return x
コード例 #18
0
def AllOutAirCAV(tS=30,
                 tIsp=18,
                 phiIsp=0.5,
                 tO=-1,
                 phiO=1,
                 Qsa=0,
                 Qla=0,
                 mi=2.12,
                 UA=935.83):
    """
    All out air
    CAV Constant Air Volume:
        mass flow rate calculated for design conditions
        maintained constant in all situations

    INPUTS:
        m     mass flow of supply dry air kg/s
        tS    supply air °C
        tIsp  indoor air setpoint °C
        phiIsp -
        tO    outdoor temperature for design °C
        phiO  outdoor relative humidity for design -
        Qsa   aux. sensible heat W
        Qla   aux. latente heat W
        mi    infiltration massflow rate kg/s
        UA    global conductivity bldg W/K

    System:
        HC:     Heating Coil
        VH:     Vapor Humidifier
        TZ:     Thermal Zone
        BL:     Building
        Kw:     Controller - humidity
        Kt:     Controller - temperature
        o:      outdoor conditions

    10 Unknowns
        0, 1, 2 points (temperature, humidity ratio)
        QsHC, QlVH, QsTZ, QlTZ

    --o->HC--0->VH--1->TZ--2-->
         /       /     ||  |
         |       |     BL  |
         |       |         |
         |       |<----Kw--|-w2
         |<------------Kt--|-t2
    """
    plt.close('all')
    wO = psy.w(tO, phiO)  # hum. out

    # Mass flow rate for design conditions
    # tOd = -1                        # outdoor design conditions
    # mid = 2.18                      # infiltration design
    QsZ = UA * (tOd - tIsp) + mid * c * (tOd - tIsp)
    m = -QsZ / (c * (tS - tIsp))
    print('Winter All_out_air CAV')
    print(f'm = {m: 5.3f} kg/s constant (from design conditions)')
    print(f'Design conditions tS = {tS: 3.1f} °C,'
          f'mi = {mid:3.1f} kg/s, tO = {tOd:3.1f} °C, '
          f'tI = {tIsp:3.1f} °C')

    # Model
    x = ModelAllOutAir(m, tS, tIsp, phiIsp, tO, phiO, Qsa, Qla, mi, UA)

    # Processes on psychrometric chart
    t = np.append(tO, x[0:5:2])
    w = np.append(wO, x[1:6:2])

    # Adjancy matrix: rows=lines; columns=points
    # Points       O    0   1   2       Elements
    A = np.array([
        [-1, 1, 0, 0],  # HC
        [0, -1, 1, 0],  # VH
        [0, 0, 1, -1]
    ])  # TZ

    psy.chartA(t, w, A)

    t = pd.Series(t)
    w = 1000 * pd.Series(w)
    P = pd.concat([t, w], axis=1)  # points
    P.columns = ['t [°C]', 'w [g/kg]']

    output = P.to_string(formatters={
        't [°C]': '{:,.2f}'.format,
        'w [g/kg]': '{:,.2f}'.format
    })
    print()
    print(output)

    Q = pd.Series(x[6:], index=['QsHC', 'QlVH', 'QsTZ', 'QlTZ'])
    # Q.columns = ['kW']
    pd.options.display.float_format = '{:,.2f}'.format
    print()
    print(Q.to_frame().T / 1000, 'kW')

    return x