-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathotec_sizing.py
192 lines (135 loc) · 6.81 KB
/
otec_sizing.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# -*- coding: utf-8 -*-
"""
Created on Tue Apr 27 11:16:02 2021
@author: jkalanger
"""
import numpy as np
from general_scripts import saturation_pressures_and_temperatures,enthalpies_entropies,pressure_drop
from parameters_and_constants import parameters_and_constants
def ammonia_pump_sizing(p_evap,p_cond,enthalpies,inputs):
m_NH3 = inputs['p_gross']/(enthalpies['h_4']-enthalpies['h_3']) # mass flow
p_pump_NH3 = m_NH3*(enthalpies['h_2']-enthalpies['h_1']) # power consumption
return m_NH3,p_pump_NH3
def evaporator_sizing(T_WW_in,del_T_WW,T_evap,m_NH3,enthalpies,inputs):
del_T_log_evap = ((T_WW_in-T_evap) - ((T_WW_in-del_T_WW)-T_evap))/np.log((T_WW_in-T_evap)/((T_WW_in-del_T_WW)-T_evap))
Q_evap = m_NH3*(enthalpies['h_3']-enthalpies['h_2'])
m_WW = Q_evap/(inputs['cp_water']*del_T_WW)
A_evap = Q_evap/(inputs['U_evap']*del_T_log_evap)
evaporator = {
'm_WW': m_WW,
'A_evap': A_evap,
'Q_evap': Q_evap
}
return evaporator
def condenser_sizing(T_CW_in,del_T_CW,T_cond,m_NH3,enthalpies,inputs):
del_T_log_cond = ((T_cond-T_CW_in) - (T_cond-(T_CW_in+del_T_CW)))/np.log((T_cond-T_CW_in)/(T_cond-(T_CW_in+del_T_CW)))
Q_cond = m_NH3*(enthalpies['h_1']-enthalpies['h_4'])
m_CW = -Q_cond/(inputs['cp_water']*del_T_CW)
A_cond = -Q_cond/(inputs['U_cond']*del_T_log_cond)
condenser = {
'm_CW': m_CW,
'A_cond': A_cond,
'Q_cond': Q_cond
}
return condenser
def seawater_pipe_sizing(T_in,m_water,rho,length,inputs):
## Load and unpack inputs to improve readibility of code below
rho_pipe,roughness_pipe = inputs['pipe_material']
length_WW, \
length_CW, \
SDR_ratio, \
K_L, \
u_pipes, \
u_HX, \
pressure_drop_nom, \
max_d, \
max_p = inputs['pipe_properties']
u_pipes = np.ones(np.size(T_in),dtype=np.float64)*u_pipes
p_drop = np.ones(np.size(T_in),dtype=np.float64)*pressure_drop_nom
while np.any(p_drop >= max_p):
u_pipes[p_drop >= max_p] = u_pipes[p_drop >= max_p] - 0.1
u_HX = u_pipes/2
A_pipes = m_water/rho/u_pipes
# To avoid making the same calculation twice for inlet and outlet pipe, we assume that they form one single pipe
# with the same properties (diameter, thickness, etc.) and loading (water flow, pressure drop, etc.)
# Therefore, we don't count the individual inlet and outlet pipes, but the pipe pairs. Once we have the required pairs,
# we multiply the pairs with 2 to obtain the number of actual pipes needed.
pipe_pairs = np.zeros(np.size(T_in),dtype=np.float64)
d_pipes = np.ones(np.size(T_in),dtype=np.float64)*(max_d+0.1)
thickness = d_pipes/SDR_ratio
while np.any(d_pipes > max_d):
pipe_pairs[d_pipes > max_d] = pipe_pairs[d_pipes > max_d] + 1
d_pipes = np.sqrt(A_pipes*4/(np.pi*pipe_pairs))
thickness = d_pipes/SDR_ratio # adjust the thickness of the pipe based on its diameter
m_pipes = np.pi/4*((d_pipes+2*thickness)**2-d_pipes**2)*length*rho_pipe*pipe_pairs
num_pipes = pipe_pairs*2
# print(d_pipes,thickness)
p_drop = pressure_drop(T_in,u_pipes,d_pipes,rho,roughness_pipe,length,K_L,u_HX)
p_pump = m_water/rho*p_drop/inputs['eff_hyd']/inputs['eff_el']
pipes = {
'd_pipes': d_pipes,
'num_pipes': num_pipes,
'm_pipes': m_pipes,
'A_pipes': A_pipes,
'p_pump': p_pump
}
return pipes
def otec_sizing(T_WW_in,T_CW_in,del_T_WW,del_T_CW,inputs,cost_level):
# inputs = parameters_and_constants(cost_level)
T_evap,T_cond,p_evap,p_cond = saturation_pressures_and_temperatures(T_WW_in,T_CW_in,del_T_WW,del_T_CW,inputs)
enthalpies = enthalpies_entropies(p_evap,p_cond,inputs)
m_NH3,p_pump_NH3 = ammonia_pump_sizing(p_evap,p_cond,enthalpies,inputs)
evaporator = evaporator_sizing(T_WW_in,del_T_WW,T_evap,m_NH3,enthalpies,inputs)
condenser = condenser_sizing(T_CW_in,del_T_CW,T_cond,m_NH3,enthalpies,inputs)
pipes_WW = seawater_pipe_sizing(T_WW_in,
evaporator['m_WW'],
inputs['rho_WW'],
inputs['length_WW'],
inputs)
pipes_CW = seawater_pipe_sizing(T_CW_in,
condenser['m_CW'],
inputs['rho_CW'],
inputs['length_CW'],
inputs)
p_pump_total = p_pump_NH3/inputs['eff_pump_NH3_mech'] + pipes_WW['p_pump'] + pipes_CW['p_pump']
p_net = (inputs['p_gross']*inputs['eff_turb_el']*inputs['eff_turb_mech'] + p_pump_total)*inputs['eff_trans']
eff_net = -p_net/evaporator['Q_evap']
if np.any(p_net > 0):
# print('Infeasible systems detected and replaced by NaN')
p_net = np.where(p_net > 0, np.nan, p_net)
# Pack results
otec_plant_nominal = {
'm_NH3_nom': m_NH3,
'del_T_WW' : del_T_WW,
'T_evap_nom' : T_evap,
'p_evap_nom' : p_evap,
'm_WW_nom' : evaporator['m_WW'],
'A_evap' : evaporator['A_evap'],
'Q_evap_nom' : evaporator['Q_evap'],
'p_gross_nom': np.ones(np.shape(p_net),dtype=np.float64)*inputs['p_gross'],
'p_net_nom': p_net,
'p_pump_total_nom': p_pump_total,
'p_pump_NH3_nom': p_pump_NH3,
'p_pump_WW_nom' : pipes_WW['p_pump'],
'p_pump_CW_nom' : pipes_CW['p_pump'],
'eff_net_nom' : eff_net,
'del_T_CW' : del_T_CW,
'T_cond_nom' : T_cond,
'p_cond_nom' : p_cond,
'm_CW_nom' : condenser['m_CW'],
'A_cond' : condenser['A_cond'],
'Q_cond_nom' : condenser['Q_cond'],
'd_pipes_WW': pipes_WW['d_pipes'],
'num_pipes_WW': pipes_WW['num_pipes'],
'm_pipes_WW': pipes_WW['m_pipes'],
'A_pipes_WW': pipes_WW['A_pipes'],
'd_pipes_CW': pipes_CW['d_pipes'],
'num_pipes_CW': pipes_CW['num_pipes'],
'm_pipes_CW': pipes_CW['m_pipes'],
'A_pipes_CW': pipes_CW['A_pipes'],
'h_1_nom': enthalpies['h_1'],
'h_2_nom': enthalpies['h_2'],
'h_3_nom': enthalpies['h_3'],
'h_4_nom': enthalpies['h_4']
}
return otec_plant_nominal