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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

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