/[ascend]/trunk/models/flash.a4l
ViewVC logotype

Contents of /trunk/models/flash.a4l

Parent Directory Parent Directory | Revision Log Revision Log


Revision 576 - (show annotations) (download) (as text)
Tue May 9 03:42:08 2006 UTC (14 years, 1 month ago) by johnpye
File MIME type: text/x-ascend
File size: 46906 byte(s)
Changed all cases of *.fixed := {TRUE,FALSE} to 'FIX' and 'FREE' statements.
1 REQUIRE "stream_holdup.a4l";
2 (* => stream_holdup.a4l, thermodynamics.a4l, components.a4l, phases.a4l,
3 * atoms.a4l, measures.a4l, system.a4l, basemodel.a4l *)
4 PROVIDE "flash.a4l";
5
6 (*
7 * flash.a4l
8 * by Ben Allan, Jennifer Perry, and Art Westerberg
9 * Part of the ASCEND Library
10 * $Date: 1998/06/17 19:05:50 $
11 * $Revision: 1.7 $
12 * $Author: mthomas $
13 * $Source: /afs/cs.cmu.edu/project/ascend/Repository/models/flash.a4l,v $
14 *
15 * This file is part of the ASCEND Modeling Library.
16 *
17 * The file provide basic vapor-liquid equilibrium flash calcuations
18 * in various unit operation configurations.
19 *
20 * Copyright (C) 1998 Carnegie Mellon University
21 *
22 * The ASCEND Modeling Library is free software; you can redistribute
23 * it and/or modify it under the terms of the GNU General Public
24 * License as published by the Free Software Foundation; either
25 * version 2 of the License, or (at your option) any later version.
26 *
27 * The ASCEND Modeling Library is distributed in hope that it will be
28 * useful, but WITHOUT ANY WARRANTY; without even the implied
29 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
30 * See the GNU General Public License for more details.
31 *
32 * You should have received a copy of the GNU General Public License
33 * along with the program; if not, write to the Free Software
34 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139 USA. Check
35 * the file named COPYING.
36 *)
37
38 MODEL flash_base(
39 Qin WILL_BE energy_rate;
40 ) REFINES cmumodel;
41
42 NOTES
43 'usage' SELF {
44 Never create one of these directly.
45 This is just a common ancestor type to provide Qin and
46 boundwidth uniformly and to make type tree navigation
47 easier.
48 }
49 'purpose' SELF {
50 This library provides models:
51 vapor_liquid_flash - a simple two product flash of an arbitrary feed.
52 simple_reboiler - a reboiler with "stream" connections for use in columns.
53 total_condenser - a total condenser with "stream" connections for use in columns.
54 tray - a tray with "stream" connections for use in columns.
55 feed_tray - a feed tray with "stream" connections for use in columns.
56 detailed_tray - a tray with "detailed_stream" connections for use in stacks.
57 }
58 END NOTES;
59
60 boundwidth IS_A bound_width;
61 END flash_base;
62
63 MODEL vapor_liquid_flash(
64 Qin WILL_BE energy_rate;
65 equilibrated WILL_BE boolean;
66 feed WILL_BE stream;
67 vapout WILL_BE stream;
68 liqout WILL_BE stream;
69 ) WHERE (
70 feed, vapout, liqout WILL_NOT_BE_THE_SAME;
71 feed.cd, vapout.cd, liqout.cd WILL_BE_THE_SAME;
72 vapout.pd.phase_indicator == 'V';
73 liqout.pd.phase_indicator == 'L';
74 (feed.pd.phase_indicator IN ['V','L','VL','VLL']) == TRUE;
75 ) REFINES flash_base;
76
77 NOTES
78 'purpose' SELF {
79 This MODEL computes a VL flash with the potential that the whole
80 feed subcools or superheats into one or the other product.
81 The user supplies all streams, a heat input Qin, and boolean
82 equilibrated. If equilibrated is TRUE, V-L equilibrium will be
83 attempted, OTHERWISE the unit will solve only the mass balances.
84 }
85 'developer-ben' SELF {
86 This is the allegedly simple to use wrapper for the detailed flash
87 MODEL. The user creates a vapor product, a liquid product, and any
88 feed and gives them to us with a heat input and an equilibrium
89 control variable. We do the assembly of the flash VLE MODEL from
90 the given output stream states.
91 }
92 'developer-art' SELF {
93 A vapor-liquid flash MODEL. This MODEL shares the phase_partial
94 information between the vapor and liquid product streams with the
95 flash state. Equilibrium between these phases for the flash state
96 supplies the equilibrium equations for the flash unit. A user
97 parameterizes this MODEL with the feed and the liquid and vapor
98 product streams. The user must also share a variable for the heat
99 into the unit.
100 }
101 END NOTES;
102
103 cd ALIASES feed.cd;
104 P ALIASES vapout.P;
105 T ALIASES vapout.T;
106 alpha ALIASES state.phase['vapor'].alpha;
107 (* when equilbrated, the relative volatilities alpha become K-values *)
108
109 (* flash thermo options are derived from product streams *)
110 pdVL IS_A phases_data('VL', vapout.pd.vapor_option,
111 liqout.pd.liquid1_option, 'none');
112
113 (* flash Vapor-Liquid state comes from thermo of product streams. *)
114 phaseVL[VLphases] ALIASES
115 (vapout.phase['vapor'], liqout.phase['liquid1'])
116 WHERE VLphases IS_A set OF symbol_constant
117 WITH_VALUE ('vapor','liquid1');
118 state IS_A thermodynamics(cd, pdVL, phaseVL, equilibrated);
119
120 x "liquid product composition" ALIASES liqout.state.y;
121 y "vapor product composition" ALIASES vapout.state.y;
122 z "feed composition" ALIASES feed.state.y;
123
124 (* Link Nc - 1 components of overall state to feed. state
125 * will calculate the last component from SUM[y[i]]=1;
126 *)
127 FOR i IN cd.other_components CREATE
128 connect_feed[i]: state.y[i] = feed.y[i];
129 END FOR;
130
131 flowscale IS_A molar_rate_scale;
132
133 vapor_balance: (vapout.flow -
134 state.phase_fraction['vapor'] * feed.flow)/flowscale = 0;
135 liquid_balance: (liqout.flow -
136 state.phase_fraction['liquid1'] * feed.flow)/flowscale = 0;
137
138 H_flowscale IS_A energy_rate_scale;
139 energy_balance: (feed.H_flow + Qin -
140 (vapout.H_flow + liqout.H_flow))/H_flowscale = 0;
141
142 (* Qin is energy balance error when equilibrated is FALSE.
143 * use_energy:
144 * WHEN (equilibrated)
145 * CASE TRUE: USE energy_balance;
146 * OTHERWISE: (* do not close energy balance *)
147 * END WHEN;
148 * Always use EB equation. relaxation is in the thermo equilibrium condition.
149 *)
150
151
152 METHODS
153
154 METHOD check_self;
155 IF (liqout.flow < 1e-4 {mole/s}) THEN
156 STOP {Liquid flow dried up in flash};
157 END IF;
158 IF (vapout.flow < 1e-4 {mole/s}) THEN
159 STOP {All vapor condensed in flash};
160 END IF;
161 IF (feed.flow < 1e-4 {mole/s}) THEN
162 STOP {No feed flowing to flash};
163 END IF;
164 IF (abs(feed.flow - vapout.flow - liqout.flow)/flowscale > 1.0e-4) THEN
165 STOP {Flash violates overall mass-balance};
166 END IF;
167 RUN pdVL.check_self;
168 RUN state.check_self;
169 END check_self;
170
171 METHOD check_all;
172 RUN feed.check_all;
173 RUN vapout.check_all;
174 RUN liqout.check_all;
175 RUN check_self;
176 END check_all;
177
178 METHOD default_self;
179 boundwidth :=10;
180 flowscale := feed.Details.flowscale;
181 H_flowscale := feed.Details.H_flowscale;
182 RUN pdVL.default_self;
183 RUN state.default_self;
184 END default_self;
185
186 METHOD default_all;
187 Qin := 0 {watt};
188 equilibrated := FALSE;
189 RUN feed.default_all;
190 RUN vapout.default_all;
191 RUN liqout.default_all;
192 RUN default_self;
193 END default_all;
194
195 METHOD bound_self;
196 state.boundwidth := boundwidth;
197 RUN pdVL.bound_self;
198 RUN state.bound_self;
199 END bound_self;
200
201 METHOD bound_all;
202 feed.boundwidth := boundwidth;
203 vapout.boundwidth := boundwidth;
204 liqout.boundwidth := boundwidth;
205 RUN feed.bound_all;
206 RUN vapout.bound_all;
207 RUN liqout.bound_all;
208 RUN bound_self;
209 END bound_all;
210
211 METHOD scale_self;
212 flowscale := feed.flow;
213 H_flowscale := feed.H_flow;
214 RUN pdVL.scale_self;
215 RUN state.scale_self;
216 END scale_self;
217
218 METHOD scale_all;
219 RUN feed.scale_all;
220 RUN vapout.scale_all;
221 RUN liqout.scale_all;
222 RUN scale_self;
223 END scale_all;
224
225 METHOD seqmod;
226 RUN state.specify;
227 FREE state.y[cd.components];
228 END seqmod;
229
230 METHOD reset_to_massbal;
231 equilibrated := FALSE;
232 RUN reset;
233 END reset_to_massbal;
234
235 METHOD reset_to_fullthermo;
236 equilibrated := TRUE;
237 RUN reset;
238 END reset_to_fullthermo;
239
240 METHOD specify;
241 NOTES 'usage' SELF {
242 The standard initialization for this unit assumes the user has
243 specified enough information to fully specify the feed stream and
244 then has specified the flash pressure, P, and fraction of the feed
245 leaving in the vapor stream. This split fraction specification makes
246 it easy to keep the flash in the two phase region.
247 } END NOTES;
248 RUN specify_P_and_vapor_fraction;
249 END specify;
250
251 METHOD specify_P_and_vapor_fraction;
252 RUN feed.specify;
253 RUN seqmod;
254 END specify_P_and_vapor_fraction;
255
256 METHOD specify_P_and_heat_input;
257 NOTES 'usage' SELF {
258 This can be used to obtain an adiabatic flash by setting
259 Qin to zero and equilibrated to TRUE.
260 } END NOTES;
261 RUN specify_P_and_vapor_fraction;
262 FIX Qin;
263 IF (equilibrated) THEN
264 FREE state.phase_fraction['vapor'];
265 END IF;
266 END specify_P_and_heat_input;
267
268 END vapor_liquid_flash;
269
270
271 MODEL tray_base(
272 Qin WILL_BE energy_rate;
273 ) REFINES flash_base;
274 END tray_base;
275
276 MODEL detailed_tray(
277 Qin WILL_BE energy_rate;
278 equilibrated WILL_BE boolean;
279 liqin WILL_BE detailed_stream;
280 vapin WILL_BE detailed_stream;
281 liqout WILL_BE detailed_stream;
282 vapout WILL_BE detailed_stream;
283 state WILL_BE thermodynamics;
284 ) WHERE (
285 vapin.state.pd.phase_indicator IN ['V','M'] == TRUE;
286 vapout.state.pd.phase_indicator == 'V';
287 liqin.state.pd.phase_indicator IN ['L','M'] == TRUE;
288 liqout.state.pd.phase_indicator == 'L';
289 state.pd.phase_indicator == 'VL';
290 liqout.state, vapout.state WILL_NOT_BE_THE_SAME;
291 state.phase['liquid1'], liqout.state.phase['liquid1'] WILL_BE_THE_SAME;
292 state.phase['vapor'], vapout.state.phase['vapor'] WILL_BE_THE_SAME;
293 state.cd, liqin.state.cd, liqout.state.cd,
294 vapin.state.cd, vapout.state.cd WILL_BE_THE_SAME;
295 ) REFINES tray_base;
296
297 alpha "relative volatilities" ALIASES state.phase['vapor'].alpha;
298 x "liquid product composition" ALIASES liqout.state.y;
299 y "vapor product composition" ALIASES vapout.state.y;
300 P ALIASES state.P;
301 T ALIASES state.T;
302
303 cmo_ratio "constant molar overflow ratio" IS_A factor;
304 cmo_eqn: (cmo_ratio * liqin.flow - liqout.flow)/flowscale = 0;
305
306 flowscale IS_A molar_rate_scale;
307 FOR i IN state.cd.other_components CREATE
308 connect_feeds[i]: (
309 state.y[i] * (liqin.flow + vapin.flow) -
310 (vapin.state.y[i] * vapin.flow + liqin.state.y[i] * liqin.flow)
311 ) / flowscale = 0;
312 END FOR;
313
314 vapor_balance: (vapout.flow -
315 state.phase_fraction['vapor'] * (vapin.flow+liqin.flow))
316 / flowscale = 0;
317
318 liquid_balance: (liqout.flow -
319 state.phase_fraction['liquid1'] * (vapin.flow+liqin.flow))
320 / flowscale = 0;
321
322 H_flowscale IS_A energy_rate_scale;
323 energy_balance: ((vapin.H_flow + liqin.H_flow) + Qin -
324 (vapout.H_flow + liqout.H_flow)) / H_flowscale = 0;
325
326 METHODS
327
328 METHOD check_all;
329 RUN check_self;
330 RUN vapin.check_all;
331 RUN liqin.check_all;
332 RUN vapout.check_all;
333 RUN liqout.check_all;
334 RUN state.check_all;
335 END check_all;
336
337 METHOD check_self;
338 IF (liqout.flow < 1e-4 {mole/s}) THEN
339 STOP {Liquid flow dried up on tray};
340 END IF;
341 IF (vapout.flow < 1e-4 {mole/s}) THEN
342 STOP {All vapor condensed on tray};
343 END IF;
344 IF (abs(vapin.flow + liqin.flow -
345 vapout.flow - liqout.flow)/flowscale > 1.0e-4) THEN
346 STOP {Tray violates overall mass-balance};
347 END IF;
348 END check_self;
349
350 METHOD default_self;
351 boundwidth := 10;
352 flowscale := liqin.flowscale + vapin.flowscale;
353 H_flowscale := liqin.H_flowscale + vapin.H_flowscale;
354 END default_self;
355
356 METHOD default_all;
357 equilibrated := FALSE;
358 Qin := 0 {watt};
359 RUN vapin.default_all;
360 RUN liqin.default_all;
361 RUN vapout.default_all;
362 RUN liqout.default_all;
363 RUN state.default_all;
364 RUN default_self;
365 END default_all;
366
367 METHOD bound_self;
368 cmo_ratio.lower_bound := 0.0; (* really?? *)
369 cmo_ratio.upper_bound := cmo_ratio + boundwidth*cmo_ratio.nominal;
370 END bound_self;
371
372 METHOD bound_all;
373 liqin.boundwidth := boundwidth;
374 vapin.boundwidth := boundwidth;
375 vapout.boundwidth := boundwidth;
376 liqout.boundwidth := boundwidth;
377 state.boundwidth := boundwidth;
378 RUN liqin.bound_all;
379 RUN vapin.bound_all;
380 RUN vapout.bound_all;
381 RUN liqout.bound_all;
382 RUN state.bound_all;
383 STOP {tray bound_all needs to bound Qin somehow};
384 RUN bound_self;
385 END bound_all;
386
387 METHOD scale_self;
388 flowscale := liqin.flowscale + vapin.flowscale;
389 H_flowscale := liqin.H_flowscale + vapin.H_flowscale;
390 cmo_ratio.nominal := abs(cmo_ratio)*1.01 + 0.01;
391 END scale_self;
392
393 METHOD scale_all;
394 RUN liqin.scale_all;
395 RUN vapin.scale_all;
396 RUN vapout.scale_all;
397 RUN liqout.scale_all;
398 RUN state.scale_all;
399 RUN scale_self;
400 END scale_all;
401
402 METHOD seqmod;
403 RUN state.specify;
404 (* Equations connect_feed, vapor_balance, and liquid_balance
405 * make us free nc+1 variables.
406 *)
407 FREE state.y[state.cd.components];
408 FREE state.phase_fraction['vapor'];
409 (* Then we trade cmo_ratio for T *)
410 FIX cmo_ratio;
411 IF (equilibrated) THEN
412 FREE state.T;
413 END IF;
414 END seqmod;
415
416 METHOD seqmod_massbal;
417 equilibrated := FALSE;
418 RUN seqmod;
419 FIX vapin.state.T;
420 FIX liqin.state.T;
421 END seqmod_massbal;
422
423 METHOD seqmod_fullthermo;
424 equilibrated := TRUE;
425 RUN seqmod;
426 END seqmod_fullthermo;
427
428 METHOD seqmod_fixed_Q;
429 RUN seqmod_fullthermo;
430 FREE cmo_ratio;
431 FIX Qin;
432 END seqmod_fixed_Q;
433
434 METHOD seqmod_adiabatic;
435 RUN seqmod_fixed_Q;
436 Qin := 0{W};
437 END seqmod_adiabatic;
438
439 METHOD reset_to_massbal;
440 equilibrated := FALSE;
441 RUN reset;
442 END reset_to_massbal;
443
444 METHOD reset_to_fullthermo;
445 equilibrated := TRUE;
446 RUN reset;
447 END reset_to_fullthermo;
448
449 METHOD reset_to_adiabatic;
450 RUN reset_to_fullthermo;
451 FREE cmo_ratio;
452 FIX Qin;
453 Qin := 0{W};
454 END reset_to_adiabatic;
455
456 METHOD specify;
457 RUN seqmod;
458 RUN vapin.specify;
459 RUN liqin.specify;
460 END specify;
461
462 METHOD heat_balance;
463 FREE cmo_ratio;
464 FIX Qin;
465 END heat_balance;
466
467 METHOD CMO;
468 FIX cmo_ratio;
469 FREE Qin;
470 END CMO;
471
472 END detailed_tray;
473
474 MODEL tray(
475 Qin WILL_BE energy_rate;
476 equilibrated WILL_BE boolean;
477 liqin WILL_BE stream;
478 vapin WILL_BE stream;
479 liqout WILL_BE stream;
480 vapout WILL_BE stream;
481 ) WHERE (
482 liqin, vapin, vapout, liqout WILL_NOT_BE_THE_SAME;
483 liqin.cd, liqout.cd, vapin.cd, vapout.cd WILL_BE_THE_SAME;
484 liqin.pd.phase_indicator IN ['L','M'] == TRUE;
485 liqout.pd.phase_indicator == 'L';
486 vapin.pd.phase_indicator IN ['V','M'] == TRUE;
487 vapout.pd.phase_indicator == 'V';
488 ) REFINES flash_base;
489
490 NOTES
491 'purpose' SELF {
492 This is a VLE tray MODEL for use when a single tray is needed
493 that must be connected via streams to other units. This is
494 a tray stack one tray tall.
495 }
496 'contra-indications' SELF {
497 This tray should not be used to create a stack of trays, as
498 it has a lot of unnecessary overhead for that application.
499 }
500 END NOTES;
501
502 cd ALIASES liqin.cd;
503
504 (* flash thermo options are derived from product streams *)
505 pdVL IS_A phases_data('VL', vapout.pd.vapor_option,
506 liqout.pd.liquid1_option, 'none');
507
508 (* flash Vapor-Liquid state comes from thermo of product streams. *)
509 phaseVL[VLphases] ALIASES
510 (vapout.phase['vapor'], liqout.phase['liquid1'])
511 WHERE VLphases IS_A set OF symbol_constant
512 WITH_VALUE ('vapor','liquid1');
513 state IS_A thermodynamics(cd, pdVL, phaseVL, equilibrated);
514
515 P ALIASES state.P;
516 T ALIASES state.T;
517 alpha "relative volatility" ALIASES state.phase['vapor'].alpha;
518 x "liquid product composition" ALIASES liqout.state.y;
519 y "vapor product composition" ALIASES vapout.state.y;
520
521 Details IS_A detailed_tray(Qin,equilibrated,
522 liqin.Details,vapin.Details,
523 liqout.Details,vapout.Details,
524 state);
525
526 METHODS
527
528 METHOD check_all;
529 RUN vapin.check_all;
530 RUN liqin.check_all;
531 RUN vapout.check_all;
532 RUN liqout.check_all;
533 RUN check_self;
534 END check_all;
535
536 METHOD check_self;
537 RUN pdVL.check_self;
538 RUN state.check_self;
539 RUN Details.check_self;
540 END check_self;
541
542 METHOD default_self;
543 RUN pdVL.default_self;
544 RUN state.default_self;
545 RUN Details.default_self;
546 END default_self;
547
548 METHOD default_all;
549 equilibrated := FALSE;
550 Qin := 0 {watt};
551 RUN vapin.default_all;
552 RUN liqin.default_all;
553 RUN vapout.default_all;
554 RUN liqout.default_all;
555 RUN default_self;
556 END default_all;
557
558 METHOD bound_self;
559 state.boundwidth := boundwidth;
560 Details.boundwidth := boundwidth;
561 RUN pdVL.bound_self;
562 RUN state.bound_self;
563 RUN Details.bound_self;
564 END bound_self;
565
566 METHOD bound_all;
567 liqin.boundwidth := boundwidth;
568 vapin.boundwidth := boundwidth;
569 vapout.boundwidth := boundwidth;
570 liqout.boundwidth := boundwidth;
571 RUN liqin.bound_all;
572 RUN vapin.bound_all;
573 RUN vapout.bound_all;
574 RUN liqout.bound_all;
575 STOP {tray bound_all needs to bound Qin somehow};
576 RUN bound_self;
577 END bound_all;
578
579 METHOD scale_self;
580 RUN pdVL.scale_self;
581 RUN state.scale_self;
582 RUN Details.scale_self;
583 END scale_self;
584
585 METHOD scale_all;
586 RUN liqin.scale_all;
587 RUN vapin.scale_all;
588 RUN vapout.scale_all;
589 RUN liqout.scale_all;
590 RUN scale_self;
591 END scale_all;
592
593 METHOD seqmod;
594 RUN Details.seqmod;
595 END seqmod;
596
597 METHOD seqmod_massbalance;
598 RUN Details.seqmod_massbal;
599 END seqmod_massbalance;
600
601 METHOD seqmod_fullthermo;
602 RUN Details.seqmod_fullthermo;
603 END seqmod_fullthermo;
604
605 METHOD seqmod_fixed_Q;
606 RUN Details.seqmod_fixed_Q;
607 END seqmod_fixed_Q;
608
609 METHOD seqmod_adiabatic;
610 RUN Details.seqmod_adiabatic;
611 END seqmod_adiabatic;
612
613 METHOD reset_to_massbalance;
614 RUN Details.reset_to_massbal;
615 END reset_to_massbalance;
616
617 METHOD reset_to_fullthermo;
618 RUN Details.reset_to_fullthermo;
619 END reset_to_fullthermo;
620
621 METHOD reset_to_adiabatic;
622 RUN Details.reset_to_adiabatic;
623 END reset_to_adiabatic;
624
625 METHOD specify;
626 RUN Details.specify;
627 END specify;
628
629 METHOD heat_balance;
630 RUN Details.heat_balance;
631 END heat_balance;
632
633 METHOD CMO;
634 RUN Details.CMO;
635 END CMO;
636
637 END tray;
638
639 MODEL feed_tray(
640 Qin WILL_BE energy_rate;
641 equilibrated WILL_BE boolean;
642 feed WILL_BE stream;
643 liqin WILL_BE stream;
644 vapin WILL_BE stream;
645 liqout WILL_BE stream;
646 vapout WILL_BE stream;
647 ) WHERE (
648 feed, liqin, vapin, vapout, liqout WILL_NOT_BE_THE_SAME;
649 feed.cd, liqin.cd, liqout.cd, vapin.cd, vapout.cd WILL_BE_THE_SAME;
650 liqin.pd.phase_indicator IN ['L','M'] == TRUE;
651 liqout.pd.phase_indicator == 'L';
652 vapin.pd.phase_indicator IN ['V','M'] == TRUE;
653 vapout.pd.phase_indicator == 'V';
654 (feed.pd.phase_indicator IN ['V','L','VL']) == TRUE;
655 ) REFINES flash_base;
656
657 cd ALIASES liqin.cd;
658
659 (* flash thermo options are derived from product streams *)
660 pdVL IS_A phases_data('VL', vapout.pd.vapor_option,
661 liqout.pd.liquid1_option, 'none');
662
663 (* flash Vapor-Liquid state comes from thermo of product streams. *)
664 phaseVL[VLphases] ALIASES
665 (vapout.phase['vapor'], liqout.phase['liquid1'])
666 WHERE VLphases IS_A set OF symbol_constant
667 WITH_VALUE ('vapor','liquid1');
668 state IS_A thermodynamics(cd, pdVL, phaseVL, equilibrated);
669
670 P ALIASES state.P;
671 T ALIASES state.T;
672 alpha "relative volatility" ALIASES state.phase['vapor'].alpha;
673
674 x "liquid product composition" ALIASES liqout.state.y;
675 y "vapor product composition" ALIASES vapout.state.y;
676
677 q IS_A factor;
678
679 q_eqn: (liqout.flow - (liqin.flow + q * feed.flow)) / flowscale = 0;
680
681 flowscale IS_A molar_rate_scale;
682 FOR i IN cd.other_components CREATE
683 connect_feed[i]:
684 ( (state.y[i] * (feed.flow + liqin.flow + vapin.flow)) -
685 (vapin.state.y[i] * vapin.flow + liqin.state.y[i] * liqin.flow +
686 feed.state.y[i] * feed.flow)
687 ) / flowscale = 0;
688 END FOR;
689
690 vapor_balance: (vapout.flow -
691 state.phase_fraction['vapor'] * (vapin.flow + liqin.flow + feed.flow))
692 / flowscale = 0;
693
694 liquid_balance: (liqout.flow -
695 state.phase_fraction['liquid1'] * (vapin.flow + liqin.flow + feed.flow))
696 / flowscale = 0;
697
698 H_flowscale IS_A energy_rate_scale;
699 energy_balance: ((vapin.H_flow + liqin.H_flow + feed.H_flow) + Qin -
700 (vapout.H_flow + liqout.H_flow)) / H_flowscale = 0;
701
702
703 METHODS
704
705 METHOD default_self;
706 q := 1.0;
707 q.lower_bound := -2; (* correct?? *)
708 q.upper_bound := 2;
709 flowscale := liqin.Details.flowscale + vapin.Details.flowscale;
710 H_flowscale := liqin.Details.H_flowscale + vapin.Details.H_flowscale;
711 RUN pdVL.default_self;
712 RUN state.default_self;
713 END default_self;
714
715 METHOD default_all;
716 equilibrated := FALSE;
717 Qin := 0 {watt};
718 RUN feed.default_all;
719 RUN vapin.default_all;
720 RUN liqin.default_all;
721 RUN vapout.default_all;
722 RUN liqout.default_all;
723 RUN default_self;
724 END default_all;
725
726 METHOD check_all;
727 RUN feed.check_all;
728 RUN vapin.check_all;
729 RUN liqin.check_all;
730 RUN vapout.check_all;
731 RUN liqout.check_all;
732 RUN pdVL.check_all;
733 RUN check_self;
734 END check_all;
735
736 METHOD check_self;
737 IF (feed.flow < 1e-4 {mole/s}) THEN
738 STOP {Feed flow to feed tray disappeared};
739 END IF;
740 IF (liqout.flow < 1e-4 {mole/s}) THEN
741 STOP {Liquid flow dried up on feed tray};
742 END IF;
743 IF (vapout.flow < 1e-4 {mole/s}) THEN
744 STOP {All vapor condensed on feed tray};
745 END IF;
746 RUN pdVL.check_self;
747 RUN state.check_self;
748 IF (abs(vapin.flow + liqin.flow + feed.flow -
749 vapout.flow - liqout.flow)/flowscale > 1.0e-4) THEN
750 STOP {Feed tray violates overall mass-balance};
751 END IF;
752 END check_self;
753
754 METHOD bound_self;
755 state.boundwidth := boundwidth;
756 RUN pdVL.bound_self;
757 RUN state.bound_self;
758 q.lower_bound := q - boundwidth*q.nominal;
759 q.upper_bound := q + boundwidth*q.nominal;
760 END bound_self;
761
762 METHOD bound_all;
763 feed.boundwidth := boundwidth;
764 liqin.boundwidth := boundwidth;
765 vapin.boundwidth := boundwidth;
766 vapout.boundwidth := boundwidth;
767 liqout.boundwidth := boundwidth;
768 RUN feed.bound_all;
769 RUN liqin.bound_all;
770 RUN vapin.bound_all;
771 RUN vapout.bound_all;
772 RUN liqout.bound_all;
773 RUN bound_self;
774 END bound_all;
775
776 METHOD scale_self;
777 flowscale := liqin.Details.flowscale + vapin.Details.flowscale
778 + feed.Details.flowscale;
779 H_flowscale := liqin.Details.H_flowscale + vapin.Details.H_flowscale
780 + feed.Details.H_flowscale;
781 q.nominal := abs(q)*1.01 + 0.1;
782 RUN pdVL.scale_self;
783 RUN state.scale_self;
784 END scale_self;
785
786 METHOD scale_all;
787 RUN feed.scale_all;
788 RUN liqin.scale_all;
789 RUN vapin.scale_all;
790 RUN vapout.scale_all;
791 RUN liqout.scale_all;
792 RUN scale_self;
793 END scale_all;
794
795 METHOD seqmod;
796 RUN state.specify;
797 (* Equations connect_feed, vapor_balance, and liquid_balance
798 * make us free nc+1 variables.
799 *)
800 FREE state.y[cd.components];
801 FREE state.phase_fraction['vapor'];
802 (* swap q for T at equilibrium, or set both if
803 * ignoring equilbrium.
804 *)
805 FIX q;
806 IF (equilibrated) THEN
807 FREE T;
808 END IF;
809 END seqmod;
810
811 METHOD seqmod_massbal;
812 equilibrated := FALSE;
813 RUN seqmod;
814 FIX vapin.state.T;
815 FIX liqin.state.T;
816 END seqmod_massbal;
817
818 METHOD seqmod_fullthermo;
819 equilibrated := TRUE;
820 RUN seqmod;
821 END seqmod_fullthermo;
822
823 METHOD seqmod_fixed_Q;
824 RUN fullthermo_seqmod;
825 FREE q;
826 FIX Qin;
827 END seqmod_fixed_Q;
828
829 METHOD seqmod_adiabatic;
830 RUN seqmod_fixed_Q;
831 Qin := 0{W};
832 END seqmod_adiabatic;
833
834 METHOD reset_to_massbal;
835 equilibrated := FALSE;
836 RUN reset;
837 END reset_to_massbal;
838
839 METHOD reset_to_fullthermo;
840 equilibrated := TRUE;
841 RUN reset;
842 END reset_to_fullthermo;
843
844 METHOD reset_to_adiabatic;
845 RUN reset_to_fullthermo;
846 FREE q;
847 FIX Qin;
848 Qin := 0{W};
849 END reset_to_adiabatic;
850
851 METHOD specify;
852 RUN seqmod;
853 RUN feed.specify;
854 IF (feed.equilibrated AND (feed.pd.phase_indicator == 'VL')) THEN
855 FREE feed.Details.state.phase[pd.reference_phase].T;
856 FIX feed.Details.state.phase_fraction[pd.other_phases];
857 END IF;
858 RUN vapin.specify;
859 RUN liqin.specify;
860 END specify;
861
862 END feed_tray;
863
864 MODEL total_condenser(
865 Qin WILL_BE energy_rate;
866 vapin WILL_BE stream;
867 liqout WILL_BE stream;
868 distillate WILL_BE stream;
869 ) WHERE (
870 vapin, liqout, distillate WILL_NOT_BE_THE_SAME;
871 distillate.state, liqout.state WILL_NOT_BE_THE_SAME;
872 distillate.cd, liqout.cd, vapin.cd WILL_BE_THE_SAME;
873 vapin.pd.phase_indicator IN ['V','M'] == TRUE;
874 liqout.pd.phase_indicator == 'L';
875 distillate.pd.phase_indicator == 'L';
876 ) REFINES flash_base;
877
878 NOTES
879 'purpose' SELF {
880 This models a total condenser. A partial condenser
881 would need a vapor-liquid state constructed from the
882 vapor product and the distillate product streams.
883 }
884 'ascii-picture' SELF {
885 |
886 v Vapin
887 /-------------\
888 |OOOOOOOOOOOOO+--< Qin
889 |~~~~~~~~~~~~~|
890 \_____________+--> Distillate
891 | Liqout
892 v
893 }
894 END NOTES;
895
896 cd ALIASES vapin.cd;
897 state ALIASES distillate.state;
898 P ALIASES state.P;
899 T ALIASES state.T;
900
901 reflux_ratio IS_A factor;
902
903 reflux_eqn: (liqout.flow - reflux_ratio * distillate.flow)
904 / flowscale = 0;
905
906 FOR i IN cd.other_components CREATE
907 distillate.state.y[i] = vapin.state.y[i];
908 liqout.state.y[i] = vapin.state.y[i];
909 END FOR;
910
911 flowscale IS_A molar_rate_scale;
912 (vapin.flow - distillate.flow - liqout.flow) / flowscale = 0;
913
914 H_flowscale IS_A energy_rate_scale;
915 energy_balance: (vapin.H_flow + Qin -
916 (liqout.H_flow + distillate.H_flow)) / H_flowscale =0;
917
918
919
920 METHODS
921
922 METHOD check_all;
923 RUN vapin.check_all;
924 RUN liqout.check_all;
925 RUN distillate.check_all;
926 RUN check_self;
927 END check_all;
928
929 METHOD check_self;
930 IF (vapin.flow < 1e-4 {mole/s}) THEN
931 STOP {Vapor flow to condenser disappeared};
932 END IF;
933 IF (liqout.flow < 1e-4 {mole/s}) THEN
934 STOP {No reflux leaving condenser};
935 END IF;
936 IF (distillate.flow < 1e-4 {mole/s}) THEN
937 STOP {No distillate leaving condenser};
938 END IF;
939 IF (abs(vapin.flow -
940 distillate.flow - liqout.flow)/flowscale > 1.0e-4) THEN
941 STOP {Condenser violates overall mass-balance};
942 END IF;
943 END check_self;
944
945 METHOD default_self;
946 H_flowscale := vapin.H_flow + abs(Qin);
947 flowscale := vapin.Details.flowscale;
948 reflux_ratio := 10;
949 reflux_ratio.upper_bound := 1000;
950 reflux_ratio.lower_bound := 0;
951 END default_self;
952
953 METHOD default_all;
954 RUN vapin.default_all;
955 RUN liqout.default_all;
956 RUN distillate.default_all;
957 RUN default_self;
958 END default_all;
959
960 METHOD bound_self;
961 reflux_ratio.lower_bound :=
962 reflux_ratio - boundwidth * reflux_ratio.nominal;
963 reflux_ratio.upper_bound :=
964 reflux_ratio + boundwidth * reflux_ratio.nominal;
965 IF (reflux_ratio.lower_bound < 0) THEN
966 reflux_ratio.lower_bound := 0;
967 END IF;
968 END bound_self;
969
970 METHOD bound_all;
971 vapin.boundwidth := boundwidth;
972 liqout.boundwidth := boundwidth;
973 distillate.boundwidth := boundwidth;
974 RUN vapin.bound_all;
975 RUN liqout.bound_all;
976 RUN distillate.bound_all;
977 RUN bound_self;
978 STOP {MODEL total_condenser method bound_all needs to do Qin};
979 END bound_all;
980
981 METHOD scale_self;
982 flowscale := vapin.Details.flowscale + liqout.Details.flowscale
983 + distillate.Details.flowscale;
984 H_flowscale := liqout.Details.H_flowscale + vapin.Details.H_flowscale
985 + distillate.Details.H_flowscale;
986 reflux_ratio.nominal := abs(reflux_ratio)*1.01 + 1;
987 END scale_self;
988
989 METHOD scale_all;
990 RUN vapin.scale_all;
991 RUN liqout.scale_all;
992 RUN distillate.scale_all;
993 RUN scale_self;
994 STOP {MODEL total_condenser method scale_all needs to do Qin};
995 END scale_all;
996
997 METHOD seqmod;
998 RUN liqout.seqmod;
999 RUN distillate.seqmod;
1000 FIX reflux_ratio;
1001 END seqmod;
1002
1003 METHOD specify;
1004 RUN seqmod;
1005 RUN vapin.specify;
1006 END specify;
1007
1008 END total_condenser;
1009
1010 MODEL simple_reboiler(
1011 Qin WILL_BE energy_rate;
1012 equilibrated WILL_BE boolean;
1013 liqin WILL_BE stream;
1014 vapout WILL_BE stream;
1015 bottoms WILL_BE stream;
1016 ) WHERE (
1017 liqin, vapout, bottoms WILL_NOT_BE_THE_SAME;
1018 liqin.cd, vapout.cd, bottoms.cd WILL_BE_THE_SAME;
1019 liqin.pd.phase_indicator IN ['L','M'] == TRUE;
1020 vapout.pd.phase_indicator == 'V';
1021 bottoms.pd.phase_indicator == 'L';
1022 ) REFINES flash_base;
1023
1024 NOTES
1025 'purpose' SELF {
1026 This models a reboiler where the liquid bottoms product is
1027 in equilibrium with the vapor returned to the bottom of the
1028 column. Taking a vapor product off this reboiler should be
1029 done, if desired, by routing the vapout stream through a
1030 splitter before returning it to the column.
1031 }
1032 'ascii-picture' SELF {
1033 | ^
1034 v liqin | vapout
1035 /-------------\
1036 | |
1037 |~~~~~~~~~~~~~|
1038 \__OOO________+--> bottoms
1039 | |
1040 Qin ^ .
1041 }
1042 END NOTES;
1043
1044 cd ALIASES liqin.cd;
1045 P ALIASES vapout.P;
1046 T ALIASES vapout.T;
1047 alpha "relative volatility" ALIASES state.phase['vapor'].alpha;
1048
1049 (* flash thermo options are derived from product streams *)
1050 pdVL IS_A phases_data('VL', vapout.pd.vapor_option,
1051 bottoms.pd.liquid1_option, 'none');
1052
1053 (* flash Vapor-Liquid state comes from thermo of product streams. *)
1054 phaseVL[VLphases] ALIASES
1055 (vapout.phase['vapor'], bottoms.phase['liquid1'])
1056 WHERE VLphases IS_A set OF symbol_constant
1057 WITH_VALUE ('vapor','liquid1');
1058 state IS_A thermodynamics(cd, pdVL, phaseVL, equilibrated);
1059
1060 x "bottoms product composition" ALIASES bottoms.state.y;
1061 y "vapor product composition" ALIASES vapout.state.y;
1062
1063 reboil_ratio "vapor flow to product flow ratio"
1064 IS_A factor;
1065
1066 reboil_eqn: (vapout.flow - reboil_ratio * bottoms.flow)
1067 / flowscale = 0;
1068
1069 FOR i IN cd.other_components CREATE
1070 connect_feed[i]: state.y[i] = liqin.state.y[i];
1071 END FOR;
1072
1073 flowscale IS_A molar_rate_scale;
1074
1075 vapor_balance: (vapout.flow -
1076 state.phase_fraction['vapor'] * liqin.flow)
1077 / flowscale = 0;
1078 liquid_balance: (bottoms.flow -
1079 state.phase_fraction['liquid1'] * liqin.flow)
1080 / flowscale = 0;
1081
1082 H_flowscale IS_A energy_rate_scale;
1083 energy_balance: (liqin.H_flow + Qin -
1084 (vapout.H_flow + bottoms.H_flow)) / H_flowscale = 0;
1085
1086
1087 METHODS
1088
1089 METHOD check_all;
1090 RUN liqin.check_all;
1091 RUN vapout.check_all;
1092 RUN bottoms.check_all;
1093 RUN check_self;
1094 END check_all;
1095
1096 METHOD check_self;
1097 IF (liqin.flow < 1e-4 {mole/s}) THEN
1098 STOP {Liquid flow to reboiler disappeared};
1099 END IF;
1100 IF (vapout.flow < 1e-4 {mole/s}) THEN
1101 STOP {No boilup leaving reboiler.};
1102 END IF;
1103 IF (bottoms.flow < 1e-4 {mole/s}) THEN
1104 STOP {No bottoms leaving reboiler.};
1105 END IF;
1106 IF (abs(liqin.flow -
1107 bottoms.flow - vapout.flow)/flowscale > 1.0e-4) THEN
1108 STOP {Reboiler violates overall mass-balance};
1109 END IF;
1110 END check_self;
1111
1112 METHOD default_self;
1113 H_flowscale := abs(liqin.H_flow) + abs(Qin);
1114 flowscale := liqin.Details.flowscale;
1115 reboil_ratio := 1;
1116 reboil_ratio.upper_bound := 1000;
1117 reboil_ratio.lower_bound := 0;
1118 END default_self;
1119
1120 METHOD default_all;
1121 equilibrated := FALSE;
1122 RUN liqin.default_all;
1123 RUN vapout.default_all;
1124 RUN bottoms.default_all;
1125 RUN default_self;
1126 STOP {MODEL simple_reboiler needs to set Qin in default_all};
1127 END default_all;
1128
1129 METHOD bound_self;
1130 reboil_ratio.lower_bound :=
1131 reboil_ratio - boundwidth * reboil_ratio.nominal;
1132 reboil_ratio.upper_bound :=
1133 reboil_ratio + boundwidth * reboil_ratio.nominal;
1134 IF (reboil_ratio.lower_bound < 0) THEN
1135 reboil_ratio.lower_bound := 0;
1136 END IF;
1137 END bound_self;
1138
1139 METHOD bound_all;
1140 liqin.boundwidth := boundwidth;
1141 vapout.boundwidth := boundwidth;
1142 bottoms.boundwidth := boundwidth;
1143 RUN liqin.bound_all;
1144 RUN vapout.bound_all;
1145 RUN bottoms.bound_all;
1146 RUN bound_self;
1147 STOP
1148 {MODEL simple_reboiler method bound_all needs to do Qin, reboil_ratio};
1149 END bound_all;
1150
1151 METHOD scale_self;
1152 flowscale := liqin.Details.flowscale + vapout.Details.flowscale
1153 + bottoms.Details.flowscale;
1154 H_flowscale := liqin.Details.H_flowscale + vapout.Details.H_flowscale
1155 + bottoms.Details.H_flowscale;
1156 reboil_ratio.nominal := abs(reboil_ratio)*1.01 + 1;
1157 END scale_self;
1158
1159 METHOD scale_all;
1160 RUN liqin.scale_all;
1161 RUN vapout.scale_all;
1162 RUN bottoms.scale_all;
1163 RUN scale_self;
1164 STOP
1165 {MODEL simple_reboiler method scale_all needs to do Qin, reboil_ratio};
1166 END scale_all;
1167
1168
1169 METHOD seqmod;
1170 RUN state.specify;
1171 FREE state.y[cd.components];
1172 FREE state.phase_fraction['vapor'];
1173 FIX reboil_ratio;
1174 IF (equilibrated) THEN
1175 FREE state.T;
1176 END IF;
1177 END seqmod;
1178
1179 METHOD reset_to_massbal;
1180 state.equilibrated := FALSE;
1181 RUN reset;
1182 END reset_to_massbal;
1183
1184 METHOD reset_to_fullthermo;
1185 state.equilibrated := TRUE;
1186 RUN reset;
1187 END reset_to_fullthermo;
1188
1189 METHOD specify;
1190 RUN seqmod;
1191 RUN liqin.specify;
1192 END specify;
1193
1194 END simple_reboiler;
1195
1196 (**************************************************************************)
1197
1198 MODEL testflashmodel() REFINES testcmumodel();
1199 (* root for flash based test models *)
1200 boundwidth IS_A bound_width;
1201 END testflashmodel;
1202
1203 MODEL test_vapor_liquid_flash() REFINES testflashmodel();
1204
1205 (* the next 5 are probably used throughout a flowsheet *)
1206 cd IS_A components_data(['n_pentane','n_hexane','n_heptane'],'n_heptane');
1207 pdV IS_A phases_data('V', 'ideal_vapor_mixture', 'none', 'none');
1208 pdL IS_A phases_data('L', 'none', 'UNIFAC_liquid_mixture', 'none');
1209 pdVL IS_A phases_data('VL', 'ideal_vapor_mixture',
1210 'UNIFAC_liquid_mixture', 'none');
1211 equilibrated IS_A start_false;
1212
1213 (* Qin is unit specific *)
1214 Qin IS_A energy_rate;
1215
1216 feed IS_A stream(cd, pdVL, equilibrated);
1217 liq IS_A stream(cd, pdL, equilibrated);
1218 vap IS_A stream(cd, pdV, equilibrated);
1219 fl1 IS_A vapor_liquid_flash(Qin, equilibrated, feed, vap, liq);
1220
1221
1222 METHODS
1223
1224 METHOD default_all;
1225 RUN default_self;
1226 END default_all;
1227
1228 METHOD default_self;
1229 boundwidth := 10;
1230 RUN feed.default_self;
1231 RUN liq.default_self;
1232 RUN vap.default_self;
1233 RUN fl1.default_self;
1234 (* or could be RUN fl1.default_all; *)
1235 END default_self;
1236
1237 METHOD check_all;
1238 RUN check_self;
1239 END check_all;
1240
1241 METHOD check_self;
1242 RUN feed.check_self;
1243 RUN liq.check_self;
1244 RUN vap.check_self;
1245 RUN fl1.check_self;
1246 (* or could be RUN check_all; *)
1247 END check_self;
1248
1249 METHOD bound_all;
1250 RUN bound_self;
1251 END bound_all;
1252
1253 METHOD bound_self;
1254 fl1.boundwidth := boundwidth;
1255 liq.boundwidth := boundwidth;
1256 vap.boundwidth := boundwidth;
1257 feed.boundwidth := boundwidth;
1258 (* The right, later reusable, way to finish this method is as follows:
1259 RUN feed.bound_self;
1260 RUN liq.bound_self;
1261 RUN vap.bound_self;
1262 RUN fl1.bound_self;
1263 * where we didn't have to look inside the parts we're using because
1264 * we know they follow the standard in system.a4l.
1265 *)
1266 (* The quick and dirty way, since there are no parts passed into
1267 * this MODEL is like so:
1268 *)
1269 RUN fl1.bound_all;
1270 (* This works, but we had to look into the VLflash MODEL to be sure. *)
1271 END bound_self;
1272
1273 METHOD scale_self;
1274 RUN feed.scale_self;
1275 RUN liq.scale_self;
1276 RUN vap.scale_self;
1277 RUN fl1.scale_self;
1278 (* or could be RUN fl1.scale_all; *)
1279 END scale_self;
1280
1281 METHOD specify;
1282 RUN fl1.specify;
1283 END specify;
1284
1285 METHOD reset_T;
1286 RUN ClearAll;
1287 RUN specify_T;
1288 END reset_T;
1289
1290 METHOD specify_T;
1291 RUN specify;
1292 FREE fl1.state.phase_fraction['vapor'];
1293 fl1.T := 340{K};
1294 FIX fl1.T;
1295 END specify_T;
1296
1297 METHOD values;
1298 feed.P := 1 {atm};
1299 feed.T := 298 {K};
1300 feed.f[cd.components] := 3 {mole/s};
1301 feed.phase['vapor'].alpha['n_pentane'] := 5;
1302 feed.phase['vapor'].alpha['n_hexane'] := 2;
1303 feed.phase['vapor'].alpha['n_heptane'] := 1;
1304 fl1.alpha['n_pentane'] := 5;
1305 fl1.alpha['n_hexane'] := 2;
1306 fl1.alpha['n_heptane'] := 1;
1307 fl1.state.phase_fraction['vapor'] := 0.5;
1308 fl1.P := 1 {atm};
1309 fl1.T := 365 {K};
1310 fl1.Qin := 0 {kW};
1311 equilibrated := FALSE;
1312 END values;
1313
1314 END test_vapor_liquid_flash;
1315
1316 MODEL test2_vapor_liquid_flash() REFINES testflashmodel();
1317
1318 (* the next 5 are probably used throughout a flowsheet *)
1319 cd IS_A components_data(['methanol','water'],'water');
1320 pdV IS_A phases_data('V', 'ideal_vapor_mixture', 'none', 'none');
1321 pdL IS_A phases_data('L', 'none', 'UNIFAC_liquid_mixture', 'none');
1322 pdVL IS_A phases_data('VL', 'ideal_vapor_mixture',
1323 'UNIFAC_liquid_mixture', 'none');
1324 equilibrated IS_A start_false;
1325
1326 (* Qin is unit specific *)
1327 Qin IS_A energy_rate;
1328
1329 feed IS_A stream(cd, pdVL, equilibrated);
1330 liq IS_A stream(cd, pdL, equilibrated);
1331 vap IS_A stream(cd, pdV, equilibrated);
1332 fl1 IS_A vapor_liquid_flash(Qin, equilibrated, feed, vap, liq);
1333
1334
1335 METHODS
1336
1337 METHOD default_all;
1338 RUN default_self;
1339 END default_all;
1340
1341 METHOD default_self;
1342 boundwidth := 10;
1343 RUN feed.default_self;
1344 RUN liq.default_self;
1345 RUN vap.default_self;
1346 RUN fl1.default_self;
1347 (* or could be RUN fl1.default_all; *)
1348 END default_self;
1349
1350 METHOD check_all;
1351 RUN check_self;
1352 END check_all;
1353
1354 METHOD check_self;
1355 RUN feed.check_self;
1356 RUN liq.check_self;
1357 RUN vap.check_self;
1358 RUN fl1.check_self;
1359 (* or could be RUN check_all; *)
1360 END check_self;
1361
1362 METHOD bound_all;
1363 RUN bound_self;
1364 END bound_all;
1365
1366 METHOD bound_self;
1367 fl1.boundwidth := boundwidth;
1368 liq.boundwidth := boundwidth;
1369 vap.boundwidth := boundwidth;
1370 feed.boundwidth := boundwidth;
1371 (* The right, later reusable, way to finish this method is as follows:
1372 RUN feed.bound_self;
1373 RUN liq.bound_self;
1374 RUN vap.bound_self;
1375 RUN fl1.bound_self;
1376 * where we didn't have to look inside the parts we're using because
1377 * we know they follow the standard in system.a4l.
1378 *)
1379 (* The quick and dirty way, since there are no parts passed into
1380 * this MODEL is like so:
1381 *)
1382 RUN fl1.bound_all;
1383 (* This works, but we had to look into the VLflash MODEL to be sure. *)
1384 END bound_self;
1385
1386 METHOD scale_self;
1387 RUN feed.scale_self;
1388 RUN liq.scale_self;
1389 RUN vap.scale_self;
1390 RUN fl1.scale_self;
1391 (* or could be RUN fl1.scale_all; *)
1392 END scale_self;
1393
1394 METHOD specify;
1395 RUN fl1.specify;
1396 END specify;
1397
1398 METHOD reset_T;
1399 RUN ClearAll;
1400 RUN specify_T;
1401 END reset_T;
1402
1403 METHOD specify_T;
1404 RUN specify;
1405 FREE fl1.state.phase_fraction['vapor'];
1406 fl1.T := 340{K};
1407 FIX fl1.T;
1408 END specify_T;
1409
1410 METHOD values;
1411 feed.P := 1 {atm};
1412 feed.T := 365 {K};
1413 feed.f['methanol'] := 0.01 {kmol/s};
1414 feed.f['water'] := 0.02 {kmol/s};
1415 feed.phase['vapor'].alpha['methanol'] := 2.1;
1416 feed.phase['vapor'].alpha['water'] := 0.9;
1417 fl1.alpha['methanol'] := 2;
1418 fl1.alpha['water'] := 1;
1419 fl1.state.phase_fraction['vapor'] := 0.5;
1420 fl1.P := 1 {atm};
1421 fl1.T := 365 {K};
1422 fl1.Qin := 0 {kW};
1423 equilibrated := FALSE;
1424 END values;
1425
1426 END test2_vapor_liquid_flash;
1427 MODEL test5_vapor_liquid_flash() REFINES testflashmodel();
1428
1429 (* the next 5 are probably used throughout a flowsheet *)
1430 cd IS_A components_data(
1431 ['n_butane','n_pentane','n_hexane','n_heptane','n_octane'],
1432 'n_octane');
1433 pdV IS_A phases_data('V', 'ideal_vapor_mixture', 'none', 'none');
1434 pdL IS_A phases_data('L', 'none', 'UNIFAC_liquid_mixture', 'none');
1435 pdVL IS_A phases_data('VL', 'ideal_vapor_mixture',
1436 'UNIFAC_liquid_mixture', 'none');
1437 equilibrated IS_A start_false;
1438
1439 (* Qin is unit specific *)
1440 Qin IS_A energy_rate;
1441
1442 feed IS_A stream(cd, pdVL, equilibrated);
1443 liq IS_A stream(cd, pdL, equilibrated);
1444 vap IS_A stream(cd, pdV, equilibrated);
1445 fl1 IS_A vapor_liquid_flash(Qin, equilibrated, feed, vap, liq);
1446
1447 (* boundwidth might be unit specific *)
1448
1449 METHODS
1450
1451 METHOD default_all;
1452 RUN default_self;
1453 END default_all;
1454
1455 METHOD default_self;
1456 boundwidth := 10;
1457 RUN feed.default_self;
1458 RUN liq.default_self;
1459 RUN vap.default_self;
1460 RUN fl1.default_self;
1461 (* or could be RUN fl1.default_all; *)
1462 END default_self;
1463
1464 METHOD check_all;
1465 RUN check_self;
1466 END check_all;
1467
1468 METHOD check_self;
1469 RUN feed.check_self;
1470 RUN liq.check_self;
1471 RUN vap.check_self;
1472 RUN fl1.check_self;
1473 (* or could be RUN check_all; *)
1474 END check_self;
1475
1476 METHOD bound_all;
1477 RUN bound_self;
1478 END bound_all;
1479
1480 METHOD bound_self;
1481 fl1.boundwidth := boundwidth;
1482 liq.boundwidth := boundwidth;
1483 vap.boundwidth := boundwidth;
1484 feed.boundwidth := boundwidth;
1485 (* The right, later reusable, way to finish this method is as follows:
1486 RUN feed.bound_self;
1487 RUN liq.bound_self;
1488 RUN vap.bound_self;
1489 RUN fl1.bound_self;
1490 * where we didn't have to look inside the parts we're using because
1491 * we know they follow the standard in system.a4l.
1492 *)
1493 (* The quick and dirty way, since there are no parts passed into
1494 * this MODEL is like so:
1495 *)
1496 RUN fl1.bound_all;
1497 (* This works, but we had to look into the VLflash MODEL to be sure. *)
1498 END bound_self;
1499
1500 METHOD scale_self;
1501 RUN feed.scale_self;
1502 RUN liq.scale_self;
1503 RUN vap.scale_self;
1504 RUN fl1.scale_self;
1505 (* or could be RUN fl1.scale_all; *)
1506 END scale_self;
1507
1508 METHOD specify;
1509 RUN fl1.specify;
1510 END specify;
1511
1512 METHOD reset_T;
1513 RUN ClearAll;
1514 RUN specify_T;
1515 END reset_T;
1516
1517 METHOD specify_T;
1518 RUN specify;
1519 FREE fl1.state.phase_fraction['vapor'];
1520 fl1.T := 340{K};
1521 FIX fl1.T;
1522 END specify_T;
1523
1524 METHOD values;
1525 feed.P := 1 {atm};
1526 feed.T := 365 {K};
1527 feed.f[cd.components] := 0.1 {kmol/s};
1528 feed.phase['vapor'].alpha['n_butane'] := 3.0;
1529 feed.phase['vapor'].alpha['n_pentane'] := 2.0;
1530 feed.phase['vapor'].alpha['n_hexane'] := 1.6;
1531 feed.phase['vapor'].alpha['n_heptane'] := 1.3;
1532 feed.phase['vapor'].alpha['n_octane'] := 0.9;
1533 fl1.alpha['n_butane'] := 3.0;
1534 fl1.alpha['n_pentane'] := 2.0;
1535 fl1.alpha['n_hexane'] := 1.6;
1536 fl1.alpha['n_heptane'] := 1.3;
1537 fl1.alpha['n_octane'] := 0.9;
1538 fl1.state.phase_fraction['vapor'] := 0.5;
1539 fl1.P := 1 {atm};
1540 fl1.T := 365 {K};
1541 fl1.Qin := 0 {kW};
1542 equilibrated := FALSE;
1543 END values;
1544
1545 END test5_vapor_liquid_flash;
1546 MODEL test_vlflashes;
1547 f2 IS_A test2_vapor_liquid_flash;
1548 f3 IS_A test_vapor_liquid_flash;
1549 f5 IS_A test5_vapor_liquid_flash;
1550 equilibrated IS_A boolean;
1551 f2.equilibrated,f3.equilibrated,f5.equilibrated,equilibrated ARE_THE_SAME;
1552 METHODS
1553 METHOD default_all;
1554 RUN default_self;
1555 END default_all;
1556
1557 METHOD default_self;
1558 RUN f2.default_self;
1559 RUN f3.default_self;
1560 RUN f5.default_self;
1561 END default_self;
1562
1563 METHOD specify;
1564 RUN f2.specify;
1565 RUN f3.specify;
1566 RUN f5.specify;
1567 END specify;
1568
1569 METHOD values;
1570 RUN f2.values;
1571 RUN f3.values;
1572 RUN f5.values;
1573 END values;
1574
1575 END test_vlflashes;
1576
1577 MODEL test_hard_vapor_liquid_flash() REFINES testflashmodel();
1578
1579
1580 (* the next 5 are probably used throughout a flowsheet *)
1581 cd IS_A components_data(['acetone','chloroform','benzene'],'benzene');
1582 pdV IS_A phases_data('V', 'ideal_vapor_mixture', 'none', 'none');
1583 pdL IS_A phases_data('L', 'none', 'UNIFAC_liquid_mixture', 'none');
1584 equilibrated IS_A start_false;
1585
1586 (* Qin is unit specific *)
1587 Qin IS_A energy_rate;
1588
1589 feed IS_A stream(cd, pdL, equilibrated);
1590 liq IS_A stream(cd, pdL, equilibrated);
1591 vap IS_A stream(cd, pdV, equilibrated);
1592 fl1 IS_A vapor_liquid_flash(Qin, equilibrated, feed, vap, liq);
1593
1594
1595 METHODS
1596
1597 METHOD default_all;
1598 RUN default_self;
1599 END default_all;
1600
1601 METHOD default_self;
1602 boundwidth := 10;
1603 RUN feed.default_self;
1604 RUN liq.default_self;
1605 RUN vap.default_self;
1606 RUN fl1.default_self;
1607 (* or could be RUN fl1.default_all; *)
1608 END default_self;
1609
1610 METHOD check_all;
1611 RUN check_self;
1612 END check_all;
1613
1614 METHOD check_self;
1615 RUN feed.check_self;
1616 RUN liq.check_self;
1617 RUN vap.check_self;
1618 RUN fl1.check_self;
1619 (* or could be RUN check_all; *)
1620 END check_self;
1621
1622 METHOD bound_all;
1623 RUN bound_self;
1624 END bound_all;
1625
1626 METHOD bound_self;
1627 fl1.boundwidth := boundwidth;
1628 liq.boundwidth := boundwidth;
1629 vap.boundwidth := boundwidth;
1630 feed.boundwidth := boundwidth;
1631 (* The right, later reusable, way to finish this method is as follows:
1632 RUN feed.bound_self;
1633 RUN liq.bound_self;
1634 RUN vap.bound_self;
1635 RUN fl1.bound_self;
1636 * where we didn't have to look inside the parts we're using because
1637 * we know they follow the standard in system.a4l.
1638 *)
1639 (* The quick and dirty way, since there are no parts passed into
1640 * this MODEL is like so:
1641 *)
1642 RUN fl1.bound_all;
1643 (* This works, but we had to look into the VLflash MODEL to be sure. *)
1644 END bound_self;
1645
1646 METHOD scale_self;
1647 RUN feed.scale_self;
1648 RUN liq.scale_self;
1649 RUN vap.scale_self;
1650 RUN fl1.scale_self;
1651 (* or could be RUN fl1.scale_all; *)
1652 END scale_self;
1653
1654 METHOD specify;
1655 RUN fl1.specify;
1656 END specify;
1657
1658 METHOD reset_T;
1659 RUN ClearAll;
1660 RUN specify_T;
1661 END reset_T;
1662
1663 METHOD specify_T;
1664 RUN specify;
1665 FREE fl1.state.phase_fraction['vapor'];
1666 fl1.T := 310{K};
1667 FIX fl1.T;
1668 END specify_T;
1669
1670 METHOD values;
1671 fl1.alpha['acetone'] := 3;
1672 fl1.alpha['chloroform'] := 2;
1673 fl1.alpha['benzene'] := 1;
1674 fl1.T := 298 {K};
1675 fl1.P := 1{atm};
1676 feed.f[cd.components] := 3{mole/s};
1677 END values;
1678
1679 END test_hard_vapor_liquid_flash;
1680
1681 MODEL test_tray() REFINES testflashmodel();
1682
1683 cd IS_A components_data(['n_pentane','n_hexane','n_heptane'],
1684 'n_heptane');
1685 pdV IS_A phases_data('V', 'ideal_vapor_mixture', 'none', 'none');
1686 pdL IS_A phases_data('L', 'none', 'UNIFAC_liquid_mixture', 'none');
1687
1688 equilibrated IS_A start_false;
1689
1690 (* Qin is unit specific *)
1691 Qin IS_A energy_rate;
1692
1693 Liqin IS_A stream(cd, pdL, equilibrated);
1694 Vapin IS_A stream(cd, pdV, equilibrated);
1695 Liqout IS_A stream(cd, pdL, equilibrated);
1696 Vapout IS_A stream(cd, pdV, equilibrated);
1697
1698
1699 Tray IS_A tray(Qin, equilibrated, Liqin, Vapin, Liqout, Vapout);
1700
1701 METHODS
1702
1703 METHOD default_all;
1704 RUN default_self;
1705 END default_all;
1706
1707 METHOD default_self;
1708 Qin := 0{kW};
1709 boundwidth := 10;
1710 RUN Liqin.default_self;
1711 RUN Vapin.default_self;
1712 RUN Liqout.default_self;
1713 RUN Vapout.default_self;
1714 RUN Tray.default_self;
1715 END default_self;
1716
1717 METHOD values;
1718 Tray.alpha['n_pentane'] := 3;
1719 Tray.alpha['n_hexane'] := 2;
1720 Tray.alpha['n_heptane'] := 1;
1721 Tray.state.T := 298 {K};
1722 Tray.state.P := 1{atm};
1723 Liqin.f['n_pentane'] := 3{mole/s};
1724 Liqin.f['n_hexane'] := 3{mole/s};
1725 Liqin.f['n_heptane'] := 3{mole/s};
1726 END values;
1727
1728 METHOD specify;
1729 RUN Tray.specify;
1730 END specify;
1731
1732 END test_tray;
1733
1734 MODEL test_feed_tray() REFINES testflashmodel();
1735
1736 (* The next 5 are probably used throughout a flowsheet *)
1737 cd IS_A components_data(['n_pentane','n_hexane','n_heptane'],
1738 'n_heptane');
1739 pdV IS_A phases_data('V', 'ideal_vapor_mixture', 'none', 'none');
1740 pdL IS_A phases_data('L', 'none', 'UNIFAC_liquid_mixture', 'none');
1741
1742 equilibrated IS_A start_false;
1743
1744 (* Qin is unit specific *)
1745 Qin IS_A energy_rate;
1746
1747 Feedin IS_A stream(cd, pdL, equilibrated);
1748 Liqin IS_A stream(cd, pdL, equilibrated);
1749 Vapin IS_A stream(cd, pdV, equilibrated);
1750 Liqout IS_A stream(cd, pdL, equilibrated);
1751 Vapout IS_A stream(cd, pdV, equilibrated);
1752
1753 Feed_tray IS_A
1754 feed_tray(Qin, equilibrated, Feedin, Liqin, Vapin, Liqout, Vapout);
1755
1756 METHODS
1757
1758 METHOD default_all;
1759 RUN default_self;
1760 END default_all;
1761
1762 METHOD default_self;
1763 Qin := 0{kW};
1764 boundwidth := 10;
1765 RUN Feedin.default_self;
1766 RUN Liqin.default_self;
1767 RUN Vapin.default_self;
1768 RUN Liqout.default_self;
1769 RUN Vapout.default_self;
1770 RUN Feed_tray.default_self;
1771 END default_self;
1772
1773 METHOD values;
1774 Feed_tray.alpha['n_pentane'] := 3;
1775 Feed_tray.alpha['n_hexane'] := 2;
1776 Feed_tray.alpha['n_heptane'] := 1;
1777 Feed_tray.T := 298 {K};
1778 Feed_tray.P := 1{atm};
1779 Liqin.f['n_pentane'] := 3{mole/s};
1780 Liqin.f['n_hexane'] := 3{mole/s};
1781 Liqin.f['n_heptane'] := 3{mole/s};
1782 END values;
1783
1784 METHOD specify;
1785 RUN Feed_tray.specify;
1786 END specify;
1787
1788 END test_feed_tray;
1789
1790 MODEL test_condenser() REFINES testflashmodel();
1791
1792 cd IS_A components_data(['n_pentane','n_hexane','n_heptane'],
1793 'n_heptane');
1794 pdV IS_A phases_data('V', 'ideal_vapor_mixture', 'none', 'none');
1795 pdL IS_A phases_data('L', 'none', 'UNIFAC_liquid_mixture', 'none');
1796
1797 (* Qin is unit specific *)
1798 Qin IS_A energy_rate;
1799
1800 equilibrated IS_A start_false;
1801
1802 Vapin IS_A stream(cd, pdV, equilibrated);
1803 Liqout IS_A stream(cd, pdL, equilibrated);
1804 Distillate IS_A stream(cd, pdL, equilibrated);
1805
1806 Condenser IS_A total_condenser(Qin, Vapin, Liqout, Distillate);
1807
1808 METHODS
1809
1810 METHOD default_all;
1811 RUN default_self;
1812 END default_all;
1813
1814 METHOD default_self;
1815 Qin := 100{kW};
1816 boundwidth := 10;
1817 RUN Vapin.default_self;
1818 RUN Liqout.default_self;
1819 RUN Distillate.default_self;
1820 RUN Condenser.default_self;
1821 END default_self;
1822
1823 METHOD values;
1824 Condenser.state.T := 298 {K};
1825 Condenser.state.P := 1{atm};
1826 Vapin.f['n_pentane'] := 3{mole/s};
1827 Vapin.f['n_hexane'] := 3{mole/s};
1828 Vapin.f['n_heptane'] := 3{mole/s};
1829 END values;
1830
1831 METHOD specify;
1832 RUN Condenser.specify;
1833 END specify;
1834 END test_condenser;
1835
1836 MODEL test_reboiler() REFINES testflashmodel();
1837
1838 (* The next 5 are probably used throughout a flowsheet *)
1839 cd IS_A components_data(['n_pentane','n_hexane','n_heptane'],
1840 'n_heptane');
1841 pdV IS_A phases_data('V', 'ideal_vapor_mixture', 'none', 'none');
1842 pdL IS_A phases_data('L', 'none', 'UNIFAC_liquid_mixture', 'none');
1843
1844 equilibrated IS_A start_false;
1845
1846 (* Qin is unit specific *)
1847 Qin IS_A energy_rate;
1848
1849 Vapout IS_A stream(cd, pdV, equilibrated);
1850 Liqin IS_A stream(cd, pdL, equilibrated);
1851 Bottoms IS_A stream(cd, pdL, equilibrated);
1852
1853 Reboiler IS_A
1854 simple_reboiler(Qin, equilibrated, Liqin, Vapout, Bottoms);
1855
1856 METHODS
1857
1858 METHOD default_all;
1859 RUN default_self;
1860 END default_all;
1861
1862 METHOD default_self;
1863 Qin := 100{kW};
1864 RUN Liqin.default_self;
1865 RUN Vapout.default_self;
1866 RUN Bottoms.default_self;
1867 RUN Reboiler.default_self;
1868 END default_self;
1869
1870 METHOD values;
1871 Reboiler.alpha['n_pentane'] := 3;
1872 Reboiler.alpha['n_hexane'] := 2;
1873 Reboiler.alpha['n_heptane'] := 1;
1874 Reboiler.T := 298 {K};
1875 Reboiler.P := 1{atm};
1876 Liqin.f['n_pentane'] := 3{mole/s};
1877 Liqin.f['n_hexane'] := 3{mole/s};
1878 Liqin.f['n_heptane'] := 3{mole/s};
1879 END values;
1880
1881 METHOD specify;
1882 RUN Reboiler.specify;
1883 END specify;
1884 END test_reboiler;

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