241 暖房向け自然冷媒ヒートポンプサイクル¶
読み込み¶
In [1]:
import numpy as np
import pandas as pd
import CoolProp.CoolProp as CP
import matplotlib.pyplot as plt
%matplotlib inline
import warnings
warnings.filterwarnings("ignore")
パラメータ定義¶
汎用¶
In [2]:
K = 273.16 # converter from degC to K
外生条件¶
In [3]:
params = {
'WF':'CarbonDioxide', # working fluid
'T_bldg': 20 +K, #freezer air temperature degC
'T_amb': -5 +K, # Outdoor air temperature degC
'DT_cond':5, # condenser approach temperature difference K
'DT_sc':3, # degree of subcooling K
'DT_evap':4, # evaporator approach temprature difference K
'DT_sh':2, # degree of superheat K
'V_dot_cond_f':2.0, # condenser fan volumetric flow rate m3/s
'V_dot_evap_f':2.5, # evaporator fan volumetric flow rate m3/s
'W_dot_cond_f':200, # condenser fan power W
'W_dot_evap_f':300, # evaporator fan power W
'ETA_cond':0.72, # condenser effectiveness
'ETA_evap':0.81, # evaporator effectiveness
'c':0.025, # clearance volume rate
'V_dot_disp':2*1e-3, # compressor displacement m^3/sec
}
データフレーム用意¶
Nomenclature¶
Symbol | Description | Unit |
---|---|---|
\(T\) | Temperature | \(K\) |
\(P\) | Pressure | \(Pa\) |
\(s\) | Specific entropy | \(J/kg-K\) |
\(s_s\) | Specific entropy leaving reversible process | \(J/kg-K\) |
\(v\) | Specific volume | \(m^3/kg\) |
\(h\) | Specific enthalpy | \(J/kg\) |
\(h_s\) | Specific enthalpy leaving reversible process | \(J/kg\) |
In [4]:
states = pd.DataFrame(columns=['T', 'P', 's', 's_s', 'v', 'h', 'h_s'],
index=list(range(1,4+1)))
State 4¶
\begin{align}
State4 =& f(T_{cond}, x_4=0) \\
\rm{where} & \\
T_4 =& T_{bldg} + \Delta T_{cond}, \\
T_{cond} =& T_4 + \Delta T_{sc}.
\end{align}
In [5]:
states.loc[4, 'T'] = params['T_bldg'] + params['DT_cond']
T_cond = states.loc[4, 'T'] + params['DT_sc']
states.loc[4, 'P'] = CP.PropsSI('P', 'T', T_cond, 'Q', 0, params['WF']) # Satuation pressure
states.loc[4, 's'] = CP.PropsSI('S', 'T', states.loc[4, 'T'],
'P', states.loc[4, 'P'], params['WF'])
states.loc[4, 'h'] = CP.PropsSI('H', 'T', states.loc[4, 'T'],
'P', states.loc[4, 'P'], params['WF'])
ax = plt.axes([0,0,0,0])
ax.axis('off')
plt.text(0, 0, "$T_{cond}$="+'{:.02f} K'.format(T_cond), size=14)
plt.show()

State 2¶
\begin{align}
State2 =& f(T_{evap}, x_2=1) \\
\rm{where} & \\
T_2 =& T_{amb} - \Delta T_{evap}, \\
T_{evap} =& T_2 - \Delta T_{sh}.
\end{align}
In [6]:
states.loc[2, 'T'] = params['T_amb'] - params['DT_evap']
T_evap = states.loc[2, 'T'] - params['DT_sh']
states.loc[2, 'P'] = CP.PropsSI('P', 'T', T_evap, 'Q', 1, params['WF']) # Satuation pressure
states.loc[2, 's'] = CP.PropsSI('S', 'T', states.loc[2, 'T'],
'P', states.loc[2, 'P'], params['WF'])
states.loc[2, 'h'] = CP.PropsSI('H', 'T', states.loc[2, 'T'],
'P', states.loc[2, 'P'], params['WF'])
states.loc[2, 'v'] = 1/CP.PropsSI('D', 'T', states.loc[2, 'T'],
'P', states.loc[2, 'P'], params['WF'])
ax = plt.axes([0,0,0,0])
ax.axis('off')
plt.text(0, 0, "$T_{evap}$="+'{:.02f} K'.format(T_evap), size=14)
plt.show()

