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

Annotation of /trunk/models/flash.a4l

Parent Directory Parent Directory | Revision Log Revision Log


Revision 576 - (hide annotations) (download) (as text)
Tue May 9 03:42:08 2006 UTC (18 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 aw0a 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 johnpye 576 FREE state.y[cd.components];
228 aw0a 1 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 johnpye 576 FIX Qin;
263 aw0a 1 IF (equilibrated) THEN
264 johnpye 576 FREE state.phase_fraction['vapor'];
265 aw0a 1 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 johnpye 576 FREE state.y[state.cd.components];
408     FREE state.phase_fraction['vapor'];
409 aw0a 1 (* Then we trade cmo_ratio for T *)
410 johnpye 576 FIX cmo_ratio;
411 aw0a 1 IF (equilibrated) THEN
412 johnpye 576 FREE state.T;
413 aw0a 1 END IF;
414     END seqmod;
415    
416     METHOD seqmod_massbal;
417     equilibrated := FALSE;
418     RUN seqmod;
419 johnpye 576 FIX vapin.state.T;
420     FIX liqin.state.T;
421 aw0a 1 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 johnpye 576 FREE cmo_ratio;
431     FIX Qin;
432 aw0a 1 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 johnpye 576 FREE cmo_ratio;
452     FIX Qin;
453 aw0a 1 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 johnpye 576 FREE cmo_ratio;
464     FIX Qin;
465 aw0a 1 END heat_balance;
466    
467     METHOD CMO;
468 johnpye 576 FIX cmo_ratio;
469     FREE Qin;
470 aw0a 1 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 johnpye 576 FREE state.y[cd.components];
801     FREE state.phase_fraction['vapor'];
802 aw0a 1 (* swap q for T at equilibrium, or set both if
803     * ignoring equilbrium.
804     *)
805 johnpye 576 FIX q;
806 aw0a 1 IF (equilibrated) THEN
807 johnpye 576 FREE T;
808 aw0a 1 END IF;
809     END seqmod;
810    
811     METHOD seqmod_massbal;
812     equilibrated := FALSE;
813     RUN seqmod;
814 johnpye 576 FIX vapin.state.T;
815     FIX liqin.state.T;
816 aw0a 1 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 johnpye 576 FREE q;
826     FIX Qin;
827 aw0a 1 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 johnpye 576 FREE q;
847     FIX Qin;
848 aw0a 1 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 johnpye 576 FREE feed.Details.state.phase[pd.reference_phase].T;
856     FIX feed.Details.state.phase_fraction[pd.other_phases];
857 aw0a 1 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 johnpye 576 FIX reflux_ratio;
1001 aw0a 1 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 johnpye 576 FREE state.y[cd.components];
1172     FREE state.phase_fraction['vapor'];
1173     FIX reboil_ratio;
1174 aw0a 1 IF (equilibrated) THEN
1175 johnpye 576 FREE state.T;
1176 aw0a 1 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 johnpye 576 FREE fl1.state.phase_fraction['vapor'];
1293 aw0a 1 fl1.T := 340{K};
1294 johnpye 576 FIX fl1.T;
1295 aw0a 1 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 johnpye 576 FREE fl1.state.phase_fraction['vapor'];
1406 aw0a 1 fl1.T := 340{K};
1407 johnpye 576 FIX fl1.T;
1408 aw0a 1 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 johnpye 576 FREE fl1.state.phase_fraction['vapor'];
1520 aw0a 1 fl1.T := 340{K};
1521 johnpye 576 FIX fl1.T;
1522 aw0a 1 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 johnpye 576 FREE fl1.state.phase_fraction['vapor'];
1666 aw0a 1 fl1.T := 310{K};
1667 johnpye 576 FIX fl1.T;
1668 aw0a 1 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