/[ascend]/trunk/models/johnpye/rankine.a4c
ViewVC logotype

Contents of /trunk/models/johnpye/rankine.a4c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1675 - (show annotations) (download) (as text)
Tue Dec 18 04:59:37 2007 UTC (11 years, 7 months ago) by jpye
File MIME type: text/x-ascend
File size: 14323 byte(s)
Fixed rankine_reheat (there is a bit of a question about how to calculate cycle efficiency when pump work is *not* neglected).
1 REQUIRE "atoms.a4l";
2 REQUIRE "johnpye/thermo_types.a4c";
3
4 IMPORT "freesteam";
5
6 (* Model of simple Rankine cycle with boiler, turbine, condenser, pump *)
7
8 (*------------------------------------------------------------------------------
9 BACKGROUND STUFF
10 *)
11
12 (*
13 Thermo properties -- IAPWS-IF97
14 *)
15 MODEL steam_state;
16 p IS_A pressure;
17 h IS_A specific_enthalpy;
18 u IS_A specific_energy;
19 v IS_A specific_volume;
20 T IS_A temperature;
21 x IS_A fraction;
22 s IS_A specific_entropy;
23 mu IS_A viscosity;
24
25 thermo: iapws97_uvTxsmu_ph(
26 p,h : INPUT;
27 u,v,T,x,s,mu : OUTPUT
28 );
29 METHODS
30 METHOD default;
31 p := 10{bar};
32 p.nominal := 42 {bar};
33 v.nominal := 10 {L/kg};
34 u := 2000 {kJ/kg};
35 T := 400 {K};
36 x := 0.8;
37 END default;
38 METHOD solve;
39 EXTERNAL do_solve(SELF);
40 END solve;
41 METHOD on_load;
42 RUN default_all;
43 FIX p, h;
44 END on_load;
45 END steam_state;
46
47 (* a simple connector that includes calculation of steam properties *)
48 MODEL steam_node;
49 state IS_A steam_state;
50 p ALIASES state.p;
51 h ALIASES state.h;
52 u ALIASES state.u;
53 v ALIASES state.v;
54 T ALIASES state.T;
55 x ALIASES state.x;
56 s ALIASES state.s;
57 mu ALIASES state.mu;
58 mdot IS_A mass_rate;
59 METHODS
60 METHOD default;
61 mdot.nominal := 2 {kg/s};
62 END default;
63 METHOD solve;
64 EXTERNAL do_solve(SELF);
65 END solve;
66 METHOD on_load;
67 RUN default_all; RUN reset; RUN values;
68 FIX p,h;
69 END on_load;
70 END steam_node;
71
72 MODEL steam_equipment;
73 inlet IS_A steam_node;
74 outlet IS_A steam_node;
75
76 inlet.mdot, outlet.mdot ARE_THE_SAME;
77 mdot ALIASES inlet.mdot;
78 END steam_equipment;
79
80 (*------------------------------------------------------------------------------
81 PUMP COMPONENT
82 *)
83
84 MODEL pump_simple REFINES steam_equipment;
85
86 dp IS_A delta_pressure;
87 inlet.p + dp = outlet.p;
88
89 outlet_is IS_A steam_state;
90 outlet_is.p, outlet.p ARE_THE_SAME;
91
92 outlet_is.s, inlet.s ARE_THE_SAME;
93 eta IS_A fraction;
94
95 eta * (inlet.h - outlet.h) = (inlet.h - outlet_is.h);
96
97 (* work done on the environment, will be negative *)
98 Wdot IS_A energy_rate;
99 Wdot = eta * mdot * (inlet.h - outlet.h);
100
101 w IS_A specific_energy;
102 w = eta * (outlet.h - inlet.h);
103
104 END pump_simple;
105
106 MODEL pump_simple_test REFINES pump_simple;
107 (* no equations here *)
108 METHODS
109 METHOD on_load;
110 FIX inlet.p;
111 FIX inlet.h;
112 FIX outlet.p;
113 FIX eta;
114 FIX mdot;
115
116 inlet.p := 5 {bar};
117 inlet.h := 400 {kJ/kg};
118 outlet.p := 100 {bar};
119 eta := 0.65;
120 mdot := 900 {t/d};
121 END on_load;
122 END pump_simple_test;
123
124 (*------------------------------------------------------------------------------
125 TURBINE COMPONENT
126 *)
127
128 MODEL turbine_simple REFINES steam_equipment;
129
130 dp IS_A delta_pressure;
131 inlet.p + dp = outlet.p;
132
133 outlet_is IS_A steam_state;
134 outlet_is.p, outlet.p ARE_THE_SAME;
135 outlet_is.s, inlet.s ARE_THE_SAME;
136
137 eta IS_A fraction;
138 eta * (inlet.h - outlet_is.h) = (inlet.h - outlet.h);
139
140 (* work done on the environment, will be positive *)
141 Wdot IS_A energy_rate;
142 Wdot = eta * mdot * (inlet.h - outlet.h);
143
144 w IS_A specific_energy;
145 w = inlet.h - outlet.h;
146
147 END turbine_simple;
148
149 MODEL turbine_simple_test REFINES turbine_simple;
150 (* no equations here *)
151 METHODS
152 METHOD on_load;
153 FIX inlet.p;
154 FIX inlet.h;
155 FIX outlet.p;
156 FIX eta;
157 FIX mdot;
158
159 inlet.p := 100 {bar};
160 inlet.h := 3000 {kJ/kg};
161 outlet.p := 5 {bar};
162 eta := 0.85;
163 mdot := 900 {t/d};
164 END on_load;
165 END turbine_simple_test;
166
167 (*------------------------------------------------------------------------------
168 BOILER COMPONENT
169 *)
170
171 (*
172 simple model assumes no pressure drop, but heating losses due to
173 flue gas temperature
174 *)
175 MODEL boiler_simple REFINES steam_equipment;
176
177 inlet.p, outlet.p ARE_THE_SAME;
178 Qdot_fuel IS_A energy_rate;
179 Qdot IS_A energy_rate;
180
181 Qdot = mdot * (outlet.h - inlet.h);
182
183 eta IS_A fraction;
184 Qdot = eta * Qdot_fuel;
185 END boiler_simple;
186
187 MODEL boiler_simple_test REFINES boiler_simple;
188 (* nothing here *)
189 METHODS
190 METHOD on_load;
191 FIX inlet.p;
192 FIX inlet.h;
193 FIX eta;
194 FIX outlet.h;
195 FIX mdot;
196
197 inlet.p := 100 {bar};
198 inlet.h := 500 {kJ/kg};
199
200 eta := 0.8;
201 outlet.h := 3000 {kJ/kg};
202 mdot := 900 {t/d};
203 END on_load;
204 END boiler_simple_test;
205
206 (*------------------------------------------------------------------------------
207 CONDENSER COMPONENT
208 *)
209
210 (*
211 this is really simple (fluid props permitting): just work out the heat
212 that must be expelled to get the water down to a certain state
213 *)
214 MODEL condenser_simple REFINES steam_equipment;
215
216 inlet.p, outlet.p ARE_THE_SAME;
217 Qdot IS_A energy_rate;
218
219 Qdot = mdot * (outlet.h - inlet.h);
220
221 END condenser_simple;
222
223 MODEL condenser_simple_test REFINES condenser_simple;
224 (* nothing here *)
225 METHODS
226 METHOD on_load;
227 FIX inlet.p, inlet.x;
228 FIX outlet.h;
229 FIX mdot;
230
231 inlet.p := 5 {bar};
232 inlet.x := 0.95;
233 outlet.h := 500 {kJ/kg};
234 mdot := 900 {t/d};
235 END on_load;
236 END condenser_simple_test;
237
238 (*------------------------------------------------------------------------------
239 FEEDWATER HEATER
240 *)
241
242 (*
243 open heater does not have inlet.mdot==outlet.mdot, so not a refinement
244 of 'steam_equipment'.
245 *)
246 MODEL heater_open;
247
248 inlet IS_A steam_node;
249 inlet_heat IS_A steam_node;
250 outlet IS_A steam_node;
251
252 inlet_heat.p, inlet.p, outlet.p ARE_THE_SAME;
253
254 (* cons. mass *)
255 cons_mass: inlet.mdot + inlet_heat.mdot = outlet.mdot;
256
257 (* cons. energy *)
258 cons_en: inlet.mdot * inlet.h + inlet_heat.mdot * inlet_heat.h = outlet.mdot * outlet.h;
259
260 END heater_open;
261
262 MODEL heater_open_test REFINES heater_open;
263 (* nothing here *)
264 METHODS
265 METHOD on_load;
266 FIX inlet.p, inlet.h;
267 inlet.p := 40 {bar};
268 inlet.h := 634 {kJ/kg};
269 FIX inlet_heat.h;
270 inlet_heat.h := 2960 {kJ/kg};
271
272 FIX outlet.mdot;
273 outlet.mdot := 900 {t/d};
274
275 FIX inlet.mdot;
276 inlet.mdot := 700 {t/d};
277 END on_load;
278 END heater_open_test;
279
280 (*------------------------------------------------------------------------------
281 TEE PIECE
282 *)
283
284 (*
285 it's not a car :-)
286 *)
287 MODEL tee;
288 inlet IS_A steam_node;
289 outlet IS_A steam_node;
290 outlet_branch IS_A steam_node;
291
292
293 inlet.p, outlet.p, outlet_branch.p ARE_THE_SAME;
294 inlet.h, outlet.h, outlet_branch.h ARE_THE_SAME;
295
296 (* cons. mass *)
297 cons_mass: inlet.mdot = outlet.mdot + outlet_branch.mdot;
298
299 phi IS_A fraction;
300 phi * inlet.mdot = outlet_branch.mdot;
301
302 END tee;
303
304 (*------------------------------------------------------------------------------
305 OVERALL CYCLE
306 *)
307
308 (*
309 simplest possible rankine cycle
310 *)
311 MODEL rankine;
312
313 BO IS_A boiler_simple;
314 TU IS_A turbine_simple;
315 CO IS_A condenser_simple;
316 PU IS_A pump_simple;
317
318 BO.outlet, TU.inlet ARE_THE_SAME;
319 TU.outlet, CO.inlet ARE_THE_SAME;
320 CO.outlet, PU.inlet ARE_THE_SAME;
321 PU.outlet, BO.inlet ARE_THE_SAME;
322
323 Qdot_loss ALIASES CO.Qdot;
324
325 T_H ALIASES BO.outlet.T;
326 T_C ALIASES CO.outlet.T;
327
328 eta IS_A fraction;
329 eta * (BO.Qdot_fuel - PU.Wdot) = TU.Wdot;
330
331 eta_carnot IS_A fraction;
332 eta_carnot = 1 - T_C / T_H;
333
334 mdot ALIASES TU.mdot;
335 x_turb_out ALIASES TU.outlet.x;
336 METHODS
337 (* first test case: just some plausible values *)
338 METHOD specify_1;
339 RUN ClearAll;
340 FIX PU.inlet.p;
341 FIX PU.inlet.h;
342 FIX PU.outlet.p;
343 FIX BO.outlet.h;
344 FIX TU.eta;
345 FIX PU.eta;
346 FIX BO.eta;
347 FIX mdot;
348 END specify_1;
349 METHOD values_1;
350 PU.inlet.p := 1 {bar};
351 PU.inlet.h := 104.9 {kJ/kg};
352 PU.outlet.p := 250 {bar};
353 BO.outlet.h := 3772 {kJ/kg};
354 TU.eta := 0.85;
355 PU.eta := 0.65;
356 BO.eta := 0.9;
357 mdot := 900 {t/d};
358 END values_1;
359 (*
360 second test case: numbers from Example 2.1, K Weston, 'Energy Conversion',
361 1992, http://www.personal.utulsa.edu/~kenneth-weston/
362 *)
363 METHOD specify;
364 RUN ClearAll;
365 FIX PU.outlet.p;
366 FIX BO.outlet.T;
367 FIX PU.inlet.p;
368 FIX PU.inlet.h;
369 FIX TU.eta;
370 FIX PU.eta;
371 FIX BO.eta;
372 FIX mdot;
373 END specify;
374 METHOD values;
375 PU.outlet.p := 2000 {psi};
376 BO.outlet.T := 1460 {R}; BO.outlet.h := 3400 {kJ/kg};
377 PU.inlet.p := 1 {psi};
378 PU.inlet.h := 69.73 {btu/lbm};
379 TU.eta := 1.0;
380 PU.eta := 1.0;
381 BO.eta := 1.0;
382 mdot := 900 {t/d};
383 END values;
384 METHOD on_load;
385 RUN specify;
386 RUN values;
387 END on_load;
388 METHOD self_test;
389 (* check the results against those from K Weston's book *)
390 (* note that we have NOT neglected pump work in this case! *)
391 ASSERT abs(eta - 0.4294) < 0.0005;
392 ASSERT abs(eta_carnot - 0.6152) < 0.0005;
393 ASSERT abs(TU.outlet.x - 0.7736) < 0.0005;
394 END self_test;
395 END rankine;
396
397 (*------------------------------------------------------------------------------
398 REHEAT RANKINE CYCLE
399 *)
400 MODEL rankine_reheat;
401
402 BO1 IS_A boiler_simple;
403 BO2 IS_A boiler_simple;
404 TU1 IS_A turbine_simple;
405 TU2 IS_A turbine_simple;
406 CO IS_A condenser_simple;
407 PU IS_A pump_simple;
408
409 BO1.outlet, TU1.inlet ARE_THE_SAME;
410 TU1.outlet, BO2.inlet ARE_THE_SAME;
411 BO2.outlet, TU2.inlet ARE_THE_SAME;
412 TU2.outlet, CO.inlet ARE_THE_SAME;
413 CO.outlet, PU.inlet ARE_THE_SAME;
414 PU.outlet, BO1.inlet ARE_THE_SAME;
415
416 BO1.eta, BO2.eta ARE_THE_SAME;
417
418 (* boiler peak temperature is reached for both main and reheat... *)
419 BO1.outlet.T, BO2.outlet.T ARE_THE_SAME;
420
421 mdot ALIASES PU.mdot;
422
423 T_H ALIASES BO1.outlet.T;
424 T_C ALIASES CO.outlet.T;
425
426 eta IS_A fraction;
427 eta * (BO1.Qdot_fuel + BO2.Qdot_fuel - PU.Wdot) = TU1.Wdot + TU2.Wdot;
428
429 eta_carnot IS_A fraction;
430 eta_carnot = 1 - T_C / T_H;
431
432 METHODS
433 (*
434 The on_load scenario reproduces the same calculation from
435 K Weston, op. cit., Example 2.5, p. 51.
436 *)
437 METHOD on_load;
438 FIX BO1.eta;
439 BO1.eta := 1.0;
440 FIX TU1.eta, TU2.eta;
441 TU1.eta := 1.0;
442 TU2.eta := 1.0;
443 FIX PU.eta;
444 PU.eta := 1.0;
445 FIX PU.inlet.p;
446 PU.inlet.p := 1 {psi};
447 FIX PU.inlet.h;
448 PU.inlet.h := 69.73 {btu/lbm};
449 FIX BO1.outlet.T;
450 BO1.outlet.T := 1460 {R};
451 BO1.outlet.h := 3000 {kJ/kg}; (* guess *)
452 TU1.outlet.h := 3000 {kJ/kg}; (* guess *)
453 FIX PU.outlet.p;
454 PU.outlet.p := 2000 {psi};
455 FIX mdot;
456 mdot := 900 {t/d};
457
458 (* this value here is what defines the intermediate pressure *)
459 FIX TU1.outlet.T;
460 TU1.outlet.T := 860 {R};
461
462 TU2.inlet.h := 3000 {kJ/kg}; (* guess *)
463 END on_load;
464 METHOD self_test;
465 ASSERT abs(eta - 0.443) < 0.0005;
466 ASSERT abs(TU2.outlet.x - 0.926) < 0.0015;
467 ASSERT abs(TU1.w + TU2.w) - 763.1 {btu/lbm} < 1 {btu/lbm};
468 END self_test;
469 END rankine_reheat;
470
471 (*------------------------------------------------------------------------------
472 REGENERATIVE RANKINE CYCLE
473 *)
474 (*
475 Add a boiler feedwater heater and two-stage turbine
476 *)
477 MODEL rankine_regen;
478
479 BO IS_A boiler_simple;
480 TU1 IS_A turbine_simple;
481 BL IS_A tee; (* bleed *)
482 TU2 IS_A turbine_simple;
483 CO IS_A condenser_simple;
484 HE IS_A heater_open;
485 PU1 IS_A pump_simple;
486 PU2 IS_A pump_simple;
487
488 (* main loop *)
489 BO.outlet, TU1.inlet ARE_THE_SAME;
490 TU1.outlet, BL.inlet ARE_THE_SAME;
491 BL.outlet, TU2.inlet ARE_THE_SAME;
492 TU2.outlet, CO.inlet ARE_THE_SAME;
493 CO.outlet, PU1.inlet ARE_THE_SAME;
494 PU1.outlet, HE.inlet ARE_THE_SAME;
495 HE.outlet, PU2.inlet ARE_THE_SAME;
496 PU2.outlet, BO.inlet ARE_THE_SAME;
497
498 (* bleed stream *)
499 BL.outlet_branch, HE.inlet_heat ARE_THE_SAME;
500 phi ALIASES BL.phi;
501 p_bleed ALIASES TU1.outlet.p;
502
503 mdot ALIASES BO.mdot;
504
505 T_H ALIASES BO.outlet.T;
506 T_C ALIASES CO.outlet.T;
507
508 eta IS_A fraction;
509 eta * (BO.Qdot_fuel) = TU1.Wdot + TU2.Wdot + PU1.Wdot + PU2.Wdot;
510
511 Wdot_TU1 ALIASES TU1.Wdot;
512 Wdot_TU2 ALIASES TU2.Wdot;
513 Wdot_PU1 ALIASES PU1.Wdot;
514 Wdot_PU2 ALIASES PU2.Wdot;
515 Qdot_fuel ALIASES BO.Qdot_fuel;
516
517 eta_carnot IS_A fraction;
518 eta_carnot = 1 - T_C / T_H;
519
520 (* some checking output... *)
521
522 phi_weston IS_A fraction;
523 phi_weston = (PU2.inlet.h - PU1.outlet.h) / (TU1.outlet.h - PU1.outlet.h);
524
525 w_net IS_A specific_energy;
526 TU1.mdot * w_net = TU1.mdot * (TU1.inlet.h - TU1.outlet.h) + TU2.mdot * (TU2.inlet.h - TU2.outlet.h);
527
528 q_a IS_A specific_energy;
529 q_a = TU1.inlet.h - PU2.outlet.h;
530 METHODS
531 (*
532 The on_load scenario here is example 2.6 from K Weston (op. cit.), p. 55.
533 *)
534 METHOD on_load;
535 RUN ClearAll;
536
537 (* all ideal components *)
538 FIX BO.eta; BO.eta := 1.0;
539 FIX TU1.eta; TU1.eta := 1.0;
540 FIX TU2.eta; TU2.eta := 1.0;
541 FIX PU1.eta; PU1.eta := 1.0;
542 FIX PU2.eta; PU2.eta := 1.0;
543
544 (* mass flow rate is arbitrary *)
545 FIX mdot;
546 mdot := 10 {kg/s};
547
548 (* max pressure constraint *)
549 FIX PU2.outlet.p;
550 PU2.outlet.p := 2000 {psi};
551 PU2.outlet.h := 1400 {btu/lbm}; (* guess *)
552
553 (* boiler max temp *)
554 FIX BO.outlet.T;
555 BO.outlet.T := 1460 {R};
556 BO.outlet.h := 1400 {btu/lbm}; (* guess *)
557
558 (* intermediate temperature setting *)
559 FIX TU1.outlet.p;
560 TU1.outlet.p := 200 {psi};
561 (* FIX TU1.outlet.T;
562 TU1.outlet.T := 860 {R}; (* 400 °F *)
563 TU1.outlet.h := 3000 {kJ/kg}; (* guess *) *)
564
565 (* minimum pressure constraint *)
566 FIX CO.outlet.p;
567 CO.outlet.p := 1 {psi};
568
569 (* condenser outlet is saturated liquid *)
570 FIX CO.outlet.h;
571 CO.outlet.h := 69.73 {btu/lbm};
572
573 (* remove the redundant balance equations *)
574 HE.cons_mass.included := FALSE;
575 (* HE.cons_en.included := FALSE; *)
576
577 (* fix the bleed ratio *)
578 FIX BL.phi;
579 BL.phi := 0.251;
580
581 (* FIX BL.outlet.h;
582 BL.outlet.h := 355.5 {btu/lbm}; *)
583
584 END on_load;
585 METHOD self_test;
586 ASSERT abs(TU1.inlet.s - 1.5603 {btu/lbm/R}) < 0.01 {btu/lbm/R};
587 ASSERT abs(TU1.outlet.s - 1.5603 {btu/lbm/R}) < 0.01 {btu/lbm/R};
588 ASSERT abs(TU2.outlet.s - 1.5603 {btu/lbm/R}) < 0.01 {btu/lbm/R};
589 ASSERT abs(PU1.inlet.s - 0.1326 {btu/lbm/R}) < 0.001 {btu/lbm/R};
590 ASSERT abs(PU1.outlet.s - 0.1326 {btu/lbm/R}) < 0.002 {btu/lbm/R};
591 ASSERT abs(PU2.inlet.s - 0.5438 {btu/lbm/R}) < 0.002 {btu/lbm/R};
592 ASSERT abs(PU2.outlet.s - 0.5438 {btu/lbm/R}) < 0.002 {btu/lbm/R};
593
594 ASSERT abs(TU1.inlet.h - 1474.1 {btu/lbm}) < 1.5 {btu/lbm};
595 ASSERT abs(TU1.outlet.h - 1210.0 {btu/lbm}) < 1.5 {btu/lbm};
596 ASSERT abs(TU2.outlet.h - 871.0 {btu/lbm}) < 1.5 {btu/lbm};
597 ASSERT abs(PU1.inlet.h - 69.73 {btu/lbm}) < 0.001 {btu/lbm};
598 ASSERT abs(PU1.outlet.h - 69.73 {btu/lbm}) < 1.0 {btu/lbm};
599 ASSERT abs(PU2.inlet.h - 355.5 {btu/lbm}) < 1.5 {btu/lbm};
600 ASSERT abs(PU2.outlet.h - 355.5 {btu/lbm}) < 8 {btu/lbm};
601
602 ASSERT abs(w_net - 518.1 {btu/lbm}) < 0.3 {btu/lbm};
603
604 ASSERT abs(w_net * mdot - (TU1.Wdot + TU2.Wdot)) < 1 {W};
605
606 ASSERT abs(q_a - 1118.6 {btu/lbm}) < 7 {btu/lbm};
607
608 ASSERT abs(eta - 0.463) < 0.003;
609 END self_test;
610 END rankine_regen;
611
612 MODEL rankine_compare;
613 simple IS_A rankine;
614 regen IS_A rankine_regen;
615 simple.BO.inlet.p, regen.BO.inlet.p ARE_THE_SAME;
616 simple.BO.inlet.h, regen.BO.inlet.h ARE_THE_SAME;
617 simple.BO.Qdot_fuel, regen.BO.Qdot_fuel ARE_THE_SAME;
618 simple.CO.outlet.T, regen.CO.outlet.T ARE_THE_SAME;
619 simple.BO.eta, regen.BO.eta ARE_THE_SAME;
620 simple.TU.eta, regen.TU1.eta, regen.TU2.eta ARE_THE_SAME;
621 simple.PU.eta, regen.PU1.eta, regen.PU2.eta ARE_THE_SAME;
622 simple.mdot, regen.mdot ARE_THE_SAME;
623 METHODS
624 METHOD on_load;
625 RUN ClearAll;
626 RUN regen.on_load;
627 END on_load;
628 END rankine_compare;

john.pye@anu.edu.au
ViewVC Help
Powered by ViewVC 1.1.22