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

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

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