/[ascend]/trunk/models/ben/bencolumn.a4l
ViewVC logotype

Contents of /trunk/models/ben/bencolumn.a4l

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1 - (show annotations) (download) (as text)
Fri Oct 29 20:54:12 2004 UTC (19 years, 8 months ago) by aw0a
File MIME type: text/x-ascend
File size: 25531 byte(s)
Setting up web subdirectory in repository
1 REQUIRE "ben/benflash.a4l";
2 (* --> measures,system,atoms,components,options,HGthermo,stream,flash *)
3 PROVIDE "bencolumn.a4l";
4
5 (*********************************************************************\
6 column.lib
7 by Ben Allan and Jennifer Perry
8 Part of the Ascend Library
9
10 This file is part of the Ascend modeling library.
11 It defines basic tray-by-tray steady-state distillation models.
12
13 Copyright (C) 1997 Carnegie Mellon University
14
15 The Ascend modeling library is free software; you can redistribute
16 it and/or modify it under the terms of the GNU General Public License as
17 published by the Free Software Foundation; either version 2 of the
18 License, or (at your option) any later version.
19
20 The Ascend Language Interpreter is distributed in hope that it will be
21 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 General Public License for more details.
24
25 You should have received a copy of the GNU General Public License along with
26 the program; if not, write to the Free Software Foundation, Inc., 675
27 Mass Ave, Cambridge, MA 02139 USA. Check the file named COPYING.
28
29 \*********************************************************************)
30
31 (*********************************************************************\
32 $Date: 1998/06/01 15:43:22 $
33 $Revision: 1.1 $
34 $Author: ballan $
35 $Source: /afs/cs.cmu.edu/project/ascend/Repository/models/ben/bencolumn.a4l,v $
36 \*********************************************************************)
37
38 MODEL colmodel() REFINES cmumodel();
39 END colmodel;
40
41 MODEL tray_stack(
42 n_trays WILL_BE integer_constant;
43 vapout WILL_BE vapor_stream;
44 liqin WILL_BE liquid_stream;
45 vapin WILL_BE vapor_stream;
46 liqout WILL_BE liquid_stream;
47 reduce WILL_BE fraction;
48 equilibrated WILL_BE boolean;
49 ) WHERE (
50 n_trays > 1;
51 vapout, liqin, vapin, liqout WILL_NOT_BE_THE_SAME;
52 vapout.state.options, vapin.state.options WILL_BE_THE_SAME;
53 liqout.state.options, liqin.state.options WILL_BE_THE_SAME;
54 ) REFINES colmodel();
55
56 NOTES 'ascii-picture'
57 SELF {
58 vapout ^ |
59 | v liqin
60 +---+
61 |_1_|
62 |___| n_trays (at least 2)
63 |___|
64 |_n_|
65 vapin ^ |
66 | v liqout
67 }
68 'usage'
69 equilbrated {
70 When TRUE, enforces equilbrium between phases on all the trays.
71 When FALSE, uses constant alpha between phases on all the trays.
72 }
73 reduce {
74 Homotopy parameter used by reduce_Q to move fixed errors in the
75 energy balances (Qin per tray) toward 0.
76 }
77 END NOTES;
78
79 liquid_options ALIASES liqout.state.options;
80 vapor_options ALIASES vapout.state.options;
81 internal_tray_P[2..n_trays-1] IS_A pressure;
82 internal_tray_T[2..n_trays-1] IS_A temperature;
83
84 (*
85 * The ALIASES/IS_A break if the liqout,vapout are on the same tray.
86 *)
87 tray_P[tsP] ALIASES
88 (vapout.state.P, internal_tray_P[2..n_trays-1], liqout.state.P)
89 WHERE tsP IS_A set OF integer_constant
90 WITH_VALUE (1..n_trays);
91 tray_T[tsT] ALIASES
92 (vapout.state.T, internal_tray_T[2..n_trays-1], liqout.state.T)
93 WHERE tsT IS_A set OF integer_constant
94 WITH_VALUE (1..n_trays);
95
96 FOR i IN [1..n_trays-1] CREATE
97 internal_liquid_state[i] IS_A liquid_mixture(
98 tray_P[i],
99 tray_T[i],
100 liquid_options
101 );
102 END FOR;
103 FOR i IN [2..n_trays] CREATE
104 internal_vapor_state[i] IS_A vapor_mixture(
105 tray_P[i],
106 tray_T[i],
107 vapor_options
108 );
109 END FOR;
110
111 tray_liquid_state[tsL] ALIASES
112 (internal_liquid_state[1..n_trays-1], liqout.state)
113 WHERE tsL IS_A set OF integer_constant
114 WITH_VALUE (1..n_trays);
115 tray_vapor_state[tsV] ALIASES
116 (vapout.state,internal_vapor_state[2..n_trays])
117 WHERE tsV IS_A set OF integer_constant
118 WITH_VALUE (1..n_trays);
119
120 FOR i IN [1..n_trays] CREATE
121 tray_state[i] IS_A td_VLE_mixture(
122 tray_P[i],
123 tray_T[i],
124 tray_vapor_state[i],
125 tray_liquid_state[i],
126 equilibrated
127 );
128 END FOR;
129 (* now like P,T, need to set up
130 * tray_liqin[1..n_trays+1], tray_vapin[0..n_trays],
131 * input streams.
132 *)
133 FOR i IN [2..n_trays] CREATE
134 internal_vapout[i] IS_A vapor_stream(
135 internal_vapor_state[i]
136 );
137 END FOR;
138 tray_vapin[tsIV] ALIASES
139 (vapout, internal_vapout[2..n_trays], vapin)
140 WHERE tsIV IS_A set OF integer_constant
141 WITH_VALUE (0..n_trays);
142
143 FOR i IN [1..n_trays-1] CREATE
144 internal_liqout[i] IS_A liquid_stream(
145 internal_liquid_state[i]
146 );
147 END FOR;
148 tray_liqin[tsIL] ALIASES
149 (liqin, internal_liqout[1..n_trays-1], liqout)
150 WHERE tsIL IS_A set OF integer_constant
151 WITH_VALUE (1..n_trays+1);
152
153 Tray_set IS_A set OF integer_constant;
154 (* TRUE but not necessary: Tray_set, tsL, tsV, tsP, tsT ARE_THE_SAME; *)
155 Tray_set :== tsL;
156
157 FOR i IN Tray_set CREATE
158 Stack[i] IS_A tray(
159 tray_liqin[i],
160 tray_vapin[i],
161 tray_liqin[i+1],
162 tray_vapin[i-1],
163 tray_state[i]
164 );
165 END FOR;
166
167 METHODS
168
169 METHOD defaults;
170 RUN liqin.defaults;
171 RUN liqout.defaults;
172 RUN vapin.defaults;
173 RUN vapout.defaults;
174 RUN internal_liqout[1..n_trays-1].defaults;
175 RUN internal_vapout[2..n_trays].defaults;
176 Stack[Tray_set].F_scale := 10{mole/second};
177 Stack[Tray_set].H_scale := 1000{J/second};
178 END defaults;
179
180 METHOD clear;
181 RUN Stack[Tray_set].clear;
182 END clear;
183
184 METHOD specify;
185 RUN seqmod;
186 RUN liqin.specify;
187 RUN vapin.specify;
188 END specify;
189
190 METHOD seqmod;
191 RUN Stack[Tray_set].seqmod;
192 END seqmod;
193
194 METHOD reset;
195 RUN clear;
196 RUN specify;
197 END reset;
198
199 METHOD scale;
200 RUN Stack[Tray_set].scale;
201 END scale;
202
203 METHOD reset_to_massbal;
204 equilibrated := FALSE;
205 RUN reset;
206 END reset_to_massbal;
207
208 METHOD reset_to_fullthermo;
209 equilibrated := TRUE;
210 RUN reset;
211 END reset_to_fullthermo;
212
213 METHOD reset_to_adiabatic;
214 RUN reset_to_fullthermo;
215 Stack[Tray_set].cmo_ratio.fixed := FALSE;
216 Stack[Tray_set].Qin.fixed := TRUE;
217 Stack[Tray_set].Qin := 0{W};
218 END reset_to_adiabatic;
219
220 METHOD reduce_Q;
221 FOR j IN [Tray_set] DO
222 Stack[j].Qin := reduce * Stack[j].Qin;
223 END FOR;
224 END reduce_Q;
225
226 END tray_stack;
227
228 MODEL test_tray_stack() REFINES testcmumodel();
229 n_trays_below IS_A integer_constant;
230 n_trays_below :== 2;
231 equilibrated IS_A boolean_start_false;
232 reduce IS_A fraction;
233
234 NOTES
235 'usage' equilibrated {
236 This variable and feed.equilibrated may or may not be the same.
237 Do not assume they are when writing methods.
238 }
239 reduce {
240 This is a fraction from 0 to 1. The method reduce_Q uses it
241 to move the Qin on each stack and feed tray toward 0.
242 Essentially this is a physical homotopy parameter.
243 }
244 END NOTES;
245
246 ds IS_A td_component_data_set(
247 ['n_pentane','n_hexane','n_heptane'],
248 'n_heptane'
249 );
250 vapor_options IS_A vapor_phase_options(ds,'Pitzer','Pitzer');
251 liquid_options IS_A liquid_phase_options(ds,'Rackett','UNIFAC');
252
253 vapout_P, liqin_P, vapin_P, liqout_P IS_A pressure;
254
255 vapout_T, liqin_T, vapin_T, liqout_T IS_A temperature;
256
257 vapout_state IS_A vapor_mixture(vapout_P, vapout_T, vapor_options);
258 liqin_state IS_A liquid_mixture(liqin_P, liqin_T, liquid_options);
259 vapin_state IS_A vapor_mixture(vapin_P, vapin_T, vapor_options);
260 liqout_state IS_A liquid_mixture(liqout_P, liqout_T, liquid_options);
261
262 Vapout IS_A vapor_stream(vapout_state);
263 Liqin IS_A liquid_stream(liqin_state);
264 Vapin IS_A vapor_stream(vapin_state);
265 Liqout IS_A liquid_stream(liqout_state);
266
267 Section IS_A tray_stack(
268 n_trays_below,
269 Vapout,
270 Liqin,
271 Vapin,
272 Liqout,
273 reduce,
274 equilibrated
275 );
276
277 METHODS
278
279 METHOD defaults;
280 equilibrated := FALSE;
281 RUN Section.defaults;
282 END defaults;
283 METHOD reset;
284 RUN clear;
285 RUN specify;
286 END reset;
287
288 METHOD clear;
289 RUN Section.clear;
290 END clear;
291
292 METHOD specify;
293 RUN Section.specify;
294 END specify;
295
296 METHOD reset_to_adiabatic;
297 RUN Section.reset_to_adiabatic;
298 END reset_to_adiabatic;
299
300 METHOD scale;
301 RUN section.scale;
302 END scale;
303 END test_tray_stack;
304
305 MODEL simple_column(
306 distillate WILL_BE liquid_stream;
307 n_trays_above WILL_BE integer_constant;
308 feed WILL_BE vapor_liquid_stream;
309 n_trays_below WILL_BE integer_constant;
310 bottoms WILL_BE liquid_stream;
311 equilibrated WILL_BE boolean;
312 reduce WILL_BE fraction;
313 ) WHERE (
314 n_trays_above > 1;
315 n_trays_below > 1;
316 distillate, bottoms, feed WILL_NOT_BE_THE_SAME;
317 bottoms.state.options, distillate.state.options,
318 feed.state.heavy.options WILL_BE_THE_SAME;
319 ) REFINES colmodel();
320
321 liquid_options ALIASES feed.state.heavy.options;
322 vapor_options ALIASES feed.state.light.options;
323
324 NOTES
325 'ascii-picture' SELF {
326 ___ total condenser
327 / \________> distillate liquid
328 |___|
329 (condensor_vapin)^ |
330 | |
331 | v(rectifier_liqin)
332 +---+
333 |___|
334 |___| n_trays_above (at least 2)
335 |___|
336 |___|
337 (rectifier_vapin)^ |
338 | |
339 | v(feed_tray_liqin)
340 +---+
341 V/L feed ----->| |
342 +___+
343 (feed_tray_vapin)^ |
344 | |
345 | v(stripper_liqin)
346 +---+
347 |___|
348 |___| n_trays_below (at least 2)
349 |___|
350 |___|
351 (stripper_vapin)^ |
352 | |
353 | v(reboiler_liqin)
354 ___
355 | |________> bottoms liquid
356 \___/ non-adiabatic flash
357 }
358 'usage' equilibrated {
359 This variable and feed.equilibrated may or may not be the same.
360 Do not assume they are when writing methods.
361 }
362 reduce {
363 This is a fraction from 0 to 1. The method reduce_Q uses it
364 to move the Qin on each stack and feed tray toward 0.
365 Essentially this is a physical homotopy parameter.
366 }
367 'changing' SELF {
368 This MODEL is very large, therefore it is very carefully
369 structured following the ascii-picture.
370 It should be relatively easy to modify this MODEL
371 just by carefully following the patterns we use. The pattern is
372 that all streams are given names corresponding to their input
373 roles and then all the subordinate P, T, state parts are named
374 by suffixing the corresponding stream names. When a part is
375 in common with the output streams, we create an internal name
376 following the regular pattern to keep the symmetries clear.
377 Note that the symmetries are preserved even in this aliasing.
378 }
379 END NOTES;
380
381 (*
382 * The creation steps:
383 * alias the options from the feed stream. (done above).
384 * inter-section P,T, states (single phase)
385 * inter-section streams (single phase)
386 * reboiler and feed_tray states (two phase)
387 * column sections
388 * At the end of the steps, everything has been wired up
389 * simply by passing common parts to both places they belong.
390 * For clarity, no arrays are used.
391 *
392 * If you are nuts enough to reimplement this MODEL using
393 * arrays, have a look at tray_stack for techniques to avoid
394 * sending the compiler to hell.
395 *
396 * The thermodynamic options of the feed propagate to the whole
397 * column without using ARE_ALIKE or ARE_THE_SAME.
398 *)
399 (* thermodynamic P,T and state definitions for inter-section streams *)
400
401 feed_tray_P IS_A pressure;
402 feed_tray_T IS_A temperature;
403
404 condenser_vapin_P IS_A pressure;
405 rectifier_liqin_P ALIASES distillate.state.P;
406 rectifier_vapin_P ALIASES feed_tray_P;
407 feed_tray_liqin_P IS_A pressure;
408 feed_tray_vapin_P IS_A pressure;
409 stripper_liqin_P ALIASES feed_tray_P;
410 stripper_vapin_P ALIASES bottoms.state.P;
411 reboiler_liqin_P IS_A pressure;
412
413 condenser_vapin_T IS_A temperature;
414 rectifier_liqin_T ALIASES distillate.state.T;
415 rectifier_vapin_T ALIASES feed_tray_T;
416 feed_tray_liqin_T IS_A temperature;
417 feed_tray_vapin_T IS_A temperature;
418 stripper_liqin_T ALIASES feed_tray_T;
419 stripper_vapin_T ALIASES bottoms.state.T;
420 reboiler_liqin_T IS_A temperature;
421
422 condenser_vapin_state IS_A vapor_mixture(
423 condenser_vapin_P,
424 condenser_vapin_T,
425 vapor_options
426 );
427 rectifier_liqin_state ALIASES distillate.state;
428 rectifier_vapin_state IS_A vapor_mixture(
429 rectifier_vapin_P,
430 rectifier_vapin_T,
431 vapor_options
432 );
433 feed_tray_liqin_state IS_A liquid_mixture(
434 feed_tray_liqin_P,
435 feed_tray_liqin_T,
436 liquid_options
437 );
438 feed_tray_vapin_state IS_A vapor_mixture(
439 feed_tray_vapin_P,
440 feed_tray_vapin_T,
441 vapor_options
442 );
443 stripper_liqin_state IS_A liquid_mixture(
444 stripper_liqin_P,
445 stripper_liqin_T,
446 liquid_options
447 );
448 stripper_vapin_state IS_A vapor_mixture(
449 stripper_vapin_P,
450 stripper_vapin_T,
451 vapor_options
452 );
453 reboiler_liqin_state IS_A liquid_mixture(
454 reboiler_liqin_P,
455 reboiler_liqin_T,
456 liquid_options
457 );
458
459 (* thermodynamic state definitions for reboiler, feed_tray *)
460 feed_tray_state IS_A td_VLE_mixture(
461 feed_tray_P,
462 feed_tray_T,
463 rectifier_vapin_state,
464 stripper_liqin_state,
465 equilibrated
466 );
467
468 reboiler_state IS_A td_VLE_mixture(
469 stripper_vapin_P,
470 stripper_vapin_T,
471 stripper_vapin_state,
472 bottoms.state,
473 equilibrated
474 );
475
476 (* inter-section streams *)
477 condenser_vapin IS_A vapor_stream(
478 condenser_vapin_state
479 );
480 rectifier_liqin IS_A liquid_stream(
481 rectifier_liqin_state
482 );
483 rectifier_vapin IS_A vapor_stream(
484 rectifier_vapin_state
485 );
486 feed_tray_liqin IS_A liquid_stream(
487 feed_tray_liqin_state
488 );
489 feed_tray_vapin IS_A vapor_stream(
490 feed_tray_vapin_state
491 );
492 stripper_liqin IS_A liquid_stream(
493 stripper_liqin_state
494 );
495 stripper_vapin IS_A vapor_stream(
496 stripper_vapin_state
497 );
498 reboiler_liqin IS_A liquid_stream(
499 reboiler_liqin_state
500 );
501
502 (* column sections *)
503 condenser IS_A simple_condenser(
504 condenser_vapin,
505 rectifier_liqin,
506 distillate
507 );
508 rectifying_section IS_A tray_stack(
509 n_trays_above,
510 condenser_vapin,
511 rectifier_liqin,
512 rectifier_vapin,
513 feed_tray_liqin,
514 reduce,
515 equilibrated
516 );
517 feed_tray IS_A feed_tray(
518 feed,
519 feed_tray_liqin,
520 feed_tray_vapin,
521 stripper_liqin,
522 rectifier_vapin,
523 feed_tray_state
524 );
525 stripping_section IS_A tray_stack(
526 n_trays_below,
527 feed_tray_vapin,
528 stripper_liqin,
529 stripper_vapin,
530 reboiler_liqin,
531 reduce,
532 equilibrated
533 );
534 reboiler IS_A simple_reboiler(
535 reboiler_liqin,
536 stripper_vapin,
537 bottoms,
538 reboiler_state
539 );
540
541 (* tray by tray profiles commonly desired *)
542 N_trays IS_A integer_constant;
543 N_trays :== n_trays_above + 1 + n_trays_below + 1;
544 VLE_set IS_A set OF integer_constant;
545 VLE_set :== [1 .. N_trays];
546 Feed_loc IS_A integer_constant;
547 Feed_loc :== n_trays_above +1;
548
549 Tray[zTr] ALIASES (
550 condenser,
551 rectifying_section.Stack[1..n_trays_above],
552 feed_tray,
553 stripping_section.Stack[1..n_trays_below],
554 reboiler)
555 WHERE zTr IS_A set OF integer_constant
556 WITH_VALUE (0..N_trays);
557
558 Profile_traynum[VLE_set] IS_A integer_constant;
559 FOR i IN VLE_set CREATE
560 Profile_traynum[i] :== i;
561 END FOR;
562
563 Profile_P[zP] ALIASES (
564 rectifying_section.tray_P[1..n_trays_above],
565 feed_tray_P,
566 stripping_section.tray_P[1..n_trays_below],
567 bottoms.state.P)
568 WHERE zP IS_A set OF integer_constant WITH_VALUE (VLE_set);
569
570 Profile_cmo_ratio[zc] ALIASES (
571 rectifying_section.Stack[1..n_trays_above].cmo_ratio,
572 stripping_section.Stack[1..n_trays_below].cmo_ratio)
573 WHERE zc IS_A set OF integer_constant
574 WITH_VALUE (1 .. n_trays_above, Feed_loc+1 .. Feed_loc+n_trays_below);
575
576 Profile_T[zT] ALIASES (
577 rectifying_section.tray_T[1..n_trays_above],
578 feed_tray_T,
579 stripping_section.tray_T[1..n_trays_below],
580 bottoms.state.T)
581 WHERE zT IS_A set OF integer_constant WITH_VALUE (VLE_set);
582
583 Profile_Qin[zQ] ALIASES (Tray[0..N_trays].Qin)
584 WHERE zQ IS_A set OF integer_constant WITH_VALUE (0..N_trays);
585
586 Profile_Lin[zL] ALIASES (
587 rectifying_section.tray_liqin[1..n_trays_above].Ftot,
588 feed_tray.liqin.Ftot,
589 stripping_section.tray_liqin[1..n_trays_below].Ftot,
590 reboiler.liqin.Ftot)
591 WHERE zL IS_A set OF integer_constant WITH_VALUE (VLE_set);
592
593 Profile_Vin[zV] ALIASES (
594 rectifying_section.tray_vapin[0..n_trays_above].Ftot,
595 feed_tray.vapin.Ftot,
596 stripping_section.tray_vapin[1..n_trays_below].Ftot)
597 WHERE zV IS_A set OF integer_constant WITH_VALUE (0..N_trays-1);
598
599 components ALIASES feed.state.light.options.ds.components;
600 reference ALIASES feed.state.light.options.ds.reference;
601
602 FOR i IN components CREATE
603
604 Profile_x[i][zx[i]] ALIASES (
605 rectifying_section.Stack[1..n_trays_above].tray_state.heavy.y[i],
606 feed_tray_state.heavy.y[i],
607 stripping_section.Stack[1..n_trays_below].tray_state.heavy.y[i],
608 bottoms.state.y[i])
609 WHERE zx[i] IS_A set OF integer_constant WITH_VALUE (VLE_set);
610
611 Profile_y[i][zy[i]] ALIASES (
612 rectifying_section.Stack[1..n_trays_above].tray_state.light.y[i],
613 feed_tray_state.light.y[i],
614 stripping_section.Stack[1..n_trays_below].tray_state.light.y[i],
615 reboiler_state.light.y[i])
616 WHERE zy[i] IS_A set OF integer_constant WITH_VALUE (VLE_set);
617
618 Profile_kvalues_when_full_thermo[i][zk[i]] ALIASES (
619 rectifying_section.Stack[1..n_trays_above].tray_state.alpha[i],
620 feed_tray_state.alpha[i],
621 stripping_section.Stack[1..n_trays_below].tray_state.alpha[i],
622 reboiler_state.alpha[i])
623 WHERE zk[i] IS_A set OF integer_constant WITH_VALUE (VLE_set);
624
625 END FOR;
626
627 (*
628 VLE_set,
629 zx[components], zy[components], zk[components],
630 zT, zP ARE_THE_SAME; TRUE but not needed *)
631 (* zTr, zQ ARE_THE_SAME; TRUE but not needed *)
632
633 omb_slack[components] IS_A molar_rate;
634 FOR i IN components CREATE
635 OMB[i]: feed.f[i] = (distillate.f[i] + bottoms.f[i] + omb_slack[i]);
636 END FOR;
637
638 METHODS
639 METHOD defaults;
640 omb_slack[components] := 0{mol/s};
641 omb_slack[components].lower_bound := -1000{mole/s};
642 RUN condenser.defaults;
643 RUN rectifying_section.defaults;
644 RUN feed_tray.defaults;
645 RUN stripping_section.defaults;
646 RUN reboiler.defaults;
647 END defaults;
648
649 METHOD clear;
650 RUN Tray[zTr].clear;
651 reduce.fixed:= FALSE;
652 omb_slack[components].fixed := FALSE;
653 OMB[components].included:= TRUE;
654 END clear;
655
656 METHOD overall_mb;
657 (* is this method still useful? *)
658 (* tray[Feed_loc].totfeedflow[components].included := FALSE; *)
659 omb_slack[components] := 0.0{mol/s};
660 omb_slack[components].fixed := TRUE;
661 END overall_mb;
662
663 METHOD propagate_feed;
664 (* propagate feed tray flows and relative volatilities,
665 * presumably after solving the feed tray.
666 *)
667 FOR i IN components DO
668 rectifying_section.tray_state[1..n_trays_above].alpha[i] :=
669 feed_tray_state.alpha[i];
670 stripping_section.tray_state[1..n_trays_below].alpha[i] :=
671 feed_tray_state.alpha[i];
672 reboiler_state.alpha[i] := feed_tray_state.alpha[i];
673 (* copy feed flow rates to all internal streams *)
674 Tray[0..N_trays-1].liqout.f[i] := feed.f[i];
675 Tray[1..N_trays].vapout.f[i] := feed.f[i];
676 (* This copying should probably factor in the RR and BR *)
677 END FOR;
678 END propagate_feed;
679
680 METHOD total_reflux;
681 (* this method is BROKEN in both this library and Bob's *)
682 condenser.reflux_ratio.fixed := TRUE;
683 condenser.reflux_def.included := FALSE;
684 (*
685 Tray[0].totprod.Ftot := 0.0{mol/s};
686 Tray[0].totprod.Ftot.fixed := FALSE;
687 *)
688 feed.f[components].fixed := FALSE;
689 feed_tray.qeq.included := FALSE;
690 feed.Ftot := 0.0{mol/s};
691 feed.Ftot.fixed := TRUE;
692 feed_tray_state.y[components - [reference]].fixed := TRUE;
693 feed_tray_state.phi['liquid'].fixed := TRUE;
694 feed_tray_state.phi['liquid'] := 0.5;
695 RUN feed_tray.liqout.specify;
696 reboiler.reboil_ratio.fixed := TRUE;
697 reboiler.reboil_def.included := FALSE;
698 END total_reflux;
699
700 METHOD scale;
701 RUN condenser.scale;
702 RUN rectifying_section.scale;
703 RUN feed_tray.scale;
704 RUN stripping_section.scale;
705 RUN reboiler.scale;
706 END scale;
707
708 METHOD seqmod;
709 RUN condenser.seqmod;
710 RUN rectifying_section.seqmod;
711 RUN feed_tray.seqmod;
712 RUN stripping_section.seqmod;
713 RUN reboiler.seqmod;
714 END seqmod;
715
716 METHOD specify;
717 RUN seqmod;
718 RUN feed.specify;
719 END specify;
720
721 METHOD reset;
722 RUN clear;
723 RUN specify;
724 END reset;
725
726 METHOD reset_to_massbal;
727 equilibrated := FALSE;
728 feed.state.equilibrated := FALSE;
729 RUN reset;
730 END reset_to_massbal;
731
732 METHOD reset_to_fullthermo;
733 equilibrated := TRUE;
734 feed.state.equilibrated := TRUE;
735 RUN reset;
736 END reset_to_fullthermo;
737
738 METHOD reset_to_adiabatic;
739 RUN reset_to_fullthermo;
740 (* condenser, reboiler Qin left free *)
741 rectifying_section.Stack[1..n_trays_above].cmo_ratio.fixed := FALSE;
742 stripping_section.Stack[1..n_trays_below].cmo_ratio.fixed := FALSE;
743 Tray[1..N_trays-1].Qin.fixed := TRUE;
744 Tray[1..N_trays-1].Qin := 0{W};
745 feed_tray.q.fixed := FALSE;
746 END reset_to_adiabatic;
747
748 END simple_column;
749
750 MODEL test_simple_column() REFINES testcmumodel();
751
752 ds IS_A td_component_data_set(
753 ['n_pentane','n_hexane','n_heptane'],
754 'n_heptane'
755 );
756 vapor_options IS_A vapor_phase_options(ds,'Pitzer','Pitzer');
757 liquid_options IS_A liquid_phase_options(ds,'Rackett','UNIFAC');
758
759 feed_P IS_A pressure;
760 feed_T IS_A temperature;
761 feed_vapor_state IS_A vapor_mixture(
762 feed_P,
763 feed_T,
764 vapor_options
765 );
766 feed_liquid_state IS_A liquid_mixture(
767 feed_P,
768 feed_T,
769 liquid_options
770 );
771 Equilibrated IS_A boolean_start_false;
772 feed_state IS_A td_VLE_mixture(
773 feed_P,
774 feed_T,
775 feed_vapor_state,
776 feed_liquid_state,
777 Equilibrated
778 );
779 Feed IS_A vapor_liquid_stream(feed_state);
780
781 distillate_P IS_A pressure;
782 distillate_T IS_A temperature;
783 distillate_state IS_A liquid_mixture(
784 distillate_P,
785 distillate_T,
786 liquid_options
787 );
788 Distillate IS_A liquid_stream(distillate_state);
789
790 bottoms_P IS_A pressure;
791 bottoms_T IS_A temperature;
792 bottoms_state IS_A liquid_mixture(
793 bottoms_P,
794 bottoms_T,
795 liquid_options
796 );
797 Bottoms IS_A liquid_stream(bottoms_state);
798
799 n_trays_above, n_trays_below IS_A integer_constant;
800 n_trays_above :== 6;
801 n_trays_below :== 5;
802 reduce IS_A fraction;
803 Column IS_A simple_column(
804 Distillate,
805 n_trays_above,
806 Feed,
807 n_trays_below,
808 Bottoms,
809 Equilibrated,
810 reduce
811 );
812
813 METHODS
814 METHOD defaults;
815 RUN Column.defaults;
816 END defaults;
817 METHOD clear;
818 RUN Feed.clear;
819 RUN Column.clear;
820 Equilibrated := TRUE;
821 END clear;
822
823 METHOD values;
824 Column.feed_tray_state.alpha['n_pentane'] := 3;
825 Column.feed_tray_state.alpha['n_hexane'] := 2;
826 Column.feed_tray_state.alpha['n_heptane'] := 1;
827 Column.condenser.reflux_ratio := 1.3;
828 feed_T := 298 {K};
829 feed_P := 1{atm};
830 Feed.f['n_pentane'] := 3{mole/s};
831 Feed.f['n_hexane'] := 3{mole/s};
832 Feed.f['n_heptane'] := 3{mole/s};
833 (* here we should SOLVE the feed tray *)
834 RUN Column.propagate_feed;
835 END values;
836
837 METHOD scale;
838 RUN Column.scale;
839 END scale;
840 END test_simple_column;
841
842 MODEL demo_column(
843 components IS_A set OF symbol_constant;
844 reference IS_A symbol_constant;
845 n_trays IS_A integer_constant;
846 feed_location IS_A integer_constant;
847 ) WHERE (
848 reference IN components == TRUE;
849 n_trays > 5;
850 feed_location > 2;
851 feed_location < n_trays - 2;
852 ) REFINES colmodel();
853
854 ds IS_A td_component_data_set(components,reference);
855 vapor_options IS_A vapor_phase_options(ds,'Pitzer','Pitzer');
856 liquid_options IS_A liquid_phase_options(ds,'Rackett','UNIFAC');
857
858 feed_P IS_A pressure;
859 feed_T IS_A temperature;
860 feed_vapor_state IS_A vapor_mixture(
861 feed_P,
862 feed_T,
863 vapor_options
864 );
865 feed_liquid_state IS_A liquid_mixture(
866 feed_P,
867 feed_T,
868 liquid_options
869 );
870 Equilibrated IS_A boolean_start_true;
871 feed_state IS_A td_VLE_mixture(
872 feed_P,
873 feed_T,
874 feed_vapor_state,
875 feed_liquid_state,
876 Equilibrated
877 );
878 Feed IS_A vapor_liquid_stream(feed_state);
879
880 distillate_P IS_A pressure;
881 distillate_T IS_A temperature;
882 distillate_state IS_A liquid_mixture(
883 distillate_P,
884 distillate_T,
885 liquid_options
886 );
887 Distillate IS_A liquid_stream(distillate_state);
888
889 bottoms_P IS_A pressure;
890 bottoms_T IS_A temperature;
891 bottoms_state IS_A liquid_mixture(
892 bottoms_P,
893 bottoms_T,
894 liquid_options
895 );
896 Bottoms IS_A liquid_stream(bottoms_state);
897
898 n_trays_above, n_trays_below IS_A integer_constant;
899 n_trays_above :== feed_location - 1;
900 n_trays_below :== n_trays - feed_location - 1;
901 reduce IS_A fraction;
902 Column IS_A simple_column(
903 Distillate,
904 n_trays_above,
905 Feed,
906 n_trays_below,
907 Bottoms,
908 Equilibrated,
909 reduce
910 );
911
912 (* component names in order of boiling point. useful for methods. *)
913 z_boiling_comp[1..CARD[components]] IS_A symbol;
914 z_bc IS_A symbol;
915 z_bi IS_A integer;
916 METHODS
917 METHOD defaults;
918 RUN Column.defaults;
919 END defaults;
920 METHOD clear;
921 RUN Feed.clear;
922 RUN Column.clear;
923 Equilibrated := TRUE;
924 END clear;
925
926 METHOD values;
927 (* The demo user may very well want to rewrite this method
928 * for their particular mixture.
929 *)
930 z_bi := 1;
931 (* order the components arbitrarily in a list *)
932 FOR i IN components DO
933 z_boiling_comp[z_bi] := i;
934 z_bi := z_bi + 1;
935 END FOR;
936 (* use a bubble point sort, pun intended, to order the components. *)
937 FOR i IN [1..CARD[components]-1] DO
938 FOR j IN [i+1 .. CARD[components]] DO
939 IF ds.data[z_boiling_comp[i]].Tb >
940 ds.data[z_boiling_comp[j]].Tb THEN
941 z_bc := z_boiling_comp[j];
942 z_boiling_comp[j] := z_boiling_comp[i];
943 z_boiling_comp[i] := z_bc;
944 END IF;
945 END FOR;
946 END FOR;
947 z_bi := 1;
948 (* assign integer alpha's *)
949 FOR i IN [1.. CARD[components]] DO
950 Column.feed_tray_state.alpha[z_boiling_comp[i]] :=
951 CARD[components]-i+1;
952 END FOR;
953 Column.condenser.reflux_ratio := 1.3;
954 feed_T := 298 {K};
955 feed_P := 1{atm};
956 Feed.f[components] := 3{mole/s};
957 RUN Column.propagate_feed;
958 END values;
959
960 METHOD scale;
961 RUN Column.scale;
962 END scale;
963 END demo_column;
964
965 MODEL test_demo_column() REFINES testcmumodel();
966 END test_demo_column;
967
968 MODEL mw_demo_column() REFINES test_demo_column();
969 mw_column IS_A demo_column(['methanol','water'],'water',13,7);
970 METHODS
971 METHOD defaults;
972 RUN mw_column.defaults;
973 END defaults;
974 END mw_demo_column;
975
976 MODEL abc_demo_column() REFINES test_demo_column();
977 abc_column IS_A
978 demo_column(['benzene','chloroform','acetone'],'benzene',13,7);
979 METHODS
980 METHOD defaults;
981 RUN abc_column.defaults;
982 END defaults;
983 END abc_demo_column;
984
985 MODEL c567_demo_column() REFINES test_demo_column();
986 c567_column IS_A
987 demo_column(['n_pentane','n_hexane','n_heptane'],'n_heptane',13,7);
988 METHODS
989 METHOD defaults;
990 RUN c567_column.defaults;
991 END defaults;
992 END c567_demo_column;

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