State 1¶
\begin{align}
State1 =& f(P_1, h_1) \\
\rm{where} \\
P_1 =& P_2 \text{ which means that pressure loss in the evaporator is neglected,} \\
h_1 =& h_4 \text{ which means that the valve is isenthalpic.}
\end{align}
In [7]:
states.loc[1, 'P'] = states.loc[2, 'P']
states.loc[1, 'h'] = states.loc[4, 'h']
states.loc[1, 's'] = CP.PropsSI('S', 'P', states.loc[1, 'P'],
'H', states.loc[1, 'h'], params['WF'])
states.loc[1, 'T'] = CP.PropsSI('T', 'P', states.loc[1, 'P'],
'H', states.loc[1, 'h'], params['WF'])
State 3¶
\begin{align}
State3 =& f(P_3, h_3, ) \\
\rm{where} \\
P_3 =& P_4 \text{ which means that pressure loss in the condenser is neglected,} \\
\frac{\dot{W}_{s,c}}{\dot{m}} =& h_{s,3} -h_2 \\
\frac{\dot{W}_{c}}{\dot{m}} =& \frac{1}{\eta_c}\frac{\dot{W}_{s,c}}{\dot{m}}\\
h_3 =& h_2+\frac{\dot{W}_{c}}{\dot{m}}
\end{align}
In [8]:
states.loc[3, 'P'] = states.loc[4, 'P']
eta_c = 0.79 - 0.0074*(T_cond - T_evap)
states.loc[3, 's_s'] = states.loc[2, 's'] # specific entropy leaving isentropic compressor
states.loc[3, 'h_s'] = CP.PropsSI('H', 'P', states.loc[3, 'P'],
'S', states.loc[3, 's_s'], params['WF']) # specific enthalpy leaving isentropic compressor
W_dot_s_c_m_dot = states.loc[3, 'h_s'] - states.loc[2, 'h']
W_dot_c_m_dot = W_dot_s_c_m_dot/eta_c
states.loc[3, 'h'] = states.loc[2, 'h'] + W_dot_c_m_dot
states.loc[3, 's'] = CP.PropsSI('S', 'P', states.loc[3, 'P'],
'H', states.loc[3, 'h'], params['WF'])
states.loc[3, 'T'] = CP.PropsSI('T', 'P', states.loc[3, 'P'],
'H', states.loc[3, 'h'], params['WF'])
states.loc[3, 'v'] = 1/CP.PropsSI('D', 'P', states.loc[3, 'P'],
'H', states.loc[3, 'h'], params['WF'])
In [9]:
ax = plt.axes([0,0,0,0.1])
ax.axis('off')
plt.text(0, 1.0, "$\eta_{c}$="+'{:.02f}'.format(eta_c), size=14)
plt.text(0, 0.5, "$\dot{W}_{s,c}/\dot{m}$="+'{:.02f} J/kg'.format(W_dot_s_c_m_dot), size=14)
plt.text(0, 0, "$\dot{W}_{c}/\dot{m}$="+'{:.02f} J/kg'.format(W_dot_s_c_m_dot), size=14)
plt.show()
display(states)

