1 |
# -*- coding: utf8 -*- |
2 |
import extpy, sys |
3 |
from solverreporter import * |
4 |
|
5 |
import sys, os, os.path |
6 |
sys.path.append(os.path.expanduser("~/ascend/models/johnpye/fprops/python")) |
7 |
import fprops |
8 |
|
9 |
try: |
10 |
from pylab import * |
11 |
except: |
12 |
pass |
13 |
|
14 |
#--- for (T,s) plots --- |
15 |
|
16 |
def sat_curve(D): |
17 |
Tt = D.T_t |
18 |
Tc = D.T_c |
19 |
TT = [] |
20 |
pp = [] |
21 |
ssf = [] |
22 |
ssg = [] |
23 |
for T in linspace(Tt,Tc,100): |
24 |
# TODO this is inefficient because of repeated saturation solutions. |
25 |
SF = D.set_Tx(T,0) |
26 |
SG = D.set_Tx(T,1) |
27 |
TT.append(SF.T - 273.15) |
28 |
pp.append(SF.p) |
29 |
ssf.append(SF.s/1.e3) |
30 |
ssg.append(SG.s/1.e3) |
31 |
plot(ssf,TT,"b--") |
32 |
plot(ssg,TT,"r--") |
33 |
|
34 |
class TSPoint: |
35 |
def __init__(self,T,s): |
36 |
self.T = T |
37 |
self.s = s |
38 |
|
39 |
def write(msg): |
40 |
extpy.getbrowser().reporter.reportNote(msg) |
41 |
|
42 |
def pconst(S1,S2,n): |
43 |
"""Return a set of (T,s) points between two states, with pressure held constant.""" |
44 |
D = fprops.fluid(str(S1.cd.component.getSymbolValue())) |
45 |
out = [] |
46 |
hh = linspace(float(S1.h), float(S2.h), n) |
47 |
for h in hh: |
48 |
S = D.set_ph(float(S1.p), h) |
49 |
out += [TSPoint(S.T,S.s)] |
50 |
return out |
51 |
|
52 |
|
53 |
def plot_Ts(SS,style='b-'): |
54 |
xx = [] |
55 |
yy = [] |
56 |
for S in SS: |
57 |
yy.append(float(S.T) - 273.15) |
58 |
xx.append(float(S.s)/1.e3) |
59 |
plot(xx,yy,style) |
60 |
|
61 |
#--- for (T,H) plots --- |
62 |
|
63 |
class THPoint: |
64 |
def __init__(self,T,h,mdot = 1.): |
65 |
self.T = T |
66 |
self.h = h |
67 |
self.mdot = mdot |
68 |
|
69 |
def pconsth(S1,S2,n): |
70 |
"""Return a set of (T,H) points between two states, with pressure constant""" |
71 |
D = fprops.fluid(str(S1.cd.component.getSymbolValue())) |
72 |
out = [] |
73 |
hh = linspace(float(S1.h), float(S2.h), n) |
74 |
mdot = float(S1.mdot) |
75 |
for h in hh: |
76 |
# TODO add try/except |
77 |
S = D.set_ph(float(S1.p),h) |
78 |
out += [THPoint(S.T,h * mdot)] |
79 |
return out |
80 |
|
81 |
def plot_TH(SS,style='b-',Href = 0): |
82 |
xx = [] |
83 |
yy = [] |
84 |
for S in SS: |
85 |
yy.append(float(S.T) - 273.15) |
86 |
xx.append(((float(S.h)*float(S.mdot)) - Href)/1.e6) |
87 |
plot(xx,yy,style) |
88 |
|
89 |
#--- various Rankine cycle configurations --- |
90 |
|
91 |
def cycle_plot_rankine(self): |
92 |
"""Plot T-s diagram for a simple Rankine cycle""" |
93 |
import loading |
94 |
loading.load_matplotlib(throw=True) |
95 |
ioff() |
96 |
figure() |
97 |
hold(1) |
98 |
D = fprops.fluid(str(self.cd.component.getSymbolValue())) |
99 |
sat_curve(D) |
100 |
|
101 |
boiler_curve = pconst(self.BO.inlet, self.BO.outlet,100) |
102 |
condenser_curve = pconst(self.CO.inlet,self.CO.outlet,100) |
103 |
SS = [self.PU.outlet, self.BO.inlet] + boiler_curve + [self.TU.inlet, self.TU.outlet] + condenser_curve + [self.CO.outlet, self.PU.outlet] |
104 |
plot_Ts(SS) |
105 |
|
106 |
title(unicode(r"Rankine cycle with %s" % D.name)) |
107 |
ylabel(unicode(r"T / [��C]")) |
108 |
aa = axis(); axis([aa[0],aa[1],-100,600]) |
109 |
xlabel("s / [kJ/kg/K]") |
110 |
|
111 |
extpy.getbrowser().reporter.reportNote("Plotting completed") |
112 |
ion() |
113 |
show() |
114 |
savefig(os.path.expanduser("~/Desktop/rankine.eps")) |
115 |
|
116 |
def cycle_plot_rankine_regen2(self): |
117 |
"""Plot T-s diagram for a regenerative Rankine cycle (bleed steam regen)""" |
118 |
import loading |
119 |
loading.load_matplotlib(throw=True) |
120 |
ioff() |
121 |
figure() |
122 |
hold(1) |
123 |
D = fprops.fprops_fluid(str(self.cd.component.getSymbolValue())) |
124 |
sat_curve(D) |
125 |
|
126 |
boiler_curve = pconst(self.BO.inlet, self.BO.outlet,100) |
127 |
condenser_curve = pconst(self.CO.inlet,self.CO.outlet,100) |
128 |
|
129 |
SS = [self.PU1.inlet, self.PU1.outlet] + \ |
130 |
pconst(self.HE.inlet, self.HE.outlet, 100) + \ |
131 |
[self.PU2.inlet, self.PU2.outlet] + \ |
132 |
boiler_curve + \ |
133 |
[self.TU1.inlet, self.TU1.outlet, self.TU2.outlet] + \ |
134 |
condenser_curve + [self.PU1.inlet] |
135 |
|
136 |
plot_Ts(SS) |
137 |
plot_Ts( |
138 |
[self.PU1.inlet, self.PU1.outlet, self.HE.inlet, self.HE.outlet, |
139 |
self.PU2.inlet, self.PU2.outlet, self.TU1.inlet, self.TU1.outlet, |
140 |
self.TU2.outlet, self.PU1.inlet] |
141 |
,'bo' |
142 |
) |
143 |
|
144 |
# line for the heat exchanger |
145 |
plot_Ts(pconst(self.HE.inlet_heat, self.HE.outlet,100),'b-') |
146 |
|
147 |
title(unicode(r"Regenerative Rankine cycle with %s" % D.name)) |
148 |
ylabel(unicode(r"T / [��C]")) |
149 |
aa = axis(); axis([aa[0],aa[1],-100,600]) |
150 |
xlabel("s / [kJ/kg/K]") |
151 |
|
152 |
extpy.getbrowser().reporter.reportNote("Plotting completed") |
153 |
ion() |
154 |
show() |
155 |
savefig(os.path.expanduser("~/Desktop/regen2.eps")) |
156 |
|
157 |
|
158 |
|
159 |
def cycle_plot_rankine_regen1(self): |
160 |
"""Plot T-s diagram for a regenerative Rankine cycle""" |
161 |
import loading |
162 |
loading.load_matplotlib(throw=True) |
163 |
ioff() |
164 |
figure() |
165 |
hold(1) |
166 |
D = fprops.fluid(str(self.cd.component.getSymbolValue())) |
167 |
sat_curve(D) |
168 |
|
169 |
boiler_curve = pconst(self.BO.inlet, self.BO.outlet,100) |
170 |
condenser_curve = pconst(self.CO.inlet,self.CO.outlet,100) |
171 |
he_hot = pconst(self.HE.inlet_heat, self.HE.outlet_heat,100) |
172 |
he_cold = pconst(self.HE.inlet, self.HE.outlet,100) |
173 |
|
174 |
SS = [self.PU.outlet] + he_cold + [self.BO.inlet] + boiler_curve + [self.TU.inlet, self.TU.outlet] + he_hot + condenser_curve + [self.PU.inlet, self.PU.outlet] |
175 |
|
176 |
plot_Ts(SS) |
177 |
plot_Ts( |
178 |
[self.PU.outlet,self.BO.inlet,self.TU.inlet, self.TU.outlet |
179 |
,self.HE.outlet_heat, self.PU.inlet, self.PU.outlet] |
180 |
,'bo' |
181 |
) |
182 |
|
183 |
# dotted lines for the heat exchanger |
184 |
plot_Ts([self.HE.inlet_heat, self.HE.outlet],'b:') |
185 |
plot_Ts([self.HE.outlet_heat, self.HE.inlet],'b:') |
186 |
|
187 |
title(unicode(r"Regenerative Rankine cycle with %s" % D.name)) |
188 |
ylabel(unicode(r"T / [��C]")) |
189 |
aa = axis(); axis([aa[0],aa[1],-100,600]) |
190 |
xlabel("s / [kJ/kg/K]") |
191 |
|
192 |
extpy.getbrowser().reporter.reportNote("Plotting completed") |
193 |
ion() |
194 |
show() |
195 |
savefig(os.path.expanduser("~/Desktop/regen1.eps")) |
196 |
|
197 |
|
198 |
#--- heat exchange (T,H) plot --- |
199 |
|
200 |
def heater_closed_plot(self): |
201 |
"""Plot T-H diagram of heat transfer in a heater_closed model""" |
202 |
import loading |
203 |
loading.load_matplotlib(throw=True) |
204 |
ioff() |
205 |
figure() |
206 |
hold(1) |
207 |
D = fprops.fluid(str(self.cd.component.getSymbolValue())) |
208 |
HE = self.HE |
209 |
|
210 |
extpy.getbrowser().reporter.reportNote("Fluid is %s" % D.name) |
211 |
|
212 |
plot_TH(pconsth(HE.inlet_heat, HE.outlet_heat, 50),'r-', |
213 |
Href = (float(HE.outlet_heat.h)*float(HE.outlet_heat.mdot))\ |
214 |
) |
215 |
|
216 |
plot_TH(pconsth(HE.inlet, HE.outlet, 50),'b-', |
217 |
Href = (float(HE.inlet.h)*float(HE.inlet.mdot))\ |
218 |
) |
219 |
|
220 |
title(unicode(r"Closed feedwater heater with %s" % D.name)) |
221 |
ylabel(unicode(r"T / [��C]")) |
222 |
xlabel("H / [MW]") |
223 |
|
224 |
extpy.getbrowser().reporter.reportNote("Plotting completed") |
225 |
ion() |
226 |
show() |
227 |
savefig(os.path.expanduser("~/Desktop/heater_closed.eps")) |
228 |
|
229 |
#--- the big one: a combined-cycle GT --- |
230 |
|
231 |
def cycle_plot_ccgt(self): |
232 |
"""Plot T-s diagram for combined-cycle gas turbine""" |
233 |
import loading |
234 |
loading.load_matplotlib(throw=True) |
235 |
ioff() |
236 |
figure() |
237 |
|
238 |
D = fprops.fluid(str(self.cd_rankine.component.getSymbolValue())) |
239 |
|
240 |
# plot gas turbine cycle |
241 |
SS = [self.GC.inlet, self.GC.outlet, self.GT.inlet, self.GT.outlet, self.HE.inlet, self.HE.outlet, self.GC.inlet] |
242 |
plot_Ts(SS,'g-') |
243 |
plot_Ts(SS,'go') |
244 |
hold(1) |
245 |
|
246 |
sat_curve(D) |
247 |
|
248 |
boiler_curve = pconst(self.HE.inlet_cold,self.HE.outlet_cold,100) |
249 |
condenser_curve = pconst(self.CO.inlet,self.CO.outlet,100) |
250 |
SS2 = [self.PU.outlet, self.HE.inlet_cold] + boiler_curve + [self.HE.outlet_cold, self.TU.inlet, self.TU.outlet, self.CO.inlet] + condenser_curve + [self.CO.outlet, self.PU.inlet, self.PU.outlet] |
251 |
plot_Ts(SS2) |
252 |
plot_Ts([self.PU.outlet, self.HE.inlet_cold,self.HE.outlet_cold, self.TU.inlet, self.TU.outlet, self.CO.inlet,self.CO.outlet, self.PU.inlet, self.PU.outlet],'bo') |
253 |
|
254 |
title(unicode(r"Combined cycle with air and %s" % D.name)) |
255 |
ylabel(unicode(r"T / [��C]")) |
256 |
xlabel("s / [kJ/kg/K]") |
257 |
|
258 |
extpy.getbrowser().reporter.reportNote("Plotting completed") |
259 |
ion() |
260 |
show() |
261 |
savefig(os.path.expanduser("~/Desktop/ccgt.eps")) |
262 |
savefig(os.path.expanduser("~/Desktop/ccgt.png")) |
263 |
|
264 |
|
265 |
#--- simple gas turbine models --- |
266 |
|
267 |
|
268 |
def cycle_plot_brayton_regen(self): |
269 |
"""Plot T-s diagran for regenerative gas turbine""" |
270 |
import loading |
271 |
loading.load_matplotlib(throw=True) |
272 |
ioff() |
273 |
figure() |
274 |
|
275 |
# plot gas turbine cycle |
276 |
SS = [self.CO.inlet, self.CO.outlet, self.RE.inlet, self.RE.outlet, self.BU.inlet,self.BU.outlet, self.TU.inlet, self.TU.outlet,self.RE.inlet_hot, self.RE.outlet_hot, self.DI.inlet, self.DI.outlet,self.CO.inlet] |
277 |
plot_Ts(SS,'g-') |
278 |
plot_Ts(SS,'go') |
279 |
hold(1) |
280 |
|
281 |
title(unicode(r"Regenerative Brayton cycle")) |
282 |
ylabel(unicode(r"T / [��C]")) |
283 |
xlabel("s / [kJ/kg/K]") |
284 |
|
285 |
extpy.getbrowser().reporter.reportNote("Plotting completed") |
286 |
ion() |
287 |
show() |
288 |
savefig(os.path.expanduser("~/Desktop/brayton_regen.eps")) |
289 |
|
290 |
#--- air-to-stream heat exchanger plot --- |
291 |
|
292 |
def air_stream_heat_exchanger_plot(self): |
293 |
"""Plot T-H diagram of heat transfer in a heater_closed model""" |
294 |
import loading |
295 |
loading.load_matplotlib(throw=True) |
296 |
ioff() |
297 |
figure() |
298 |
hold(1) |
299 |
D = fprops.fluid(str(self.cd_cold.component.getSymbolValue())) |
300 |
|
301 |
n = self.n.getIntValue() |
302 |
extpy.getbrowser().reporter.reportNote("Fluid is %s" % D.name) |
303 |
|
304 |
# hot side is the air, calculated in the model |
305 |
plot_TH( [self.H[i] for i in range(1+int(n))],'r-',\ |
306 |
Href = (float(self.outlet.h)*float(self.outlet.mdot))\ |
307 |
) |
308 |
|
309 |
plot_TH(pconsth(self.inlet_cold, self.outlet_cold, 50),'b-', |
310 |
Href = (float(self.inlet_cold.h)*float(self.inlet_cold.mdot))\ |
311 |
) |
312 |
|
313 |
title(unicode(r"Combined-cycle air-%s heat exchanger" % D.name)) |
314 |
ylabel(unicode(r"T / [��C]")) |
315 |
xlabel("H / [MW]") |
316 |
|
317 |
extpy.getbrowser().reporter.reportNote("Plotting completed") |
318 |
ion() |
319 |
show() |
320 |
savefig(os.path.expanduser("~/Desktop/air_stream_heatex.eps")) |
321 |
|
322 |
|
323 |
extpy.registermethod(cycle_plot_rankine) |
324 |
extpy.registermethod(cycle_plot_rankine_regen1) |
325 |
extpy.registermethod(cycle_plot_rankine_regen2) |
326 |
extpy.registermethod(cycle_plot_brayton_regen) |
327 |
extpy.registermethod(cycle_plot_ccgt) |
328 |
|
329 |
extpy.registermethod(heater_closed_plot) |
330 |
extpy.registermethod(air_stream_heat_exchanger_plot) |
331 |
|
332 |
#the above method can be called using "EXTERNAL fourbarplot(SELF)" in ASCEND. |