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

Annotation of /trunk/models/flash.a4l

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2651 - (hide 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 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 jpye 2651 * along with this program. If not, see <http://www.gnu.org/licenses/>.
34 aw0a 1 *)
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 johnpye 576 FREE state.y[cd.components];
226 aw0a 1 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 johnpye 576 FIX Qin;
261 aw0a 1 IF (equilibrated) THEN
262 johnpye 576 FREE state.phase_fraction['vapor'];
263 aw0a 1 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 johnpye 576 FREE state.y[state.cd.components];
406     FREE state.phase_fraction['vapor'];
407 aw0a 1 (* Then we trade cmo_ratio for T *)
408 johnpye 576 FIX cmo_ratio;
409 aw0a 1 IF (equilibrated) THEN
410 johnpye 576 FREE state.T;
411 aw0a 1 END IF;
412     END seqmod;
413    
414     METHOD seqmod_massbal;
415     equilibrated := FALSE;
416     RUN seqmod;
417 johnpye 576 FIX vapin.state.T;
418     FIX liqin.state.T;
419 aw0a 1 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 johnpye 576 FREE cmo_ratio;
429     FIX Qin;
430 aw0a 1 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 johnpye 576 FREE cmo_ratio;
450     FIX Qin;
451 aw0a 1 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 johnpye 576 FREE cmo_ratio;
462     FIX Qin;
463 aw0a 1 END heat_balance;
464    
465     METHOD CMO;
466 johnpye 576 FIX cmo_ratio;
467     FREE Qin;
468 aw0a 1 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 johnpye 576 FREE state.y[cd.components];
799     FREE state.phase_fraction['vapor'];
800 aw0a 1 (* swap q for T at equilibrium, or set both if
801     * ignoring equilbrium.
802     *)
803 johnpye 576 FIX q;
804 aw0a 1 IF (equilibrated) THEN
805 johnpye 576 FREE T;
806 aw0a 1 END IF;
807     END seqmod;
808    
809     METHOD seqmod_massbal;
810     equilibrated := FALSE;
811     RUN seqmod;
812 johnpye 576 FIX vapin.state.T;
813     FIX liqin.state.T;
814 aw0a 1 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 johnpye 576 FREE q;
824     FIX Qin;
825 aw0a 1 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 johnpye 576 FREE q;
845     FIX Qin;
846 aw0a 1 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 johnpye 576 FREE feed.Details.state.phase[pd.reference_phase].T;
854     FIX feed.Details.state.phase_fraction[pd.other_phases];
855 aw0a 1 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 johnpye 576 FIX reflux_ratio;
999 aw0a 1 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 johnpye 576 FREE state.y[cd.components];
1170     FREE state.phase_fraction['vapor'];
1171     FIX reboil_ratio;
1172 aw0a 1 IF (equilibrated) THEN
1173 johnpye 576 FREE state.T;
1174 aw0a 1 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 johnpye 576 FREE fl1.state.phase_fraction['vapor'];
1291 aw0a 1 fl1.T := 340{K};
1292 johnpye 576 FIX fl1.T;
1293 aw0a 1 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 johnpye 576 FREE fl1.state.phase_fraction['vapor'];
1404 aw0a 1 fl1.T := 340{K};
1405 johnpye 576 FIX fl1.T;
1406 aw0a 1 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 johnpye 576 FREE fl1.state.phase_fraction['vapor'];
1518 aw0a 1 fl1.T := 340{K};
1519 johnpye 576 FIX fl1.T;
1520 aw0a 1 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 johnpye 576 FREE fl1.state.phase_fraction['vapor'];
1664 aw0a 1 fl1.T := 310{K};
1665 johnpye 576 FIX fl1.T;
1666 aw0a 1 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