T | P | s | s_s | v | h | h_s | |
---|---|---|---|---|---|---|---|
1 | 262.16 | 2.57478e+06 | 1271.96 | NaN | NaN | 269834 | NaN |
2 | 264.16 | 2.57478e+06 | 1914.6 | NaN | 0.0147807 | 438320 | NaN |
3 | 367.845 | 6.89339e+06 | 2032.34 | 1914.6 | 0.00827627 | 521470 | 480011 |
4 | 298.16 | 6.89339e+06 | 1229.75 | NaN | NaN | 269834 | NaN |
飽和蒸気曲線の作成¶
In [10]:
P_list = list(range(int(5.2*1e+5), int(7.377*1e+6), int(1e+3)))
saturation_curve = {}
saturation_curve['Ts'] = {'s':[], 'T':[]}
for P in P_list:
saturation_curve['Ts']['T'].append(CP.PropsSI('T', 'P', P, 'Q', 0, params['WF']))
saturation_curve['Ts']['s'].append(CP.PropsSI('S', 'P', P, 'Q', 0, params['WF']))
for P in P_list[::-1]:
saturation_curve['Ts']['T'].append(CP.PropsSI('T', 'P', P, 'Q', 1, params['WF']))
saturation_curve['Ts']['s'].append(CP.PropsSI('S', 'P', P, 'Q', 1, params['WF']))
saturation_curve['ph'] = {'p':[], 'h':[]}
T_list = list(range(217, 304))
for T in T_list:
saturation_curve['ph']['p'].append(CP.PropsSI('P', 'T', T, 'Q', 0, params['WF'])/1e6)
saturation_curve['ph']['h'].append(CP.PropsSI('H', 'T', T, 'Q', 0, params['WF'])/1e6)
for T in T_list[::-1]:
saturation_curve['ph']['p'].append(CP.PropsSI('P', 'T', T, 'Q', 1, params['WF'])/1e6)
saturation_curve['ph']['h'].append(CP.PropsSI('H', 'T', T, 'Q', 1, params['WF'])/1e6)
Chart¶
T-s¶
In [11]:
s_max = 2500
s_list = range(0, s_max)
plt.plot(s_list, [params['T_bldg']]*s_max, label='$T_{bldg}$', color='red')
plt.plot(s_list, [params['T_amb']]*s_max, label='$T_{amb}$', color='blue')
plt.plot(saturation_curve['Ts']['s'], saturation_curve['Ts']['T'], color='gray')
nb_points = 1000
s12 = np.linspace(states.loc[1, 's'], states.loc[2, 's'], nb_points)
s23 = np.linspace(states.loc[2, 's'], states.loc[3, 's'], nb_points)
s34 = np.linspace(states.loc[3, 's'], states.loc[4, 's'], nb_points)
s41 = np.linspace(states.loc[4, 's'], states.loc[1, 's'], nb_points)
T12 = np.linspace(states.loc[1, 'T'], states.loc[2, 'T'], nb_points)
T23 = np.linspace(states.loc[2, 'T'], states.loc[3, 'T'], nb_points)
T34 = []
for s in s34:
T34.append(CP.PropsSI('T', 'S', s, 'P', states.loc[3, 'P'], params['WF']))
T41 = np.linspace(states.loc[4, 'T'], states.loc[1, 'T'], nb_points)
L_T = [T12, T23, T34, T41]
L_s = [s12, s23, s34, s41]
for i in range(len(L_s)):
plt.plot(L_s[i],L_T[i],label='{}$\\to${}'.format(i+1,(i+1)%5+1))
plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left', borderaxespad=0)
plt.xlabel('Specific entropy $s$ J/kg-K')
plt.ylabel('Temperature $T$ K')
plt.grid()
plt.show()

P-h¶
In [12]:
plt.plot(saturation_curve['ph']['h'], saturation_curve['ph']['p'], color='gray')
nb_points = 1000
h12 = np.linspace(states.loc[1, 'h'], states.loc[2, 'h'], nb_points)
h23 = np.linspace(states.loc[2, 'h'], states.loc[3, 'h'], nb_points)
h34 = np.linspace(states.loc[3, 'h'], states.loc[4, 'h'], nb_points)
h41 = np.linspace(states.loc[4, 'h'], states.loc[1, 'h'], nb_points)
P12 = np.linspace(states.loc[1, 'P'], states.loc[2, 'P'], nb_points)
P23 = np.linspace(states.loc[2, 'P'], states.loc[3, 'P'], nb_points)
P34 = np.linspace(states.loc[3, 'P'], states.loc[4, 'P'], nb_points)
P41 = np.linspace(states.loc[4, 'P'], states.loc[1, 'P'], nb_points)
L_h = [h12, h23, h34, h41]
L_P = [P12, P23, P34, P41]
for i in range(len(L_h)):
plt.plot(L_h[i]/1e6, L_P[i]/1e6,label='{}$\\to${}'.format(i+1,(i+1)%5+1))
plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left', borderaxespad=0)
plt.xlabel("Specific enthalpy $h$ J/kg x$10^6$")
plt.ylabel('Pressire $P$ MPa')
#plt.yscale("log")
plt.grid()
plt.show()

Perfoemance of heat pump cycle¶
Power required by the compressor¶
\begin{align}
\eta_{vol} = 1-c(\frac{v_2}{v_3}-1) \\
\dot{m} = \frac{\dot{V}_{disp}\eta_{vol}}{v_2} \\
\dot{W}_c = \frac{\dot{W}_c}{\dot{m}}\dot{m} \\
\end{align}
In [13]:
eta_vol = 1- params['c']*(states.loc[2, 'v']/states.loc[3, 'v'] - 1)
m_dot = params['V_dot_disp']*eta_vol/states.loc[2, 'v']
W_dot_c = W_dot_c_m_dot*m_dot
ax = plt.axes([0,0,0,0.2])
ax.axis('off')
plt.text(0, 1, "$\eta_{vol}$="+'{:.02f}'.format(eta_vol), size=14)
plt.text(0, 0.5, "$\dot{m}$="+'{:.02f} kg/s'.format(m_dot), size=14)
plt.text(0, 0, "$\dot{W}_{c}$="+'{:.02f} kW'.format(W_dot_c/1e3), size=14)
plt.show()

Condenser heat transfer rate¶
\begin{align}
\dot{Q}_{cond} = \dot{m}(h_3-h_4) \text{ or } \eta_{cond}\dot{m}_{a,cond}c_{p,a,cond}(T_{cond}-T_{bldg}) \\
\dot{m}_{a,cond} = \frac{\dot{V}_{cond,f}}{v_{a,cond}}
\end{align}
In [14]:
Q_dot_cond = m_dot*(states.loc[3, 'h'] -states.loc[4, 'h'])
cP_a_cond = CP.PropsSI('Cp0mass', 'T', params['T_bldg'], 'P', 101325, 'Air')
v_a_cond = 1/CP.PropsSI('D', 'T', params['T_bldg'], 'P', 101325, 'Air')
m_dot_a_cond = params['V_dot_cond_f'] / v_a_cond
Q_dot_cond_alt = params['ETA_cond']*m_dot_a_cond*cP_a_cond*(T_cond - params['T_bldg'])
ax = plt.axes([0,0,0,0.3])
ax.axis('off')
plt.text(0, 1.0, "$\dot{Q}_{cond}$="+'{:.02f} kW'.format(Q_dot_cond/1e3), size=14)
plt.text(0, 0.75, "$\dot{Q}_{cond}^{alt}$="+'{:.02f} kW'.format(Q_dot_cond_alt/1e3), size=14)
plt.text(0, 0.5, "$\dot{c}_{p,a,cond}$="+'{:.02f} kJ/kg/K'.format(cP_a_cond/1e3), size=14)
plt.text(0, 0.25, "$v_{a,cond}$="+'{:.02f} $m^3$/kg'.format(v_a_cond), size=14)
plt.text(0, 0.0, "$\dot{m}_{a,cond}$="+'{:.02f} kg/s'.format(m_dot_a_cond), size=14)
plt.show()

Evaporator heat transfer rate¶
\begin{align}
\dot{Q}_{evap} = \dot{m}(h_2-h_1) \text{ or } \eta_{evap}\dot{m}_{a,evap}c_{p,a,evap}(T_{amb}-T_{evap}) \\
\dot{m}_{a,evap} = \frac{\dot{V}_{evap,f}}{v_{a,evap}}
\end{align}
In [15]:
Q_dot_evap = m_dot*(states.loc[2, 'h']-states.loc[1, 'h'])
cP_a_evap = CP.PropsSI('Cp0mass', 'T', params['T_amb'], 'P', 101325, 'Air')
v_a_evap = 1/CP.PropsSI('D', 'T', params['T_amb'], 'P', 101325, 'Air')
m_dot_a_evap = params['V_dot_evap_f'] / v_a_evap
Q_dot_evap_alt = params['ETA_evap']*m_dot_a_evap*cP_a_evap*(params['T_amb'] - T_evap)
ax = plt.axes([0,0,0,0.3])
ax.axis('off')
plt.text(0, 1.0, "$\dot{Q}_{evap}$="+'{:.02f} kW'.format(Q_dot_evap/1e3), size=14)
plt.text(0, 0.75, "$\dot{Q}_{evap}^{alt}$="+'{:.02f} kW'.format(Q_dot_evap_alt/1e3), size=14)
plt.text(0, 0.5, "$\dot{c}_{p,a,evap}$="+'{:.02f} kJ/kg/K'.format(cP_a_evap/1e3), size=14)
plt.text(0, 0.25, "$v_{a,evap}$="+'{:.02f} $m^3$/kg'.format(v_a_evap), size=14)
plt.text(0, 0.0, "$\dot{m}_{a,evap}$="+'{:.02f} kg/s'.format(m_dot_a_evap), size=14)
plt.show()

COP of the heat pump system¶
\begin{align}
COP = \frac{\dot{Q}_{cond}}{\dot{W}_{c} + \dot{W}_{cond,f} + \dot{W}_{evap,f}}
\end{align}
In [16]:
COP = Q_dot_cond / (W_dot_c + params['W_dot_cond_f'] + params['W_dot_evap_f'])
display(COP)
2.895050928533937